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 > 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>
 /// Authenticate SNMP version 3 message.
 ///
 /// Before calling this member, entire SNMP version 3 packet needs to be encoded. After authentication
 /// process is completed, authenticationParameters value in the USM header is updated and SNMPv3 packet
 /// needs to be re-encoded to include it in the BER encoded stream prior to transmission.
 /// </summary>
 /// <param name="wholePacket">SNMP version 3 BER encoded packet.</param>
 public void Authenticate(ref MutableByte wholePacket)
 {
     if (authentication != AuthenticationDigests.None)
     {
         IAuthenticationDigest authProto = Security.Authentication.GetInstance(authentication);
         byte[] authParam = authProto.Authenticate(AuthenticationSecret, EngineId.ToArray(), wholePacket);
         authenticationParameters = new OctetString(authParam);
     }
 }
Beispiel #3
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)
        {
            MutableByte tmp = new MutableByte();

            contextEngineId.Encode(tmp);
            contextName.Encode(tmp);

            // Encode base
            base.Encode(tmp);
            BuildHeader(buffer, SnmpConstants.SmiSequence, tmp.Length);
            buffer.Append(tmp);
        }
Beispiel #4
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);
     }
 }
Beispiel #5
0
 /// <summary>Copy constructor.</summary>
 /// <param name="value">Class to copy values from</param>
 public UserSecurityModel(UserSecurityModel value)
     : this()
 {
     engineId.Set(value.EngineId);
     engineBoots.Value = value.EngineBoots;
     engineTime.Value  = value.EngineTime;
     securityName.Set(value.SecurityName);
     authenticationParameters = new OctetString();
     privacySecret            = new MutableByte();
     privacy           = EPrivacyProtocols.None;
     privacyParameters = new OctetString();
 }
Beispiel #6
0
        /// <summary>
        /// Encode SNMP packet for sending.
        /// </summary>
        /// <returns>BER encoded SNMP packet.</returns>
        public override byte[] Encode()
        {
            MutableByte tmpBuffer = new MutableByte();

            //
            // encode the community strings
            _snmpCommunity.Encode(tmpBuffer);
            Pdu.Encode(tmpBuffer);

            base.Encode(tmpBuffer);

            return((byte[])tmpBuffer);
        }
Beispiel #7
0
        /// <summary>Authenticate incoming packet</summary>
        /// <param name="authKey">Authentication key (not password)</param>
        /// <param name="wholePacket">Received BER encoded SNMP version 3 packet</param>
        /// <returns>True if packet is successfully authenticated, otherwise false.</returns>
        public bool IsAuthentic(byte[] authKey, MutableByte wholePacket)
        {
            if (authentication != AuthenticationDigests.None)
            {
                IAuthenticationDigest authProto = Security.Authentication.GetInstance(authentication);
                if (authProto != null)
                {
                    return(authProto.AuthenticateIncomingMsg(authKey, authenticationParameters, wholePacket));
                }
            }

            return(false); // Nothing to authenticate
        }
        /// <summary>
        ///     Encode SNMP packet for sending.
        /// </summary>
        /// <returns>BER encoded SNMP packet.</returns>
        public override byte[] encode()
        {
            var tmpBuffer = new MutableByte();

            //
            // encode the community strings
            _snmpCommunity.encode(tmpBuffer);
            Pdu.encode(tmpBuffer);

            base.encode(tmpBuffer);

            return(tmpBuffer);
        }
Beispiel #9
0
        /// <summary>
        /// Reset USM object to default values. All OctetString and MutableByte members are reset to 0 length and
        /// privacy and authentication protocols are set to none.
        /// </summary>
        public void Reset()
        {
            Type           = 3;
            engineId       = new OctetString();
            engineBoots    = new Integer32();
            engineTime     = new Integer32();
            authentication = AuthenticationDigests.None;

            securityName             = new OctetString();
            authenticationSecret     = new MutableByte();
            authenticationParameters = new OctetString();
            privacySecret            = new MutableByte();
            privacy           = EPrivacyProtocols.None;
            privacyParameters = new OctetString();
        }
Beispiel #10
0
        public void Generate()
        {
            var i      = new Counter64(300);
            var buffer = new MutableByte();

            i.Encode(buffer);

            var expected = new byte[]
            {
                SnmpConstants.SmiCounter64, // ASN.1 Type
                0x02,                       // Length
                0x01, 0x2C,                 // 300 in big endian
            };

            Assert.Equal(expected, buffer);
        }
Beispiel #11
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);
            }
        }
