SNMP Version 3 Scoped Protocol Data Unit.
ScopedPdu extends the Pdu class by adding SNMP version 3 specific Context Engine Id and Context Name variables to the beginning of the packet. Context engine id is retrieved from the agent using the SNMP version 3 standard defined discovery process. Context name is used to define which subsection of the agents MIB user is allowed (or wants) to access. When creating a new ScopedPdu, for a valid request, ContextEngineId value has to be set for a valid reply to be received. Context value is implementation specific (depends on the configuration of the agent) and might not be required for a successful request.
Inheritance: Pdu
Beispiel #1
0
 /// <summary>Constructor.</summary>
 /// <remarks>
 /// Sets internal ScopedPdu class to the argument supplied instance of the
 /// class. This is a good cheat that will allow you direct access to the internal ScopedPdu class
 /// since it is not cloned but assigned to the internal variable.
 /// </remarks>
 /// <param name="pdu"><see cref="ScopedPdu"/> class assigned to the class</param>
 public SnmpV3Packet(ScopedPdu pdu)
     : this()
 {
     if (pdu != null)
     {
         scopedPdu = pdu;
     }
 }
Beispiel #2
0
 /// <summary>Constructor</summary>
 /// <remarks>
 /// Create new SNMPv3 packet class and initialize security parameters and ScopedPdu.
 /// </remarks>
 /// <param name="param">SNMPv3 security parameters</param>
 /// <param name="pdu">ScopedPdu assigned to the class</param>
 public SnmpV3Packet(SecureAgentParameters param, ScopedPdu pdu)
     : this(param)
 {
     if (pdu != null)
     {
         scopedPdu = pdu;
     }
 }
Beispiel #3
0
 /// <summary>
 /// Standard constructor.
 /// </summary>
 public SnmpV3Packet()
     : base(SnmpVersion.Ver3)
 {
     _messageId           = new Integer32();
     _maxMessageSize      = new Integer32(64 * 1024);
     _msgFlags            = new MsgFlags();
     _msgFlags.Reportable = true;             // Make sure reportable is set to true by default
     _securityModel       = new Integer32();
     _userSecurityModel   = new UserSecurityModel();
     _scopedPdu           = new ScopedPdu();
 }
Beispiel #4
0
        /// <summary>Standard constructor.</summary>
        public SnmpV3Packet()
            : base(ESnmpVersion.Ver3)
        {
            messageId      = new Integer32();
            maxMessageSize = new Integer32(64 * 1024);

            messageFlags = new MsgFlags
            {
                Reportable = true, // Make sure reportable is set to true by default
            };

            securityModel     = new Integer32();
            userSecurityModel = new UserSecurityModel();
            scopedPdu         = new ScopedPdu();
        }
