From 59133a9c8f112f50fa1fcedea5e3d5feef1c952f Mon Sep 17 00:00:00 2001 From: Harald Wolff Date: Tue, 12 Mar 2019 00:54:39 +0100 Subject: [PATCH] USM Beta --- BasicEncodingRules.cs | 22 ++++-- SNMPEngine.cs | 83 ++++++++++------------ SNMPInterface.cs | 20 +++--- authtest | Bin 0 -> 146 bytes authtest.hex | 1 + authtest1 | Bin 0 -> 146 bytes endpoint/SNMPEndpoint.cs | 36 ++++++---- endpoint/SnmpV1Endpoint.cs | 5 +- endpoint/SnmpV2Endpoint.cs | 21 ++---- endpoint/USMEndpoint.cs | 137 +++++++++++++++++++++++++++++-------- ln.snmp.csproj | 3 + rfc1213/RFC1213.cs | 91 ++++++++++++++++++++++++ types/IPAddr.cs | 34 +++++++++ types/ObjectIdentifier.cs | 13 ++++ types/PDU.cs | 9 +-- types/ScopedPDU.cs | 8 +++ types/USMMessage.cs | 14 ++-- types/Variable.cs | 13 ++++ 18 files changed, 379 insertions(+), 131 deletions(-) create mode 100644 authtest create mode 100644 authtest.hex create mode 100644 authtest1 create mode 100644 rfc1213/RFC1213.cs create mode 100644 types/IPAddr.cs diff --git a/BasicEncodingRules.cs b/BasicEncodingRules.cs index 5235d15..842689c 100644 --- a/BasicEncodingRules.cs +++ b/BasicEncodingRules.cs @@ -26,13 +26,18 @@ namespace ln.snmp public bool Constructed; public ulong Number; - public Identifier(IdentifierClass identifierClass,bool constructed,ulong number) + public Identifier(IdentifierClass identifierClass, bool constructed, ulong number) { IdentifierClass = identifierClass; Constructed = constructed; Number = number; } + public bool Is(IdentifierClass identifierClass, bool constructed, ulong number) + { + return ((IdentifierClass == identifierClass) && (Constructed == constructed) && (Number == number)); + } + public byte Firstbyte { 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); } + + + } public static class BasicEncodingRules @@ -131,10 +139,16 @@ namespace ln.snmp } else { - byte[] bytes = EncodeInteger(length); - byte bl = (byte)(0x80 | bytes.Length); + byte[] bytes = BitConverter.GetBytes(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.Write(bytes, 0, bytes.Length); + stream.Write(finalbytes, 0, finalbytes.Length); } } diff --git a/SNMPEngine.cs b/SNMPEngine.cs index 4a1b5c6..d481ea7 100644 --- a/SNMPEngine.cs +++ b/SNMPEngine.cs @@ -67,35 +67,22 @@ namespace ln.snmp Logging.Log(LogLevel.DEBUG,"SNMPClient: Received: {0}", BitConverter.ToString(datagram)); ASN1Value asn = new ASN1Value(datagram); - - asn.Dump(); - SnmpMessage snmpMessage = asn; - snmpMessage.Dump(); - - lock (queuedRequests) + if (currentEndpoints.ContainsKey(remoteEndpoint)) { - if (queuedRequests.ContainsKey(snmpMessage.MessageID)) - { - SnmpMessage snmpRequestMessage = queuedRequests[snmpMessage.MessageID]; - lock (snmpRequestMessage) - { - queuedRequests[snmpMessage.MessageID] = snmpMessage; - Monitor.PulseAll(snmpRequestMessage); - } - } - else - { - Logging.Log(LogLevel.WARNING, "SnmpEngine.Receiver(): Can't find pending request with MessageID {0} ( 0x{0:x8} )",snmpMessage.MessageID); - } + SnmpEndpoint snmpEndpoint = currentEndpoints[remoteEndpoint]; + snmpEndpoint.Received(snmpMessage); + } + else + { + Logging.Log(LogLevel.WARNING, "SnmpEngine.Receiver(): Received message from unknown endpoint ({0})",remoteEndpoint); } - } catch (SocketException se) { - Logging.Log(se); + //Logging.Log(se); } catch (Exception e) { @@ -115,40 +102,40 @@ namespace ln.snmp } } - public SnmpMessage SNMPRequest(IPEndPoint remoteEndpoint,SnmpMessage snmpMessage,int timeout) - { - lock (queuedRequests) - { - ASN1Value snmpRequest = snmpMessage; - byte[] snmpRequestBytes = snmpRequest.AsByteArray; + //public SnmpMessage SNMPRequest(IPEndPoint remoteEndpoint,SnmpMessage snmpMessage,int timeout) + //{ + // lock (queuedRequests) + // { + // ASN1Value snmpRequest = snmpMessage; + // 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,"sent snmpMessage with MessageID {0} ( 0x{0:x8} )",snmpMessage.MessageID); - snmpMessage.Dump(); + // Logging.Log(LogLevel.DEBUG,"SNMPClient: Send: {0}", BitConverter.ToString(snmpRequestBytes)); + // Logging.Log(LogLevel.DEBUG,"sent snmpMessage with MessageID {0} ( 0x{0:x8} )",snmpMessage.MessageID); + // snmpMessage.Dump(); - LocalEndpoint.Send(snmpRequestBytes, snmpRequestBytes.Length, remoteEndpoint); + // LocalEndpoint.Send(snmpRequestBytes, snmpRequestBytes.Length, remoteEndpoint); - lock (snmpMessage) - { - Monitor.Exit(queuedRequests); - bool success = Monitor.Wait(snmpMessage, timeout); - Monitor.Enter(queuedRequests); + // lock (snmpMessage) + // { + // Monitor.Exit(queuedRequests); + // bool success = Monitor.Wait(snmpMessage, timeout); + // Monitor.Enter(queuedRequests); - if (!success) - { - queuedRequests.Remove(snmpMessage.MessageID); - throw new TimeoutException(); - } - } + // if (!success) + // { + // queuedRequests.Remove(snmpMessage.MessageID); + // throw new TimeoutException(); + // } + // } - SnmpMessage responseMessage = queuedRequests[snmpMessage.MessageID]; - queuedRequests.Remove(snmpMessage.MessageID); + // SnmpMessage responseMessage = queuedRequests[snmpMessage.MessageID]; + // queuedRequests.Remove(snmpMessage.MessageID); - return responseMessage; - } - } + // return responseMessage; + // } + //} public void RegisterEndpoint(SnmpEndpoint intf) { diff --git a/SNMPInterface.cs b/SNMPInterface.cs index ff1e4e6..75071ef 100644 --- a/SNMPInterface.cs +++ b/SNMPInterface.cs @@ -18,7 +18,7 @@ namespace ln.snmp { } - public abstract PDU snmpRequest(PDU pdu); + public abstract PDU DispatchRequest(PDU pdu); private List snmpRequest(IEnumerable objectIdentifiers) where T: PDU, new() { @@ -28,7 +28,7 @@ namespace ln.snmp pdu.Add(new Sequence(new Variable[] { oid, NullValue.Instance })); } - PDU responsePDU = snmpRequest(pdu); + PDU responsePDU = DispatchRequest(pdu); if (responsePDU.Error.LongValue != 0) { @@ -84,7 +84,7 @@ namespace ln.snmp { try { - return snmpRequest(bulkRequest); + return DispatchRequest(bulkRequest); } catch (SnmpError se) { if ((se.Error == 1)&&(bulkRequest.MaxRepetitions.LongValue > 1)) @@ -122,17 +122,19 @@ namespace ln.snmp Variable[] values = responsePDU.VarBinds.Items; nchunk = values.Length / ncolumns; - inTree = false; for (int n = 0; n < nchunk; n++) { + inTree = false; + Sequence[] row = new Sequence[ncolumns]; for (int c = 0; c < ncolumns; c++) { 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; } } @@ -171,7 +173,9 @@ namespace ln.snmp { ObjectIdentifier oid = ps.Items[0] as ObjectIdentifier; if (objectIdentifier.Contains(oid)) - results.Add(ps); + { + results.Add(new Sequence(new Variable[] { oid.IndexTo(objectIdentifier), ps.Items[1] })); + } else return results; } @@ -259,9 +263,9 @@ namespace ln.snmp return snmpWalk(new ObjectIdentifier(objectIdentifier)); } + public virtual void Dispose() { - SNMPEngine.UnregisterEndpoint(this); } } } diff --git a/authtest b/authtest new file mode 100644 index 0000000000000000000000000000000000000000..04ed92255c19482c1c887019e89531006a265d83 GIT binary patch literal 146 zcmXqL>}O(RHV|ZD(eU#<%f!s^|1k?AD^Q5V+Q5=UtbxI*hsDI%%GA}$z}d>s#LCFT z%F>jHk&lU4c*1)Y_TucylA`=P7M`4v??wvw3z{Du>ORTBU|@wyD+|LyIiOty(JPo3 Z8Gy(@z<`g9OPh_6iIItkk%fho0RY7wA3p#9 literal 0 HcmV?d00001 diff --git a/authtest.hex b/authtest.hex new file mode 100644 index 0000000..4aec257 --- /dev/null +++ b/authtest.hex @@ -0,0 +1 @@ +30818f0201033011020428e35a0c020300ffe3040105020103043b3039041680003a8c0434433a35453a30433a31343a32343a393502010e0203136f860407736b7974726f6e040cc12bbc3135344c067e3eb8890400303a041680003a8c0434433a35453a30433a31343a32343a39350400a11e020469bb65e80201000201003010300e060a2b0601020102020104040500 diff --git a/authtest1 b/authtest1 new file mode 100644 index 0000000000000000000000000000000000000000..1ab04cff6fbf884f3e894be2fe622efd04816763 GIT binary patch literal 146 zcmXqL>}O(RHV|ZDiD|nK!Nkn)_XP_hD^Q5V+Q5=UtbxI*hsDI%%GA}$z}d>s#LCFT z%F>jHk&lU4c;;6Y_TucylA`=P7M|I^xVBkDhE~k7KDv~J!N3ZaRu+bZa!f3Fa}NhI aF){#=fq(%Y8<#d4BNHPN6C(=?D+2)Q?jMl= literal 0 HcmV?d00001 diff --git a/endpoint/SNMPEndpoint.cs b/endpoint/SNMPEndpoint.cs index 07fb3dc..bfb2a19 100644 --- a/endpoint/SNMPEndpoint.cs +++ b/endpoint/SNMPEndpoint.cs @@ -15,27 +15,31 @@ namespace ln.snmp.endpoint public SNMPEngine SNMPEngine { get; } public IPEndPoint RemoteEndpoint { get; set; } + public int Retries { get; set; } = 3; + public SnmpEndpoint(SNMPEngine snmpEngine, IPEndPoint remoteEndpoint) { SNMPEngine = snmpEngine; RemoteEndpoint = remoteEndpoint; + SNMPEngine.RegisterEndpoint(this); } public virtual void Send(SnmpMessage message) { + //message.MessageID = SNMPEngine.NextMessageID; + //if (requestMessage.snmpPDU != null) + //{ + // requestMessage.snmpPDU.RequestID.LongValue = SNMPEngine.NextMessageID; + //} + message = Encrypt(message); message = ApplyAuthentication(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) { if (queuedRequests.ContainsKey(message.MessageID)) @@ -54,21 +58,27 @@ namespace ln.snmp.endpoint } } - public abstract SnmpMessage Encrypt(SnmpMessage message); - public abstract SnmpMessage ApplyAuthentication(SnmpMessage message); + public virtual void Received(SnmpMessage message) + { + message = CheckAuthentication(message); + message = Decrypt(message); - public abstract SnmpMessage CheckAuthentication(SnmpMessage message); - public abstract SnmpMessage Decrypt(SnmpMessage message); + DispatchReceived(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 - **/ + **/ private Dictionary queuedRequests = new Dictionary(); public SnmpMessage EnqueueRequest(SnmpMessage requestMessage) { - requestMessage.MessageID = SNMPEngine.NextMessageID; - lock (queuedRequests) { queuedRequests.Add(requestMessage.MessageID, requestMessage); diff --git a/endpoint/SnmpV1Endpoint.cs b/endpoint/SnmpV1Endpoint.cs index 89c0f07..498cb49 100644 --- a/endpoint/SnmpV1Endpoint.cs +++ b/endpoint/SnmpV1Endpoint.cs @@ -27,14 +27,13 @@ namespace ln.snmp.endpoint CommunityString = new OctetString(communityString); } - public override PDU snmpRequest(PDU pdu) + public override PDU DispatchRequest(PDU pdu) { SnmpV1Message request = new SnmpV1Message(); - request.MessageID = SNMPEngine.NextMessageID; request.snmpCommunity = CommunityString; request.snmpPDU = pdu; - SnmpV1Message response = SNMPEngine.SNMPRequest(RemoteEndpoint, request, SNMPEngine.Timeout) as SnmpV1Message; + SnmpV1Message response = EnqueueRequest(request) as SnmpV1Message; return response.snmpPDU; } diff --git a/endpoint/SnmpV2Endpoint.cs b/endpoint/SnmpV2Endpoint.cs index 9f1cb1f..43e3858 100644 --- a/endpoint/SnmpV2Endpoint.cs +++ b/endpoint/SnmpV2Endpoint.cs @@ -5,10 +5,8 @@ using System.Collections.Generic; namespace ln.snmp.endpoint { - public class SnmpV2Endpoint : SnmpEndpoint + public class SnmpV2Endpoint : SnmpV1Endpoint { - public OctetString CommunityString { get; set; } - public override SnmpVersion SnmpVersion => SnmpVersion.V2c; public SnmpV2Endpoint(SNMPEngine snmpEngine, IPEndPoint remoteEndpoint) @@ -17,24 +15,19 @@ namespace ln.snmp.endpoint CommunityString = "public"; } public SnmpV2Endpoint(SNMPEngine snmpEngine, IPEndPoint remoteEndpoint, OctetString communityString) - : base(snmpEngine, remoteEndpoint) - { - CommunityString = communityString; - } + : base(snmpEngine, remoteEndpoint, communityString) + { } public SnmpV2Endpoint(SNMPEngine snmpEngine, IPEndPoint remoteEndpoint, String communityString) - : base(snmpEngine, remoteEndpoint) - { - CommunityString = new OctetString(communityString); - } + : base(snmpEngine, remoteEndpoint, communityString) + { } - public override PDU snmpRequest(PDU pdu) + public override PDU DispatchRequest(PDU pdu) { SnmpV2Message request = new SnmpV2Message(); - request.MessageID = SNMPEngine.NextMessageID; request.snmpCommunity = CommunityString; request.snmpPDU = pdu; - SnmpV2Message response = SNMPEngine.SNMPRequest(RemoteEndpoint, request, SNMPEngine.Timeout) as SnmpV2Message; + SnmpV2Message response = EnqueueRequest(request) as SnmpV2Message; return response.snmpPDU; } diff --git a/endpoint/USMEndpoint.cs b/endpoint/USMEndpoint.cs index 6b76275..c46e35a 100644 --- a/endpoint/USMEndpoint.cs +++ b/endpoint/USMEndpoint.cs @@ -6,6 +6,8 @@ using System.Security.Cryptography; using ln.snmp.asn1; using System.Linq; using ln.logging; +using System.Threading; +using System.IO; namespace ln.snmp.endpoint { @@ -31,12 +33,62 @@ namespace ln.snmp.endpoint public SnmpV3PrivMethod PrivMethod { get; set; } public override SnmpVersion SnmpVersion => SnmpVersion.V3; + + private object reportDispatchLock = new object(); public USMEndpoint(SNMPEngine snmpEngine,IPEndPoint 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 { 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(); } - USMMessage request = new USMMessage(); - ScopedPDU scopedPDU = new ScopedPDU(); + int retries = Retries; + 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; - scopedPDU.PDU = pdu; + if (RemoteEngineID == null) + { + scopedPDU.contextEngineID = new OctetString(); + } + else + { + scopedPDU.contextEngineID = RemoteEngineID; + } - AuthenticateMessage(request); + scopedPDU.PDU = pdu; - USMMessage replyUSM = InternalRequest(request); - - PDU responsePDU = (replyUSM.msgData as ScopedPDU).PDU; - - return responsePDU; + try + { + USMMessage replyUSM = DispatchRequest(request); + PDU responsePDU = (replyUSM.msgData as ScopedPDU).PDU; + 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; - CacheAuthoritativeEngineBoots = usmReply.SecurityParameters.msgAuthoritativeEngineBoots; - CacheAuthoritativeEngineTime = usmReply.SecurityParameters.msgAuthoritativeEngineTime; - return usmReply; } @@ -96,25 +160,24 @@ namespace ln.snmp.endpoint queryMessage.msgData = scopedPDU; - queryMessage.Dump(); - - USMMessage usmReply = InternalRequest(queryMessage); - - RemoteEngineID = usmReply.SecurityParameters.msgAuthoritativeEngineID; - //RemoteEngineID.Bytes = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 }; + lock (reportDispatchLock) + { + Send(queryMessage); + if (!Monitor.Wait(reportDispatchLock, SNMPEngine.Timeout)) + throw new TimeoutException("could not query engine id"); + } LocalizeKeys(); } 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.msgAuthoritativeEngineID = RemoteEngineID; + message.SecurityParameters.msgAuthoritativeEngineID = RemoteEngineID == null ? new OctetString() : RemoteEngineID; message.SecurityParameters.msgAuthenticationParameters.Bytes = new byte[12]; 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; @@ -146,9 +209,23 @@ namespace ln.snmp.endpoint 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(); } + Logging.Log(LogLevel.DEBUG, "Authenticating Message: {0}",BitConverter.ToString(wholeMsg)); + Logging.Log(LogLevel.DEBUG, "Authenticated Message: {0}", BitConverter.ToString(((ASN1Value)message).AsByteArray)); + return true; } @@ -180,7 +257,7 @@ namespace ln.snmp.endpoint return AuthMethod == SnmpV3AuthMethod.SHA ? (HashAlgorithm)SHA1.Create() : (HashAlgorithm)MD5.Create(); } - private void LocalizeKeys() + public void LocalizeKeys() { if ((AuthKey != null) && (RemoteEngineID != null)) { diff --git a/ln.snmp.csproj b/ln.snmp.csproj index 8c10bb1..64fbb35 100644 --- a/ln.snmp.csproj +++ b/ln.snmp.csproj @@ -58,11 +58,14 @@ + + + diff --git a/rfc1213/RFC1213.cs b/rfc1213/RFC1213.cs new file mode 100644 index 0000000..e639899 --- /dev/null +++ b/rfc1213/RFC1213.cs @@ -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 interfaces = new Dictionary(); + + 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 _IPAddresses = new List(); + + + 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()))); + } + } + + + + + } +} diff --git a/types/IPAddr.cs b/types/IPAddr.cs new file mode 100644 index 0000000..04a5ab3 --- /dev/null +++ b/types/IPAddr.cs @@ -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(); + } + } +} diff --git a/types/ObjectIdentifier.cs b/types/ObjectIdentifier.cs index 334fe8b..d4644e7 100644 --- a/types/ObjectIdentifier.cs +++ b/types/ObjectIdentifier.cs @@ -52,6 +52,19 @@ namespace ln.snmp.types 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 { diff --git a/types/PDU.cs b/types/PDU.cs index bdedf38..58094d5 100644 --- a/types/PDU.cs +++ b/types/PDU.cs @@ -20,26 +20,21 @@ namespace ln.snmp.types public Sequence VarBinds { get; private set; } - private Variable[] items; - public PDU(Identifier identifier) : base(identifier) { //RequestID = new Integer(Environment.TickCount); - RequestID = new Integer(0xDEADBEEF); + RequestID = new Integer((int)(DateTimeOffset.Now.ToUnixTimeMilliseconds()) & 0x7FFFFFFF); Error = new Integer(); ErrorIndex = new Integer(); VarBinds = new Sequence(); - - items = new Variable[] { RequestID, Error, ErrorIndex, VarBinds }; } public PDU(ASN1Value value) : base(value.Identifier) { RequestID = (Integer)value.Items[0]; - Error = (Integer)value.Items[1]; Error = (Integer)value.Items[2]; VarBinds = (Sequence)value.Items[3]; @@ -47,7 +42,7 @@ namespace ln.snmp.types public override Variable[] Items { - get => items; + get => new Variable[] { RequestID, Error, ErrorIndex, VarBinds }; set { RequestID = value[0] as Integer; diff --git a/types/ScopedPDU.cs b/types/ScopedPDU.cs index 476bd2c..78d2ac4 100644 --- a/types/ScopedPDU.cs +++ b/types/ScopedPDU.cs @@ -9,6 +9,8 @@ // **/ using System; using System.Runtime.Remoting.Messaging; +using ln.snmp.asn1; +using System.Linq; namespace ln.snmp.types { public class ScopedPDU : AbstractSequence @@ -26,6 +28,12 @@ namespace ln.snmp.types PDU = new GetRequest(); } + public ScopedPDU(ASN1Value asn) + :this() + { + Items = asn.Items.Select((x) => (Variable)x).ToArray(); + } + public override Variable[] Items { get => new Variable[] { contextEngineID, contextName, PDU }; diff --git a/types/USMMessage.cs b/types/USMMessage.cs index f8cbd35..cff02b3 100644 --- a/types/USMMessage.cs +++ b/types/USMMessage.cs @@ -60,8 +60,14 @@ namespace ln.snmp.types msgGlobalData = new MsgGlobalData(value[1]); SecurityParameters = new UsmSecurityParameters(new ASN1Value(value[2].Bytes)); - // ToDo: Check if value[3] is OctetString (Encrypted) or Sequence (ScopedPDU) - msgData = value[3]; + if (value[3].Identifier.Is(IdentifierClass.UNIVERSAL,false,0x04)) + { + 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())); msgMaxSize = new Integer(65000); - msgFlags = new OctetString("\0"); + msgFlags = new OctetString(new byte[] { 0x04 }); msgSecurityModel = new Integer(3); } public MsgGlobalData(ASN1Value asn) :this() { - + Items = asn.Items.ToVariableArray(); } public override void Add(Variable item) => throw new NotImplementedException(); diff --git a/types/Variable.cs b/types/Variable.cs index 6cc799b..b0725f9 100644 --- a/types/Variable.cs +++ b/types/Variable.cs @@ -125,6 +125,8 @@ namespace ln.snmp.types registerKnownType(); registerKnownType(); + registerKnownType(); + registerKnownType(); registerKnownType(); registerKnownType(); @@ -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(); + } + + + } + }