Beispiel #12
0
        /// <summary>Encode single OID instance value</summary>
        /// <param name="number">Instance value</param>
        /// <returns>Encoded instance value</returns>
        protected byte[] EncodeInstance(uint number)
        {
            MutableByte result = new MutableByte();

            if (number <= 127)
            {
                result.Set((byte)number);
            }
            else
            {
                uint        val = number;
                MutableByte tmp = new MutableByte();
                while (val != 0)
                {
                    byte[] b = BitConverter.GetBytes(val);

                    byte bval = b[0];
                    if ((bval & 0x80) != 0)
                    {
                        bval = (byte)(bval & ~HighBit); // 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 (int i = tmp.Length - 1; i >= 0; i--)
                {
                    if (i > 0)
                    {
                        result.Append((byte)(tmp[i] | HighBit));
                    }
                    else
                    {
                        result.Append(tmp[i]);
                    }
                }
            }

            return(result);
        }
Beispiel #13
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 #14
0
        /// <summary>
        /// Decode received packet. This method overrides the base implementation that cannot be used with this type of the packet.
        /// </summary>
        /// <param name="buffer">Packet buffer</param>
        /// <param name="length">Buffer length</param>
        public override int Decode(byte[] buffer, int length)
        {
            int         offset = 0;
            MutableByte buf    = new MutableByte(buffer, length);

            offset = base.Decode(buffer, length);


            // parse community
            offset = _snmpCommunity.Decode(buf, offset);

            // look ahead to make sure this is a TRAP packet
            int  tmpOffset  = offset;
            byte tmpAsnType = AsnType.ParseHeader(buffer, ref tmpOffset, out int headerLen);

            if (tmpAsnType != (byte)PduType.Trap)
            {
                throw new SnmpException(string.Format("Invalid SNMP ASN.1 type. Received: {0:x2}", tmpAsnType));
            }
            // decode protocol data unit
            offset = Pdu.Decode(buf, offset);
            return(offset);
        }
Beispiel #15
0
        /// <summary>Encode SNMP v3 message flag field</summary>
        /// <param name="buffer">Buffer to append encoded value to</param>
        public override void Encode(MutableByte buffer)
        {
            byte flag = 0x00;

            if (Authentication)
            {
                flag |= FlagAuth;
            }

            if (Privacy)
            {
                flag |= FlagPrivacy;
            }

            if (Reportable)
            {
                flag |= FlagReportable;
            }

            OctetString flagObject = new OctetString(flag);

            flagObject.Encode(buffer);
        }
Beispiel #16
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();

            uint[] 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 (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);
        }
Beispiel #17
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);
 }
