Beispiel #1
0
        /// <summary>BER encode class value.</summary>
        /// <param name="buffer">Target buffer. Value is appended to the end of it.</param>
        public override void encode(MutableByte buffer)
        {
            MutableByte tmp = new MutableByte();

            byte[] b = BitConverter.GetBytes(_value);

            for (int i = 3; i >= 0; i--)
            {
                if (b[i] != 0 || tmp.Length > 0)
                {
                    tmp.Append(b[i]);
                }
            }
            // if (tmp.Length > 1 && tmp[0] == 0xff && (tmp[1] & 0x80) != 0)
            if (tmp.Length > 0 && (tmp[0] & 0x80) != 0)
            {
                tmp.Prepend(0);
            }
            else if (tmp.Length == 0)
            {
                tmp.Append(0);
            }
            BuildHeader(buffer, Type, tmp.Length);
            buffer.Append(tmp);
        }
Beispiel #2
0
        /// <summary>
        /// Append BER encoded length to the <see cref="MutableByte"/>
        /// </summary>
        /// <param name="mb">MutableArray to append BER encoded length to</param>
        /// <param name="asnLength">Length value to encode.</param>
        /// <exception cref="ArgumentOutOfRangeException">Thrown when length value to encode is less then 0</exception>
        internal static void BuildLength(MutableByte mb, int asnLength)
        {
            if (asnLength < 0)
            {
                throw new ArgumentOutOfRangeException("Length cannot be less then 0.");
            }
            byte[]      len = BitConverter.GetBytes(asnLength);
            MutableByte buf = new MutableByte();

            for (int i = 3; i >= 0; i--)
            {
                if (len[i] != 0 || buf.Length > 0)
                {
                    buf.Append(len[i]);
                }
            }
            if (buf.Length == 0)
            {
                // we are encoding a 0 value. Can't have a 0 byte length encoding
                buf.Append(0);
            }
            // check for short form encoding
            if (buf.Length == 1 && (buf[0] & HIGH_BIT) == 0)
            {
                mb.Append(buf);                 // done
            }
            else
            {
                // long form encoding
                byte encHeader = (byte)buf.Length;
                encHeader = (byte)(encHeader | HIGH_BIT);
                mb.Append(encHeader);
                mb.Append(buf);
            }
        }
Beispiel #3
0
        /// <summary>
        /// Convert user password to acceptable authentication key.
        /// </summary>
        /// <param name="userPassword">Authentication password</param>
        /// <param name="engineID">Authoritative engine id</param>
        /// <returns>Localized authentication key</returns>
        /// <exception cref="SnmpAuthenticationException">Thrown when key length is less then 8 bytes</exception>
        public byte[] PasswordToKey(byte[] userPassword, byte[] engineID)
        {
            // key length has to be at least 8 bytes long (RFC3414)
            if (userPassword == null || userPassword.Length < 8)
            {
                throw new SnmpAuthenticationException("Secret key is too short.");
            }

            int password_index = 0;
            int count          = 0;
            MD5 md5            = new MD5CryptoServiceProvider();

            byte[] sourceBuffer = new byte[1048576];
            byte[] buf          = new byte[64];
            while (count < 1048576)
            {
                for (int i = 0; i < 64; ++i)
                {
                    buf[i] = userPassword[password_index++ % userPassword.Length];
                }
                Buffer.BlockCopy(buf, 0, sourceBuffer, count, buf.Length);
                count += 64;
            }

            byte[] digest = md5.ComputeHash(sourceBuffer);

            MutableByte tmpbuf = new MutableByte();

            tmpbuf.Append(digest);
            tmpbuf.Append(engineID);
            tmpbuf.Append(digest);
            byte[] key = md5.ComputeHash(tmpbuf);

            return(key);
        }
