示例#1
0
        private static ISnmpMessage ParseMessage(int first, Stream stream, UserRegistry registry)
        {
            var array = DataFactory.CreateSnmpData(first, stream);

            if (array.TypeCode != SnmpType.Sequence)
            {
                throw new SnmpException("not an SNMP message");
            }

            var body = (Sequence)array;

            if (body.Length != 3 && body.Length != 4)
            {
                throw new SnmpException("not an SNMP message");
            }

            var                version = (VersionCode)((Integer32)body[0]).ToInt32();
            Header             header;
            SecurityParameters parameters;
            IPrivacyProvider   privacy;
            Scope              scope;

            if (body.Length == 3)
            {
                header     = Header.Empty;
                parameters = SecurityParameters.Create((OctetString)body[1]);
                privacy    = DefaultPrivacyProvider.DefaultPair;
                scope      = new Scope((ISnmpPdu)body[2]);
            }
            else
            {
                header     = new Header(body[1]);
                parameters = new SecurityParameters((OctetString)body[2]);
                if (header.SecurityModel == SecurityModel.Tsm)
                {
                    privacy = new TsmPrivacyProvider(TsmAuthenticationProvider.Instance);
                }
                else
                {
                    var temp = registry.Find(parameters.UserName ?? OctetString.Empty);
                    if (temp == null)
                    {
                        // handle decryption exception.
                        return(new MalformedMessage(header.MessageId, parameters.UserName ?? OctetString.Empty, body[3]));
                    }

                    privacy = temp;
                }

                var code = body[3].TypeCode;
                if (code == SnmpType.Sequence)
                {
                    // v3 not encrypted
                    scope = new Scope((Sequence)body[3]);
                }
                else if (code == SnmpType.OctetString)
                {
                    // v3 encrypted
                    try
                    {
                        scope = new Scope((Sequence)privacy.Decrypt(body[3], parameters));
                    }
                    catch (DecryptionException)
                    {
                        // handle decryption exception.
                        return(new MalformedMessage(header.MessageId, parameters.UserName ?? OctetString.Empty, body[3]));
                    }
                }
                else
                {
                    throw new SnmpException(string.Format(CultureInfo.InvariantCulture, "invalid v3 packets scoped data: {0}", code));
                }

                if (header.SecurityModel != SecurityModel.Tsm && !privacy.VerifyHash(version, header, parameters, body[3], body.GetLengthBytes()))
                {
                    parameters.IsInvalid = true;
                }
            }

            var scopeCode = scope.Pdu.TypeCode;

            try
            {
                return(scopeCode switch
                {
                    SnmpType.TrapV1Pdu => new TrapV1Message(body),
                    SnmpType.TrapV2Pdu => new TrapV2Message(version, header, parameters, scope, privacy, body.GetLengthBytes()),
                    SnmpType.GetRequestPdu => new GetRequestMessage(version, header, parameters, scope, privacy, body.GetLengthBytes()),
                    SnmpType.ResponsePdu => new ResponseMessage(version, header, parameters, scope, privacy, false, body.GetLengthBytes()),
                    SnmpType.SetRequestPdu => new SetRequestMessage(version, header, parameters, scope, privacy, body.GetLengthBytes()),
                    SnmpType.GetNextRequestPdu => new GetNextRequestMessage(version, header, parameters, scope, privacy, body.GetLengthBytes()),
                    SnmpType.GetBulkRequestPdu => new GetBulkRequestMessage(version, header, parameters, scope, privacy, body.GetLengthBytes()),
                    SnmpType.ReportPdu => new ReportMessage(version, header, parameters, scope, privacy, body.GetLengthBytes()),
                    SnmpType.InformRequestPdu => new InformRequestMessage(version, header, parameters, scope, privacy, body.GetLengthBytes()),
                    _ => throw new SnmpException(string.Format(CultureInfo.InvariantCulture, "unsupported pdu: {0}", scopeCode)),
                });
            }
示例#2
0
        public async Task <Variable?> GetV3TsmAsync(IPAddress ip, string oid, int retries, int port, TimeSpan timeout,
                                                    X509Certificate2 certificate, TimeSpan connectionTimeout)
        {
            if (ip == null)
            {
                throw new ArgumentNullException(nameof(ip));
            }

            if (string.IsNullOrWhiteSpace(oid))
            {
                throw new ArgumentNullException(nameof(oid));
            }

            if (!Regex.IsMatch(oid, @"^(([0-9]+)\.)+[0-9]+$"))
            {
                throw new ArgumentException(oid, nameof(oid));
            }

            if (port <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(port), port.ToString());
            }

            if (retries <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(retries), retries.ToString());
            }

            if (timeout <= TimeSpan.Zero)
            {
                throw new ArgumentOutOfRangeException(nameof(timeout), timeout.ToString());
            }

            if (connectionTimeout <= TimeSpan.Zero)
            {
                throw new ArgumentOutOfRangeException(nameof(connectionTimeout));
            }

            if (certificate is null)
            {
                throw new ArgumentNullException(nameof(certificate));
            }

            var startDate   = DateTime.Now;
            var snmpType    = "GET";
            var snmpVersion = $"3 {SecurityModel.Tsm}";

            var attempt = 0;
            IEnumerable <Variable> reply = new List <Variable>();

            while (attempt < retries)
            {
                try
                {
                    var receiver       = new IPEndPoint(ip, port);
                    var clientEndPoint = ip.AddressFamily == AddressFamily.InterNetwork
                        ? new IPEndPoint(IPAddress.Any, 0) : new IPEndPoint(IPAddress.IPv6Any, 0);
                    var vList = new List <Variable>()
                    {
                        new Variable(new ObjectIdentifier(oid))
                    };

                    var chain = new X509Chain();
                    chain.Build(certificate);

                    using var client = new Client(clientEndPoint);
                    client.LoadX509Certificate(chain);
                    client.SupportedCipherSuites.Add(TCipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA);

                    var auth = TsmAuthenticationProvider.Instance;
                    IPrivacyProvider priv = new TsmPrivacyProvider(auth);

                    var          request  = new GetRequestMessage(VersionCode.V3, Messenger.NextMessageId, Messenger.NextRequestId, OctetString.Empty, vList, priv, Messenger.MaxMessageSize);
                    ISnmpMessage response = await request.GetSecureResponseAsync(connectionTimeout, timeout, receiver, client).ConfigureAwait(false);

                    if (response is ReportMessage)
                    {
                        if (response.Pdu().Variables.Count == 0)
                        {
                            throw new Exception("wrong report message received");
                        }

                        var id = response.Pdu().Variables[0].Id;
                        if (id != Messenger.NotInTimeWindow)
                        {
                            var error = id.GetErrorMessage();
                            throw new Exception($"ERROR: {error}");
                        }

                        // according to RFC 3414, send a second request to sync time.
                        var request2 = new GetRequestMessage(VersionCode.V3, Messenger.NextMessageId, Messenger.NextRequestId, OctetString.Empty, OctetString.Empty, vList, priv, Messenger.MaxMessageSize, response);
                        response = await request2.GetSecureResponseAsync(connectionTimeout, timeout, receiver, client).ConfigureAwait(false);
                    }
                    else if (response.Pdu().ErrorStatus.ToInt32() != 0) // != ErrorCode.NoError
                    {
                        throw ErrorException.Create(
                                  "error in response",
                                  receiver.Address,
                                  response);
                    }

                    reply = response.Pdu().Variables;
                    break;
                }
                catch (Exception ex) when(ex is SnmpException || ex is SocketException || ex is OperationCanceledException || ex is System.TimeoutException)
                {
                    if (ex is System.TimeoutException && ex.Message == "Could Not Connect To Server")
                    {
                        _Logger.LogInformation($"{ip} - DTLS failed {attempt + 1} time(s)");
                    }

                    await _SnmpLog.LogTransactionAsync(startDate, ip.ToString(), oid, null, snmpType, snmpVersion, ex.GetType().ToString(), ex.Message).ConfigureAwait(false);

                    ++attempt;
                    if (attempt >= retries)
                    {
                        throw;
                    }
                }
            }

            var type = string.Empty;
            var data = string.Empty;

            foreach (var res in reply)
            {
                type += res.Data.TypeCode;
                data += res.Data.ToString();
            }

            await _SnmpLog.LogTransactionAsync(startDate, ip.ToString(), oid, null, snmpType, snmpVersion, type, data).ConfigureAwait(false);

            return(reply.FirstOrDefault());
        }
