/// <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); }
/// <summary> /// Encode SNMP packet for sending. /// </summary> /// <returns>BER encoded SNMP packet.</returns> public override byte[] encode() { MutableByte buf = new MutableByte(); if (this.Pdu.Type != PduType.Get && this.Pdu.Type != PduType.GetNext && this.Pdu.Type != PduType.Set && this.Pdu.Type != PduType.V2Trap && this.Pdu.Type != PduType.Response && this.Pdu.Type != PduType.GetBulk && this.Pdu.Type != PduType.Inform) { throw new SnmpInvalidPduTypeException("Invalid SNMP PDU type while attempting to encode PDU: " + string.Format("0x{0:x2}", this.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); }
/// <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> /// Convert <see cref="ScopedPdu" /> into a BER encoded byte array. Resulting byte array is appended /// to the argument specified <see cref="MutableByte" /> class. /// Privacy operations are not performed by this method. Value encoded and returned by this method is /// suitable for sending in NoAuthNoPriv or AuthNoPriv security configurations. If privacy is required, /// caller will have to perform encryption and decryption operations after BER encoding is performed. /// In privacy protected SNMP version 3 packets, ScopedPdu is 1) encrypted using configured encryption /// method, 2) added to a <see cref="OctetString" /> field, and 3) appended to the data buffer. /// Because privacy operation is intrusive, it is recommended that BER encoding of the ScopedPdu packet /// is stored in a temporary <see cref="MutableByte" /> class, where it can be privacy protected and /// added to the <see cref="OctetString" /> class for final encoding into the target SNMP v3 packet. /// </summary> /// <param name="buffer"> /// <see cref="MutableByte" /> class passed by reference that encoded ScopedPdu /// value is appended to. /// </param> public override void encode(MutableByte buffer) { var tmp = new MutableByte(); _contextEngineId.encode(tmp); _contextName.encode(tmp); // Encode base base.encode(tmp); BuildHeader(buffer, SnmpConstants.SMI_SEQUENCE, tmp.Length); buffer.Append(tmp); }
/// <summary> /// Encode SNMP packet for sending. /// </summary> /// <returns>BER encoded SNMP packet.</returns> public override byte[] encode() { MutableByte tmpBuffer = new MutableByte(); // // encode the community strings _snmpCommunity.encode(tmpBuffer); this.Pdu.encode(tmpBuffer); base.encode(tmpBuffer); return((byte[])tmpBuffer); }
/// <summary> /// Encode SNMP v3 message flag field /// </summary> /// <param name="buffer">Buffer to append encoded value to</param> public override void encode(MutableByte buffer) { byte flag = 0x00; if (_authenticationFlag) { flag |= FLAG_AUTH; } if (_privacyFlag) { flag |= FLAG_PRIV; } if (_reportableFlag) { flag |= FLAG_REPORTABLE; } OctetString flagObject = new OctetString(flag); flagObject.encode(buffer); }
/// <summary> /// Encode SNMP version 3 packet /// </summary> /// <param name="authKey">Authentication key (not password)</param> /// <param name="privKey">Privacy key (not password)</param> /// <remarks> /// Before encoding the packet into a byte array you need to ensure all required information is /// set. Examples of required information is request type, Vbs (Oid + values pairs), USM settings including /// SecretName, authentication method and secret (if needed), privacy method and secret (if needed), etc. /// </remarks> /// <returns>Byte array BER encoded SNMP packet.</returns> public byte[] encode(byte[] authKey, byte[] privKey) { MutableByte buffer = new MutableByte(); // encode the global message data sequence header information MutableByte globalMessageData = new MutableByte(); // if message id is 0 then generate a new, random message id if (_messageId.Value == 0) { Random rand = new Random(); _messageId.Value = rand.Next(1, Int32.MaxValue); } // encode message id _messageId.encode(globalMessageData); // encode max message size _maxMessageSize.encode(globalMessageData); // message flags _msgFlags.encode(globalMessageData); // security model code _securityModel.Value = _userSecurityModel.Type; _securityModel.encode(globalMessageData); // add global message data to the main buffer // encode sequence header and add data AsnType.BuildHeader(buffer, SnmpConstants.SMI_SEQUENCE, globalMessageData.Length); buffer.Append(globalMessageData); MutableByte packetHeader = new MutableByte(buffer); // before going down this road, check if this is a discovery packet OctetString savedUserName = new OctetString(); bool privacy = _msgFlags.Privacy; bool authentication = _msgFlags.Authentication; bool reportable = _msgFlags.Reportable; if (_userSecurityModel.EngineId.Length <= 0) { // save USM settings prior to encoding a Discovery packet savedUserName.Set(_userSecurityModel.SecurityName); _userSecurityModel.SecurityName.Reset(); // delete security name for discovery packets _msgFlags.Authentication = false; _msgFlags.Privacy = false; _msgFlags.Reportable = true; } _userSecurityModel.encode(buffer); if (_userSecurityModel.EngineId.Length <= 0) { // restore saved USM values _userSecurityModel.SecurityName.Set(savedUserName); _msgFlags.Authentication = authentication; _msgFlags.Privacy = privacy; _msgFlags.Reportable = reportable; } // Check if privacy encryption is required MutableByte encodedPdu = new MutableByte(); if (_msgFlags.Privacy && _userSecurityModel.EngineId.Length > 0) { IPrivacyProtocol privacyProtocol = PrivacyProtocol.GetInstance(_userSecurityModel.Privacy); if (privacyProtocol == null) { throw new SnmpException(SnmpException.UnsupportedPrivacyProtocol, "Specified privacy protocol is not supported."); } // Get BER encoded ScopedPdu MutableByte unencryptedPdu = new MutableByte(); _scopedPdu.encode(unencryptedPdu); byte[] privacyParameters = null; // we have to expand the key IAuthenticationDigest auth = Authentication.GetInstance(_userSecurityModel.Authentication); if (auth == null) { throw new SnmpException(SnmpException.UnsupportedNoAuthPriv, "Invalid authentication protocol. noAuthPriv mode not supported."); } byte[] encryptedBuffer = privacyProtocol.Encrypt(unencryptedPdu, 0, unencryptedPdu.Length, privKey, _userSecurityModel.EngineBoots, _userSecurityModel.EngineTime, out privacyParameters, auth); _userSecurityModel.PrivacyParameters.Set(privacyParameters); OctetString encryptedOctetString = new OctetString(encryptedBuffer); encryptedOctetString.encode(encodedPdu); // now redo packet encoding buffer.Reset(); buffer.Set(packetHeader); _userSecurityModel.encode(buffer); int preEncodedLength = encodedPdu.Length; buffer.Append(encodedPdu); if (_maxMessageSize.Value != 0) { // verify compliance with maximum message size if ((encodedPdu.Length - preEncodedLength) > _maxMessageSize) { throw new SnmpException(SnmpException.MaximumMessageSizeExceeded, "ScopedPdu exceeds maximum message size."); } } } else { _scopedPdu.encode(encodedPdu); buffer.Append(encodedPdu); } base.encode(buffer); if (_msgFlags.Authentication && _userSecurityModel.EngineId.Length > 0) { _userSecurityModel.Authenticate(authKey, ref buffer); // Now re-encode the packet with the authentication information _userSecurityModel.encode(packetHeader); packetHeader.Append(encodedPdu); base.encode(packetHeader); buffer = packetHeader; } return(buffer); }