Beispiel #4
0
        /// <summary>Encode Pdu class to BER byte buffer</summary>
        /// <remarks>
        /// Encodes the protocol data unit using the passed encoder and stores
        /// the results in the passed buffer. An exception is thrown if an
        /// error occurs with the encoding of the information.
        /// </remarks>
        /// <param name="buffer">The buffer to write the encoded information.</param>
        public override void Encode(MutableByte buffer)
        {
            MutableByte tmpBuffer = new MutableByte();

            // if request id is 0, get a random value
            if (requestId.Value == 0)
            {
                requestId.SetRandom();
            }

            requestId.Encode(tmpBuffer);
            errorStatus.Encode(tmpBuffer);
            errorIndex.Encode(tmpBuffer);

            // if V2TRAP PDU type, add sysUpTime and trapObjectID OIDs before encoding VarBind
            if (Type == EPduType.V2Trap || Type == EPduType.Inform)
            {
                if (VbList.Count == 0)
                {
                    // add sysUpTime and trapObjectID to the VbList
                    VbList.Add(SnmpConstants.SysUpTime, TrapSysUpTime);
                    VbList.Add(SnmpConstants.TrapObjectId, trapObjectID);
                }
                else
                {
                    // Make sure user didn't manually add sysUpTime and trapObjectID values
                    // to the pdu

                    // if we have more then one item in the VarBinds array check for sysUpTime
                    if (VbList.Count > 0)
                    {
                        // if the first Vb in the VarBinds array is not sysUpTime append it in the
                        // encoded byte array
                        if (!VbList[0].Oid.Equals(SnmpConstants.SysUpTime))
                        {
                            Vb sysUpTimeVb = new Vb(SnmpConstants.SysUpTime, TrapSysUpTime);
                            VbList.Insert(0, sysUpTimeVb);
                        }
                    }

                    // if we have 2 or more Vbs in the VarBinds array check for trapObjectID Vb
                    if (VbList.Count > 1)
                    {
                        // if second Vb in the VarBinds array is not trapObjectId encode the value
                        if (!VbList[1].Oid.Equals(SnmpConstants.TrapObjectId))
                        {
                            Vb trapObjectIdVb = new Vb(SnmpConstants.TrapObjectId, trapObjectID);
                            VbList.Insert(1, trapObjectIdVb);
                        }
                    }
                }
            }

            // encode variable bindings
            VbList.Encode(tmpBuffer);

            // Now encode the header for the PDU
            BuildHeader(buffer, (byte)Type, tmpBuffer.Length);
            buffer.Append(tmpBuffer);
        }
Beispiel #5
0
        /// <summary>
        /// Encode SNMP packet for sending.
        /// </summary>
        /// <returns>BER encoded SNMP packet.</returns>
        /// <exception cref="SnmpInvalidPduTypeException">Thrown when PDU being encoded is not a valid SNMP version 1 PDU. Acceptable
        /// protocol version 1 operations are GET, GET-NEXT, SET and RESPONSE.</exception>
        public override byte[] encode()
        {
            if (this.Pdu.Type != PduType.Get && this.Pdu.Type != PduType.GetNext &&
                this.Pdu.Type != PduType.Set && this.Pdu.Type != PduType.Response)
            {
                throw new SnmpInvalidVersionException("Invalid SNMP PDU type while attempting to encode PDU: " + string.Format("0x{0:x2}", this.Pdu.Type));
            }
            if (this.Pdu.RequestId == 0)
            {
                System.Random rand = new System.Random((System.Int32)DateTime.Now.Ticks);
                this.Pdu.RequestId = rand.Next();
            }
            MutableByte tmpBuffer = new MutableByte();

            // snmp version
            _protocolVersion.encode(tmpBuffer);

            // community string
            _snmpCommunity.encode(tmpBuffer);

            // pdu
            this.Pdu.encode(tmpBuffer);

            MutableByte buf = new MutableByte();

            // wrap the packet into a sequence
            AsnType.BuildHeader(buf, SnmpConstants.SMI_SEQUENCE, tmpBuffer.Length);

            buf.Append(tmpBuffer);
            return(buf);
        }
        /// <summary>
        /// Convert user password to acceptable authentication key.
        /// </summary>
        /// <param name="userPassword">User password</param>
        /// <param name="engineID">Authoritative engine id</param>
        /// <returns>Localized authentication key</returns>
        /// <exception cref="SnmpAuthenticationException">Thrown when key length is less then 8 bytes</exception>
        public byte[] PasswordToKey(byte[] userPassword, byte[] engineID)
        {
            // key length has to be at least 8 bytes long (RFC3414)
            if (userPassword == null || userPassword.Length < 8)
            {
                throw new SnmpAuthenticationException("Secret key is too short.");
            }

            int password_index = 0;
            int count          = 0;

#if !NETCOREAPP11 && !NETSTANDARD15
            SHA1 sha = new SHA1CryptoServiceProvider();
#else
            SHA1 sha = SHA1.Create();
#endif

            /* Use while loop until we've done 1 Megabyte */
            byte[] sourceBuffer = new byte[1048576];
            byte[] buf          = new byte[64];
            while (count < 1048576)
            {
                for (int i = 0; i < 64; ++i)
                {
                    // Take the next octet of the password, wrapping
                    // to the beginning of the password as necessary.
                    buf[i] = userPassword[password_index++ % userPassword.Length];
                }
                Buffer.BlockCopy(buf, 0, sourceBuffer, count, buf.Length);
                count += 64;
            }

            byte[] digest = sha.ComputeHash(sourceBuffer);

            MutableByte tmpbuf = new MutableByte();
            tmpbuf.Append(digest);
            tmpbuf.Append(engineID);
            tmpbuf.Append(digest);
            byte[] res = sha.ComputeHash(tmpbuf);
#if !NETCOREAPP11 && !NETSTANDARD15
            sha.Clear();
#else
            sha.Dispose();
#endif
            return(res);
        }