示例#3
0
        public async Task <ISnmpMessage?> SetV3TsmAsync <T>(IPAddress ip, string oid, int retries, int port, TimeSpan timeout,
                                                            X509Certificate2 certificate, TimeSpan connectionTimeout, T setValue)
        {
            if (ip == null)
            {
                throw new ArgumentNullException(nameof(ip));
            }

            if (string.IsNullOrWhiteSpace(oid))
            {
                throw new ArgumentNullException(nameof(oid));
            }

            if (!Regex.IsMatch(oid, @"^(([0-9]+)\.)+[0-9]+$"))
            {
                throw new ArgumentException(oid, nameof(oid));
            }

            if (port <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(port), port.ToString());
            }

            if (retries <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(retries), retries.ToString());
            }

            if (timeout <= TimeSpan.Zero)
            {
                throw new ArgumentOutOfRangeException(nameof(timeout), timeout.ToString());
            }

            if (connectionTimeout <= TimeSpan.Zero)
            {
                throw new ArgumentOutOfRangeException(nameof(connectionTimeout));
            }

            if (certificate is null)
            {
                throw new ArgumentNullException(nameof(certificate));
            }

            var startDate   = DateTime.Now;
            var snmpType    = "SET";
            var snmpVersion = $"3 {SecurityModel.Tsm}";

            var          attempt  = 0;
            ISnmpMessage?response = null;

            while (attempt < retries)
            {
                var setValueByType = setValue switch
                {
                    int x => new Variable(new ObjectIdentifier(oid), new Integer32(x)),
                    string x => new Variable(new ObjectIdentifier(oid), new OctetString(x)),
                    IPAddress x => new Variable(new ObjectIdentifier(oid), new IP(x.ToString())),
                    uint x => new Variable(new ObjectIdentifier(oid), new Gauge32(x)),
                    byte[] x => new Variable(new ObjectIdentifier(oid), new OctetString(x)),
                    _ => throw new ArgumentOutOfRangeException(nameof(setValue)),
                };

                try
                {
                    var receiver       = new IPEndPoint(ip, port);
                    var clientEndPoint = ip.AddressFamily == AddressFamily.InterNetwork
                        ? new IPEndPoint(IPAddress.Any, 0) : new IPEndPoint(IPAddress.IPv6Any, 0);
                    var vList = new List <Variable>()
                    {
                        setValueByType
                    };

                    var chain = new X509Chain();
                    chain.Build(certificate);

                    using var client = new Client(clientEndPoint);
                    client.LoadX509Certificate(chain);
                    client.SupportedCipherSuites.Add(TCipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA);

                    var auth = TsmAuthenticationProvider.Instance;
                    IPrivacyProvider priv = new TsmPrivacyProvider(auth);

                    var request = new SetRequestMessage(VersionCode.V3, Messenger.NextMessageId, Messenger.NextRequestId, OctetString.Empty, vList, priv, Messenger.MaxMessageSize);
                    response = await request.GetSecureResponseAsync(connectionTimeout, timeout, receiver, client).ConfigureAwait(false);

                    if (response is ReportMessage)
                    {
                        if (response.Pdu().Variables.Count == 0)
                        {
                            throw new Exception("wrong report message received");
                        }

                        var id = response.Pdu().Variables[0].Id;
                        if (id != Messenger.NotInTimeWindow)
                        {
                            var error = id.GetErrorMessage();
                            throw new Exception($"ERROR: {error}");
                        }

                        var request2 = new GetRequestMessage(VersionCode.V3, Messenger.NextMessageId, Messenger.NextRequestId, OctetString.Empty, OctetString.Empty, vList, priv, Messenger.MaxMessageSize, response);
                        response = await request2.GetSecureResponseAsync(connectionTimeout, timeout, receiver, client).ConfigureAwait(false);
                    }

                    break;
                }
                catch (Exception ex) when(ex is SnmpException || ex is SocketException || ex is OperationCanceledException || ex is System.TimeoutException)
                {
                    if (ex is System.TimeoutException && ex.Message == "Could Not Connect To Server")
                    {
                        _Logger.LogInformation($"{ip} - DTLS failed {attempt + 1} time(s)");
                    }

                    await _SnmpLog.LogTransactionAsync(startDate, ip.ToString(), oid, null, snmpType, snmpVersion, ex.GetType().ToString(), ex.Message).ConfigureAwait(false);

                    ++attempt;
                    if (attempt >= retries)
                    {
                        throw;
                    }
                }
            }

            if (response is null)
            {
                await _SnmpLog.LogTransactionAsync(startDate, ip.ToString(), oid, null, snmpType, snmpVersion, SnmpType.Null.ToString(), null).ConfigureAwait(false);

                return(response);
            }

            var type = response.Pdu().TypeCode;
            var data = response.Pdu().ErrorStatus;

            await _SnmpLog.LogTransactionAsync(startDate, ip.ToString(), oid, null, snmpType, snmpVersion, type.ToString(), data.ToString()).ConfigureAwait(false);

            return(response);
        }
