public static GetInstance ( AuthenticationDigests authProtocol ) : IAuthenticationDigest | ||
authProtocol | AuthenticationDigests | Authentication protocol code. Available codes are |
return | IAuthenticationDigest |
/// <summary>Encode SNMP version 3 packet</summary> /// <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 override byte[] Encode() { byte[] pkey = null; byte[] akey = null; if (messageFlags.Authentication && userSecurityModel.EngineId.Length > 0) { IAuthenticationDigest auth = Authentication.GetInstance(userSecurityModel.Authentication); if (auth == null) { throw new SnmpException(SnmpException.EErrorCode.UnsupportedNoAuthPriv, "Invalid authentication protocol."); } akey = auth.PasswordToKey(userSecurityModel.AuthenticationSecret, userSecurityModel.EngineId); 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."); } pkey = privacyProtocol.PasswordToKey(userSecurityModel.PrivacySecret, userSecurityModel.EngineId, auth); } } return(Encode(akey, pkey)); }
/// <summary>Generate privacy key from authentication password and engine id</summary> /// <returns>Privacy key on success or null on failure</returns> public byte[] GeneratePrivacyKey() { if (userSecurityModel.Authentication == AuthenticationDigests.None) { return(null); } if (userSecurityModel.Privacy == EPrivacyProtocols.None) { return(null); } if (userSecurityModel.PrivacySecret == null || userSecurityModel.PrivacySecret.Length <= 0) { return(null); } IAuthenticationDigest authProto = Authentication.GetInstance(userSecurityModel.Authentication); if (authProto != null) { IPrivacyProtocol privProto = PrivacyProtocol.GetInstance(userSecurityModel.Privacy); if (privProto != null) { return(privProto.PasswordToKey(userSecurityModel.PrivacySecret, userSecurityModel.EngineId, authProto)); } } return(null); }
/// <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> public override int Decode(byte[] berBuffer, int length) { byte[] pkey = null; byte[] akey = null; if (MsgFlags.Authentication && USM.EngineId.Length > 0) { IAuthenticationDigest auth = Authentication.GetInstance(USM.Authentication); if (auth == null) { throw new SnmpException(SnmpException.UnsupportedNoAuthPriv, "Invalid authentication protocol."); } akey = auth.PasswordToKey(USM.AuthenticationSecret, USM.EngineId); 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."); } pkey = privacyProtocol.PasswordToKey(USM.PrivacySecret, USM.EngineId, auth); } } return(Decode(berBuffer, length, akey, pkey)); }
/// <summary> /// Generate authentication key from authentication password and engine id /// </summary> /// <returns>Authentication key on success or null on failure</returns> public byte[] GenerateAuthenticationKey() { if (_userSecurityModel.EngineId == null || _userSecurityModel.EngineId.Length <= 0) return null; if (_userSecurityModel.AuthenticationSecret == null || _userSecurityModel.AuthenticationSecret.Length <= 0) return null; if (_userSecurityModel.Authentication != AuthenticationDigests.None) { IAuthenticationDigest authProto = Authentication.GetInstance(_userSecurityModel.Authentication); if (authProto != null) { return authProto.PasswordToKey(_userSecurityModel.AuthenticationSecret, _userSecurityModel.EngineId); } } return null; }
/// <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); }
/// <summary> /// Encode SNMP version 3 packet /// </summary> /// <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 override byte[] encode() { 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[] pkey = privacyProtocol.PasswordToKey(_userSecurityModel.PrivacySecret, _userSecurityModel.EngineId, auth); byte[] encryptedBuffer = privacyProtocol.Encrypt(unencryptedPdu, 0, unencryptedPdu.Length, pkey, _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); } int preVersionLength = buffer.Length; base.encode(buffer); int versionHeaderLength = buffer.Length - preVersionLength; if (_msgFlags.Authentication && _userSecurityModel.EngineId.Length > 0) { _userSecurityModel.Authenticate(ref buffer); // Now re-encode the packet with the authentication information _userSecurityModel.encode(packetHeader); packetHeader.Append(encodedPdu); base.encode(packetHeader); buffer = packetHeader; } return(buffer); }
/// <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> public override int decode(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 int len = 0; byte asnType = AsnType.ParseHeader(buffer, ref offset, out len); // 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 != _userSecurityModel.Type) { throw new SnmpException(SnmpException.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 (_msgFlags.Authentication && _userSecurityModel.EngineId.Length > 0) { // Authenticate packet if (_userSecurityModel.AuthenticationParameters.Length != 12) { throw new SnmpAuthenticationException("Invalid authentication parameter field length."); } if (!_userSecurityModel.IsAuthentic(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 && _userSecurityModel.EngineId.Length > 0) { IPrivacyProtocol privacyProtocol = PrivacyProtocol.GetInstance(_userSecurityModel.Privacy); if (privacyProtocol == null) { throw new SnmpException(SnmpException.UnsupportedPrivacyProtocol, "Privacy protocol requested is not supported."); } if (_userSecurityModel.PrivacyParameters.Length != privacyProtocol.PrivacyParametersLength) { throw new SnmpException(SnmpException.InvalidPrivacyParameterLength, "Invalid privacy parameters field length."); } // build privacy key IAuthenticationDigest auth = Authentication.GetInstance(_userSecurityModel.Authentication); if (auth == null) { throw new SnmpException(SnmpException.UnsupportedNoAuthPriv, "Invalid authentication protocol."); } byte[] pkey = auth.PasswordToKey(_userSecurityModel.PrivacySecret, _userSecurityModel.EngineId); // extend key if it is too short if (pkey.Length < privacyProtocol.MinimumKeyLength) { pkey = privacyProtocol.ExtendShortKey(pkey, new OctetString(_userSecurityModel.PrivacySecret), _userSecurityModel.EngineId, auth); } // 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, pkey, _userSecurityModel.EngineBoots, _userSecurityModel.EngineTime, _userSecurityModel.PrivacyParameters); int tempOffset = 0; offset = _scopedPdu.decode(decryptedScopedPdu, tempOffset); } else { offset = _scopedPdu.decode(buffer, offset); } return(offset); }