Base class for all ASN.1 value classes
Inheritance: ICloneable
Example #1
1
        /// <summary>Decode BER encoded variable binding.
        /// </summary>
        /// <param name="buffer">BER encoded buffer
        /// </param>
        /// <param name="offset">Offset in the data buffer from where to start decoding. Offset is
        /// passed by reference and will contain the offset of the byte immediately after the parsed
        /// variable binding.
        /// </param>
        /// <returns>Buffer position after the decoded value</returns>
        public override int decode(byte[] buffer, int offset)
        {
            int headerLength;
            byte asnType = ParseHeader(buffer, ref offset, out headerLength);

            if (asnType != Type)
                throw new SnmpException(string.Format("Invalid ASN.1 type. Expected 0x{0:x2} received 0x{1:x2}", Type, asnType));

            // verify the length
            if ((buffer.Length - offset) < headerLength)
                throw new OverflowException("Buffer underflow error");

            _oid = new Oid();
            offset = _oid.decode(buffer, offset);
            int saveOffset = offset;
            // Look ahead in the header to see the data type we need to parse
            asnType = ParseHeader(buffer, ref saveOffset, out headerLength);
            _value = SnmpConstants.GetSyntaxObject(asnType);
            if (_value == null)
                throw new SnmpDecodingException(String.Format("Invalid ASN.1 type encountered 0x{0:x2}. Unable to continue decoding.", asnType));
            offset = _value.decode(buffer, offset);
            return offset;
        }
Example #2
1
 /// <summary>
 /// Construct Vb with the OID and value
 /// </summary>
 /// <param name="oid">OID</param>
 /// <param name="value">Value</param>
 public Vb(Oid oid, AsnType value)
     : this(oid)
 {
     _value = (AsnType)value.Clone();
 }
Example #3
0
        /// <summary>
        /// Decode received SNMP packet.
        /// </summary>
        /// <param name="buffer">BER encoded packet buffer</param>
        /// <param name="length">BER encoded packet buffer length</param>
        /// <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 offset = 0;

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

            if (Version != SnmpVersion.Ver2)
            {
                throw new SnmpInvalidVersionException("Invalid protocol version");
            }

            offset = _snmpCommunity.Decode(buf, offset);
            int  tmpOffset = offset;
            byte asnType   = AsnType.ParseHeader(buf, ref tmpOffset, out int 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.GetBulk && asnType != (byte)PduType.Response && asnType != (byte)PduType.V2Trap &&
                asnType != (byte)PduType.Inform)
            {
                throw new SnmpInvalidPduTypeException("Invalid SNMP operation received: " + string.Format("0x{0:x2}", asnType));
            }

            // Now process the Protocol Data Unit
            offset = Pdu.Decode(buf, offset);
            return(length);
        }
Example #4
0
        /// <summary>
        /// Encode SNMP packet for sending.
        /// </summary>
        /// <returns>BER encoded SNMP packet.</returns>
        public override byte[] Encode()
        {
            MutableByte buf = new MutableByte();

            if (Pdu.Type != PduType.Get && Pdu.Type != PduType.GetNext &&
                Pdu.Type != PduType.Set && Pdu.Type != PduType.V2Trap &&
                Pdu.Type != PduType.Response && Pdu.Type != PduType.GetBulk &&
                Pdu.Type != PduType.Inform)
            {
                throw new SnmpInvalidPduTypeException("Invalid SNMP PDU type while attempting to encode PDU: " + string.Format("0x{0:x2}", Pdu.Type));
            }

            // snmp version
            _protocolVersion.Encode(buf);

            // community string
            _snmpCommunity.Encode(buf);

            // pdu
            _pdu.Encode(buf);

            // wrap the packet into a sequence
            MutableByte tmpBuf = new MutableByte();

            AsnType.BuildHeader(tmpBuf, SnmpConstants.SMI_SEQUENCE, buf.Length);

            buf.Prepend(tmpBuf);
            return(buf);
        }