Beispiel #5
0
        /// <summary>
        /// Make SNMP request. With this method you can make blocked SNMP version 1, 2 and 3 requests of type GET,
        /// GET-NEXT, GET-BULK, SET and REPORT (request types have to compatible with the SNMP protocol version you
        /// are using).
        ///
        /// This method will pass through any exceptions thrown by parsing classes/methods so see individual packet
        /// classes, ASN.1 type classes, authentication, privacy, etc. classes for exceptions thrown.
        /// </summary>
        /// <param name="pdu">Pdu class (do not pass ScopedPdu)</param>
        /// <param name="agentParameters">Security information for the request. Use <see cref="AgentParameters"/>
        /// for SNMP versions 1 and 2 requests. Use <see cref="SecureAgentParameters"/> for SNMP version 3
        /// requests.</param>
        /// <param name="responseCallback">Callback that receives the result of the async operation.</param>
        /// <returns>True if async request was successfully initiated, otherwise false.</returns>
        public bool RequestAsync(Pdu pdu, IAgentParameters agentParameters, SnmpAsyncResponse responseCallback)
        {
            if (IsBusy)
            {
                return(false);                // class is busy
            }
            _response        = null;
            _response       += responseCallback;
            _agentParameters = agentParameters;
            byte[] outPacket;
            if (agentParameters.Version == SnmpVersion.Ver3)
            {
                SecureAgentParameters secparams = (SecureAgentParameters)agentParameters;
                if (secparams.Authentication != AuthenticationDigests.None && secparams.AuthenticationSecret.Length <= 0)
                {
                    // _response(AsyncRequestResult.AuthenticationError, null);
                    return(false);
                }
                if (secparams.Privacy != PrivacyProtocols.None && secparams.PrivacySecret.Length <= 0)
                {
                    // _response(AsyncRequestResult.PrivacyError, null);
                    return(false);
                }
                _noSourceCheck = false;                 // this option is not valid for SNMP v3 requests
                ScopedPdu outPdu = new ScopedPdu(pdu);
                outPdu.ContextEngineId.Set(secparams.EngineId);
                outPdu.ContextName.Set(secparams.ContextName);
                SnmpV3Packet packet = new SnmpV3Packet(outPdu);
                secparams.InitializePacket(packet);
                try
                {
                    if (secparams.HasCachedKeys)
                    {
                        outPacket = packet.encode(secparams.AuthenticationKey, secparams.PrivacyKey);
                    }
                    else
                    {
                        outPacket = packet.encode();
                    }
                }
                catch (Exception ex)
                {
                    ex.GetType();
                    _response(AsyncRequestResult.EncodeError, packet);
                    return(false);
                }
            }
            else if (agentParameters.Version == (int)SnmpVersion.Ver1)
            {
                AgentParameters param = (AgentParameters)agentParameters;
                _noSourceCheck = param.DisableReplySourceCheck;
                SnmpV1Packet packet = new SnmpV1Packet();
                packet.Pdu.Set(pdu);
                packet.Community.Set(param.Community);
                try
                {
                    outPacket = packet.encode();
                }
                catch (Exception ex)
                {
                    ex.GetType();
                    _response(AsyncRequestResult.EncodeError, packet);
                    return(false);
                }
            }
            else if (agentParameters.Version == SnmpVersion.Ver2)
            {
                AgentParameters param = (AgentParameters)agentParameters;
                _noSourceCheck = param.DisableReplySourceCheck;
                SnmpV2Packet packet = new SnmpV2Packet();
                packet.Pdu.Set(pdu);
                packet.Community.Set(param.Community);
                try
                {
                    outPacket = packet.encode();
                }
                catch (Exception ex)
                {
                    ex.GetType();
                    _response(AsyncRequestResult.EncodeError, packet);
                    return(false);
                }
            }
            else
            {
                throw new SnmpInvalidVersionException("Unsupported SNMP version.");
            }

            if (!base.RequestAsync(_address, _port, outPacket, outPacket.Length, _timeout, _retry, new SnmpAsyncCallback(AsyncResponse)))
            {
                return(false);
            }
            return(true);
        }