Beispiel #18
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)
        {
            byte asnType = ParseHeader(buffer, ref offset, out int 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);
            }

            List <uint> list = new List <uint>();

            // decode the first byte
            headerLength--;

            uint 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] & HighBit) == 0)
                    {
                        // short encoding
                        result  = buffer[offset];
                        offset += 1;
                        headerLength--;
                    }
                    else
                    {
                        // long encoding
                        MutableByte tmp       = new MutableByte();
                        bool        completed = false;
                        do
                        {
                            tmp.Append((byte)(buffer[offset] & ~HighBit));

                            if ((buffer[offset] & HighBit) == 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 (int 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);
        }
        /// <summary>
        /// Decode received packet. This method overrides the base implementation that cannot be used with this type of the packet.
        /// </summary>
        /// <param name="buffer">Packet buffer</param>
        /// <param name="length">Buffer length</param>
        public override int decode(byte[] buffer, int length)
        {
            int offset = 0;
            MutableByte buf = new MutableByte(buffer, length);

            offset = base.decode(buffer, length);

            // parse community
            offset = _snmpCommunity.decode(buf, offset);

            // look ahead to make sure this is a TRAP packet
            int tmpOffset = offset;
            int headerLen;
            byte tmpAsnType = AsnType.ParseHeader(buffer, ref tmpOffset, out headerLen);
            if (tmpAsnType != (byte)PduType.Trap)
            {
                throw new SnmpException(string.Format("Invalid SNMP ASN.1 type. Received: {0:x2}", tmpAsnType));
            }
            // decode protocol data unit
            offset = this.Pdu.decode(buf, offset);
            return offset;
        }
 /// <summary>
 /// Authenticate incoming packet
 /// </summary>
 /// <param name="authKey">Authentication key (not password)</param>
 /// <param name="wholePacket">Received BER encoded SNMP version 3 packet</param>
 /// <returns>True if packet is successfully authenticated, otherwise false.</returns>
 public bool IsAuthentic(byte[] authKey, MutableByte wholePacket)
 {
     if (_authentication != AuthenticationDigests.None)
     {
         IAuthenticationDigest authProto = SnmpSharpNet.Authentication.GetInstance(_authentication);
         if (authProto != null)
         {
             return authProto.authenticateIncomingMsg(authKey, _authenticationParameters, wholePacket);
         }
     }
     return false; // Nothing to authenticate
 }
 /// <summary>
 /// Authenticate SNMP version 3 message.
 /// 
 /// Before calling this member, entire SNMP version 3 packet needs to be encoded. After authentication
 /// process is completed, authenticationParameters value in the USM header is updated and SNMPv3 packet
 /// needs to be re-encoded to include it in the BER encoded stream prior to transmission.
 /// </summary>
 /// <param name="authKey">Authentication key (not password)</param>
 /// <param name="wholePacket">SNMP version 3 BER encoded packet.</param>
 public void Authenticate(byte[] authKey, ref MutableByte wholePacket)
 {
     IAuthenticationDigest authProto = SnmpSharpNet.Authentication.GetInstance(_authentication);
     byte[] authParam = authProto.authenticate(authKey, wholePacket);
     _authenticationParameters = new OctetString(authParam);
 }
        /// <summary>
        /// Standard constructor.
        /// </summary>
        public UserSecurityModel()
        {
            _asnType = 3;
            _engineId = new OctetString();
            _engineBoots = new Integer32();
            _engineTime = new Integer32();
            _authentication = AuthenticationDigests.None;

            _securityName = new OctetString();
            _authenticationSecret = new MutableByte();
            _authenticationParameters = new OctetString();
            _privacySecret = new MutableByte();
            _privacy = PrivacyProtocols.None;
            _privacyParameters = new OctetString();
        }
Beispiel #23
0
        /// <summary>
        /// Verifies correct SHA-1 authentication of the frame. Prior to calling this method, you have to extract authentication
        /// parameters from the wholeMessage and reset authenticationParameters field in the USM information block to 12 0x00
        /// values.
        /// </summary>
        /// <param name="userPassword">User password</param>
        /// <param name="engineId">Authoritative engine id</param>
        /// <param name="authenticationParameters">Extracted USM authentication parameters</param>
        /// <param name="wholeMessage">Whole message with authentication parameters zeroed (0x00) out</param>
        /// <returns>True if message authentication has passed the check, otherwise false</returns>
        public bool AuthenticateIncomingMessage(byte[] userPassword, byte[] engineId, byte[] authenticationParameters, MutableByte wholeMessage)
        {
            byte[] hash = Authenticate(userPassword, engineId, wholeMessage);

            return(hash.SequenceEqual(authenticationParameters));
        }
Beispiel #24
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)
 {
     MutableByte 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 #25
0
 /// <summary>
 /// Decode SNMP packet header. This class decodes the initial sequence and SNMP protocol version
 /// number.
 /// </summary>
 /// <param name="buffer">BER encoded SNMP packet</param>
 /// <param name="length">Packet length</param>
 /// <returns>Offset position after the initial sequence header and protocol version value</returns>
 /// <exception cref="SnmpDecodingException">Thrown when invalid sequence type is found at the start of the SNMP packet being decoded</exception>
 public virtual int decode(byte[] buffer, int length)
 {
     int offset = 0;
     if (length < 2)
     {
         // we need at least 2 bytes
         throw new OverflowException("Packet too small.");
     }
     // make sure you get the right length buffer to be able to check for over/under flow errors
     MutableByte buf = new MutableByte(buffer, length);
     Sequence seq = new Sequence();
     offset = seq.decode(buf, offset);
     if( seq.Type != SnmpConstants.SMI_SEQUENCE )
         throw new SnmpDecodingException("Invalid sequence type at the start of the SNMP packet.");
     offset = _protocolVersion.decode(buf, offset);
     return offset;
 }
Beispiel #26
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;
        }
Beispiel #27
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);
        }
