/// <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); }
/// <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); }
/// <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); }
/// <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); }