Beispiel #6
0
        /// <summary>Make SNMP Request</summary>
        /// <remarks>
        /// Make SNMP request. With this method you can make blocked SNMP version 1, 2 and 3 requests of type GET,
        /// GET-NEXT, GET-BULK, SET and REPORT (request types have to compatible with the SNMP protocol version you
        /// are using).
        ///
        /// This method will pass through any exceptions thrown by parsing classes/methods so see individual packet
        /// classes, ASN.1 type classes, authentication, privacy, etc. classes for exceptions thrown.
        /// </remarks>
        /// <param name="pdu">Pdu class (do not pass ScopedPdu)</param>
        /// <param name="agentParameters">Security information for the request. Use <see cref="AgentParameters"/>
        /// for SNMP versions 1 and 2 requests. Use <see cref="SecureAgentParameters"/> for SNMP version 3
        /// requests.</param>
        /// <returns>Appropriate SNMP packet class for the reply received (<see cref="SnmpV1Packet"/>,
        /// <see cref="SnmpV2Packet"/>, or <see cref="SnmpV3Packet"/>. Null value if there was an error
        /// with the request.</returns>
        /// <exception cref="SnmpAuthenticationException">Thrown on SNMPv3 requests when authentication password
        /// is not specified on authNoPriv or authPriv requests in SecureAgentParameters or if incoming packet
        /// authentication check failed.
        ///
        /// With SNMP ver1 and ver2c, authentication check fails when invalid community name is parsed in the reply.</exception>
        /// <exception cref="SnmpPrivacyException">Thrown on SNMPv3 requests when privacy password is not
        /// specified in SecureAgentParameters on authPriv requests.</exception>
        /// <exception cref="SnmpException">Thrown in following cases:
        ///
        /// * IAgentParameters.Valid() returned false. SnmpException.ErrorCode is set to SnmpException.InvalidIAgentParameters
        /// * No data received on request. SnmpException.ErrorCode is set to SnmpException.NoDataReceived
        /// * Invalid RequestId in reply. SnmpException.ErrorCode is set to SnmpException.InvalidRequestId
        /// </exception>
        public SnmpPacket Request(Pdu pdu, IAgentParameters agentParameters)
        {
            byte[] outPacket;
            if (agentParameters.Version == SnmpVersion.Ver3)
            {
                SecureAgentParameters secparams = (SecureAgentParameters)agentParameters;
                if (secparams.Authentication != AuthenticationDigests.None && secparams.AuthenticationSecret.Length <= 0)
                {
                    throw new SnmpAuthenticationException("Authentication password not specified.");
                }
                if (secparams.Privacy != PrivacyProtocols.None && secparams.PrivacySecret.Length <= 0)
                {
                    throw new SnmpPrivacyException("Privacy password not specified.");
                }
                _noSourceCheck = false;                 // this option is not valid for SNMP v3 requests
                ScopedPdu    outPdu = new ScopedPdu(pdu);
                SnmpV3Packet packet = new SnmpV3Packet(outPdu);
                secparams.InitializePacket(packet);
                if (secparams.HasCachedKeys)
                {
                    outPacket = packet.encode(secparams.AuthenticationKey, secparams.PrivacyKey);
                }
                else
                {
                    outPacket = packet.encode();
                }
            }
            else if (agentParameters.Version == SnmpVersion.Ver1)
            {
                AgentParameters param = (AgentParameters)agentParameters;
                if (!param.Valid())
                {
                    throw new SnmpException(SnmpException.InvalidIAgentParameters, "Invalid AgentParameters. Unable to process request.");
                }
                SnmpV1Packet packet = new SnmpV1Packet();
                packet.Pdu.Set(pdu);
                packet.Community.Set(param.Community);
                outPacket      = packet.encode();
                _noSourceCheck = param.DisableReplySourceCheck;
            }
            else if (agentParameters.Version == SnmpVersion.Ver2)
            {
                AgentParameters param = (AgentParameters)agentParameters;
                if (!param.Valid())
                {
                    throw new SnmpException(SnmpException.InvalidIAgentParameters, "Invalid AgentParameters. Unable to process request.");
                }
                SnmpV2Packet packet = new SnmpV2Packet();
                packet.Pdu.Set(pdu);
                packet.Community.Set(param.Community);
                _noSourceCheck = param.DisableReplySourceCheck;
                outPacket      = packet.encode();
            }
            else
            {
                throw new SnmpInvalidVersionException("Unsupported SNMP version.");
            }

            byte[] inBuffer = base.Request(_address, _port, outPacket, outPacket.Length, _timeout, _retry);

            if (inBuffer == null || inBuffer.Length <= 0)
            {
                throw new SnmpException(SnmpException.NoDataReceived, "No data received on request.");
            }
            // verify packet
            if (agentParameters.Version == SnmpVersion.Ver1)
            {
                SnmpV1Packet    packet = new SnmpV1Packet();
                AgentParameters param  = (AgentParameters)agentParameters;
                packet.decode(inBuffer, inBuffer.Length);
                if (packet.Community != param.Community)
                {
                    // invalid community name received. Ignore the rest of the packet
                    throw new SnmpAuthenticationException("Invalid community name in reply.");
                }
                if (packet.Pdu.RequestId != pdu.RequestId)
                {
                    // invalid request id. unmatched response ignored
                    throw new SnmpException(SnmpException.InvalidRequestId, "Invalid request id in reply.");
                }
                return(packet);
            }
            else if (agentParameters.Version == SnmpVersion.Ver2)
            {
                SnmpV2Packet    packet = new SnmpV2Packet();
                AgentParameters param  = (AgentParameters)agentParameters;
                packet.decode(inBuffer, inBuffer.Length);
                if (packet.Community != param.Community)
                {
                    // invalid community name received. Ignore the rest of the packet
                    throw new SnmpAuthenticationException("Invalid community name in reply.");
                }
                if (packet.Pdu.RequestId != pdu.RequestId)
                {
                    // invalid request id. unmatched response ignored
                    throw new SnmpException(SnmpException.InvalidRequestId, "Invalid request id in reply.");
                }
                return(packet);
            }
            else if (agentParameters.Version == SnmpVersion.Ver3)
            {
                SnmpV3Packet          packet    = new SnmpV3Packet();
                SecureAgentParameters secparams = (SecureAgentParameters)agentParameters;
                secparams.InitializePacket(packet);
                if (secparams.HasCachedKeys)
                {
                    packet.decode(inBuffer, inBuffer.Length, secparams.AuthenticationKey, secparams.PrivacyKey);
                }
                else
                {
                    packet.decode(inBuffer, inBuffer.Length);
                }
                // first check if packet is a discovery response and process it
                if (packet.Pdu.Type == PduType.Report && packet.Pdu.VbCount > 0 && packet.Pdu.VbList[0].Oid.Equals(SnmpConstants.usmStatsUnknownEngineIDs))
                {
                    secparams.UpdateDiscoveryValues(packet);
                    return(packet);
                }
                else
                {
                    if (!secparams.ValidateIncomingPacket(packet))
                    {
                        return(null);
                    }
                    else
                    {
                        secparams.UpdateDiscoveryValues(packet);                         // update time, etc. values
                        return(packet);
                    }
                }
            }
            return(null);
        }