Beispiel #28
0
        /// <summary>
        /// "Look-ahead" decode of SNMP packet header including USM information
        /// </summary>
        /// <remarks>
        /// Decode first component of the SNMP version 3 packet allowing the caller to retrieve USM SecureName needed to retrieve
        /// client security parameters that will allow authentication and privacy decryption to take place.
        /// 
        /// This method is used to support Agent like behavior or to handle unsolicited packets like TRAP and INFORMs. In all of
        /// these cases, sender of packets will forward a packet without a request being sent by you. In turn, you will need
        /// to parse enough of the packet to retrieve SecureName which you can use to retrieve security parameters associated with
        /// that user and attempt to authorize and privacy decrypt the received packet.
        /// 
        /// Only use this method when your application is acting as an Agent or if you need to process TRAP and INFORM packets.
        /// </remarks>
        /// <param name="berBuffer">Raw SNMP version 3 packet</param>
        /// <param name="length">SNMP version 3 packet length</param>
        /// <returns>UserSecurityModel class parsed from the parameter SNMP version 3 packet</returns>
        /// <exception cref="SnmpInvalidVersionException">Thrown when attempting to parse an SNMP packet that is not version 3</exception>
        /// <exception cref="OverflowException">Thrown when header specifies packet length that is longer then the amount of data received.</exception>
        /// <exception cref="SnmpDecodingException">Thrown when invalid sequence is enountered while decoding global message data sequence</exception>
        /// <exception cref="SnmpException">Thrown with SnmpException.UnsupportedNoAuthPriv when packet is using privacy without authentication (not allowed)</exception>
        /// <exception cref="SnmpException">Thrown with SnmpException.UnsupportedSecurityModel when packet is sent with security model other then USM (only USM is defined in SNMPv3 standard)</exception>
        public UserSecurityModel GetUSM(byte[] berBuffer, int length)
        {
            MutableByte buffer = new MutableByte(berBuffer, length);

            int offset = 0;

            // let base class parse first sequence and SNMP version number
            offset = base.decode(buffer, length);

            // check for correct SNMP protocol version
            if (_protocolVersion != (int) SnmpVersion.Ver3)
                throw new SnmpInvalidVersionException("Expecting SNMP version 3.");

            // now grab the global message data sequence header information
            int len = 0;
            byte asnType = AsnType.ParseHeader(buffer, ref offset, out len);

            if( asnType != SnmpConstants.SMI_SEQUENCE )
                throw new SnmpDecodingException("Invalid sequence type when decoding global message data sequence.");

            // check that packet size can accommodate the length specified in the header
            if (len > (buffer.Length - offset))
                throw new OverflowException("Packet is too small to contain the data described in the header.");

            // retrieve message id
            offset = _messageId.decode(buffer, offset);

            // max message size
            offset = _maxMessageSize.decode(buffer, offset);

            // message flags
            offset = _msgFlags.decode(buffer, offset);

            // verify that a valid authentication/privacy configuration is present in the packet
            if (_msgFlags.Authentication == false && _msgFlags.Privacy == true)
                throw new SnmpException(SnmpException.UnsupportedNoAuthPriv,
                                        "SNMP version 3 noAuthPriv security combination is not supported.");

            // security model code
            offset = _securityModel.decode(buffer, offset);

            // we only support USM. code = 0x03
            if (_securityModel.Value != _userSecurityModel.Type)
                throw new SnmpException(SnmpException.UnsupportedSecurityModel,
                                        "Class only support SNMP Version 3 User Security Model.");

            // parse user security model
            offset = _userSecurityModel.decode(buffer, offset);

            return _userSecurityModel;
        }
Beispiel #29
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, 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[] encryptedBuffer = privacyProtocol.Encrypt(unencryptedPdu, 0, unencryptedPdu.Length, privKey, _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);
            }

            base.encode(buffer);

            if (_msgFlags.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);
                base.encode(packetHeader);
                buffer = packetHeader;
            }
            return buffer;
        }