Beispiel #7
0
        /// <summary>
        /// Encodes ASN.1 object identifier and append it to the end of the passed buffer.
        /// </summary>
        /// <param name="buffer">
        /// Buffer to append the encoded information to.
        /// </param>
        public override void encode(MutableByte buffer)
        {
            MutableByte tmpBuffer = new MutableByte();

            UInt32[] values = _data;
            if (values == null || values.Length < 2)
            {
                values    = new UInt32[2];
                values[0] = values[1] = 0;
            }

            // silently create an oid = ".0.0" for arrays
            // less than 2 in length
            if (_data.Length < 2)
            {
                values    = new UInt32[2];
                values[0] = 0;
                values[1] = 0;
            }

            // verify that it is a valid object id!
            if (values[0] < 0 || values[0] > 2)
            {
                throw new SnmpException("Invalid Object Identifier");
            }

            if (values[1] < 0 || values[1] > 40)
            {
                throw new SnmpException("Invalid Object Identifier");
            }


            // add the first oid!
            tmpBuffer.Append((byte)(values[0] * 40 + values[1]));

            // encode remaining instance values
            for (int i = 2; i < values.Length; i++)
            {
                tmpBuffer.Append(encodeInstance(values[i]));
            }

            // build value header
            BuildHeader(buffer, Type, tmpBuffer.Length);
            // Append encoded value to the result buffer
            buffer.Append(tmpBuffer);
        }
        /// <summary>BER encode security model field.</summary>
        /// <remarks>
        /// USM security model is a SEQUENCE encoded inside a OCTETSTRING. To encode it, first encode the sequence
        /// of class values then "wrap" it inside a OCTETSTRING field
        /// </remarks>
        /// <param name="buffer">Buffer to store encoded USM security model header</param>
        public override void encode(MutableByte buffer)
        {
            MutableByte tmp = new MutableByte();

            // First encode all the values that will form the sequence
            _engineId.encode(tmp);
            // Encode engine boots
            _engineBoots.encode(tmp);
            // encode engine time
            _engineTime.encode(tmp);
            _securityName.encode(tmp);
            if (_authentication != AuthenticationDigests.None)
            {
                if (_authenticationParameters.Length <= 0)
                {
                    // If authentication is used, set authentication parameters field to 12 bytes set to 0x00
                    _authenticationParameters.Set(new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 });
                }
            }
            else
            {
                _authenticationParameters.Reset();
            }
            _authenticationParameters.encode(tmp);
            if (_privacy != PrivacyProtocols.None)
            {
                if (_privacyParameters.Length <= 0)
                {
                    IPrivacyProtocol privProto = PrivacyProtocol.GetInstance(_privacy);
                    if (privProto != null)
                    {
                        byte[] parameter = new byte[privProto.PrivacyParametersLength];
                        for (int i = 0; i < privProto.PrivacyParametersLength; i++)
                        {
                            parameter[i] = 0x00; // This is not necessary since all array members are, by default, initialized to 0
                        }
                        _privacyParameters.Set(parameter);
                    }
                    else
                    {
                        throw new SnmpException(SnmpException.UnsupportedPrivacyProtocol, "Unrecognized privacy protocol specified.");
                    }
                }
            }
            else
            {
                _privacyParameters.Reset();
            }
            _privacyParameters.encode(tmp);
            MutableByte tmp1 = new MutableByte();

            BuildHeader(tmp1, SnmpConstants.SMI_SEQUENCE, tmp.Length);
            tmp1.Append(tmp);

            BuildHeader(buffer, OCTETSTRING, tmp1.Length);

            buffer.Append(tmp1);
        }
Beispiel #9
0
        /// <summary>BER encode class value</summary>
        /// <param name="buffer">MutableByte to append BER encoded value to.
        /// </param>
        public override void encode(MutableByte buffer)
        {
            byte[]      b   = BitConverter.GetBytes(_value);
            MutableByte tmp = new MutableByte();

            for (int i = b.Length - 1; i >= 0; i--)
            {
                if (b[i] != 0 || tmp.Length > 0)
                {
                    tmp.Append(b[i]);
                }
            }
            if (tmp.Length == 0)
            {
                tmp.Append(0); // value is 0. can't have an empty encoding
            }
            BuildHeader(buffer, Type, tmp.Length);
            buffer.Append(tmp);
        }
Beispiel #10
0
 /// <summary>
 ///     Convert <see cref="ScopedPdu" /> into a BER encoded byte array. Resulting byte array is appended
 ///     to the argument specified <see cref="MutableByte" /> class.
 ///     Privacy operations are not performed by this method. Value encoded and returned by this method is
 ///     suitable for sending in NoAuthNoPriv or AuthNoPriv security configurations. If privacy is required,
 ///     caller will have to perform encryption and decryption operations after BER encoding is performed.
 ///     In privacy protected SNMP version 3 packets, ScopedPdu is 1) encrypted using configured encryption
 ///     method, 2) added to a <see cref="OctetString" /> field, and 3) appended to the data buffer.
 ///     Because privacy operation is intrusive, it is recommended that BER encoding of the ScopedPdu packet
 ///     is stored in a temporary <see cref="MutableByte" /> class, where it can be privacy protected and
 ///     added to the <see cref="OctetString" /> class for final encoding into the target SNMP v3 packet.
 /// </summary>
 /// <param name="buffer">
 ///     <see cref="MutableByte" /> class passed by reference that encoded ScopedPdu
 ///     value is appended to.
 /// </param>
 public override void encode(MutableByte buffer)
 {
     var tmp = new MutableByte();
     _contextEngineId.encode(tmp);
     _contextName.encode(tmp);
     // Encode base
     base.encode(tmp);
     BuildHeader(buffer, SnmpConstants.SMI_SEQUENCE, tmp.Length);
     buffer.Append(tmp);
 }