Beispiel #7
0
 /// <summary>
 /// Constructor.
 /// </summary>
 /// <remarks>
 /// Sets internal ScopedPdu class to the argument supplied instance of the
 /// class. This is a good cheat that will allow you direct access to the internal ScopedPdu class
 /// since it is not cloned but assigned to the internal variable.
 /// </remarks>
 /// <param name="pdu"><see cref="ScopedPdu"/> class assigned to the class</param>
 public SnmpV3Packet(ScopedPdu pdu)
     : this()
 {
     if( pdu != null )
         _scopedPdu = pdu;
 }
Beispiel #8
0
 /// <summary>
 /// Constructor
 /// </summary>
 /// <remarks>
 /// Create new SNMPv3 packet class and initialize security parameters and ScopedPdu.
 /// </remarks>
 /// <param name="param">SNMPv3 security parameters</param>
 /// <param name="pdu">ScopedPdu assigned to the class</param>
 public SnmpV3Packet(SecureAgentParameters param, ScopedPdu pdu)
     : this(param)
 {
     if( pdu != null )
         _scopedPdu = pdu;
 }
Beispiel #9
0
 /// <summary>
 /// Standard constructor.
 /// </summary>
 public SnmpV3Packet()
     : base(SnmpVersion.Ver3)
 {
     _messageId = new Integer32();
     _maxMessageSize = new Integer32(64 * 1024);
     _msgFlags = new MsgFlags();
     _msgFlags.Reportable = true; // Make sure reportable is set to true by default
     _securityModel = new Integer32();
     _userSecurityModel = new UserSecurityModel();
     _scopedPdu = new ScopedPdu();
 }