Beispiel #30
0
        /// <summary>
        /// Decode SNMP version 3 packet. This method will perform authentication check and decode privacy protected <see cref="ScopedPdu"/>. This method will
        /// not check for the timeliness of the packet, correct engine boot value or engine id because it does not have a reference to the engine time prior to this call.
        /// </summary>
        /// <param name="berBuffer">BER encoded SNMP version 3 packet buffer</param>
        /// <param name="length">Buffer length</param>
        /// <param name="authKey">Authentication key (not password)</param>
        /// <param name="privKey">Privacy key (not password)</param>
        public int decode(byte[] berBuffer, int length, byte[] authKey, byte[] privKey)
        {
            MutableByte buffer = new MutableByte(berBuffer, length);

            int offset = 0;

            // let base class parse first sequence and SNMP version number
            offset = base.decode(buffer, length);

            // check for correct SNMP protocol version
            if (_protocolVersion != (int)SnmpVersion.Ver3)
                throw new SnmpInvalidVersionException("Expecting SNMP version 3.");

            // now grab the global message data sequence header information
            int len = 0;
            byte asnType = AsnType.ParseHeader(buffer, ref offset, out len);
            if (asnType != SnmpConstants.SMI_SEQUENCE)
                throw new SnmpDecodingException("Invalid sequence type in global message data sequence.");

            // check that packet size can accommodate the length specified in the header
            if (len > (buffer.Length - offset))
                throw new OverflowException("Packet is too small to contain the data described in the header.");

            // retrieve message id
            offset = _messageId.decode(buffer, offset);

            // max message size
            offset = _maxMessageSize.decode(buffer, offset);

            // message flags
            offset = _msgFlags.decode(buffer, offset);

            // verify that a valid authentication/privacy configuration is present in the packet
            if (_msgFlags.Authentication == false && _msgFlags.Privacy == true)
                throw new SnmpException(SnmpException.UnsupportedNoAuthPriv, "SNMP version 3 noAuthPriv security combination is not supported.");

            // security model code
            offset = _securityModel.decode(buffer, offset);

            // we only support USM. code = 0x03
            if (_securityModel.Value != _userSecurityModel.Type)
                throw new SnmpException(SnmpException.UnsupportedSecurityModel, "Class only support SNMP Version 3 User Security Model.");

            // parse user security model
            offset = _userSecurityModel.decode(buffer, offset);

            // Authenticate message if authentication flag is set and packet is not a discovery packet
            if (_msgFlags.Authentication && _userSecurityModel.EngineId.Length > 0)
            {
                // Authenticate packet
                if (_userSecurityModel.AuthenticationParameters.Length != 12)
                    throw new SnmpAuthenticationException("Invalid authentication parameter field length.");
                if (!_userSecurityModel.IsAuthentic(authKey, buffer))
                    throw new SnmpAuthenticationException("Authentication of the incoming packet failed.");
            }

            // Decode ScopedPdu if it is privacy protected and packet is not a discovery packet
            if (_msgFlags.Privacy && _userSecurityModel.EngineId.Length > 0)
            {
                IPrivacyProtocol privacyProtocol = PrivacyProtocol.GetInstance(_userSecurityModel.Privacy);
                if (privacyProtocol == null)
                {
                    throw new SnmpException(SnmpException.UnsupportedPrivacyProtocol, "Privacy protocol requested is not supported.");
                }
                if (_userSecurityModel.PrivacyParameters.Length != privacyProtocol.PrivacyParametersLength)
                    throw new SnmpException(SnmpException.InvalidPrivacyParameterLength, "Invalid privacy parameters field length.");

                // Initialize a temporary OctetString class to hold encrypted ScopedPdu
                OctetString encryptedScopedPdu = new OctetString();
                offset = encryptedScopedPdu.decode(buffer, offset);

                // decode encrypted packet
                byte[] decryptedScopedPdu = privacyProtocol.Decrypt(encryptedScopedPdu, 0, encryptedScopedPdu.Length, privKey, _userSecurityModel.EngineBoots, _userSecurityModel.EngineTime, _userSecurityModel.PrivacyParameters);
                int tempOffset = 0;
                offset = _scopedPdu.decode(decryptedScopedPdu, tempOffset);
            }
            else
                offset = _scopedPdu.decode(buffer, offset);
            return offset;
        }
Beispiel #31
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 #32
0
 /// <summary>BER encode SNMP version 2 error.</summary>
 /// <param name="buffer">Buffer to append encoded value to the end of</param>
 public override void Encode(MutableByte buffer)
 {
     BuildHeader(buffer, Type, 0);
 }
Beispiel #33
0
 /// <summary> 
 /// ASN.1 encode Null value
 /// </summary>
 /// <param name="buffer"><see cref="MutableByte"/> class to the end of which encoded data is appended
 /// </param>
 public override void encode(MutableByte buffer)
 {
     BuildHeader(buffer, Type, 0);
 }
Beispiel #34
0
 /// <summary>
 /// Encode SNMP v3 message flag field
 /// </summary>
 /// <param name="buffer">Buffer to append encoded value to</param>
 public override void encode(MutableByte buffer)
 {
     byte flag = 0x00;
     if (_authenticationFlag)
         flag |= FLAG_AUTH;
     if (_privacyFlag)
         flag |= FLAG_PRIV;
     if (_reportableFlag)
         flag |= FLAG_REPORTABLE;
     OctetString flagObject = new OctetString(flag);
     flagObject.encode(buffer);
 }
Beispiel #35
0
        /// <summary>
        /// Reset the class. Initialize all member values to class defaults.
        /// </summary>
        public void Reset()
        {
            _address = new IpAddress(System.Net.IPAddress.Loopback);
            _port = 161;
            _version = SnmpVersion.Ver3;
            _timeout = 2000;
            _retry = 1;

            _engineId = new OctetString();
            _engineBoots = new Integer32();
            _engineTime = new Integer32();

            _engineTimeStamp = DateTime.MinValue;

            _privacyProtocol = PrivacyProtocols.None;
            _authenticationProtocol = AuthenticationDigests.None;

            _privacySecret = new MutableByte();
            _authenticationSecret = new MutableByte();

            _contextEngineId = new OctetString();
            _contextName = new OctetString();
            _securityName = new OctetString();

            // max message size is initialized to 64KB by default. It will be
            // to the smaller of the two values after discovery process
            _maxMessageSize = new Integer32(64 * 1024);

            _reportable = true;
        }