Beispiel #11
0
        /// <summary>
        /// Encode VarBind collection sequence
        /// </summary>
        /// <param name="buffer">Target buffer. Encoded VarBind collection is appended.</param>
        public override void Encode(MutableByte buffer)
        {
            MutableByte tmp = new MutableByte();

            foreach (Vb v in _vbs)
            {
                v.Encode(tmp);
            }
            BuildHeader(buffer, Type, tmp.Length);
            buffer.Append(tmp);
        }
Beispiel #12
0
        /// <summary>BER encode the variable binding
        /// </summary>
        /// <param name="buffer"><see cref="MutableByte"/> class to the end of which encoded variable
        /// binding values will be added.
        /// </param>
        public override void encode(MutableByte buffer)
        {
            // encode oid to the temporary buffer
            MutableByte oidbuf = new MutableByte();

            _oid.encode(oidbuf);
            // encode value to a temporary buffer
            MutableByte valbuf = new MutableByte();

            _value.encode(valbuf);

            // calculate data content length of the vb
            int vblen = oidbuf.Length + valbuf.Length;

            // encode vb header at the end of the result
            BuildHeader(buffer, Type, vblen);
            // add values to the encoded arrays to the end of the result
            buffer.Append(oidbuf);
            buffer.Append(valbuf);
        }
Beispiel #13
0
 /// <summary>BER encode OctetString variable.</summary>
 /// <param name="buffer"><see cref="MutableByte"/> encoding destination.</param>
 public override void encode(MutableByte buffer)
 {
     if (_data == null || _data.Length == 0)
     {
         BuildHeader(buffer, Type, 0);
     }
     else
     {
         BuildHeader(buffer, Type, _data.Length);
         buffer.Append(_data);
     }
 }
        /// <summary>
        ///     Convert user password to acceptable authentication key.
        /// </summary>
        /// <param name="userPassword">User password</param>
        /// <param name="engineID">Authoritative engine id</param>
        /// <returns>Localized authentication key</returns>
        /// <exception cref="SnmpAuthenticationException">Thrown when key length is less then 8 bytes</exception>
        public byte[] PasswordToKey(byte[] userPassword, byte[] engineID)
        {
            // key length has to be at least 8 bytes long (RFC3414)
            if (userPassword == null || userPassword.Length < 8)
            {
                throw new SnmpAuthenticationException("Secret key is too short.");
            }

            var  password_index = 0;
            var  count          = 0;
            SHA1 sha            = new SHA1CryptoServiceProvider();

            /* Use while loop until we've done 1 Megabyte */
            var sourceBuffer = new byte[1048576];
            var buf          = new byte[64];

            while (count < 1048576)
            {
                for (var i = 0; i < 64; ++i)
                {
                    // Take the next octet of the password, wrapping
                    // to the beginning of the password as necessary.
                    buf[i] = userPassword[password_index++ % userPassword.Length];
                }
                Buffer.BlockCopy(buf, 0, sourceBuffer, count, buf.Length);
                count += 64;
            }

            var digest = sha.ComputeHash(sourceBuffer);

            var tmpbuf = new MutableByte();

            tmpbuf.Append(digest);
            tmpbuf.Append(engineID);
            tmpbuf.Append(digest);
            var res = sha.ComputeHash(tmpbuf);

            sha.Clear(); // release resources
            return(res);
        }
Beispiel #15
0
        /// <summary>
        ///     Encode single OID instance value
        /// </summary>
        /// <param name="number">Instance value</param>
        /// <returns>Encoded instance value</returns>
        protected byte[] encodeInstance(uint number)
        {
            var result = new MutableByte();

            if (number <= 127)
            {
                result.Set((byte)number);
            }
            else
            {
                var val = number;
                var tmp = new MutableByte();
                while (val != 0)
                {
                    var b    = BitConverter.GetBytes(val);
                    var bval = b[0];
                    if ((bval & 0x80) != 0)
                    {
                        bval = (byte)(bval & ~HIGH_BIT); // clear high bit
                    }
                    val >>= 7;                           // shift original value by 7 bits
                    tmp.Append(bval);
                }
                // now we need to reverse the bytes for the final encoding
                for (var i = tmp.Length - 1; i >= 0; i--)
                {
                    if (i > 0)
                    {
                        result.Append((byte)(tmp[i] | HIGH_BIT));
                    }
                    else
                    {
                        result.Append(tmp[i]);
                    }
                }
            }
            return(result);
        }
