master
Harald Wolff 2019-03-12 00:54:39 +01:00
parent 3a084820f5
commit 59133a9c8f
18 changed files with 379 additions and 131 deletions

View File

@ -26,13 +26,18 @@ namespace ln.snmp
public bool Constructed; public bool Constructed;
public ulong Number; public ulong Number;
public Identifier(IdentifierClass identifierClass,bool constructed,ulong number) public Identifier(IdentifierClass identifierClass, bool constructed, ulong number)
{ {
IdentifierClass = identifierClass; IdentifierClass = identifierClass;
Constructed = constructed; Constructed = constructed;
Number = number; Number = number;
} }
public bool Is(IdentifierClass identifierClass, bool constructed, ulong number)
{
return ((IdentifierClass == identifierClass) && (Constructed == constructed) && (Number == number));
}
public byte Firstbyte public byte Firstbyte
{ {
get get
@ -49,6 +54,9 @@ namespace ln.snmp
{ {
return String.Format("[ASN.1 Type Class={0} Constructed={1} Number={2} FirstByte=0x{3,2:X}]",IdentifierClass,Constructed,Number,Firstbyte); return String.Format("[ASN.1 Type Class={0} Constructed={1} Number={2} FirstByte=0x{3,2:X}]",IdentifierClass,Constructed,Number,Firstbyte);
} }
} }
public static class BasicEncodingRules public static class BasicEncodingRules
@ -131,10 +139,16 @@ namespace ln.snmp
} }
else else
{ {
byte[] bytes = EncodeInteger(length); byte[] bytes = BitConverter.GetBytes(length);
byte bl = (byte)(0x80 | bytes.Length); int n;
for (n = 3; n > 0 && bytes[n] == 0; n--) { }
n++;
byte[] finalbytes = new byte[n];
Array.Copy(bytes, finalbytes, n);
byte bl = (byte)(0x80 | finalbytes.Length);
stream.WriteByte(bl); stream.WriteByte(bl);
stream.Write(bytes, 0, bytes.Length); stream.Write(finalbytes, 0, finalbytes.Length);
} }
} }

View File