Beispiel #36
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);

            _variables.encode(trapBuffer);
            MutableByte tmpBuffer = new MutableByte();

            BuildHeader(tmpBuffer, (byte)PduType.Trap, trapBuffer.Length);
            trapBuffer.Prepend(tmpBuffer);
            buffer.Append(trapBuffer);
        }
Beispiel #37
0
        /// <summary>Verify SHA-1 authentication of a packet.</summary>
        /// <param name="authKey">Authentication key (not password)</param>
        /// <param name="authenticationParameters">Authentication parameters extracted from the packet being authenticated</param>
        /// <param name="wholeMessage">Entire packet being authenticated</param>
        /// <returns>True on authentication success, otherwise false</returns>
        public bool AuthenticateIncomingMsg(byte[] authKey, byte[] authenticationParameters, MutableByte wholeMessage)
        {
            byte[] hash = Authenticate(authKey, wholeMessage);

            return(hash.SequenceEqual(authenticationParameters));
        }
        /// <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;
        }
        /// <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 #40
0
        /// <summary>
        /// Decode received SNMP packet.
        /// </summary>
        /// <param name="buffer">BER encoded packet buffer</param>
        /// <param name="length">BER encoded packet buffer length</param>
        /// <returns>Buffer position after the decoded packet.</returns>
        /// <exception cref="SnmpException">Thrown when invalid encoding has been found in the packet</exception>
        /// <exception cref="OverflowException">Thrown when parsed header points to more data then is available in the packet</exception>
        /// <exception cref="SnmpInvalidVersionException">Thrown when parsed packet is not SNMP version 1</exception>
        /// <exception cref="SnmpInvalidPduTypeException">Thrown when received PDU is of a type not supported by SNMP version 1</exception>
        public override int decode(byte[] buffer, int length)
        {
            MutableByte buf = new MutableByte(buffer, length);

            int headerLength;
            int offset = 0;

            offset = base.decode(buffer, buffer.Length);

            if (_protocolVersion.Value != (int)SnmpVersion.Ver1 )
                throw new SnmpInvalidVersionException("Invalid protocol version");

            offset = _snmpCommunity.decode(buf, offset);
            int tmpOffset = offset;
            byte asnType = AsnType.ParseHeader(buf, ref tmpOffset, out headerLength);

            // Check packet length
            if (headerLength + offset > buf.Length)
                throw new OverflowException("Insufficient data in packet");

            if (asnType != (byte)PduType.Get && asnType != (byte)PduType.GetNext && asnType != (byte)PduType.Set && asnType != (byte)PduType.Response)
                throw new SnmpInvalidPduTypeException("Invalid SNMP operation received: " + string.Format("0x{0:x2}", asnType));
            // Now process the Protocol Data Unit
            offset = this.Pdu.decode(buf, offset);
            return length;
        }
Beispiel #41
0
        /// <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 != EPrivacyProtocols.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.EErrorCode.UnsupportedPrivacyProtocol, "Unrecognized privacy protocol specified.");
                    }
                }
            }
            else
            {
                privacyParameters.Reset();
            }

            privacyParameters.Encode(tmp);
            MutableByte tmp1 = new MutableByte();

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

            BuildHeader(buffer, (byte)EAsnType.OctetString, tmp1.Length);

            buffer.Append(tmp1);
        }
Beispiel #42
0
 /// <summary>
 /// Encodes the data object in the specified buffer
 /// </summary>
 /// <param name="buffer">The buffer to write the encoded information</param>
 public abstract void encode(MutableByte buffer);