Beispiel #16
0
        /// <summary>
        /// BER encode sequence
        /// </summary>
        /// <param name="buffer">Target buffer</param>
        public override void encode(MutableByte buffer)
        {
            int dataLen = 0;

            if (_data != null && _data.Length > 0)
            {
                dataLen = _data.Length;
            }
            BuildHeader(buffer, Type, dataLen);
            if (dataLen > 0)
            {
                buffer.Append(_data);
            }
        }
        /// <summary>
        ///     Encode VarBind collection sequence
        /// </summary>
        /// <param name="buffer">Target buffer. Encoded VarBind collection is appended.</param>
        public override void encode(MutableByte buffer)
        {
            var tmp = new MutableByte();

            //foreach (Vb v in _vbs)
            //{
            //	v.encode(tmp);
            //}
            //Awais this optimization needs review.
            Parallel.ForEach(_vbs, v => { v.encode(tmp); });

            BuildHeader(buffer, Type, tmp.Length);
            buffer.Append(tmp);
        }
Beispiel #18
0
        /// <summary>
        ///     Encodes ASN.1 object identifier and append it to the end of the passed buffer.
        /// </summary>
        /// <param name="buffer">
        ///     Buffer to append the encoded information to.
        /// </param>
        public override void encode(MutableByte buffer)
        {
            var tmpBuffer = new MutableByte();
            var values    = _data;

            if (values == null || values.Length < 2)
            {
                values    = new uint[2];
                values[0] = values[1] = 0;
            }

            // verify that it is a valid object id!
            if (values[0] < 0 || values[0] > 2)
            {
                throw new SnmpException("Invalid Object Identifier");
            }

            if (values[1] < 0 || values[1] > 40)
            {
                throw new SnmpException("Invalid Object Identifier");
            }


            // add the first oid!
            tmpBuffer.Append((byte)(values[0] * 40 + values[1]));

            // encode remaining instance values
            for (var i = 2; i < values.Length; i++)
            {
                tmpBuffer.Append(encodeInstance(values[i]));
            }

            // build value header
            BuildHeader(buffer, Type, tmpBuffer.Length);
            // Append encoded value to the result buffer
            buffer.Append(tmpBuffer);
        }
Beispiel #19
0
        /// <summary>ASN.1 encode SNMP version 1 trap</summary>
        /// <param name="buffer"><see cref="MutableByte"/> buffer to the end of which encoded values are appended.</param>
        public override void Encode(MutableByte buffer)
        {
            MutableByte trapBuffer = new MutableByte();

            // encode the enterprise id & address
            _enterprise.Encode(trapBuffer);

            _agentAddr.Encode(trapBuffer);

            _generic.Encode(trapBuffer);

            _specific.Encode(trapBuffer);

            _timeStamp.Encode(trapBuffer);

            VbList.Encode(trapBuffer);
            MutableByte tmpBuffer = new MutableByte();

            BuildHeader(tmpBuffer, (byte)PduType.Trap, trapBuffer.Length);
            trapBuffer.Prepend(tmpBuffer);
            buffer.Append(trapBuffer);
        }
Beispiel #20
0
        /// <summary>Encode SNMP packet for sending.</summary>
        /// <returns>BER encoded SNMP packet.</returns>
        /// <exception cref="SnmpInvalidPduTypeException">
        /// Thrown when PDU being encoded is not a valid SNMP version 1 PDU. Acceptable
        /// protocol version 1 operations are GET, GET-NEXT, SET and RESPONSE.
        /// </exception>
        public override byte[] Encode()
        {
            if (
                Pdu.Type != EPduType.Get &&
                Pdu.Type != EPduType.GetNext &&
                Pdu.Type != EPduType.Set &&
                Pdu.Type != EPduType.Response)
            {
                throw new SnmpInvalidVersionException("Invalid SNMP PDU type while attempting to encode PDU: " + string.Format("0x{0:x2}", Pdu.Type));
            }

            if (Pdu.RequestId == 0)
            {
                Random rand = new Random((int)DateTime.Now.Ticks);
                Pdu.RequestId = rand.Next();
            }

            MutableByte tmpBuffer = new MutableByte();

            // snmp version
            protocolVersion.Encode(tmpBuffer);

            // community string
            Community.Encode(tmpBuffer);

            // pdu
            Pdu.Encode(tmpBuffer);

            MutableByte buf = new MutableByte();

            // wrap the packet into a sequence
            AsnType.BuildHeader(buf, SnmpConstants.SmiSequence, tmpBuffer.Length);

            buf.Append(tmpBuffer);

            return(buf);
        }