@ -67,35 +67,22 @@ namespace ln.snmp
Logging.Log(LogLevel.DEBUG,"SNMPClient: Received: {0}", BitConverter.ToString(datagram)); Logging.Log(LogLevel.DEBUG,"SNMPClient: Received: {0}", BitConverter.ToString(datagram));
ASN1Value asn = new ASN1Value(datagram); ASN1Value asn = new ASN1Value(datagram);
asn.Dump();
SnmpMessage snmpMessage = asn; SnmpMessage snmpMessage = asn;
snmpMessage.Dump(); if (currentEndpoints.ContainsKey(remoteEndpoint))
lock (queuedRequests)
{ {
if (queuedRequests.ContainsKey(snmpMessage.MessageID)) SnmpEndpoint snmpEndpoint = currentEndpoints[remoteEndpoint];
{ snmpEndpoint.Received(snmpMessage);
SnmpMessage snmpRequestMessage = queuedRequests[snmpMessage.MessageID]; }
lock (snmpRequestMessage) else
{ {
queuedRequests[snmpMessage.MessageID] = snmpMessage; Logging.Log(LogLevel.WARNING, "SnmpEngine.Receiver(): Received message from unknown endpoint ({0})",remoteEndpoint);
Monitor.PulseAll(snmpRequestMessage);
}
}
else
{
Logging.Log(LogLevel.WARNING, "SnmpEngine.Receiver(): Can't find pending request with MessageID {0} ( 0x{0:x8} )",snmpMessage.MessageID);
}
} }
} }
catch (SocketException se) catch (SocketException se)
{ {
Logging.Log(se); //Logging.Log(se);
} }
catch (Exception e) catch (Exception e)
{ {
@ -115,40 +102,40 @@ namespace ln.snmp
} }
} }
public SnmpMessage SNMPRequest(IPEndPoint remoteEndpoint,SnmpMessage snmpMessage,int timeout) //public SnmpMessage SNMPRequest(IPEndPoint remoteEndpoint,SnmpMessage snmpMessage,int timeout)
{ //{
lock (queuedRequests) // lock (queuedRequests)
{ // {
ASN1Value snmpRequest = snmpMessage; // ASN1Value snmpRequest = snmpMessage;
byte[] snmpRequestBytes = snmpRequest.AsByteArray; // byte[] snmpRequestBytes = snmpRequest.AsByteArray;
queuedRequests.Add(snmpMessage.MessageID, snmpMessage); // queuedRequests.Add(snmpMessage.MessageID, snmpMessage);
Logging.Log(LogLevel.DEBUG,"SNMPClient: Send: {0}", BitConverter.ToString(snmpRequestBytes)); // Logging.Log(LogLevel.DEBUG,"SNMPClient: Send: {0}", BitConverter.ToString(snmpRequestBytes));
Logging.Log(LogLevel.DEBUG,"sent snmpMessage with MessageID {0} ( 0x{0:x8} )",snmpMessage.MessageID); // Logging.Log(LogLevel.DEBUG,"sent snmpMessage with MessageID {0} ( 0x{0:x8} )",snmpMessage.MessageID);
snmpMessage.Dump(); // snmpMessage.Dump();
LocalEndpoint.Send(snmpRequestBytes, snmpRequestBytes.Length, remoteEndpoint); // LocalEndpoint.Send(snmpRequestBytes, snmpRequestBytes.Length, remoteEndpoint);
lock (snmpMessage) // lock (snmpMessage)
{ // {
Monitor.Exit(queuedRequests); // Monitor.Exit(queuedRequests);
bool success = Monitor.Wait(snmpMessage, timeout); // bool success = Monitor.Wait(snmpMessage, timeout);
Monitor.Enter(queuedRequests); // Monitor.Enter(queuedRequests);
if (!success) // if (!success)
{ // {
queuedRequests.Remove(snmpMessage.MessageID); // queuedRequests.Remove(snmpMessage.MessageID);
throw new TimeoutException(); // throw new TimeoutException();
} // }
} // }
SnmpMessage responseMessage = queuedRequests[snmpMessage.MessageID]; // SnmpMessage responseMessage = queuedRequests[snmpMessage.MessageID];
queuedRequests.Remove(snmpMessage.MessageID); // queuedRequests.Remove(snmpMessage.MessageID);
return responseMessage; // return responseMessage;
} // }
} //}
public void RegisterEndpoint(SnmpEndpoint intf) public void RegisterEndpoint(SnmpEndpoint intf)
{ {

View File

@ -18,7 +18,7 @@ namespace ln.snmp
{ {
} }
public abstract PDU snmpRequest(PDU pdu); public abstract PDU DispatchRequest(PDU pdu);
private List<Sequence> snmpRequest<T>(IEnumerable<ObjectIdentifier> objectIdentifiers) where T: PDU, new() private List<Sequence> snmpRequest<T>(IEnumerable<ObjectIdentifier> objectIdentifiers) where T: PDU, new()
{ {
@ -28,7 +28,7 @@ namespace ln.snmp
pdu.Add(new Sequence(new Variable[] { oid, NullValue.Instance })); pdu.Add(new Sequence(new Variable[] { oid, NullValue.Instance }));
} }
PDU responsePDU = snmpRequest(pdu); PDU responsePDU = DispatchRequest(pdu);
if (responsePDU.Error.LongValue != 0) if (responsePDU.Error.LongValue != 0)
{ {
@ -84,7 +84,7 @@ namespace ln.snmp
{ {
try try
{ {
return snmpRequest(bulkRequest); return DispatchRequest(bulkRequest);
} catch (SnmpError se) } catch (SnmpError se)
{ {
if ((se.Error == 1)&&(bulkRequest.MaxRepetitions.LongValue > 1)) if ((se.Error == 1)&&(bulkRequest.MaxRepetitions.LongValue > 1))
@ -122,17 +122,19 @@ namespace ln.snmp
Variable[] values = responsePDU.VarBinds.Items; Variable[] values = responsePDU.VarBinds.Items;
nchunk = values.Length / ncolumns; nchunk = values.Length / ncolumns;
inTree = false;
for (int n = 0; n < nchunk; n++) for (int n = 0; n < nchunk; n++)
{ {
inTree = false;
Sequence[] row = new Sequence[ncolumns]; Sequence[] row = new Sequence[ncolumns];
for (int c = 0; c < ncolumns; c++) for (int c = 0; c < ncolumns; c++)
{ {
Sequence v = values[(n * ncolumns) + c] as Sequence; Sequence v = values[(n * ncolumns) + c] as Sequence;
if (OIDs[c].Contains(v.Items[0] as ObjectIdentifier)) ObjectIdentifier oid = v.Items[0] as ObjectIdentifier;
if (OIDs[c].Contains(oid))
{ {
row[c] = v; row[c] = new Sequence(new Variable[] { oid.IndexTo(OIDs[c]), v.Items[1] });
inTree = true; inTree = true;
} }
} }
@ -171,7 +173,9 @@ namespace ln.snmp
{ {
ObjectIdentifier oid = ps.Items[0] as ObjectIdentifier; ObjectIdentifier oid = ps.Items[0] as ObjectIdentifier;
if (objectIdentifier.Contains(oid)) if (objectIdentifier.Contains(oid))
results.Add(ps); {
results.Add(new Sequence(new Variable[] { oid.IndexTo(objectIdentifier), ps.Items[1] }));
}
else else
return results; return results;
} }
@ -259,9 +263,9 @@ namespace ln.snmp
return snmpWalk(new ObjectIdentifier(objectIdentifier)); return snmpWalk(new ObjectIdentifier(objectIdentifier));
} }
public virtual void Dispose() public virtual void Dispose()
{ {
SNMPEngine.UnregisterEndpoint(this);
} }
} }
} }

BIN
authtest 100644

Binary file not shown.

1
authtest.hex 100644
View File

@ -0,0 +1 @@
30818f0201033011020428e35a0c020300ffe3040105020103043b3039041680003a8c0434433a35453a30433a31343a32343a393502010e0203136f860407736b7974726f6e040cc12bbc3135344c067e3eb8890400303a041680003a8c0434433a35453a30433a31343a32343a39350400a11e020469bb65e80201000201003010300e060a2b0601020102020104040500

BIN
authtest1 100644

Binary file not shown.

View File

@ -15,27 +15,31 @@ namespace ln.snmp.endpoint
public SNMPEngine SNMPEngine { get; } public SNMPEngine SNMPEngine { get; }
public IPEndPoint RemoteEndpoint { get; set; } public IPEndPoint RemoteEndpoint { get; set; }
public int Retries { get; set; } = 3;
public SnmpEndpoint(SNMPEngine snmpEngine, IPEndPoint remoteEndpoint) public SnmpEndpoint(SNMPEngine snmpEngine, IPEndPoint remoteEndpoint)
{ {
SNMPEngine = snmpEngine; SNMPEngine = snmpEngine;
RemoteEndpoint = remoteEndpoint; RemoteEndpoint = remoteEndpoint;
SNMPEngine.RegisterEndpoint(this); SNMPEngine.RegisterEndpoint(this);
} }
public virtual void Send(SnmpMessage message) public virtual void Send(SnmpMessage message)
{ {
//message.MessageID = SNMPEngine.NextMessageID;
//if (requestMessage.snmpPDU != null)
//{
// requestMessage.snmpPDU.RequestID.LongValue = SNMPEngine.NextMessageID;
//}
message = Encrypt(message); message = Encrypt(message);
message = ApplyAuthentication(message); message = ApplyAuthentication(message);
SNMPEngine.SendMessage(RemoteEndpoint, message); SNMPEngine.SendMessage(RemoteEndpoint, message);
} }
public virtual void Received(SnmpMessage message) public virtual void DispatchReceived(SnmpMessage message)
{ {
message = CheckAuthentication(message);
message = Decrypt(message);
lock (queuedRequests) lock (queuedRequests)
{ {
if (queuedRequests.ContainsKey(message.MessageID)) if (queuedRequests.ContainsKey(message.MessageID))
@ -54,21 +58,27 @@ namespace ln.snmp.endpoint
} }
} }
public abstract SnmpMessage Encrypt(SnmpMessage message); public virtual void Received(SnmpMessage message)
public abstract SnmpMessage ApplyAuthentication(SnmpMessage message); {
message = CheckAuthentication(message);
message = Decrypt(message);
public abstract SnmpMessage CheckAuthentication(SnmpMessage message); DispatchReceived(message);
public abstract SnmpMessage Decrypt(SnmpMessage message); }
public virtual SnmpMessage Encrypt(SnmpMessage message) => message;
public virtual SnmpMessage ApplyAuthentication(SnmpMessage message) => message;
public virtual SnmpMessage CheckAuthentication(SnmpMessage message) => message;
public virtual SnmpMessage Decrypt(SnmpMessage message) => message;
/** /**
* Requests * Requests
**/ **/
private Dictionary<int, SnmpMessage> queuedRequests = new Dictionary<int, SnmpMessage>(); private Dictionary<int, SnmpMessage> queuedRequests = new Dictionary<int, SnmpMessage>();
public SnmpMessage EnqueueRequest(SnmpMessage requestMessage) public SnmpMessage EnqueueRequest(SnmpMessage requestMessage)
{ {
requestMessage.MessageID = SNMPEngine.NextMessageID;
lock (queuedRequests) lock (queuedRequests)
{ {
queuedRequests.Add(requestMessage.MessageID, requestMessage); queuedRequests.Add(requestMessage.MessageID, requestMessage);

View File

@ -27,14 +27,13 @@ namespace ln.snmp.endpoint
CommunityString = new OctetString(communityString); CommunityString = new OctetString(communityString);
} }
public override PDU snmpRequest(PDU pdu) public override PDU DispatchRequest(PDU pdu)
{ {
SnmpV1Message request = new SnmpV1Message(); SnmpV1Message request = new SnmpV1Message();
request.MessageID = SNMPEngine.NextMessageID;
request.snmpCommunity = CommunityString; request.snmpCommunity = CommunityString;
request.snmpPDU = pdu; request.snmpPDU = pdu;
SnmpV1Message response = SNMPEngine.SNMPRequest(RemoteEndpoint, request, SNMPEngine.Timeout) as SnmpV1Message; SnmpV1Message response = EnqueueRequest(request) as SnmpV1Message;
return response.snmpPDU; return response.snmpPDU;
} }

View File

@ -5,10 +5,8 @@ using System.Collections.Generic;
namespace ln.snmp.endpoint namespace ln.snmp.endpoint
{ {
public class SnmpV2Endpoint : SnmpEndpoint public class SnmpV2Endpoint : SnmpV1Endpoint
{ {
public OctetString CommunityString { get; set; }
public override SnmpVersion SnmpVersion => SnmpVersion.V2c; public override SnmpVersion SnmpVersion => SnmpVersion.V2c;
public SnmpV2Endpoint(SNMPEngine snmpEngine, IPEndPoint remoteEndpoint) public SnmpV2Endpoint(SNMPEngine snmpEngine, IPEndPoint remoteEndpoint)
@ -17,24 +15,19 @@ namespace ln.snmp.endpoint
CommunityString = "public"; CommunityString = "public";
} }
public SnmpV2Endpoint(SNMPEngine snmpEngine, IPEndPoint remoteEndpoint, OctetString communityString) public SnmpV2Endpoint(SNMPEngine snmpEngine, IPEndPoint remoteEndpoint, OctetString communityString)
: base(snmpEngine, remoteEndpoint) : base(snmpEngine, remoteEndpoint, communityString)
{ { }
CommunityString = communityString;
}
public SnmpV2Endpoint(SNMPEngine snmpEngine, IPEndPoint remoteEndpoint, String communityString) public SnmpV2Endpoint(SNMPEngine snmpEngine, IPEndPoint remoteEndpoint, String communityString)
: base(snmpEngine, remoteEndpoint) : base(snmpEngine, remoteEndpoint, communityString)
{ { }
CommunityString = new OctetString(communityString);
}
public override PDU snmpRequest(PDU pdu) public override PDU DispatchRequest(PDU pdu)
{ {
SnmpV2Message request = new SnmpV2Message(); SnmpV2Message request = new SnmpV2Message();
request.MessageID = SNMPEngine.NextMessageID;
request.snmpCommunity = CommunityString; request.snmpCommunity = CommunityString;
request.snmpPDU = pdu; request.snmpPDU = pdu;
SnmpV2Message response = SNMPEngine.SNMPRequest(RemoteEndpoint, request, SNMPEngine.Timeout) as SnmpV2Message; SnmpV2Message response = EnqueueRequest(request) as SnmpV2Message;
return response.snmpPDU; return response.snmpPDU;
} }

View File

@ -6,6 +6,8 @@ using System.Security.Cryptography;
using ln.snmp.asn1; using ln.snmp.asn1;
using System.Linq; using System.Linq;
using ln.logging; using ln.logging;
using System.Threading;
using System.IO;
namespace ln.snmp.endpoint namespace ln.snmp.endpoint
{ {
@ -31,12 +33,62 @@ namespace ln.snmp.endpoint
public SnmpV3PrivMethod PrivMethod { get; set; } public SnmpV3PrivMethod PrivMethod { get; set; }
public override SnmpVersion SnmpVersion => SnmpVersion.V3; public override SnmpVersion SnmpVersion => SnmpVersion.V3;
private object reportDispatchLock = new object();
public USMEndpoint(SNMPEngine snmpEngine,IPEndPoint remoteEndpoint) public USMEndpoint(SNMPEngine snmpEngine,IPEndPoint remoteEndpoint)
:base(snmpEngine,remoteEndpoint) :base(snmpEngine,remoteEndpoint)
{ {
CacheAuthoritativeEngineTime = new Integer();
CacheAuthoritativeEngineBoots = new Integer();
} }
public override void DispatchReceived(SnmpMessage message)
{
Logging.Log(LogLevel.DEBUG, "Received PDU: {0}",message.snmpPDU);
USMMessage usm = message as USMMessage;
if (usm.SecurityParameters.msgAuthoritativeEngineBoots.LongValue > 0)
CacheAuthoritativeEngineBoots.LongValue = usm.SecurityParameters.msgAuthoritativeEngineBoots.LongValue;
if (usm.SecurityParameters.msgAuthoritativeEngineTime.LongValue > 0)
CacheAuthoritativeEngineTime.LongValue = usm.SecurityParameters.msgAuthoritativeEngineTime.LongValue;
if (message.snmpPDU is Report)
{
DispatchReport(message);
}
else
{
base.DispatchReceived(message);
}
}
public void DispatchReport(SnmpMessage snmpMessage)
{
USMMessage usm = snmpMessage as USMMessage;
RemoteEngineID = usm.SecurityParameters.msgAuthoritativeEngineID;
lock (reportDispatchLock)
{
Monitor.PulseAll(reportDispatchLock);
}
}
public override SnmpMessage ApplyAuthentication(SnmpMessage message)
{
if (RemoteEngineID == null)
return message;
if (AuthenticateMessage(message as USMMessage))
return message;
throw new Exception("Authentication failed");
}
public SnmpAuthLevel AuthLevel public SnmpAuthLevel AuthLevel
{ {
get get
@ -50,40 +102,52 @@ namespace ln.snmp.endpoint
} }
} }
public override PDU snmpRequest(PDU pdu) public override PDU DispatchRequest(PDU pdu)
{ {
if ((RemoteEngineID == null)||(RemoteEngineID.Bytes.Length == 0)) if ((RemoteEngineID == null) || (RemoteEngineID.Bytes.Length == 0))
{ {
QueryEngineID(); QueryEngineID();
} }
USMMessage request = new USMMessage(); int retries = Retries;
ScopedPDU scopedPDU = new ScopedPDU(); while (retries-- > 0)
{
USMMessage request = new USMMessage();
ScopedPDU scopedPDU = new ScopedPDU();
request.MessageID = SNMPEngine.NextMessageID; request.MessageID = SNMPEngine.NextMessageID;
request.msgData = scopedPDU; request.msgData = scopedPDU;
scopedPDU.contextEngineID = RemoteEngineID; if (RemoteEngineID == null)
scopedPDU.PDU = pdu; {
scopedPDU.contextEngineID = new OctetString();
}
else
{
scopedPDU.contextEngineID = RemoteEngineID;
}
AuthenticateMessage(request); scopedPDU.PDU = pdu;
USMMessage replyUSM = InternalRequest(request); try
{
PDU responsePDU = (replyUSM.msgData as ScopedPDU).PDU; USMMessage replyUSM = DispatchRequest(request);
PDU responsePDU = (replyUSM.msgData as ScopedPDU).PDU;
return responsePDU; return responsePDU;
}
catch (TimeoutException)
{
}
}
throw new TimeoutException();
} }
private USMMessage InternalRequest(USMMessage request) private USMMessage DispatchRequest(USMMessage request)
{ {
SnmpMessage reply = SNMPEngine.SNMPRequest(RemoteEndpoint, request, SNMPEngine.Timeout); SnmpMessage reply = EnqueueRequest(request);
USMMessage usmReply = reply as USMMessage; USMMessage usmReply = reply as USMMessage;
CacheAuthoritativeEngineBoots = usmReply.SecurityParameters.msgAuthoritativeEngineBoots;
CacheAuthoritativeEngineTime = usmReply.SecurityParameters.msgAuthoritativeEngineTime;
return usmReply; return usmReply;
} }
@ -96,25 +160,24 @@ namespace ln.snmp.endpoint
queryMessage.msgData = scopedPDU; queryMessage.msgData = scopedPDU;
queryMessage.Dump(); lock (reportDispatchLock)
{
USMMessage usmReply = InternalRequest(queryMessage); Send(queryMessage);
if (!Monitor.Wait(reportDispatchLock, SNMPEngine.Timeout))
RemoteEngineID = usmReply.SecurityParameters.msgAuthoritativeEngineID; throw new TimeoutException("could not query engine id");
//RemoteEngineID.Bytes = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 }; }
LocalizeKeys(); LocalizeKeys();
} }
public bool AuthenticateMessage(USMMessage message) public bool AuthenticateMessage(USMMessage message)
{ {
message.msgGlobalData.msgFlags.Bytes = new byte[] { (byte)(int)AuthLevel }; message.msgGlobalData.msgFlags.Bytes[0] |= 0x01;
message.SecurityParameters.msgUserName.StringValue = Username; message.SecurityParameters.msgUserName.StringValue = Username;
message.SecurityParameters.msgAuthoritativeEngineID = RemoteEngineID; message.SecurityParameters.msgAuthoritativeEngineID = RemoteEngineID == null ? new OctetString() : RemoteEngineID;
message.SecurityParameters.msgAuthenticationParameters.Bytes = new byte[12]; message.SecurityParameters.msgAuthenticationParameters.Bytes = new byte[12];
message.SecurityParameters.msgAuthoritativeEngineBoots = CacheAuthoritativeEngineBoots != null ? CacheAuthoritativeEngineBoots : new Integer(); message.SecurityParameters.msgAuthoritativeEngineBoots = CacheAuthoritativeEngineBoots != null ? CacheAuthoritativeEngineBoots : new Integer();
message.SecurityParameters.msgAuthoritativeEngineTime = CacheAuthoritativeEngineTime != null ? CacheAuthoritativeEngineTime : new Integer(); message.SecurityParameters.msgAuthoritativeEngineTime = CacheAuthoritativeEngineTime != null ? CacheAuthoritativeEngineTime : new Integer();
byte[] wholeMsg = ((ASN1Value)message).AsByteArray; byte[] wholeMsg = ((ASN1Value)message).AsByteArray;
@ -146,9 +209,23 @@ namespace ln.snmp.endpoint
byte[] mac = hash.ComputeHash(inter2); byte[] mac = hash.ComputeHash(inter2);
Logging.Log(LogLevel.DEBUG, "Authentication of {0}", BitConverter.ToString(wholeMsg));
Logging.Log(LogLevel.DEBUG, "AuthKey: {0}", BitConverter.ToString(AuthKey));
Logging.Log(LogLevel.DEBUG, "LocalAuthKey: {0}", BitConverter.ToString(LocalAuthKey));
Logging.Log(LogLevel.DEBUG, "Extended AuthKey: {0}", BitConverter.ToString(extendedAuthKey));
Logging.Log(LogLevel.DEBUG, "");
Logging.Log(LogLevel.DEBUG, "K1: {0}", BitConverter.ToString(K1));
Logging.Log(LogLevel.DEBUG, "K2: {0}", BitConverter.ToString(K2));
Logging.Log(LogLevel.DEBUG, "");
Logging.Log(LogLevel.DEBUG, "AuthToken: {0}", BitConverter.ToString(mac.Take(12).ToArray()));
message.SecurityParameters.msgAuthenticationParameters.Bytes = mac.Take(12).ToArray(); message.SecurityParameters.msgAuthenticationParameters.Bytes = mac.Take(12).ToArray();
} }
Logging.Log(LogLevel.DEBUG, "Authenticating Message: {0}",BitConverter.ToString(wholeMsg));
Logging.Log(LogLevel.DEBUG, "Authenticated Message: {0}", BitConverter.ToString(((ASN1Value)message).AsByteArray));
return true; return true;
} }
@ -180,7 +257,7 @@ namespace ln.snmp.endpoint
return AuthMethod == SnmpV3AuthMethod.SHA ? (HashAlgorithm)SHA1.Create() : (HashAlgorithm)MD5.Create(); return AuthMethod == SnmpV3AuthMethod.SHA ? (HashAlgorithm)SHA1.Create() : (HashAlgorithm)MD5.Create();
} }
private void LocalizeKeys() public void LocalizeKeys()
{ {
if ((AuthKey != null) && (RemoteEngineID != null)) if ((AuthKey != null) && (RemoteEngineID != null))
{ {

View File

@ -58,11 +58,14 @@
<Compile Include="types\UsmSecurityParameters.cs" /> <Compile Include="types\UsmSecurityParameters.cs" />
<Compile Include="endpoint\SNMPEndpoint.cs" /> <Compile Include="endpoint\SNMPEndpoint.cs" />
<Compile Include="SNMPInterface.cs" /> <Compile Include="SNMPInterface.cs" />
<Compile Include="rfc1213\RFC1213.cs" />
<Compile Include="types\IPAddr.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Folder Include="types\" /> <Folder Include="types\" />
<Folder Include="endpoint\" /> <Folder Include="endpoint\" />
<Folder Include="asn1\" /> <Folder Include="asn1\" />
<Folder Include="rfc1213\" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\ln.logging\ln.logging.csproj"> <ProjectReference Include="..\ln.logging\ln.logging.csproj">

91
rfc1213/RFC1213.cs 100644
View File

@ -0,0 +1,91 @@
// /**
// * File: RFC1213.cs
// * Author: haraldwolff
// *
// * This file and it's content is copyrighted by the Author and / or copyright holder.
// * Any use wihtout proper permission is illegal and may lead to legal actions.
// *
// *
// **/
using System;
using System.Net;
using System.Collections.Generic;
using ln.snmp.endpoint;
using ln.snmp.types;
using System.Linq;
namespace ln.snmp.rfc1213
{
public static class RFC1213
{
public static Interface[] GetInterfaces(SnmpEndpoint endpoint)
{
Dictionary<int,Interface> interfaces = new Dictionary<int,Interface>();
Sequence[][] ifTable = endpoint.snmpWalk(new String[] {
"1.3.6.1.2.1.2.2.1.2",
"1.3.6.1.2.1.2.2.1.10",
"1.3.6.1.2.1.2.2.1.16",
"1.3.6.1.2.1.2.2.1.14",
"1.3.6.1.2.1.2.2.1.20"
});
foreach (Sequence[] row in ifTable)
{
ObjectIdentifier index = (row[0].Items[0] as ObjectIdentifier);
Interface intf = new Interface();
intf.Name = (row[0].Items[1] as OctetString).StringValue;
interfaces.Add(index.OIDValue[0],intf);
}
Sequence[][] ipTable = endpoint.snmpWalk(new String[]
{
"1.3.6.1.2.1.4.20.1.1",
"1.3.6.1.2.1.4.20.1.2"
});
foreach (Sequence[] row in ipTable)
{
IPAddress ip = (row[0].Items[1] as IPAddr).IP;
int ifIndex = (int)(row[1].Items[1] as Integer).LongValue;
if (interfaces.ContainsKey(ifIndex))
{
interfaces[ifIndex].AddIPAddress(ip);
}
}
return interfaces.Values.ToArray();
}
public class Interface
{
public String Name { get; set; }
public System.Net.IPAddress[] IPAddresses => _IPAddresses.ToArray();
private List<System.Net.IPAddress> _IPAddresses = new List<System.Net.IPAddress>();
public Interface()
{
}
public void AddIPAddress(System.Net.IPAddress ip)
{
_IPAddresses.Add(ip);
}
public override string ToString()
{
return String.Format("[Interface Name={0} IPAddresses=({1})]",Name,String.Join(", ",IPAddresses.Select((x)=>x.ToString())));
}
}
}
}

34
types/IPAddr.cs 100644
View File

@ -0,0 +1,34 @@
// /**
// * File: IPAddress.cs
// * Author: haraldwolff
// *
// * This file and it's content is copyrighted by the Author and / or copyright holder.
// * Any use wihtout proper permission is illegal and may lead to legal actions.
// *
// *
// **/
using System;
using System.Net;
namespace ln.snmp.types
{
public class IPAddr : Variable
{
public System.Net.IPAddress IP { get; set; }
public IPAddr()
:base(new Identifier(IdentifierClass.APPLICATION,false,0x00))
{
IP = new IPAddress(0);
}
public override byte[] Bytes {
get => IP.GetAddressBytes();
set => IP = new System.Net.IPAddress(value);
}
public override object Value {
get => throw new NotImplementedException();
set => throw new NotImplementedException();
}
}
}

View File

@ -52,6 +52,19 @@ namespace ln.snmp.types
return true; return true;
} }
public ObjectIdentifier IndexTo(ObjectIdentifier b)
{
if (!b.Contains(this))
throw new FormatException("OID is not below base OID");
int[] me = OIDValue;
int[] you = b.OIDValue;
int[] result = new int[me.Length - you.Length];
Array.Copy(me, you.Length, result, 0, result.Length);
return new ObjectIdentifier(result);
}
public override byte[] Bytes public override byte[] Bytes
{ {

View File

@ -20,26 +20,21 @@ namespace ln.snmp.types
public Sequence VarBinds { get; private set; } public Sequence VarBinds { get; private set; }
private Variable[] items;
public PDU(Identifier identifier) public PDU(Identifier identifier)
: base(identifier) : base(identifier)
{ {
//RequestID = new Integer(Environment.TickCount); //RequestID = new Integer(Environment.TickCount);
RequestID = new Integer(0xDEADBEEF); RequestID = new Integer((int)(DateTimeOffset.Now.ToUnixTimeMilliseconds()) & 0x7FFFFFFF);
Error = new Integer(); Error = new Integer();
ErrorIndex = new Integer(); ErrorIndex = new Integer();
VarBinds = new Sequence(); VarBinds = new Sequence();
items = new Variable[] { RequestID, Error, ErrorIndex, VarBinds };
} }
public PDU(ASN1Value value) public PDU(ASN1Value value)
: base(value.Identifier) : base(value.Identifier)
{ {
RequestID = (Integer)value.Items[0]; RequestID = (Integer)value.Items[0];
Error = (Integer)value.Items[1]; Error = (Integer)value.Items[1];
Error = (Integer)value.Items[2]; Error = (Integer)value.Items[2];
VarBinds = (Sequence)value.Items[3]; VarBinds = (Sequence)value.Items[3];
@ -47,7 +42,7 @@ namespace ln.snmp.types
public override Variable[] Items public override Variable[] Items
{ {
get => items; get => new Variable[] { RequestID, Error, ErrorIndex, VarBinds };
set set
{ {
RequestID = value[0] as Integer; RequestID = value[0] as Integer;

View File

@ -9,6 +9,8 @@
// **/ // **/
using System; using System;
using System.Runtime.Remoting.Messaging; using System.Runtime.Remoting.Messaging;
using ln.snmp.asn1;
using System.Linq;
namespace ln.snmp.types namespace ln.snmp.types
{ {
public class ScopedPDU : AbstractSequence public class ScopedPDU : AbstractSequence
@ -26,6 +28,12 @@ namespace ln.snmp.types
PDU = new GetRequest(); PDU = new GetRequest();
} }
public ScopedPDU(ASN1Value asn)
:this()
{
Items = asn.Items.Select((x) => (Variable)x).ToArray();
}
public override Variable[] Items public override Variable[] Items
{ {
get => new Variable[] { contextEngineID, contextName, PDU }; get => new Variable[] { contextEngineID, contextName, PDU };

View File

@ -60,8 +60,14 @@ namespace ln.snmp.types
msgGlobalData = new MsgGlobalData(value[1]); msgGlobalData = new MsgGlobalData(value[1]);
SecurityParameters = new UsmSecurityParameters(new ASN1Value(value[2].Bytes)); SecurityParameters = new UsmSecurityParameters(new ASN1Value(value[2].Bytes));
// ToDo: Check if value[3] is OctetString (Encrypted) or Sequence (ScopedPDU) if (value[3].Identifier.Is(IdentifierClass.UNIVERSAL,false,0x04))
msgData = value[3]; {
EncryptedPDU = value[3] as OctetString;
msgData = EncryptedPDU;
} else {
ScopedPDU = new ScopedPDU(value[3]);
msgData = ScopedPDU;
}
} }
} }
@ -92,13 +98,13 @@ namespace ln.snmp.types
{ {
msgID = new Integer((int)(DateTimeOffset.Now.ToUnixTimeSeconds())); msgID = new Integer((int)(DateTimeOffset.Now.ToUnixTimeSeconds()));
msgMaxSize = new Integer(65000); msgMaxSize = new Integer(65000);
msgFlags = new OctetString("\0"); msgFlags = new OctetString(new byte[] { 0x04 });
msgSecurityModel = new Integer(3); msgSecurityModel = new Integer(3);
} }
public MsgGlobalData(ASN1Value asn) public MsgGlobalData(ASN1Value asn)
:this() :this()
{ {
Items = asn.Items.ToVariableArray();
} }
public override void Add(Variable item) => throw new NotImplementedException(); public override void Add(Variable item) => throw new NotImplementedException();

View File

@ -125,6 +125,8 @@ namespace ln.snmp.types
registerKnownType<Sequence>(); registerKnownType<Sequence>();
registerKnownType<ObjectIdentifier>(); registerKnownType<ObjectIdentifier>();
registerKnownType<IPAddr>();
registerKnownType<GetRequest>(); registerKnownType<GetRequest>();
registerKnownType<GetNextRequest>(); registerKnownType<GetNextRequest>();
registerKnownType<GetResponse>(); registerKnownType<GetResponse>();
@ -135,4 +137,15 @@ namespace ln.snmp.types
} }
} }
public static class VariableExtensions
{
public static Variable[] ToVariableArray(this ASN1Value[] me)
{
return me.Select((x) => (Variable)x).ToArray();
}
}
} }