Example #5
0
        /// <summary>
        /// Copy values from another Pdu class.
        /// </summary>
        /// <param name="value"><see cref="Pdu"/> cast as AsnType</param>
        /// <exception cref="ArgumentNullException">Thrown when received argument is null</exception>
        public void Set(AsnType value)
        {
            if (value == null)
            {
                throw new ArgumentNullException("value");
            }
            Pdu pdu = value as Pdu;

            if (pdu != null)
            {
                this.Type             = pdu.Type;
                this._requestId.Value = pdu.RequestId;
                if (this.Type == PduType.GetBulk)
                {
                    this.NonRepeaters   = pdu.NonRepeaters;
                    this.MaxRepetitions = pdu.MaxRepetitions;
                }
                else
                {
                    this.ErrorStatus = pdu.ErrorStatus;
                    this.ErrorIndex  = pdu.ErrorIndex;
                }
                this._vbs.Clear();
                foreach (Vb v in pdu.VbList)
                {
                    this._vbs.Add((Vb)v.Clone());
                }
            }
            else
            {
                throw new ArgumentNullException("value", "Argument is not an Oid class");
            }
        }
Example #6
0
        /// <summary>Copy values from another Pdu class.</summary>
        /// <param name="value"><see cref="Pdu"/> cast as AsnType</param>
        /// <exception cref="ArgumentNullException">Thrown when received argument is null</exception>
        public void Set(AsnType value)
        {
            if (value == null)
            {
                throw new ArgumentNullException(nameof(value));
            }

            if (value is Pdu pdu)
            {
                Type            = pdu.Type;
                requestId.Value = pdu.RequestId;

                if (Type == EPduType.GetBulk)
                {
                    NonRepeaters   = pdu.NonRepeaters;
                    MaxRepetitions = pdu.MaxRepetitions;
                }
                else
                {
                    ErrorStatus = pdu.ErrorStatus;
                    ErrorIndex  = pdu.ErrorIndex;
                }

                VbList.Clear();

                foreach (Vb v in pdu.VbList)
                {
                    VbList.Add((Vb)v.Clone());
                }
            }
            else
            {
                throw new ArgumentNullException(nameof(value), "Argument is not an Oid class");
            }
        }
Example #7
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);
        }
Example #8
0
        /// <summary>Decode BER encoded variable binding.
        /// </summary>
        /// <param name="buffer">BER encoded buffer
        /// </param>
        /// <param name="offset">Offset in the data buffer from where to start decoding. Offset is
        /// passed by reference and will contain the offset of the byte immediately after the parsed
        /// variable binding.
        /// </param>
        /// <returns>Buffer position after the decoded value</returns>
        public override int decode(byte[] buffer, int offset)
        {
            int  headerLength;
            byte asnType = ParseHeader(buffer, ref offset, out headerLength);

            if (asnType != Type)
            {
                throw new SnmpException(string.Format("Invalid ASN.1 type. Expected 0x{0:x2} received 0x{1:x2}", Type, asnType));
            }

            // verify the length
            if ((buffer.Length - offset) < headerLength)
            {
                throw new OverflowException("Buffer underflow error");
            }

            _oid   = new Oid();
            offset = _oid.decode(buffer, offset);
            int saveOffset = offset;

            // Look ahead in the header to see the data type we need to parse
            asnType = ParseHeader(buffer, ref saveOffset, out headerLength);
            _value  = SnmpConstants.GetSyntaxObject(asnType);
            if (_value == null)
            {
                throw new SnmpDecodingException(String.Format("Invalid ASN.1 type encountered 0x{0:x2}. Unable to continue decoding.", asnType));
            }
            offset = _value.decode(buffer, offset);
            return(offset);
        }
Example #9
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
            byte asnType = AsnType.ParseHeader(buffer, ref offset, out int 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 != USM.Type)
            {
                throw new SnmpException(SnmpException.UnsupportedSecurityModel,
                                        "Class only support SNMP Version 3 User Security Model.");
            }

            // parse user security model
            offset = USM.Decode(buffer, offset);

            return(USM);
        }
