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

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

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

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

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

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

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

            // Now encode the header for the PDU
            BuildHeader(buffer, (byte)Type, tmpBuffer.Length);
            buffer.Append(tmpBuffer);
        }
        /// <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);
        }
Example #3
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 #4
0
        /// <summary>ASN.1 encode SNMP version 1 trap</summary>
        /// <param name="buffer"><see cref="MutableByte"/> buffer to the end of which encoded values are appended.</param>
        public override void Encode(MutableByte buffer)
        {
            MutableByte trapBuffer = new MutableByte();

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

            _agentAddr.Encode(trapBuffer);

            _generic.Encode(trapBuffer);

            _specific.Encode(trapBuffer);

            _timeStamp.Encode(trapBuffer);

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

            BuildHeader(tmpBuffer, (byte)PduType.Trap, trapBuffer.Length);
            trapBuffer.Prepend(tmpBuffer);
            buffer.Append(trapBuffer);
        }
Example #5
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);
        }