Beispiel #10
0
        /// <summary>
        /// Make SNMP request. With this method you can make blocked SNMP version 1, 2 and 3 requests of type GET,
        /// GET-NEXT, GET-BULK, SET and REPORT (request types have to compatible with the SNMP protocol version you
        /// are using).
        /// 
        /// This method will pass through any exceptions thrown by parsing classes/methods so see individual packet
        /// classes, ASN.1 type classes, authentication, privacy, etc. classes for exceptions thrown.
        /// </summary>
        /// <param name="pdu">Pdu class (do not pass ScopedPdu)</param>
        /// <param name="agentParameters">Security information for the request. Use <see cref="AgentParameters"/>
        /// for SNMP versions 1 and 2 requests. Use <see cref="SecureAgentParameters"/> for SNMP version 3
        /// requests.</param>
        /// <param name="responseCallback">Callback that receives the result of the async operation.</param>
        /// <returns>True if async request was successfully initiated, otherwise false.</returns>
        public bool RequestAsync(Pdu pdu, IAgentParameters agentParameters, SnmpAsyncResponse responseCallback)
        {
            if (IsBusy)
            {
                return false; // class is busy
            }
            _response = null;
            _response += responseCallback;
            _agentParameters = agentParameters;
            byte[] outPacket;
            if (agentParameters.Version == SnmpVersion.Ver3)
            {
                SecureAgentParameters secparams = (SecureAgentParameters)agentParameters;
                if (secparams.Authentication != AuthenticationDigests.None && secparams.AuthenticationSecret.Length <= 0)
                {
                    // _response(AsyncRequestResult.AuthenticationError, null);
                    return false;
                }
                if (secparams.Privacy != PrivacyProtocols.None && secparams.PrivacySecret.Length <= 0)
                {
                    // _response(AsyncRequestResult.PrivacyError, null);
                    return false;
                }
                _noSourceCheck = false; // this option is not valid for SNMP v3 requests
                ScopedPdu outPdu = new ScopedPdu(pdu);
                outPdu.ContextEngineId.Set(secparams.EngineId);
                outPdu.ContextName.Set(secparams.ContextName);
                SnmpV3Packet packet = new SnmpV3Packet(outPdu);
                secparams.InitializePacket(packet);
                try
                {
                    if (secparams.HasCachedKeys)
                        outPacket = packet.encode(secparams.AuthenticationKey, secparams.PrivacyKey);
                    else
                        outPacket = packet.encode();
                }
                catch( Exception ex )
                {
                    ex.GetType();
                    _response(AsyncRequestResult.EncodeError, packet);
                    return false;
                }
            }
            else if (agentParameters.Version == (int)SnmpVersion.Ver1)
            {
                AgentParameters param = (AgentParameters)agentParameters;
                _noSourceCheck = param.DisableReplySourceCheck;
                SnmpV1Packet packet = new SnmpV1Packet();
                packet.Pdu.Set(pdu);
                packet.Community.Set(param.Community);
                try
                {
                    outPacket = packet.encode();
                }
                catch( Exception ex)
                {
                    ex.GetType();
                    _response(AsyncRequestResult.EncodeError, packet);
                    return false;
                }
            }
            else if (agentParameters.Version == SnmpVersion.Ver2)
            {
                AgentParameters param = (AgentParameters)agentParameters;
                _noSourceCheck = param.DisableReplySourceCheck;
                SnmpV2Packet packet = new SnmpV2Packet();
                packet.Pdu.Set(pdu);
                packet.Community.Set(param.Community);
                try
                {
                    outPacket = packet.encode();
                }
                catch( Exception ex )
                {
                    ex.GetType();
                    _response(AsyncRequestResult.EncodeError, packet);
                    return false;
                }
            }
            else
            {
                throw new SnmpInvalidVersionException("Unsupported SNMP version.");
            }

            if( ! base.RequestAsync(_address, _port, outPacket, outPacket.Length, _timeout, _retry, new SnmpAsyncCallback(AsyncResponse) ) ) {
                return false;
            }
            return true;
        }
