diff ServerMonitor/Objects/ServerMonitor.cs @ 5:b6fe203af9d5

Private key passwords and validation
author Brad Greco <brad@bgreco.net>
date Thu, 28 Feb 2019 21:19:32 -0500
parents 3142e52cbe69
children c1dffaac66fa
line wrap: on
line diff
--- a/ServerMonitor/Objects/ServerMonitor.cs	Sun Feb 10 20:51:26 2019 -0500
+++ b/ServerMonitor/Objects/ServerMonitor.cs	Thu Feb 28 21:19:32 2019 -0500
@@ -1,4 +1,6 @@
-using ServerMonitorApp.Properties;
+using Renci.SshNet;
+using Renci.SshNet.Common;
+using ServerMonitorApp.Properties;
 using System;
 using System.Collections.Generic;
 using System.Diagnostics;
@@ -18,6 +20,7 @@
         private readonly string configFileDir;
         private readonly Logger logger;
         private readonly Dictionary<int, CancellationTokenSource> tokens = new Dictionary<int, CancellationTokenSource>();
+        private readonly Dictionary<string, PrivateKeyFile> privateKeys = new Dictionary<string, PrivateKeyFile>();
         private readonly List<int> pausedChecks = new List<int>();
         private bool running, networkAvailable;
         private Dictionary<Task<CheckResult>, int> tasks;
@@ -33,6 +36,8 @@
 
         public string ConfigFile { get; private set; }
 
+        public IEnumerable<string> LockedKeys { get { return privateKeys.Where(kvp => kvp.Value == null).Select(kvp => kvp.Key); } }
+
         public ServerMonitor(ServerSummaryForm mainForm)
         {
             this.mainForm = mainForm;
@@ -67,6 +72,8 @@
                 // that doesn't work when using the XML serializer for some reason.
                 foreach (Server server in Servers)
                 {
+                    if (server.LoginType == LoginType.PrivateKey)
+                        OpenPrivateKey(server.KeyFile);
                     foreach (Check check in server.Checks)
                     {
                         check.Server = server;
@@ -236,7 +243,8 @@
         private void CancelCheck(Check check)
         {
             Task<CheckResult> task = tasks.FirstOrDefault(kvp => kvp.Value == check.Id).Key;
-            tasks.Remove(task);
+            if (task != null)
+                tasks.Remove(task);
             pausedChecks.RemoveAll(id => id == check.Id);
             if (tokens.TryGetValue(check.Id, out CancellationTokenSource cts))
                 cts.Cancel();
@@ -269,6 +277,38 @@
                 mainForm.Invoke((MethodInvoker)(() => Run()));
         }
 
+        public KeyStatus OpenPrivateKey(string path, string password = null)
+        {
+            KeyStatus keyStatus;
+            if (path == null)
+                return KeyStatus.NotAccessible;
+            if (privateKeys.TryGetValue(path, out PrivateKeyFile key) && key != null)
+                return KeyStatus.Open;
+            try
+            {
+               key = new PrivateKeyFile(path, password);
+                keyStatus = KeyStatus.Open;
+            }
+            catch (Exception e) when (e is SshPassPhraseNullOrEmptyException || e is InvalidOperationException)
+            {
+                keyStatus = KeyStatus.NeedPassword;
+            }
+            catch (Exception)
+            {
+                keyStatus = KeyStatus.NotAccessible;
+            }
+            foreach (Server server in Servers)
+            {
+                if (server.KeyFile == path)
+                {
+                    server.PrivateKeyFile = key;
+                    server.KeyStatus = keyStatus;
+                }
+            }
+            privateKeys[path] = key;
+            return keyStatus;
+        }
+
         private void GenerateIds()
         {
             if (Servers.Any())