From acfd6f21922b314528e814f7f10659cdf4083453 Mon Sep 17 00:00:00 2001 From: venizelou andreas Date: Tue, 2 Jul 2024 23:26:17 +0300 Subject: [PATCH] Refactoring --- Protest/Tools/LiveStats.cs | 438 +++++++++++++++++++------------------ 1 file changed, 220 insertions(+), 218 deletions(-) diff --git a/Protest/Tools/LiveStats.cs b/Protest/Tools/LiveStats.cs index 39a5ed04..baed96a0 100644 --- a/Protest/Tools/LiveStats.cs +++ b/Protest/Tools/LiveStats.cs @@ -30,6 +30,87 @@ private static void WsWriteText(WebSocket ws, byte[] bytes, object mutex) { } } + public static async void UserStats(HttpListenerContext ctx) { + WebSocket ws; + try { + WebSocketContext wsc = await ctx.AcceptWebSocketAsync(null); + ws = wsc.WebSocket; + } + catch (WebSocketException ex) { + ctx.Response.Close(); + Logger.Error(ex); + return; + } + + try { + byte[] buff = new byte[512]; + WebSocketReceiveResult receiveResult = await ws.ReceiveAsync(new ArraySegment(buff), CancellationToken.None); + string file = Encoding.Default.GetString(buff, 0, receiveResult.Count); + + if (!DatabaseInstances.users.dictionary.TryGetValue(file, out Database.Entry entry)) { + await ws.CloseAsync(WebSocketCloseStatus.NormalClosure, String.Empty, CancellationToken.None); + return; + } + + object mutex = new object(); + + if (OperatingSystem.IsWindows() && entry.attributes.TryGetValue("username", out Database.Attribute username)) { + try { + SearchResult result = Kerberos.GetUser(username.value); + if (result != null) { + if (result.Properties["lastLogonTimestamp"].Count > 0) { + if (Int64.TryParse(result.Properties["lastLogonTimestamp"][0].ToString(), out long time) && time > 0) { + WsWriteText(ws, $"{{\"info\":\"Last logon: {DateTime.FromFileTime(time)}\",\"source\":\"Kerberos\"}}", mutex); + } + } + + if (result.Properties["lastLogoff"].Count > 0) { + if (Int64.TryParse(result.Properties["lastLogoff"][0].ToString(), out long time) && time > 0) { + WsWriteText(ws, $"{{\"info\":\"Last logoff: {DateTime.FromFileTime(time)}\",\"source\":\"Kerberos\"}}", mutex); + } + } + + if (result.Properties["badPasswordTime"].Count > 0) { + if (Int64.TryParse(result.Properties["badPasswordTime"][0].ToString(), out long time) && time > 0) { + WsWriteText(ws, $"{{\"info\":\"Bad password time: {(DateTime.FromFileTime(time))}\",\"source\":\"Kerberos\"}}", mutex); + } + } + + if (result.Properties["lockoutTime"].Count > 0) { + if (Int64.TryParse(result.Properties["lockoutTime"][0].ToString(), out long time) && time > 0) { + WsWriteText(ws, $"{{\"lockedOut\":\"{DateTime.FromFileTime(time)}\",\"source\":\"Kerberos\"}}", mutex); + } + } + } + } + catch { } + } + + if (entry.attributes.TryGetValue("password", out Database.Attribute password)) { + string value = password.value; + if (value.Length > 0 && PasswordStrength.Entropy(value) < 28) { + WsWriteText(ws, "{\"warnings\":\"Weak password\"}"u8.ToArray(), mutex); + } + } + } + catch (WebSocketException ex) when (ex.WebSocketErrorCode == WebSocketError.ConnectionClosedPrematurely) { + return; + } + catch (WebSocketException ex) when (ex.WebSocketErrorCode != WebSocketError.ConnectionClosedPrematurely) { + //do nothing + } + catch (Exception ex) { + Logger.Error(ex); + } + + if (ws?.State == WebSocketState.Open) { + try { + await ws.CloseAsync(WebSocketCloseStatus.NormalClosure, String.Empty, CancellationToken.None); + } + catch { } + } + } + public static async void DeviceStats(HttpListenerContext ctx) { WebSocket ws; try { @@ -72,7 +153,7 @@ public static async void DeviceStats(HttpListenerContext ctx) { object mutex = new object(); if (pingArray.Length > 0) { - var pingTasks = new List(); + List pingTasks = new List(); for (int i = 0; i < pingArray.Length; i++) { int index = i; @@ -112,115 +193,16 @@ public static async void DeviceStats(HttpListenerContext ctx) { } } - string wmiHostname = null, adHostname = null, netbios = null, dns = null; + string wmiHostname = null, adHostname = null, netBios = null, dns = null; if (OperatingSystem.IsWindows() && _os?.value?.Contains("windows", StringComparison.OrdinalIgnoreCase) == true && - firstAlive is not null && - firstReply.Status == IPStatus.Success) { - - try { - ManagementScope scope = Protocols.Wmi.Scope(firstAlive); - if (scope is not null && scope.IsConnected) { - using ManagementObjectCollection logicalDisk = new ManagementObjectSearcher(scope, new SelectQuery("SELECT * FROM Win32_LogicalDisk WHERE DriveType = 3")).Get(); - foreach (ManagementObject o in logicalDisk.Cast()) { - string caption = o.GetPropertyValue("Caption").ToString(); - - object size = o.GetPropertyValue("Size"); - if (size is null) continue; - - object free = o.GetPropertyValue("FreeSpace"); - if (free is null) continue; - - ulong nSize = (ulong)size; - ulong nFree = (ulong)free; - - if (nSize == 0) continue; - double percent = Math.Round(100.0 * nFree / nSize, 1); - - WsWriteText(ws, $"{{\"drive\":\"{caption}\",\"total\":{nSize},\"used\":{nSize - nFree},\"path\":\"{Data.EscapeJsonText($"\\\\{firstAlive}\\{caption.Replace(":", String.Empty)}$")}\",\"source\":\"WMI\"}}", mutex); - - if (percent < 1) { - WsWriteText(ws, $"{{\"critical\":\"{percent}% free space on disk {Data.EscapeJsonText(caption)}\",\"source\":\"WMI\"}}", mutex); - } - else if (percent <= 5) { - WsWriteText(ws, $"{{\"error\":\"{percent}% free space on disk {Data.EscapeJsonText(caption)}\",\"source\":\"WMI\"}}", mutex); - } - else if (percent < 15) { - WsWriteText(ws, $"{{\"warning\":\"{percent}% free space on disk {Data.EscapeJsonText(caption)}\",\"source\":\"WMI\"}}", mutex); - } - } - - using ManagementObjectCollection currentTime = new ManagementObjectSearcher(scope, new SelectQuery("SELECT * FROM Win32_UTCTime")).Get(); - foreach (ManagementObject o in currentTime.Cast()) { - int year = (int)(uint)o.GetPropertyValue("Year"); - int month = (int)(uint)o.GetPropertyValue("Month"); - int day = (int)(uint)o.GetPropertyValue("Day"); - int hour = (int)(uint)o.GetPropertyValue("Hour"); - int minute = (int)(uint)o.GetPropertyValue("Minute"); - int second = (int)(uint)o.GetPropertyValue("Second"); - - DateTime current = new DateTime(year, month, day, hour, minute, second); - DateTime now = DateTime.UtcNow; - if (Math.Abs(current.Ticks - now.Ticks) > 600_000_000L) { - WsWriteText(ws, "{\"warning\":\"System time is off by more then 5 minutes\",\"source\":\"WMI\"}"u8.ToArray(), mutex); - } - } - - if (scope is not null) { - string startTime = Wmi.WmiGet(scope, "Win32_LogonSession", "StartTime", false, new Wmi.FormatMethodPtr(Wmi.DateTimeToString)); - if (startTime.Length > 0) { - WsWriteText(ws, $"{{\"info\":\"Start time: {Data.EscapeJsonText(startTime)}\",\"source\":\"WMI\"}}", mutex); - } - - string username = Wmi.WmiGet(scope, "Win32_ComputerSystem", "UserName", false, null); - if (username.Length > 0) { - WsWriteText(ws, $"{{\"info\":\"Logged in user: {Data.EscapeJsonText(username)}\",\"source\":\"WMI\"}}", mutex); - } - wmiHostname = Wmi.WmiGet(scope, "Win32_ComputerSystem", "DNSHostName", false, null); - - WsWriteText(ws, $"{{\"activeUser\":\"{Data.EscapeJsonText(username)}\",\"source\":\"WMI\"}}", mutex); - } - } - } - catch (NullReferenceException) { } - catch { } + firstAlive is not null && firstReply.Status == IPStatus.Success) { + WmiQuery(ws, mutex, firstAlive, ref wmiHostname); } - if (_snmpProfile is not null) { - SnmpProfiles.Profile profile = null; - if (!String.IsNullOrEmpty(_snmpProfile.value) && Guid.TryParse(_snmpProfile.value, out Guid guid)) { - SnmpProfiles.Profile[] profiles = SnmpProfiles.Load(); - for (int i = 0; i < profiles.Length; i++) { - if (profiles[i].guid == guid) { - profile = profiles[i]; - break; - } - } - } - - if (profile is not null - && firstAlive is not null - && firstReply.Status == IPStatus.Success - && IPAddress.TryParse(firstAlive, out IPAddress ipAddress)) { - - IList result = Protocols.Snmp.Polling.SnmpGetQuery(ipAddress, profile, Protocols.Snmp.Oid.LIVESTATS_OID, Protocols.Snmp.Polling.SnmpOperation.Get); - string[][] normalized = Protocols.Snmp.Polling.ParseResponse(result); - - for (int i = 0; i < normalized?.Length; i++) { - string dataString = normalized[i][1]; - switch (normalized[i][0]) { - case Protocols.Snmp.Oid.SYSTEM_UPTIME : WsWriteText(ws, $"{{\"info\":\"Uptime: {Data.EscapeJsonText(dataString)}\",\"source\":\"SNMP\"}}", mutex); break; - case Protocols.Snmp.Oid.SYSTEM_TEMPERATURE : WsWriteText(ws, $"{{\"info\":\"Temperature: {Data.EscapeJsonText(dataString)}\",\"source\":\"SNMP\"}}", mutex); break; } - } - - if (PRINTER_TYPES.Contains(_type.value)) { - SnmpPrintQuery(ws, mutex, profile, ipAddress); - } - else if (SWITCH_TYPES.Contains(_type.value)) { - //TODO: - } - } + if (_snmpProfile is not null && firstAlive is not null && firstReply.Status == IPStatus.Success) { + SnmpQuery(ws, mutex, firstAlive, _type, _snmpProfile); } if (OperatingSystem.IsWindows() && _hostname?.value?.Length > 0) { @@ -278,12 +260,12 @@ firstAlive is not null && } if (!mismatch && wmiHostname is null && adHostname is null) - netbios = await NetBios.GetBiosNameAsync(firstAlive); + netBios = await NetBios.GetBiosNameAsync(firstAlive); - if (!mismatch && !String.IsNullOrEmpty(netbios)) { - netbios = netbios?.Split('.')[0].ToUpper(); - if (netbios != dns) { - WsWriteText(ws, $"{{\"warning\":\"DNS mismatch: {Data.EscapeJsonText(netbios)}\",\"source\":\"NetBIOS\"}}", mutex); + if (!mismatch && !String.IsNullOrEmpty(netBios)) { + netBios = netBios?.Split('.')[0].ToUpper(); + if (netBios != dns) { + WsWriteText(ws, $"{{\"warning\":\"DNS mismatch: {Data.EscapeJsonText(netBios)}\",\"source\":\"NetBIOS\"}}", mutex); mismatch = true; } } @@ -336,143 +318,163 @@ firstAlive is not null && } } - private static void SnmpPrintQuery(WebSocket ws, object mutex, SnmpProfiles.Profile profile, IPAddress ipAddress) { - IList printerResult = Protocols.Snmp.Polling.SnmpGetQuery(ipAddress, profile, Protocols.Snmp.Oid.LIVESTATS_PRINTER_OID, Protocols.Snmp.Polling.SnmpOperation.Get); - string[][] printerNormalized = Protocols.Snmp.Polling.ParseResponse(printerResult); - - for (int i = 0; i < printerNormalized?.Length; i++) { - string dataPrintString = printerNormalized[i][1]; - if (String.IsNullOrEmpty(dataPrintString)) { continue; } - - switch (printerNormalized[i][0]) { - case Protocols.Snmp.Oid.PRINTER_STATUS: - string status = dataPrintString switch - { - "1" => "Other", - "2" => "Processing", - "3" => "Idle", - "4" => "Printing", - "5" => "Warmup", - _ => dataPrintString - }; - WsWriteText(ws, $"{{\"info\":\"Printer status: {Data.EscapeJsonText(status)}\",\"source\":\"SNMP\"}}", mutex); - break; - - case Protocols.Snmp.Oid.PRINTER_DISPLAY_MESSAGE: WsWriteText(ws, $"{{\"info\":\"Printer message: {Data.EscapeJsonText(dataPrintString)}\",\"source\":\"SNMP\"}}", mutex); break; - case Protocols.Snmp.Oid.PRINTER_JOBS: WsWriteText(ws, $"{{\"info\":\"Total jobs: {Data.EscapeJsonText(dataPrintString)}\",\"source\":\"SNMP\"}}", mutex); break; - } - } + private static void WmiQuery(WebSocket ws, object mutex, string firstAlive, ref string wmiHostname) { + try { + ManagementScope scope = Protocols.Wmi.Scope(firstAlive); + if (scope is not null && scope.IsConnected) { + using ManagementObjectCollection logicalDisk = new ManagementObjectSearcher(scope, new SelectQuery("SELECT * FROM Win32_LogicalDisk WHERE DriveType = 3")).Get(); + foreach (ManagementObject o in logicalDisk.Cast()) { + string caption = o.GetPropertyValue("Caption").ToString(); + + object size = o.GetPropertyValue("Size"); + if (size is null) continue; + + object free = o.GetPropertyValue("FreeSpace"); + if (free is null) continue; - string[][] componentName = Protocols.Snmp.Polling.ParseResponse(Protocols.Snmp.Polling.SnmpGetQuery(ipAddress, profile, new string[] { Protocols.Snmp.Oid.PRINTER_TONERS }, Protocols.Snmp.Polling.SnmpOperation.Walk)); - string[][] componentMax = Protocols.Snmp.Polling.ParseResponse(Protocols.Snmp.Polling.SnmpGetQuery(ipAddress, profile, new string[] { Protocols.Snmp.Oid.PRINTER_TONERS_MAX }, Protocols.Snmp.Polling.SnmpOperation.Walk)); - string[][] componentCurrent = Protocols.Snmp.Polling.ParseResponse(Protocols.Snmp.Polling.SnmpGetQuery(ipAddress, profile, new string[] { Protocols.Snmp.Oid.PRINTER_TONER_CURRENT }, Protocols.Snmp.Polling.SnmpOperation.Walk)); + ulong nSize = (ulong)size; + ulong nFree = (ulong)free; - if (componentName is not null && componentCurrent is not null && componentMax is not null) { - for (int i = 0; i < componentName.Length; i++) { - if (componentCurrent.Length <= i) { continue; } - if (componentMax.Length <= i) { continue; } - if (!int.TryParse(componentMax[i][1], out int max)) { continue; } - if (!int.TryParse(componentCurrent[i][1], out int current)) { continue; } + if (nSize == 0) continue; + double percent = Math.Round(100.0 * nFree / nSize, 1); - if (current == -2 || max == -2) { //undefined - continue; + WsWriteText(ws, $"{{\"drive\":\"{caption}\",\"total\":{nSize},\"used\":{nSize - nFree},\"path\":\"{Data.EscapeJsonText($"\\\\{firstAlive}\\{caption.Replace(":", String.Empty)}$")}\",\"source\":\"WMI\"}}", mutex); + + if (percent < 1) { + WsWriteText(ws, $"{{\"critical\":\"{percent}% free space on disk {Data.EscapeJsonText(caption)}\",\"source\":\"WMI\"}}", mutex); + } + else if (percent <= 5) { + WsWriteText(ws, $"{{\"error\":\"{percent}% free space on disk {Data.EscapeJsonText(caption)}\",\"source\":\"WMI\"}}", mutex); + } + else if (percent < 15) { + WsWriteText(ws, $"{{\"warning\":\"{percent}% free space on disk {Data.EscapeJsonText(caption)}\",\"source\":\"WMI\"}}", mutex); + } } - if (current == -3) { //full - current = max; + using ManagementObjectCollection currentTime = new ManagementObjectSearcher(scope, new SelectQuery("SELECT * FROM Win32_UTCTime")).Get(); + foreach (ManagementObject o in currentTime.Cast()) { + int year = (int)(uint)o.GetPropertyValue("Year"); + int month = (int)(uint)o.GetPropertyValue("Month"); + int day = (int)(uint)o.GetPropertyValue("Day"); + int hour = (int)(uint)o.GetPropertyValue("Hour"); + int minute = (int)(uint)o.GetPropertyValue("Minute"); + int second = (int)(uint)o.GetPropertyValue("Second"); + + DateTime current = new DateTime(year, month, day, hour, minute, second); + DateTime now = DateTime.UtcNow; + if (Math.Abs(current.Ticks - now.Ticks) > 600_000_000L) { + WsWriteText(ws, "{\"warning\":\"System time is off by more then 5 minutes\",\"source\":\"WMI\"}"u8.ToArray(), mutex); + } } - componentName[i][1] = componentName[i][1].TrimStart(new char[] { ' ', '!', '\"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', ':', ';', '<', '=', '>', '?', '@', '[', '\\', ']', '^', '_', '{', '|', '}', '~' }); + if (scope is not null) { + string startTime = Wmi.WmiGet(scope, "Win32_LogonSession", "StartTime", false, new Wmi.FormatMethodPtr(Wmi.DateTimeToString)); + if (startTime.Length > 0) { + WsWriteText(ws, $"{{\"info\":\"Start time: {Data.EscapeJsonText(startTime)}\",\"source\":\"WMI\"}}", mutex); + } + + string username = Wmi.WmiGet(scope, "Win32_ComputerSystem", "UserName", false, null); + if (username.Length > 0) { + WsWriteText(ws, $"{{\"info\":\"Logged in user: {Data.EscapeJsonText(username)}\",\"source\":\"WMI\"}}", mutex); + } + wmiHostname = Wmi.WmiGet(scope, "Win32_ComputerSystem", "DNSHostName", false, null); - int used = 100 * current / max; - if (used < 5) { - WsWriteText(ws, $"{{\"error\":\"{used}% {componentName[i][1]}\",\"source\":\"SNMP\"}}", mutex); - } - else if (used < 15) { - WsWriteText(ws, $"{{\"warning\":\"{used}% {componentName[i][1]}\",\"source\":\"SNMP\"}}", mutex); + WsWriteText(ws, $"{{\"activeUser\":\"{Data.EscapeJsonText(username)}\",\"source\":\"WMI\"}}", mutex); } } } + catch (NullReferenceException) { } + catch { } } - public static async void UserStats(HttpListenerContext ctx) { - WebSocket ws; - try { - WebSocketContext wsc = await ctx.AcceptWebSocketAsync(null); - ws = wsc.WebSocket; - } - catch (WebSocketException ex) { - ctx.Response.Close(); - Logger.Error(ex); - return; + private static void SnmpQuery(WebSocket ws, object mutex, string firstAlive, Database.Attribute _type, Database.Attribute _snmpProfile) { + SnmpProfiles.Profile profile = null; + if (!String.IsNullOrEmpty(_snmpProfile.value) && Guid.TryParse(_snmpProfile.value, out Guid guid)) { + SnmpProfiles.Profile[] profiles = SnmpProfiles.Load(); + for (int i = 0; i < profiles.Length; i++) { + if (profiles[i].guid == guid) { + profile = profiles[i]; + break; + } + } } - try { - byte[] buff = new byte[512]; - WebSocketReceiveResult receiveResult = await ws.ReceiveAsync(new ArraySegment(buff), CancellationToken.None); - string file = Encoding.Default.GetString(buff, 0, receiveResult.Count); + if (profile is not null + && IPAddress.TryParse(firstAlive, out IPAddress ipAddress)) { - if (!DatabaseInstances.users.dictionary.TryGetValue(file, out Database.Entry entry)) { - await ws.CloseAsync(WebSocketCloseStatus.NormalClosure, String.Empty, CancellationToken.None); - return; + IList result = Protocols.Snmp.Polling.SnmpGetQuery(ipAddress, profile, Protocols.Snmp.Oid.LIVESTATS_OID, Protocols.Snmp.Polling.SnmpOperation.Get); + string[][] normalized = Protocols.Snmp.Polling.ParseResponse(result); + + for (int i = 0; i < normalized?.Length; i++) { + string dataString = normalized[i][1]; + switch (normalized[i][0]) { + case Protocols.Snmp.Oid.SYSTEM_UPTIME: WsWriteText(ws, $"{{\"info\":\"Uptime: {Data.EscapeJsonText(dataString)}\",\"source\":\"SNMP\"}}", mutex); break; + case Protocols.Snmp.Oid.SYSTEM_TEMPERATURE: WsWriteText(ws, $"{{\"info\":\"Temperature: {Data.EscapeJsonText(dataString)}\",\"source\":\"SNMP\"}}", mutex); break; + } } - object mutex = new object(); + if (PRINTER_TYPES.Contains(_type.value)) { + IList printerResult = Protocols.Snmp.Polling.SnmpGetQuery(ipAddress, profile, Protocols.Snmp.Oid.LIVESTATS_PRINTER_OID, Protocols.Snmp.Polling.SnmpOperation.Get); + string[][] printerNormalized = Protocols.Snmp.Polling.ParseResponse(printerResult); + + for (int i = 0; i < printerNormalized?.Length; i++) { + string dataPrintString = printerNormalized[i][1]; + if (String.IsNullOrEmpty(dataPrintString)) { continue; } + + switch (printerNormalized[i][0]) { + case Protocols.Snmp.Oid.PRINTER_STATUS: + string status = dataPrintString switch + { + "1" => "Other", + "2" => "Processing", + "3" => "Idle", + "4" => "Printing", + "5" => "Warmup", + _ => dataPrintString + }; + WsWriteText(ws, $"{{\"info\":\"Printer status: {Data.EscapeJsonText(status)}\",\"source\":\"SNMP\"}}", mutex); + break; + + case Protocols.Snmp.Oid.PRINTER_DISPLAY_MESSAGE: WsWriteText(ws, $"{{\"info\":\"Printer message: {Data.EscapeJsonText(dataPrintString)}\",\"source\":\"SNMP\"}}", mutex); break; + case Protocols.Snmp.Oid.PRINTER_JOBS: WsWriteText(ws, $"{{\"info\":\"Total jobs: {Data.EscapeJsonText(dataPrintString)}\",\"source\":\"SNMP\"}}", mutex); break; + } + } - if (OperatingSystem.IsWindows() && entry.attributes.TryGetValue("username", out Database.Attribute username)) { - try { - SearchResult result = Kerberos.GetUser(username.value); - if (result != null) { - if (result.Properties["lastLogonTimestamp"].Count > 0) { - if (Int64.TryParse(result.Properties["lastLogonTimestamp"][0].ToString(), out long time) && time > 0) { - WsWriteText(ws, $"{{\"info\":\"Last logon: {DateTime.FromFileTime(time)}\",\"source\":\"Kerberos\"}}", mutex); - } - } + string[][] componentName = Protocols.Snmp.Polling.ParseResponse(Protocols.Snmp.Polling.SnmpGetQuery(ipAddress, profile, new string[] { Protocols.Snmp.Oid.PRINTER_TONERS }, Protocols.Snmp.Polling.SnmpOperation.Walk)); + string[][] componentMax = Protocols.Snmp.Polling.ParseResponse(Protocols.Snmp.Polling.SnmpGetQuery(ipAddress, profile, new string[] { Protocols.Snmp.Oid.PRINTER_TONERS_MAX }, Protocols.Snmp.Polling.SnmpOperation.Walk)); + string[][] componentCurrent = Protocols.Snmp.Polling.ParseResponse(Protocols.Snmp.Polling.SnmpGetQuery(ipAddress, profile, new string[] { Protocols.Snmp.Oid.PRINTER_TONER_CURRENT }, Protocols.Snmp.Polling.SnmpOperation.Walk)); - if (result.Properties["lastLogoff"].Count > 0) { - if (Int64.TryParse(result.Properties["lastLogoff"][0].ToString(), out long time) && time > 0) { - WsWriteText(ws, $"{{\"info\":\"Last logoff: {DateTime.FromFileTime(time)}\",\"source\":\"Kerberos\"}}", mutex); - } + if (componentName is not null && componentCurrent is not null && componentMax is not null) { + for (int i = 0; i < componentName.Length; i++) { + if (componentCurrent.Length <= i) { continue; } + if (componentMax.Length <= i) { continue; } + if (!int.TryParse(componentMax[i][1], out int max)) { continue; } + if (!int.TryParse(componentCurrent[i][1], out int current)) { continue; } + + if (current == -2 || max == -2) { //undefined + continue; } - if (result.Properties["badPasswordTime"].Count > 0) { - if (Int64.TryParse(result.Properties["badPasswordTime"][0].ToString(), out long time) && time > 0) { - WsWriteText(ws, $"{{\"info\":\"Bad password time: {(DateTime.FromFileTime(time))}\",\"source\":\"Kerberos\"}}", mutex); - } + if (current == -3) { //full + current = max; } - if (result.Properties["lockoutTime"].Count > 0) { - if (Int64.TryParse(result.Properties["lockoutTime"][0].ToString(), out long time) && time > 0) { - WsWriteText(ws, $"{{\"lockedOut\":\"{DateTime.FromFileTime(time)}\",\"source\":\"Kerberos\"}}", mutex); - } + componentName[i][1] = componentName[i][1].TrimStart(new char[] { ' ', '!', '\"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', ':', ';', '<', '=', '>', '?', '@', '[', '\\', ']', '^', '_', '{', '|', '}', '~' }); + + int used = 100 * current / max; + if (used < 5) { + WsWriteText(ws, $"{{\"error\":\"{used}% {componentName[i][1]}\",\"source\":\"SNMP\"}}", mutex); + } + else if (used < 15) { + WsWriteText(ws, $"{{\"warning\":\"{used}% {componentName[i][1]}\",\"source\":\"SNMP\"}}", mutex); } } } - catch { } } - - if (entry.attributes.TryGetValue("password", out Database.Attribute password)) { - string value = password.value; - if (value.Length > 0 && PasswordStrength.Entropy(value) < 28) { - WsWriteText(ws, "{\"warnings\":\"Weak password\"}"u8.ToArray(), mutex); - } + else if (SWITCH_TYPES.Contains(_type.value)) { + //TODO: } } - catch (WebSocketException ex) when (ex.WebSocketErrorCode == WebSocketError.ConnectionClosedPrematurely) { - return; - } - catch (WebSocketException ex) when (ex.WebSocketErrorCode != WebSocketError.ConnectionClosedPrematurely) { - //do nothing - } - catch (Exception ex) { - Logger.Error(ex); - } - - if (ws?.State == WebSocketState.Open) { - try { - await ws.CloseAsync(WebSocketCloseStatus.NormalClosure, String.Empty, CancellationToken.None); - } - catch { } - } } + } \ No newline at end of file