Beispiel #11
0
        /// <summary>Make SNMP Request</summary>
        /// <remarks>
        /// Make SNMP request. With this method you can make blocked SNMP version 1, 2 and 3 requests of type GET,
        /// GET-NEXT, GET-BULK, SET and REPORT (request types have to compatible with the SNMP protocol version you
        /// are using).
        /// 
        /// This method will pass through any exceptions thrown by parsing classes/methods so see individual packet
        /// classes, ASN.1 type classes, authentication, privacy, etc. classes for exceptions thrown.
        /// </remarks>
        /// <param name="pdu">Pdu class (do not pass ScopedPdu)</param>
        /// <param name="agentParameters">Security information for the request. Use <see cref="AgentParameters"/>
        /// for SNMP versions 1 and 2 requests. Use <see cref="SecureAgentParameters"/> for SNMP version 3
        /// requests.</param>
        /// <returns>Appropriate SNMP packet class for the reply received (<see cref="SnmpV1Packet"/>, 
        /// <see cref="SnmpV2Packet"/>, or <see cref="SnmpV3Packet"/>. Null value if there was an error
        /// with the request.</returns>
        /// <exception cref="SnmpAuthenticationException">Thrown on SNMPv3 requests when authentication password
        /// is not specified on authNoPriv or authPriv requests in SecureAgentParameters or if incoming packet 
        /// authentication check failed.
        /// 
        /// With SNMP ver1 and ver2c, authentication check fails when invalid community name is parsed in the reply.</exception>
        /// <exception cref="SnmpPrivacyException">Thrown on SNMPv3 requests when privacy password is not
        /// specified in SecureAgentParameters on authPriv requests.</exception>
        /// <exception cref="SnmpException">Thrown in following cases:
        /// 
        /// * IAgentParameters.Valid() returned false. SnmpException.ErrorCode is set to SnmpException.InvalidIAgentParameters
        /// * No data received on request. SnmpException.ErrorCode is set to SnmpException.NoDataReceived
        /// * Invalid RequestId in reply. SnmpException.ErrorCode is set to SnmpException.InvalidRequestId
        /// </exception>
        public SnmpPacket Request(Pdu pdu, IAgentParameters agentParameters)
        {
            byte[] outPacket;
            if (agentParameters.Version == SnmpVersion.Ver3)
            {
                SecureAgentParameters secparams = (SecureAgentParameters)agentParameters;
                if (secparams.Authentication != AuthenticationDigests.None && secparams.AuthenticationSecret.Length <= 0)
                    throw new SnmpAuthenticationException("Authentication password not specified.");
                if (secparams.Privacy != PrivacyProtocols.None && secparams.PrivacySecret.Length <= 0)
                    throw new SnmpPrivacyException("Privacy password not specified.");
                _noSourceCheck = false; // this option is not valid for SNMP v3 requests
                ScopedPdu outPdu = new ScopedPdu(pdu);
                SnmpV3Packet packet = new SnmpV3Packet(outPdu);
                secparams.InitializePacket(packet);
                if (secparams.HasCachedKeys)
                    outPacket = packet.encode(secparams.AuthenticationKey, secparams.PrivacyKey);
                else
                    outPacket = packet.encode();
            }
            else if (agentParameters.Version == SnmpVersion.Ver1)
            {
                AgentParameters param = (AgentParameters)agentParameters;
                if (!param.Valid())
                    throw new SnmpException(SnmpException.InvalidIAgentParameters,"Invalid AgentParameters. Unable to process request.");
                SnmpV1Packet packet = new SnmpV1Packet();
                packet.Pdu.Set(pdu);
                packet.Community.Set(param.Community);
                outPacket = packet.encode();
                _noSourceCheck = param.DisableReplySourceCheck;
            }
            else if (agentParameters.Version == SnmpVersion.Ver2)
            {
                AgentParameters param = (AgentParameters)agentParameters;
                if (!param.Valid())
                    throw new SnmpException(SnmpException.InvalidIAgentParameters, "Invalid AgentParameters. Unable to process request.");
                SnmpV2Packet packet = new SnmpV2Packet();
                packet.Pdu.Set(pdu);
                packet.Community.Set(param.Community);
                _noSourceCheck = param.DisableReplySourceCheck;
                outPacket = packet.encode();
            }
            else
            {
                throw new SnmpInvalidVersionException("Unsupported SNMP version.");
            }

            byte[] inBuffer = base.Request(_address, _port, outPacket, outPacket.Length, _timeout, _retry);

            if (inBuffer == null || inBuffer.Length <= 0)
            {
                return null;
            }
            // verify packet
            if (agentParameters.Version == SnmpVersion.Ver1)
            {
                SnmpV1Packet packet = new SnmpV1Packet();
                AgentParameters param = (AgentParameters)agentParameters;
                packet.decode(inBuffer, inBuffer.Length);
                if (packet.Community != param.Community)
                {
                    // invalid community name received. Ignore the rest of the packet
                    throw new SnmpAuthenticationException("Invalid community name in reply.");
                }
                if (packet.Pdu.RequestId != pdu.RequestId)
                {
                    // invalid request id. unmatched response ignored
                    throw new SnmpException(SnmpException.InvalidRequestId, "Invalid request id in reply.");
                }
                return packet;
            }
            else if (agentParameters.Version == SnmpVersion.Ver2)
            {
                SnmpV2Packet packet = new SnmpV2Packet();
                AgentParameters param = (AgentParameters)agentParameters;
                packet.decode(inBuffer, inBuffer.Length);
                if (packet.Community != param.Community)
                {
                    // invalid community name received. Ignore the rest of the packet
                    throw new SnmpAuthenticationException("Invalid community name in reply.");
                }
                if (packet.Pdu.RequestId != pdu.RequestId)
                {
                    // invalid request id. unmatched response ignored
                    throw new SnmpException(SnmpException.InvalidRequestId, "Invalid request id in reply.");
                }
                return packet;
            }
            else if (agentParameters.Version == SnmpVersion.Ver3)
            {
                SnmpV3Packet packet = new SnmpV3Packet();
                SecureAgentParameters secparams = (SecureAgentParameters)agentParameters;
                secparams.InitializePacket(packet);
                if (secparams.HasCachedKeys)
                    packet.decode(inBuffer, inBuffer.Length, secparams.AuthenticationKey, secparams.PrivacyKey);
                else
                    packet.decode(inBuffer, inBuffer.Length);
                // first check if packet is a discovery response and process it
                if (packet.Pdu.Type == PduType.Report && packet.Pdu.VbCount > 0 && packet.Pdu.VbList[0].Oid.Equals(SnmpConstants.usmStatsUnknownEngineIDs))
                {
                    secparams.UpdateDiscoveryValues(packet);
                    return packet;
                }
                else
                {
                    if (!secparams.ValidateIncomingPacket(packet))
                    {
                        return null;
                    }
                    else
                    {
                        secparams.UpdateDiscoveryValues(packet); // update time, etc. values
                        return packet;
                    }
                }
            }
            return null;
        }
