146 lines
4.3 KiB
C#
146 lines
4.3 KiB
C#
using System;
|
|
using System.Net;
|
|
using ln.snmp.types;
|
|
using System.Text;
|
|
using System.Security.Cryptography;
|
|
using ln.snmp.asn1;
|
|
using System.Linq;
|
|
|
|
namespace ln.snmp.channel
|
|
{
|
|
public enum SnmpV3AuthMethod { MD5, SHA }
|
|
public enum SnmpV3PrivMethod { DES }
|
|
public enum SnmpAuthLevel : int { noAuthNoPriv = 0, authNoPriv = 0x01, authPriv = 0x03 }
|
|
|
|
public class USMEndpoint : SNMPInterface
|
|
{
|
|
public OctetString RemoteEngineID { get; set; }
|
|
|
|
public string Username { get; set; }
|
|
public string AuthKey { get; set; }
|
|
public string PrivKey { get; set; }
|
|
|
|
public SnmpV3AuthMethod AuthMethod { get; set; }
|
|
public SnmpV3PrivMethod PrivMethod { get; set; }
|
|
|
|
public override SnmpVersion SnmpVersion => SnmpVersion.V3;
|
|
|
|
public USMEndpoint(SNMPEngine snmpEngine,IPEndPoint remoteEndpoint)
|
|
:base(snmpEngine,remoteEndpoint)
|
|
{
|
|
}
|
|
|
|
public SnmpAuthLevel AuthLevel
|
|
{
|
|
get
|
|
{
|
|
if (PrivKey != null)
|
|
return SnmpAuthLevel.authPriv;
|
|
if (AuthKey != null)
|
|
return SnmpAuthLevel.authNoPriv;
|
|
|
|
return SnmpAuthLevel.noAuthNoPriv;
|
|
}
|
|
}
|
|
|
|
public override PDU snmpRequest(PDU pdu)
|
|
{
|
|
if ((RemoteEngineID == null)||(RemoteEngineID.Bytes.Length == 0))
|
|
{
|
|
QueryEngineID();
|
|
}
|
|
|
|
USMMessage request = new USMMessage();
|
|
ScopedPDU scopedPDU = new ScopedPDU();
|
|
|
|
request.MessageID = SNMPEngine.NextMessageID;
|
|
request.msgData = scopedPDU;
|
|
|
|
scopedPDU.contextEngineID = RemoteEngineID;
|
|
scopedPDU.PDU = pdu;
|
|
|
|
AuthenticateMessage(request);
|
|
|
|
|
|
SnmpMessage reply = SNMPEngine.SNMPRequest(RemoteEndpoint, request, SNMPEngine.Timeout);
|
|
USMMessage replyUSM = reply as USMMessage;
|
|
|
|
PDU responsePDU = (replyUSM.msgData as ScopedPDU).PDU;
|
|
|
|
return responsePDU;
|
|
}
|
|
|
|
public void QueryEngineID()
|
|
{
|
|
USMMessage queryMessage = new USMMessage();
|
|
queryMessage.MessageID = SNMPEngine.NextMessageID;
|
|
|
|
ScopedPDU scopedPDU = new ScopedPDU();
|
|
|
|
queryMessage.msgData = scopedPDU;
|
|
|
|
queryMessage.Dump();
|
|
|
|
|
|
SnmpMessage reply = SNMPEngine.SNMPRequest(RemoteEndpoint, queryMessage, SNMPEngine.Timeout);
|
|
USMMessage usmReply = reply as USMMessage;
|
|
|
|
RemoteEngineID = usmReply.SecurityParameters.msgAuthoritativeEngineID;
|
|
}
|
|
|
|
public bool AuthenticateMessage(USMMessage message)
|
|
{
|
|
message.msgGlobalData.msgFlags.Bytes = new byte[] { (byte)(int)AuthLevel };
|
|
message.SecurityParameters.msgUserName.StringValue = Username;
|
|
message.SecurityParameters.msgAuthoritativeEngineID = RemoteEngineID;
|
|
message.SecurityParameters.msgAuthenticationParameters.Bytes = new byte[12];
|
|
|
|
byte[] wholeMsg = ((ASN1Value)message).AsByteArray;
|
|
|
|
byte[] extendedAuthKey = new byte[64];
|
|
byte[] authKey = Encoding.ASCII.GetBytes(AuthKey);
|
|
|
|
//Array.Copy(authKey, extendedAuthKey, 16);
|
|
|
|
//byte[] K1 = new byte[64];
|
|
//for (int n = 0; n < 64; n++)
|
|
// K1[n] = (byte)(extendedAuthKey[n] ^ IPAD[n]);
|
|
|
|
//byte[] K2 = new byte[64];
|
|
//for (int n = 0; n < 64; n++)
|
|
//K2[n] = (byte)(extendedAuthKey[n] ^ OPAD[n]);
|
|
|
|
HMAC hmac = null;
|
|
|
|
switch (AuthMethod)
|
|
{
|
|
case SnmpV3AuthMethod.MD5:
|
|
hmac = HMACMD5.Create();
|
|
break;
|
|
case SnmpV3AuthMethod.SHA:
|
|
hmac = HMACSHA1.Create();
|
|
break;
|
|
}
|
|
|
|
hmac.Key = authKey;
|
|
byte[] mac = hmac.ComputeHash(wholeMsg);
|
|
|
|
message.SecurityParameters.msgAuthenticationParameters.Bytes = mac.Take(12).ToArray();
|
|
|
|
return true;
|
|
}
|
|
|
|
static byte[] IPAD = __PAD(0x36);
|
|
static byte[] OPAD = __PAD(0x5C);
|
|
|
|
public static byte[] __PAD(byte pad)
|
|
{
|
|
byte[] ipad = new byte[0x40];
|
|
for (int n = 0; n < ipad.Length; n++)
|
|
ipad[n] = pad;
|
|
return ipad;
|
|
}
|
|
|
|
}
|
|
}
|