Example #10
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);
        }
Example #11
0
        /// <summary>
        /// SET class value from another Counter64 class cast as <seealso cref="AsnType"/>.
        /// </summary>
        /// <param name="value">Counter64 class cast as <seealso cref="AsnType"/></param>
        /// <exception cref="ArgumentException">Argument is not Counter64 type.</exception>
        public void Set(AsnType value)
        {
            Counter64 val = value as Counter64;

            if (val != null)
            {
                _value = val.Value;
            }
            else
            {
                throw new ArgumentException("Invalid argument type.");
            }
        }
Example #12
0
        /// <summary>
        /// SET class value from another Integer32 class cast as <see cref="AsnType"/>.
        /// </summary>
        /// <param name="value">Integer32 class cast as <see cref="AsnType"/></param>
        /// <exception cref="ArgumentException">Argument is not Integer32 type.</exception>
        public void Set(AsnType value)
        {
            Integer32 val = value as Integer32;

            if (val != null)
            {
                _value = val.Value;
            }
            else
            {
                throw new ArgumentException("Invalid argument type.");
            }
        }
Example #13
0
 /// <summary>
 /// SET class value from another UInteger32 or Integer32 class cast as <seealso cref="AsnType"/>.
 /// </summary>
 /// <param name="value">UInteger32 class cast as <seealso cref="AsnType"/></param>
 /// <exception cref="ArgumentNullException">Parameter is null.</exception>
 public void Set(AsnType value)
 {
     if (value == null)
     {
         throw new ArgumentNullException("value", "Parameter is null");
     }
     if (value is UInteger32)
     {
         _value = ((UInteger32)value).Value;
     }
     else if (value is Integer32)
     {
         _value = (UInt32)((Integer32)value).Value;
     }
 }
Example #14
0
        /// <summary>
        /// Get SNMP protocol version from the packet. This routine does not verify if version number is valid. Caller
        /// should verify that returned value represents a valid SNMP protocol version number.
        ///
        /// <code>
        /// int protocolVersion = Packet.GetProtocolVersion(inPacket, inLength);
        /// if( protocolVersion != -1 )
        /// {
        ///     if( protocolVersion == SnmpConstants.SNMPV1 || protocolVersion == SnmpConstants.SNMPV2 || protocolVersion == SnmpConstants.SNMPV3 )
        ///     {
        ///         // do something
        ///     }
        ///     else
        ///     {
        ///         Console.WriteLine("Invalid SNMP protocol version.");
        ///     }
        /// }
        /// else
        /// {
        ///     Console.WriteLine("Invalid SNMP packet.");
        /// }
        /// </code>
        /// </summary>
        /// <param name="buffer">BER encoded SNMP packet</param>
        /// <param name="bufferLength">Length of the BER encoded packet</param>
        /// <returns>Returns SNMP protocol version, if packet is not valid returned value is -1.</returns>
        public static int GetProtocolVersion(byte[] buffer, int bufferLength)
        {
            int  offset  = 0;
            int  length  = 0;
            byte asnType = AsnType.ParseHeader(buffer, ref offset, out length);

            if ((offset + length) > bufferLength)
            {
                return(-1);                // This is not a valid packet
            }
            Integer32 version = new Integer32();

            offset = version.decode(buffer, offset);
            return(version.Value);
        }