Beispiel #12
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 = USM.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 (USM.EngineId.Length <= 0)
            {
                // save USM settings prior to encoding a Discovery packet
                savedUserName.Set(USM.SecurityName);
                USM.SecurityName.Reset(); // delete security name for discovery packets
                MsgFlags.Authentication = false;
                MsgFlags.Privacy        = false;
                MsgFlags.Reportable     = true;
            }

            USM.Encode(buffer);

            if (USM.EngineId.Length <= 0)
            {
                // restore saved USM values
                USM.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 && USM.EngineId.Length > 0)
            {
                IPrivacyProtocol privacyProtocol = PrivacyProtocol.GetInstance(USM.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);

                // we have to expand the key
                IAuthenticationDigest auth = Authentication.GetInstance(USM.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, USM.EngineBoots, USM.EngineTime, out byte[] privacyParameters, auth);

                USM.PrivacyParameters.Set(privacyParameters);
                OctetString encryptedOctetString = new OctetString(encryptedBuffer);
                encryptedOctetString.Encode(encodedPdu);
                // now redo packet encoding
                buffer.Reset();
                buffer.Set(packetHeader);
                USM.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 && USM.EngineId.Length > 0)
            {
                USM.Authenticate(authKey, ref buffer);
                // Now re-encode the packet with the authentication information
                USM.Encode(packetHeader);
                packetHeader.Append(encodedPdu);
                base.Encode(packetHeader);
                buffer = packetHeader;
            }
            return(buffer);
        }
Beispiel #13
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
            byte asnType = AsnType.ParseHeader(buffer, ref offset, out int 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 != 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);

            // Authenticate message if authentication flag is set and packet is not a discovery packet
            if (MsgFlags.Authentication && USM.EngineId.Length > 0)
            {
                // Authenticate packet
                if (USM.AuthenticationParameters.Length != 12)
                {
                    throw new SnmpAuthenticationException("Invalid authentication parameter field length.");
                }

                if (!USM.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 && USM.EngineId.Length > 0)
            {
                IPrivacyProtocol privacyProtocol = PrivacyProtocol.GetInstance(USM.Privacy);
                if (privacyProtocol == null)
                {
                    throw new SnmpException(SnmpException.UnsupportedPrivacyProtocol, "Privacy protocol requested is not supported.");
                }
                if (USM.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, USM.EngineBoots, USM.EngineTime, USM.PrivacyParameters);
                int    tempOffset         = 0;
                offset = ScopedPdu.Decode(decryptedScopedPdu, tempOffset);
            }
            else
            {
                offset = ScopedPdu.Decode(buffer, offset);
            }

            return(offset);
        }