Browse Source

Certificate Engine fixes

Kenric Nugteren 2 years ago
parent
commit
ea2c0e4289

+ 3 - 2
prs.server/Engines/Certificate/CertHelper.cs

@@ -156,12 +156,13 @@ namespace PRSServer
 
                 if (ackp != null)
                 {
-                    var rsa = ackp.Private as RsaPrivateCrtKeyParameters;
-                    if (rsa != null)
+                    if(ackp.Private is RsaPrivateCrtKeyParameters rsa || ackp.Private is ECPrivateKeyParameters ec)
+                    {
                         return new CertPrivateKey
                         {
                             KeyPair = ackp
                         };
+                    }
                 }
 
                 throw new InvalidDataException("could not read source as PEM private key");

+ 47 - 19
prs.server/Engines/Certificate/CertificateEngine.cs

@@ -215,13 +215,18 @@ namespace PRSServer
             // We delay for 5 seconds just to give other parts of
             // the service (like request handling) to get in place
             Task.Delay(5 * 1000, cancellationToken);
-            DoTheWork();
+            if (DoTheWork())
+            {
+                Logger.Send(LogType.Information, "", "HTTPS Refresh Complete!");
+            }
+            else
+            {
+                Logger.Send(LogType.Information, "", "HTTPS Refresh Failed");
+            }
             host.Stop();
-
-            Logger.Send(LogType.Information, "", "HTTPS Refresh Complete!");
         }
 
-        private void DoTheWork()
+        private bool DoTheWork()
         {
             try
             {
@@ -231,13 +236,14 @@ namespace PRSServer
                 var acmeUrl = new Uri(Properties.CaUrl);
                 using var acme = new AcmeProtocolClient(acmeUrl, usePostAsGet: true);
 
-                ClearAuthorizations(acme).Wait();
                 var task = DoTheWorkAsync(acme);
                 task.Wait();
+                return task.Result;
             }
             catch(Exception e)
             {
                 Logger.Send(LogType.Error, "", CoreUtils.FormatException(e));
+                return false;
             }
         }
 
@@ -249,13 +255,26 @@ namespace PRSServer
                 {
                     if (authorization.Status != AcmeState.ValidStatus)
                     {
-                        await acme.DeactivateAuthorizationAsync(url);
+                        try
+                        {
+                            await acme.DeactivateAuthorizationAsync(url);
+                        }
+                        catch(Exception e)
+                        {
+                            Logger.Send(LogType.Error, "", $"Could not deactivate authorization: {CoreUtils.FormatException(e)}");
+                        }
                     }
                 }
+                Authorizations.Clear();
+                Save(AuthorizationsFile, Authorizations);
+            }
+            else
+            {
+                Authorizations = new Dictionary<string, Authorization>();
             }
         }
 
-        private async Task DoTheWorkAsync(AcmeProtocolClient acme)
+        private async Task<bool> DoTheWorkAsync(AcmeProtocolClient acme)
         {
             ServiceDirectory = await acme.GetDirectoryAsync();
             Save(ServiceDirectoryFile, ServiceDirectory);
@@ -263,22 +282,27 @@ namespace PRSServer
 
             Save(TermsOfServiceFile, await acme.GetTermsOfServiceAsync());
 
+            // This line basically has to be called before all ACME things.
             await acme.GetNonceAsync();
 
+            ClearAuthorizations(acme).Wait();
+
             if (!await ResolveAccount(acme))
-                return;
+                return false;
 
             if (!await ResolveOrder(acme))
-                return;
+                return false;
 
             if (!await ResolveChallenges(acme))
-                return;
+                return false;
 
             if (!await ResolveAuthorizations(acme))
-                return;
+                return false;
 
             if (!await ResolveCertificate(acme))
-                return;
+                return false;
+
+            return true;
         }
 
         private async Task<bool> ResolveAccount(AcmeProtocolClient acme)
@@ -286,7 +310,7 @@ namespace PRSServer
             // TODO:  All this ASSUMES a fixed key type/size for now
             if (Account == null || AccountKey == null)
             {
-                var contacts = AccountContactEmails.Select(x => $"mailto:{x}");
+                var contacts = AccountContactEmails.Where(x => !string.IsNullOrEmpty(x)).Select(x => $"mailto:{x}");
                 Logger.Send(LogType.Information, "", "Creating ACME Account");
                 Account = await acme.CreateAccountAsync(
                     contacts,
@@ -420,6 +444,8 @@ namespace PRSServer
             var now = DateTime.Now;
             do
             {
+                if (Authorizations == null)
+                    Authorizations = new Dictionary<string, Authorization>();
                 // Wait for all Authorizations to be valid or any one to go invalid
                 var validCount = 0;
                 var invalidCount = 0;
@@ -462,6 +488,8 @@ namespace PRSServer
                         Authorizations[authzUrl] = await acme.GetAuthorizationDetailsAsync(authzUrl);
             } while (true);
 
+            Save(AuthorizationsFile, Authorizations);
+
             return true;
         }
 
@@ -513,12 +541,6 @@ namespace PRSServer
                 Save(OrderFile, Order);
             }
 
-            if (AcmeState.ValidStatus != Order.Payload.Status)
-            {
-                Logger.Send(LogType.Information, "", "Order is NOT VALID");
-                return false;
-            }
-
             if (string.IsNullOrEmpty(Order.Payload.Certificate))
             {
                 Logger.Send(LogType.Information, "", "Order Certificate is NOT READY YET");
@@ -543,6 +565,12 @@ namespace PRSServer
                 } while (true);
             }
 
+            if (AcmeState.ValidStatus != Order.Payload.Status)
+            {
+                Logger.Send(LogType.Information, "", "Order is NOT VALID");
+                return false;
+            }
+
             Logger.Send(LogType.Information, "", "Retreiving Certificate");
             var certBytes = await acme.GetOrderCertificateAsync(Order);
             Save(CertificateChainFile, certBytes);