Example #15
0
        /// <summary>
        /// Return SNMP type object of the type specified by name. Supported variable types are:
        /// <see cref="Integer32"/>, <see cref="Counter32"/>, <see cref="Gauge32"/>, <see cref="Counter64"/>,
        /// <see cref="TimeTicks"/>, <see cref="OctetString"/>, <see cref="IpAddress"/>, <see cref="Oid"/>, and
        /// <see cref="Null"/>.
        ///
        /// Type names are the same as support class names compared without case sensitivity (e.g. Integer == INTEGER).
        /// </summary>
        /// <param name="name">Name of the object type (not case sensitive)</param>
        /// <returns>New <see cref="AsnType"/> object.</returns>
        public static AsnType GetSyntaxObject(string name)
        {
            AsnType obj = null;

            if (name.ToUpper().Equals("INTEGER32") || name.ToUpper().Equals("INTEGER"))
            {
                obj = new Integer32();
            }
            else if (name.ToUpper().Equals("COUNTER32"))
            {
                obj = new Counter32();
            }
            else if (name.ToUpper().Equals("GAUGE32"))
            {
                obj = new Gauge32();
            }
            else if (name.ToUpper().Equals("COUNTER64"))
            {
                obj = new Counter64();
            }
            else if (name.ToUpper().Equals("TIMETICKS"))
            {
                obj = new TimeTicks();
            }
            else if (name.ToUpper().Equals("OCTETSTRING"))
            {
                obj = new OctetString();
            }
            else if (name.ToUpper().Equals("IPADDRESS"))
            {
                obj = new IpAddress();
            }
            else if (name.ToUpper().Equals("OID"))
            {
                obj = new Oid();
            }
            else if (name.ToUpper().Equals("NULL"))
            {
                obj = new Null();
            }
            else
            {
                throw new ArgumentException("Invalid value type name");
            }

            return(obj);
        }
        /// <summary>
        /// Return SNMP type object of the type specified by name. Supported variable types are:
        /// * <see cref="Integer32"/>
        /// * <see cref="Counter32"/>
        /// * <see cref="Gauge32"/>
        /// * <see cref="Counter64"/>
        /// * <see cref="TimeTicks"/>
        /// * <see cref="OctetString"/>
        /// * <see cref="IpAddress"/>
        /// * <see cref="Oid"/>
        /// * <see cref="Null"/>
        /// </summary>
        /// <param name="name">Name of the object type</param>
        /// <returns>New <see cref="AsnType"/> object.</returns>
        public static AsnType GetSyntaxObject(string name)
        {
            AsnType obj = null;

            if (name == "Integer32")
            {
                obj = new Integer32();
            }
            else if (name == "Counter32")
            {
                obj = new Counter32();
            }
            else if (name == "Gauge32")
            {
                obj = new Gauge32();
            }
            else if (name == "Counter64")
            {
                obj = new Counter64();
            }
            else if (name == "TimeTicks")
            {
                obj = new TimeTicks();
            }
            else if (name == "OctetString")
            {
                obj = new OctetString();
            }
            else if (name == "IpAddress")
            {
                obj = new IpAddress();
            }
            else if (name == "Oid")
            {
                obj = new Oid();
            }
            else if (name == "Null")
            {
                obj = new Null();
            }
            else
            {
                throw new ArgumentException("Invalid value type name");
            }

            return(obj);
        }
Example #17
0
        /// <summary>
        /// Get SNMP protocol version from the packet. This routine does not verify if version number is valid. Caller
        /// should verify that returned value represents a valid SNMP protocol version number.
        ///
        /// <code>
        /// int protocolVersion = Packet.GetProtocolVersion(inPacket, inLength);
        /// if( protocolVersion != -1 )
        /// {
        ///     if( protocolVersion == SnmpConstants.SNMPV1 || protocolVersion == SnmpConstants.SNMPV2 || protocolVersion == SnmpConstants.SNMPV3 )
        ///     {
        ///         // do something
        ///     }
        ///     else
        ///     {
        ///         Console.WriteLine("Invalid SNMP protocol version.");
        ///     }
        /// }
        /// else
        /// {
        ///     Console.WriteLine("Invalid SNMP packet.");
        /// }
        /// </code>
        /// </summary>
        /// <param name="buffer">BER encoded SNMP packet</param>
        /// <param name="bufferLength">Length of the BER encoded packet</param>
        /// <returns>Returns SNMP protocol version, if packet is not valid returned value is -1.</returns>
        /// <exception cref="SnmpDecodingException">Thrown when invalid sequence type is found at the start of the SNMP packet being decoded</exception>
        public static int GetProtocolVersion(byte[] buffer, int bufferLength)
        {
            int  offset  = 0;
            byte asnType = AsnType.ParseHeader(buffer, ref offset, out int length);

            if ((offset + length) > bufferLength)
            {
                return(-1); // This is not a valid packet
            }
            if (asnType != SnmpConstants.SMI_SEQUENCE)
            {
                throw new SnmpDecodingException("Invalid sequence type at the start of the SNMP packet.");
            }
            Integer32 version = new Integer32();

            _ = version.decode(buffer, offset);
            return(version.Value);
        }