示例#4
0
        public async Task <(int bulkwalkResult, IList <Variable> results)> GetSubtreeV3TsmAsync(IPAddress ip, string oid, int port, int?maxRepetitions,
                                                                                                int?retries, TimeSpan?timeout, X509Certificate2 certificate, TimeSpan?connectionTimeout)
        {
            if (ip == null)
            {
                throw new ArgumentNullException(nameof(ip));
            }

            if (string.IsNullOrWhiteSpace(oid))
            {
                throw new ArgumentNullException(nameof(oid));
            }

            if (!Regex.IsMatch(oid, @"^(([0-9]+)\.)+[0-9]+$"))
            {
                throw new ArgumentException(oid, nameof(oid));
            }

            if (port <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(port), port.ToString());
            }

            var maxRepetitionsValue = maxRepetitions ?? 10;

            if (maxRepetitionsValue <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(maxRepetitions), maxRepetitions.ToString());
            }

            var retriesValue = retries ?? 2;

            if (retriesValue <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(retries), retries.ToString());
            }

            var timeoutMs = timeout ?? TimeSpan.FromSeconds(5);

            if (timeoutMs <= TimeSpan.Zero)
            {
                throw new ArgumentOutOfRangeException(nameof(timeout), timeout.ToString());
            }

            var connTimeout = connectionTimeout ?? TimeSpan.FromSeconds(2);

            if (connTimeout <= TimeSpan.Zero)
            {
                throw new ArgumentOutOfRangeException(nameof(connectionTimeout));
            }

            if (certificate is null)
            {
                throw new ArgumentNullException(nameof(certificate));
            }

            var auth = TsmAuthenticationProvider.Instance;
            var priv = new TsmPrivacyProvider(auth);

            var results        = new List <Variable>();
            var bulkwalkResult = await MyMessenger.BulkWalkV3TsmAsync(
                new IPEndPoint(ip, port),
                new ObjectIdentifier(oid),
                results,
                maxRepetitionsValue,
                retriesValue,
                timeoutMs,
                WalkMode.WithinSubtree,
                priv,
                null,
                certificate,
                connTimeout
                ).ConfigureAwait(false);

            return(bulkwalkResult, results);
        }