Beispiel #43
0
        /// <summary>
        /// Make sync request using IP/UDP with request timeouts and retries.
        /// </summary>
        /// <param name="peer">SNMP agent IP address</param>
        /// <param name="port">SNMP agent port number</param>
        /// <param name="buffer">Data to send to the agent</param>
        /// <param name="bufferLength">Data length in the buffer</param>
        /// <param name="timeout">Timeout in milliseconds</param>
        /// <param name="retries">Maximum number of retries. 0 = make a single request with no retry attempts</param>
        /// <returns>Byte array returned by the agent. Null on error</returns>
        /// <exception cref="SnmpException">Thrown on request timed out. SnmpException.ErrorCode is set to
        /// SnmpException.RequestTimedOut constant.</exception>
        /// <exception cref="SnmpException">Thrown when IPv4 address is passed to the v6 socket or vice versa</exception>
        public byte[] Request(IPAddress peer, int port, byte[] buffer, int bufferLength, int timeout, int retries)
        {
            if (_socket == null)
            {
                return null; // socket has been closed. no new operations are possible.
            }
            if (_socket.AddressFamily != peer.AddressFamily)
                throw new SnmpException("Invalid address protocol version.");

            IPEndPoint netPeer = new IPEndPoint(peer, port);

            _socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, timeout);
            int recv = 0;
            int retry = 0;
            byte[] inbuffer = new byte[64 * 1024];
            EndPoint remote = (EndPoint)new IPEndPoint(peer.AddressFamily == AddressFamily.InterNetwork ? IPAddress.Any : IPAddress.IPv6Any,0);
            while (true)
            {
                try
                {
                    _socket.SendTo(buffer, bufferLength, SocketFlags.None, (EndPoint)netPeer);
                    recv = _socket.ReceiveFrom(inbuffer, ref remote);
                }
                catch (SocketException ex)
                {
                    if (ex.ErrorCode == 10040)
                    {
                        recv = 0; // Packet too large
                    }
                    else if (ex.ErrorCode == 10050)
                    {
                        throw new SnmpNetworkException(ex, "Network error: Destination network is down.");
                    }
                    else if (ex.ErrorCode == 10051)
                    {
                        throw new SnmpNetworkException(ex, "Network error: destination network is unreachable.");
                    }
                    else if( ex.ErrorCode == 10054)
                    {
                        throw new SnmpNetworkException(ex, "Network error: connection reset by peer.");
                    }
                    else if (ex.ErrorCode == 10064)
                    {
                        throw new SnmpNetworkException(ex, "Network error: remote host is down.");
                    }
                    else if (ex.ErrorCode == 10065)
                    {
                        throw new SnmpNetworkException(ex, "Network error: remote host is unreachable.");
                    }
                    else if (ex.ErrorCode == 10061)
                    {
                        throw new SnmpNetworkException(ex, "Network error: connection refused.");
                    }
                    else if (ex.ErrorCode == 10060)
                    {
                        recv = 0; // Connection attempt timed out. Fall through to retry
                    }
                    else
                    {
                        // Assume it is a timeout
                    }
                }
                if (recv > 0)
                {
                    IPEndPoint remEP = remote as IPEndPoint;
                    if ( ! _noSourceCheck && ! remEP.Equals(netPeer))
                    {
                        if (remEP.Address != netPeer.Address)
                        {
                            Console.WriteLine("Address miss-match {0} != {1}", remEP.Address, netPeer.Address);
                        }
                        if (remEP.Port != netPeer.Port)
                        {
                            Console.WriteLine("Port # miss-match {0} != {1}", remEP.Port, netPeer.Port);
                        }
                        /* Not good, we got a response from somebody other then who we requested a response from */
                        retry++;
                        if (retry > retries)
                        {
                            throw new SnmpException(SnmpException.RequestTimedOut, "Request has reached maximum retries.");
                            // return null;
                        }
                    }
                    else
                    {
                        MutableByte buf = new MutableByte(inbuffer, recv);
                        return buf;
                    }
                }
                else
                {
                    retry++;
                    if (retry > retries)
                    {
                        return null;
                        //throw new SnmpException(SnmpException.RequestTimedOut, "Request has reached maximum retries.");
                    }
                }
            }
        }