Example #18
0
        /// <summary>
        /// Get SNMP protocol version from the packet. This routine does not verify if version number is valid. Caller
        /// should verify that returned value represents a valid SNMP protocol version number.
        ///
        /// <code>
        /// int protocolVersion = Packet.GetProtocolVersion(inPacket, inLength);
        /// if( protocolVersion != -1 )
        /// {
        ///     if( protocolVersion == SnmpConstants.SNMPV1 || protocolVersion == SnmpConstants.SNMPV2 || protocolVersion == SnmpConstants.SNMPV3 )
        ///         // do something
        ///     else
        ///         Console.WriteLine("Invalid SNMP protocol version.");
        /// }
        /// else
        ///     Console.WriteLine("Invalid SNMP packet.");
        /// </code>
        /// </summary>
        /// <param name="buffer">BER encoded SNMP packet</param>
        /// <param name="bufferLength">Length of the BER encoded packet</param>
        /// <returns>Returns SNMP protocol version, if packet is not valid returned value is -1.</returns>
        /// <exception cref="SnmpDecodingException">Thrown when invalid sequence type is found at the start of the SNMP packet being decoded</exception>
        public static ESnmpVersion GetProtocolVersion(byte[] buffer, int bufferLength)
        {
            int offset = 0;

            byte asnType = AsnType.ParseHeader(buffer, ref offset, out int length);

            if ((offset + length) > bufferLength)
            {
                throw new SnmpDecodingException("Cannot parse SNMP version from packet, input past end");
            }

            if (asnType != SnmpConstants.SmiSequence)
            {
                throw new SnmpDecodingException("Invalid sequence type at the start of the SNMP packet.");
            }

            Integer32 version = new Integer32();

            offset = version.Decode(buffer, offset);

            return((ESnmpVersion)version.Value);
        }
        /// <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 _);

            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);
        }
Example #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);
        }