Beispiel #21
0
        /// <summary>Decode BER encoded Oid value.</summary>
        /// <param name="buffer">BER encoded buffer</param>
        /// <param name="offset">The offset location to begin decoding</param>
        /// <returns>Buffer position after the decoded value</returns>
        public override int decode(byte[] buffer, int offset)
        {
            int headerLength;
            var asnType = ParseHeader(buffer, ref offset, out headerLength);

            if (asnType != Type)
            {
                throw new SnmpException("Invalid ASN.1 type.");
            }

            // check for sufficient data
            if (buffer.Length - offset < headerLength)
            {
                throw new OverflowException("Buffer underflow error");
            }

            if (headerLength == 0)
            {
                _data = null;
                return(offset);
            }

            var list = new List <uint>();


            // decode the first byte
            --headerLength;
            var oid = Convert.ToUInt32(buffer[offset++]);

            list.Add(oid / 40);
            list.Add(oid % 40);

            //
            // decode the rest of the identifiers
            //
            while (headerLength > 0)
            {
                uint result = 0;

                // this is where we decode individual values
                {
                    if ((buffer[offset] & HIGH_BIT) == 0)
                    {
                        // short encoding
                        result  = buffer[offset];
                        offset += 1;
                        --headerLength;
                    }
                    else
                    {
                        // long encoding
                        var tmp       = new MutableByte();
                        var completed = false;
                        do
                        {
                            tmp.Append((byte)(buffer[offset] & ~HIGH_BIT));
                            if ((buffer[offset] & HIGH_BIT) == 0)
                            {
                                completed = true;
                            }
                            offset += 1;    // advance offset
                            --headerLength; // take out the processed byte from the header length
                        } while (!completed);

                        // convert byte array to integer
                        for (var i = 0; i < tmp.Length; i++)
                        {
                            result <<= 7;
                            result  |= tmp[i];
                        }
                    }
                }
                list.Add(result);
            }
            _data = list.ToArray();

            if (_data.Length == 2 && _data[0] == 0 && _data[1] == 0)
            {
                _data = null;
            }

            return(offset);
        }
Beispiel #22
0
 /// <summary>
 /// Build ASN.1 header in the MutableByte array.
 /// </summary>
 /// <remarks>
 /// Header is the TL part of the TLV (type, length, value) BER encoded data representation.
 ///
 /// Each value is encoded as a Type byte, length of the data field and the actual, encoded
 /// data. This method will encode the type and length fields.
 /// </remarks>
 /// <param name="mb">MurableByte array</param>
 /// <param name="asnType">ASN.1 header type</param>
 /// <param name="asnLength">Length of the data contained in the header</param>
 internal static void BuildHeader(MutableByte mb, byte asnType, int asnLength)
 {
     mb.Append(asnType);
     BuildLength(mb, asnLength);
 }
        /// <summary>
        /// Encode SNMP version 3 packet
        /// </summary>
        /// <remarks>
        /// Before encoding the packet into a byte array you need to ensure all required information is
        /// set. Examples of required information is request type, Vbs (Oid + values pairs), USM settings including
        /// SecretName, authentication method and secret (if needed), privacy method and secret (if needed), etc.
        /// </remarks>
        /// <returns>Byte array BER encoded SNMP packet.</returns>
        public override byte[] encode()
        {
            MutableByte buffer = new MutableByte();
            // encode the global message data sequence header information

            MutableByte globalMessageData = new MutableByte();

            // if message id is 0 then generate a new, random message id
            if (_messageId.Value == 0)
            {
                Random rand = new Random();
                _messageId.Value = rand.Next(1, Int32.MaxValue);
            }

            // encode message id
            _messageId.encode(globalMessageData);

            // encode max message size
            _maxMessageSize.encode(globalMessageData);

            // message flags
            _msgFlags.encode(globalMessageData);

            // security model code
            _securityModel.Value = _userSecurityModel.Type;
            _securityModel.encode(globalMessageData);

            // add global message data to the main buffer
            // encode sequence header and add data
            AsnType.BuildHeader(buffer, SnmpConstants.SMI_SEQUENCE, globalMessageData.Length);
            buffer.Append(globalMessageData);

            MutableByte packetHeader = new MutableByte(buffer);

            // before going down this road, check if this is a discovery packet
            OctetString savedUserName  = new OctetString();
            bool        privacy        = _msgFlags.Privacy;
            bool        authentication = _msgFlags.Authentication;
            bool        reportable     = _msgFlags.Reportable;

            if (_userSecurityModel.EngineId.Length <= 0)
            {
                // save USM settings prior to encoding a Discovery packet
                savedUserName.Set(_userSecurityModel.SecurityName);
                _userSecurityModel.SecurityName.Reset();                 // delete security name for discovery packets
                _msgFlags.Authentication = false;
                _msgFlags.Privacy        = false;
                _msgFlags.Reportable     = true;
            }

            _userSecurityModel.encode(buffer);

            if (_userSecurityModel.EngineId.Length <= 0)
            {
                // restore saved USM values
                _userSecurityModel.SecurityName.Set(savedUserName);
                _msgFlags.Authentication = authentication;
                _msgFlags.Privacy        = privacy;
                _msgFlags.Reportable     = reportable;
            }

            // Check if privacy encryption is required
            MutableByte encodedPdu = new MutableByte();

            if (_msgFlags.Privacy && _userSecurityModel.EngineId.Length > 0)
            {
                IPrivacyProtocol privacyProtocol = PrivacyProtocol.GetInstance(_userSecurityModel.Privacy);
                if (privacyProtocol == null)
                {
                    throw new SnmpException(SnmpException.UnsupportedPrivacyProtocol, "Specified privacy protocol is not supported.");
                }

                // Get BER encoded ScopedPdu
                MutableByte unencryptedPdu = new MutableByte();
                _scopedPdu.encode(unencryptedPdu);

                byte[] privacyParameters = null;
                // we have to expand the key
                IAuthenticationDigest auth = Authentication.GetInstance(_userSecurityModel.Authentication);
                if (auth == null)
                {
                    throw new SnmpException(SnmpException.UnsupportedNoAuthPriv, "Invalid authentication protocol. noAuthPriv mode not supported.");
                }

                byte[] pkey = privacyProtocol.PasswordToKey(_userSecurityModel.PrivacySecret, _userSecurityModel.EngineId, auth);

                byte[] encryptedBuffer = privacyProtocol.Encrypt(unencryptedPdu, 0, unencryptedPdu.Length, pkey, _userSecurityModel.EngineBoots, _userSecurityModel.EngineTime, out privacyParameters, auth);

                _userSecurityModel.PrivacyParameters.Set(privacyParameters);
                OctetString encryptedOctetString = new OctetString(encryptedBuffer);
                encryptedOctetString.encode(encodedPdu);
                // now redo packet encoding
                buffer.Reset();
                buffer.Set(packetHeader);
                _userSecurityModel.encode(buffer);
                int preEncodedLength = encodedPdu.Length;
                buffer.Append(encodedPdu);
                if (_maxMessageSize.Value != 0)
                {
                    // verify compliance with maximum message size
                    if ((encodedPdu.Length - preEncodedLength) > _maxMessageSize)
                    {
                        throw new SnmpException(SnmpException.MaximumMessageSizeExceeded, "ScopedPdu exceeds maximum message size.");
                    }
                }
            }
            else
            {
                _scopedPdu.encode(encodedPdu);
                buffer.Append(encodedPdu);
            }

            int preVersionLength = buffer.Length;

            base.encode(buffer);

            int versionHeaderLength = buffer.Length - preVersionLength;

            if (_msgFlags.Authentication && _userSecurityModel.EngineId.Length > 0)
            {
                _userSecurityModel.Authenticate(ref buffer);
                // Now re-encode the packet with the authentication information
                _userSecurityModel.encode(packetHeader);
                packetHeader.Append(encodedPdu);
                base.encode(packetHeader);
                buffer = packetHeader;
            }
            return(buffer);
        }
