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)), }); }
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()); }
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); }
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); }