Example #21
0
        public static AsnType Get(IPAddress agent, string community, string oid)
        {
            // Define agent parameters class
            AgentParameters agentParameters = new AgentParameters(SnmpVersion.Ver2, new OctetString(community));

            // Construct target
            UdpTarget target = new UdpTarget(agent, 161, 2000, 1);

            // Pdu class used for all requests
            Pdu pdu = new Pdu(PduType.Get);

            pdu.VbList.Add(oid); //sysDescr

            // Make SNMP request
            var snmpResponse = target.Request(pdu, agentParameters) as SnmpV2Packet;

            AsnType result = null;

            // If result is null then agent didn't reply or we couldn't parse the reply.
            if (snmpResponse != null)
            {
                // ErrorStatus other then 0 is an error returned by
                // the Agent - see SnmpConstants for error definitions
                if (snmpResponse.Pdu.ErrorStatus != 0)
                {
                    // agent reported an error with the request
                    throw new Exception($"Error in SNMP reply. Error {snmpResponse.Pdu.ErrorStatus} index {snmpResponse.Pdu.ErrorIndex}");
                }
                else
                {
                    result = snmpResponse.Pdu.VbList[0].Value;
                }
            }

            target.Close();
            return(result);
        }
        /// <summary>Used to create correct variable type object for the specified encoded type</summary>
        /// <param name="asnType">ASN.1 type code</param>
        /// <returns>A new object matching type supplied or null if type was not recognized.</returns>
        public static AsnType GetSyntaxObject(byte asnType)
        {
            AsnType obj = null;

            if (asnType == SnmpConstants.SMI_INTEGER)
            {
                obj = new Integer32();
            }
            else if (asnType == SnmpConstants.SMI_COUNTER32)
            {
                obj = new Counter32();
            }
            else if (asnType == SnmpConstants.SMI_GAUGE32)
            {
                obj = new Gauge32();
            }
            else if (asnType == SnmpConstants.SMI_COUNTER64)
            {
                obj = new Counter64();
            }
            else if (asnType == SnmpConstants.SMI_TIMETICKS)
            {
                obj = new TimeTicks();
            }
            else if (asnType == SnmpConstants.SMI_STRING)
            {
                obj = new OctetString();
            }
            else if (asnType == SnmpConstants.SMI_OPAQUE)
            {
                obj = new Opaque();
            }
            else if (asnType == SnmpConstants.SMI_IPADDRESS)
            {
                obj = new IpAddress();
            }
            else if (asnType == SnmpConstants.SMI_OBJECTID)
            {
                obj = new Oid();
            }
            else if (asnType == SnmpConstants.SMI_PARTY_CLOCK)
            {
                obj = new V2PartyClock();
            }
            else if (asnType == SnmpConstants.SMI_NOSUCHINSTANCE)
            {
                obj = new NoSuchInstance();
            }
            else if (asnType == SnmpConstants.SMI_NOSUCHOBJECT)
            {
                obj = new NoSuchObject();
            }
            else if (asnType == SnmpConstants.SMI_ENDOFMIBVIEW)
            {
                obj = new EndOfMibView();
            }
            else if (asnType == SnmpConstants.SMI_NULL)
            {
                obj = new Null();
            }

            return(obj);
        }
Example #23
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);
        }