Beispiel #24
0
        /// <summary>Encode SNMP version 3 packet</summary>
        /// <param name="authKey">Authentication key (not password)</param>
        /// <param name="privKey">Privacy key (not password)</param>
        /// <remarks>
        /// Before encoding the packet into a byte array you need to ensure all required information is
        /// set. Examples of required information is request type, Vbs (Oid + values pairs), USM settings including
        /// SecretName, authentication method and secret (if needed), privacy method and secret (if needed), etc.
        /// </remarks>
        /// <returns>Byte array BER encoded SNMP packet.</returns>
        public byte[] Encode(byte[] authKey, byte[] privKey)
        {
            MutableByte buffer = new MutableByte();

            // encode the global message data sequence header information
            MutableByte globalMessageData = new MutableByte();

            // if message id is 0 then generate a new, random message id
            if (messageId.Value == 0)
            {
                Random rand = new Random();
                messageId.Value = rand.Next(1, int.MaxValue);
            }

            // encode message id
            messageId.Encode(globalMessageData);

            // encode max message size
            maxMessageSize.Encode(globalMessageData);

            // message flags
            messageFlags.Encode(globalMessageData);

            // security model code
            securityModel.Value = userSecurityModel.Type;
            securityModel.Encode(globalMessageData);

            // add global message data to the main buffer
            // encode sequence header and add data
            AsnType.BuildHeader(buffer, SnmpConstants.SmiSequence, globalMessageData.Length);
            buffer.Append(globalMessageData);

            MutableByte packetHeader = new MutableByte(buffer);

            // before going down this road, check if this is a discovery packet
            OctetString savedUserName  = new OctetString();
            bool        privacy        = messageFlags.Privacy;
            bool        authentication = messageFlags.Authentication;
            bool        reportable     = messageFlags.Reportable;

            if (userSecurityModel.EngineId.Length <= 0)
            {
                // save USM settings prior to encoding a Discovery packet
                savedUserName.Set(userSecurityModel.SecurityName);
                userSecurityModel.SecurityName.Reset(); // delete security name for discovery packets
                messageFlags.Authentication = false;
                messageFlags.Privacy        = false;
                messageFlags.Reportable     = true;
            }

            userSecurityModel.Encode(buffer);

            if (userSecurityModel.EngineId.Length <= 0)
            {
                // restore saved USM values
                userSecurityModel.SecurityName.Set(savedUserName);
                messageFlags.Authentication = authentication;
                messageFlags.Privacy        = privacy;
                messageFlags.Reportable     = reportable;
            }

            // Check if privacy encryption is required
            MutableByte encodedPdu = new MutableByte();

            if (messageFlags.Privacy && userSecurityModel.EngineId.Length > 0)
            {
                IPrivacyProtocol privacyProtocol = PrivacyProtocol.GetInstance(userSecurityModel.Privacy);
                if (privacyProtocol == null)
                {
                    throw new SnmpException(SnmpException.EErrorCode.UnsupportedPrivacyProtocol, "Specified privacy protocol is not supported.");
                }

                // Get BER encoded ScopedPdu
                MutableByte unencryptedPdu = new MutableByte();
                scopedPdu.Encode(unencryptedPdu);

                // we have to expand the key
                IAuthenticationDigest auth = Authentication.GetInstance(userSecurityModel.Authentication);
                if (auth == null)
                {
                    throw new SnmpException(SnmpException.EErrorCode.UnsupportedNoAuthPriv, "Invalid authentication protocol. noAuthPriv mode not supported.");
                }

                byte[] encryptedBuffer = privacyProtocol.Encrypt(unencryptedPdu, 0, unencryptedPdu.Length, privKey, userSecurityModel.EngineBoots, userSecurityModel.EngineTime, out byte[] privacyParameters, auth);

                userSecurityModel.PrivacyParameters.Set(privacyParameters);

                OctetString encryptedOctetString = new OctetString(encryptedBuffer);
                encryptedOctetString.Encode(encodedPdu);

                // now redo packet encoding
                buffer.Reset();
                buffer.Set(packetHeader);
                userSecurityModel.Encode(buffer);

                int preEncodedLength = encodedPdu.Length;
                buffer.Append(encodedPdu);

                if (maxMessageSize.Value != 0)
                {
                    // verify compliance with maximum message size
                    if ((encodedPdu.Length - preEncodedLength) > maxMessageSize)
                    {
                        throw new SnmpException(SnmpException.EErrorCode.MaximumMessageSizeExceeded, "ScopedPdu exceeds maximum message size.");
                    }
                }
            }
            else
            {
                scopedPdu.Encode(encodedPdu);
                buffer.Append(encodedPdu);
            }

            Encode(buffer);

            if (messageFlags.Authentication && userSecurityModel.EngineId.Length > 0)
            {
                userSecurityModel.Authenticate(authKey, ref buffer);

                // Now re-encode the packet with the authentication information
                userSecurityModel.Encode(packetHeader);
                packetHeader.Append(encodedPdu);

                Encode(packetHeader);
                buffer = packetHeader;
            }

            return(buffer);
        }