Beispiel #44
0
 /// <summary>
 /// Replacement for the base class encode method.  
 /// </summary>
 /// <param name="buffer">Buffer</param>
 private new void encode(MutableByte buffer)
 {
     throw new NotImplementedException();
 }
 /// <summary>
 /// Verify MD5 authentication of a packet.
 /// </summary>
 /// <param name="authKey">Authentication key (not password)</param>
 /// <param name="authenticationParameters">Authentication parameters extracted from the packet being authenticated</param>
 /// <param name="wholeMessage">Entire packet being authenticated</param>
 /// <returns>True on authentication success, otherwise false</returns>
 public bool authenticateIncomingMsg(byte[] authKey, byte[] authenticationParameters, MutableByte wholeMessage)
 {
     HMACMD5 md5 = new HMACMD5(authKey);
     byte[] hash = md5.ComputeHash(wholeMessage, 0, wholeMessage.Length);
     MutableByte myhash = new MutableByte(hash, 12);
     if (myhash.Equals(authenticationParameters))
     {
         return true;
     }
     return false;
 }
        /// <summary>
        /// Verifies correct MD5 authentication of the frame. Prior to calling this method, you have to extract authentication
        /// parameters from the wholeMessage and reset authenticationParameters field in the USM information block to 12 0x00
        /// values.
        /// </summary>
        /// <param name="userPassword">User password</param>
        /// <param name="engineId">Authoritative engine id</param>
        /// <param name="authenticationParameters">Extracted USM authentication parameters</param>
        /// <param name="wholeMessage">Whole message with authentication parameters zeroed (0x00) out</param>
        /// <returns>True if message authentication has passed the check, otherwise false</returns>
        public bool AuthenticateIncomingMessage(byte[] userPassword, byte[] engineId, byte[] authenticationParameters, MutableByte wholeMessage)
        {
            byte[] authenticationKey = PasswordToKey(userPassword, engineId);

            HMACMD5 md5 = new HMACMD5(authenticationKey);

            byte[] hash = md5.ComputeHash(wholeMessage, 0, wholeMessage.Length);

            return(hash.Take(12).SequenceEqual(authenticationParameters));
        }
        /// <summary>Verify MD5 authentication of a packet.</summary>
        /// <param name="authenticationKey">Authentication key (not password)</param>
        /// <param name="authenticationParameters">Authentication parameters extracted from the packet being authenticated</param>
        /// <param name="wholeMessage">Entire packet being authenticated</param>
        /// <returns>True on authentication success, otherwise false</returns>
        public bool AuthenticateIncomingMsg(byte[] authenticationKey, byte[] authenticationParameters, MutableByte wholeMessage)
        {
            HMACMD5 md5 = new HMACMD5(authenticationKey);

            byte[] hash = md5.ComputeHash(wholeMessage, 0, wholeMessage.Length);

            return(hash.Take(12).SequenceEqual(authenticationParameters));
        }
        /// <summary>
        /// Encode SNMP packet for sending.
        /// </summary>
        /// <returns>BER encoded SNMP packet.</returns>
        public override byte[] encode()
        {
            MutableByte tmpBuffer = new MutableByte();

            //
            // encode the community strings
            _snmpCommunity.encode(tmpBuffer);
            this.Pdu.encode(tmpBuffer);

            base.encode(tmpBuffer);

            return (byte[])tmpBuffer;
        }
Beispiel #49
0
 /// <summary>
 /// Wrap BER encoded SNMP information contained in the parameter <see cref="MutableByte"/> class.
 /// 
 /// Information in the parameter is prepended by the SNMP version field and wrapped in a sequence header.
 /// 
 /// Derived classes call this method to finalize SNMP packet encoding.
 /// </summary>
 /// <param name="buffer">Buffer containing BER encoded SNMP information</param>
 public virtual void encode(MutableByte buffer)
 {
     // Encode SNMP protocol version
     MutableByte temp = new MutableByte();
     _protocolVersion.encode(temp);
     buffer.Prepend(temp);
     temp.Reset();
     AsnType.BuildHeader(temp, SnmpConstants.SMI_SEQUENCE, buffer.Length);
     buffer.Prepend(temp);
 }
Beispiel #50
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);
 }
Beispiel #51
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);
        }
 /// <summary>
 /// Verify SHA-1 authentication of a packet.
 /// </summary>
 /// <param name="authKey">Authentication key (not password)</param>
 /// <param name="authenticationParameters">Authentication parameters extracted from the packet being authenticated</param>
 /// <param name="wholeMessage">Entire packet being authenticated</param>
 /// <returns>True on authentication success, otherwise false</returns>
 public bool authenticateIncomingMsg(byte[] authKey, byte[] authenticationParameters, MutableByte wholeMessage)
 {
     HMACSHA1 sha = new HMACSHA1(authKey);
     byte[] hash = sha.ComputeHash(wholeMessage);
     MutableByte myhash = new MutableByte(hash, 12);
     sha.Clear(); // release resources
     if (myhash.Equals(authenticationParameters))
     {
         return true;
     }
     return false;
 }
        /// <summary>
        /// Reset the class. Initialize all member values to class defaults.
        /// </summary>
        public void Reset()
        {
            _engineId = new OctetString();
            _engineBoots = new Integer32();
            _engineTime = new Integer32();

            _engineTimeStamp = DateTime.MinValue;

            _privacyProtocol = PrivacyProtocols.None;
            _authenticationProtocol = AuthenticationDigests.None;

            _privacySecret = new MutableByte();
            _authenticationSecret = new MutableByte();

            _contextEngineId = new OctetString();
            _contextName = new OctetString();
            _securityName = new OctetString();

            // max message size is initialized to 64KB by default. It will be
            // to the smaller of the two values after discovery process
            _maxMessageSize = new Integer32(64 * 1024);

            _reportable = true;

            _privacyKey = null;
            _authenticationKey = null;
        }
        /// <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;
            SHA1 sha = new SHA1CryptoServiceProvider();

            /* 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);
            sha.Clear(); // release resources
            return res;
        }