Example #24
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>
        /// <returns>The length of the decoded segment</returns>
        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)ESnmpVersion.Ver3)
            {
                throw new SnmpInvalidVersionException("Expecting SNMP version 3.");
            }

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

            if (asnType != SnmpConstants.SmiSequence)
            {
                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 = messageFlags.Decode(buffer, offset);

            // verify that a valid authentication/privacy configuration is present in the packet
            if (messageFlags.Authentication == false && messageFlags.Privacy == true)
            {
                throw new SnmpException(SnmpException.EErrorCode.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.EErrorCode.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 (messageFlags.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 (messageFlags.Privacy && userSecurityModel.EngineId.Length > 0)
            {
                IPrivacyProtocol privacyProtocol = PrivacyProtocol.GetInstance(userSecurityModel.Privacy);

                if (privacyProtocol == null)
                {
                    throw new SnmpException(SnmpException.EErrorCode.UnsupportedPrivacyProtocol, "Privacy protocol requested is not supported.");
                }

                if (userSecurityModel.PrivacyParameters.Length != privacyProtocol.PrivacyParametersLength)
                {
                    throw new SnmpException(SnmpException.EErrorCode.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);
        }
Example #25
0
 /// <summary>
 /// SET class value from supplied Vb class
 /// </summary>
 /// <param name="value">Vb class to clone data from</param>
 public void Set(Vb value)
 {
     _oid   = (Oid)value.Oid.Clone();
     _value = (Oid)value.Value.Clone();
 }
Example #26
0
 /// <summary>Construct Vb with the supplied OID and Null value</summary>
 /// <param name="oid">OID</param>
 public Vb(Oid oid)
     : this()
 {
     this.oid = (Oid)oid.Clone();
     value    = new Null();
 }
Example #27
0
 /// <summary>Construct Vb with the oid value and <seealso cref="Null"/> value.</summary>
 /// <param name="oid">String representing OID value to set</param>
 public Vb(string oid)
     : this()
 {
     this.oid = new Oid(oid);
     value    = new Null();
 }
Example #28
0
 /// <summary>
 /// SET class value from supplied Vb class
 /// </summary>
 /// <param name="value">Vb class to clone data from</param>
 public void Set(Vb value)
 {
     this._oid   = (Oid)value.Oid.Clone();
     this._value = (Oid)value.Value.Clone();
 }
Example #29
0
 /// <summary>
 /// Construct Vb with the oid value and <seealso cref="Null"/> value.
 /// </summary>
 /// <param name="oid">String representing OID value to set</param>
 public Vb(string oid)
     : this()
 {
     _oid   = new Oid(oid);
     _value = new Null();
 }
Example #30
0
 /// <summary>
 /// Construct Vb with the supplied OID and Null value
 /// </summary>
 /// <param name="oid">OID</param>
 public Vb(Oid oid)
     : this()
 {
     _oid   = (Oid)oid.Clone();
     _value = new Null();
 }
Example #31
0
 /// <summary>
 /// Construct Vb with the OID and value
 /// </summary>
 /// <param name="oid">OID</param>
 /// <param name="value">Value</param>
 public Vb(Oid oid, AsnType value)
     : this(oid) {
     _value = (AsnType)value.Clone();
 }
Example #32
0
 /// <summary>
 /// Reset Vb value to Null
 /// </summary>
 public void ResetValue()
 {
     _value = new Null();
 }
Example #33
-1
 /// <summary>
 /// SET class value from supplied Vb class
 /// </summary>
 /// <param name="value">Vb class to clone data from</param>
 public void Set(Vb value)
 {
     this._oid = (Oid)value.Oid.Clone();
     this._value = (Oid)value.Value.Clone();
 }
Example #34
-1
 /// <summary>
 /// Reset Vb value to Null
 /// </summary>
 public void ResetValue()
 {
     _value = new Null();
 }
Example #35
-1
        /// <summary>
        /// Executa uma requisição do tipo Set
        /// </summary>
        /// <param name="setValue">Valor a set definido</param>
        public void Send(AsnType setValue)
        {
            using (var target = new UdpTarget(Host.IP, Host.Port, TimeOut, Retries))
            {
                var agentp = new AgentParameters(SnmpVersion.Ver2, new OctetString(Host.Community));

                // Caso necessario, appenda o .0 na requisição
                var oid = new Oid(Object.OID);
                if (oid[oid.Length - 1] != 0)
                    oid.Add(0);

                // Cria pacote de dados
                RequestData = new Pdu(setValue == null ? PduType.Get : PduType.Set);

                // Adiciona dados da requisição
                switch (RequestData.Type)
                {
                    case PduType.Get:
                        RequestData.VbList.Add(oid);
                        break;
                    case PduType.Set:
                        RequestData.VbList.Add(oid, setValue);
                        break;
                    default:
                        throw new InvalidOperationException("unsupported");
                }
                try
                {
                    if (LogRequests) Logger.Self.Log(this);
                    Timestamp = DateTime.Now;

                    // Envia requisição
                    ResponsePacket = target.Request(RequestData, agentp) as SnmpV2Packet;

                    // Trata resposta
                    if (ResponsePacket != null && ResponsePacket.Pdu.ErrorStatus == (int)PduErrorStatus.noError)
                    {
                        // TODO: suportar mais de um retorno
                        var item = ResponsePacket.Pdu.VbList[0];

                        ResponseValue = item.Value;
                        if (LogRequests) Logger.Self.Log(item);
                    }
                }
                catch (Exception ex)
                {
                    if (LogRequests) Logger.Self.Log(ex);
                    throw new SnmpException("Não foi possível realizar a operação");
                }
            }
        }
Example #36
-1
 /// <summary>
 /// Construct Vb with the oid value and <seealso cref="Null"/> value.
 /// </summary>
 /// <param name="oid">String representing OID value to set</param>
 public Vb(string oid)
     : this()
 {
     _oid = new Oid(oid);
     _value = new Null();
 }
Example #37
-1
 /// <summary>
 /// Construct Vb with the supplied OID and Null value
 /// </summary>
 /// <param name="oid">OID</param>
 public Vb(Oid oid)
     : this()
 {
     _oid = (Oid)oid.Clone();
     _value = new Null();
 }