Beispiel #25
0
        /// <summary> Used to encode the integer value into an ASN.1 buffer.
        /// The passed encoder defines the method for encoding the
        /// data.
        /// </summary>
        /// <param name="buffer">Buffer target to write the encoded data</param>
        public override void Encode(MutableByte buffer)
        {
            int val = _value;

            byte[] b = BitConverter.GetBytes(_value);

            MutableByte tmp = new MutableByte();

            // if value is negative
            if (val < 0)
            {
                for (int i = 3; i >= 0; i--)
                {
                    if (tmp.Length > 0 || b[i] != 0xff)
                    {
                        tmp.Append(b[i]);
                    }
                }
                if (tmp.Length == 0)
                {
                    // if the value is -1 then all bytes in an integer are 0xff and will be skipped above
                    tmp.Append(0xff);
                }
                // make sure value is negative
                if ((tmp[0] & 0x80) == 0)
                {
                    tmp.Prepend(0xff);
                }
            }
            else if (val == 0)
            {
                // this is just a shortcut to save processing time
                tmp.Append(0);
            }
            else
            {
                // byte[] b = BitConverter.GetBytes(val);
                for (int i = 3; i >= 0; i--)
                {
                    if (b[i] != 0 || tmp.Length > 0)
                    {
                        tmp.Append(b[i]);
                    }
                }
                // if buffer length is 0 then value is 0 and we have to add it to the buffer
                if (tmp.Length == 0)
                {
                    tmp.Append(0);
                }
                else
                {
                    if ((tmp[0] & 0x80) != 0)
                    {
                        // first bit of the first byte has to be 0 otherwise value is negative.
                        tmp.Prepend(0);
                    }
                }
            }
            // check for 9 1s at the beginning of the encoded value
            if ((tmp.Length > 1 && tmp[0] == 0xff && (tmp[1] & 0x80) != 0))
            {
                tmp.Prepend(0);
            }
            BuildHeader(buffer, Type, tmp.Length);

            buffer.Append(tmp);
        }