} // proc NewCertificate private async Task <bool> GenerateAsync(AcmeStateStore state) { var r = await state.GetChallengeStateAsync(); if (r != "valid") { Log.Info("State is '{0}', expected is 'valid'.", r); return(false); } // read certificate Log.Info("Generate key."); var pfxData = await state.GenerateKeyAsync(); // install certificate in store await UpdateCertificateAsync(state, pfxData); return(true); } // func GenerateAsync
} // proc ExecuteNetsh private async Task UpdateCertificateAsync(AcmeStateStore state, byte[] pfxData) { using (var log = Log.CreateScope(LogMsgType.Information, true, false)) { log.WriteLine("Update SSL-Binding."); // install certificate in store var cert = await Task.Run(() => { var pfx = new X509Certificate2(pfxData, (string)null, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable); using (var lm = new X509Store(StoreName.My, StoreLocation.LocalMachine)) { lm.Open(OpenFlags.ReadWrite); foreach (var c in lm.Certificates) { if (String.Compare(c.Thumbprint, pfx.Thumbprint, StringComparison.OrdinalIgnoreCase) == 0) { log.WriteLine("Certificate {0} already installed in LocalMachine\\My", pfx.Thumbprint); return(c); } } log.WriteLine("Install Certificate {0} in LocalMachine\\My", pfx.Thumbprint); lm.Add(pfx); return(pfx); } }); // register in http.sys var port = 443; log.WriteLine("Register Certificate {0} for endpoint {1}", cert.Thumbprint, port); log.WriteLine("delete:"); log.WriteLine(await ExecuteNetsh(false, String.Format("http delete sslcert ipport=0.0.0.0:{0}", port))); log.WriteLine("insert:"); log.WriteLine(await ExecuteNetsh(true, String.Format("http add sslcert ipport=0.0.0.0:{0} certhash={1} appid={{d5e8e8f8-3e7b-4ffa-8ec3-1860e24402e5}}", port, cert.Thumbprint))); } } // func UpdateCertificateAsync
} // func GetAcmeUri private bool TryGetState(LogMsgType type, out AcmeStateStore state) { var acmeUri = GetAcmeUri(Config.GetAttribute("acme", null)); var hostName = Config.GetAttribute("commonName", null); if (acmeUri == null) { const string msg = "No Automatic Certificate Management Service defined."; if (type == LogMsgType.Error) { throw new ArgumentNullException(nameof(acmeUri), msg); } if (type == LogMsgType.Warning) { Log.Warn(msg); } state = null; return(false); } if (hostName == null) { const string msg = "No HostName defined."; if (type == LogMsgType.Error) { throw new ArgumentNullException(nameof(acmeUri), msg); } if (type == LogMsgType.Warning) { Log.Warn(msg); } state = null; return(false); } state = new AcmeStateStore(acmeUri, hostName, Path.ChangeExtension(LogFileName, ".state")); return(true); } // func TryGetState
} // func TryGetState #endregion #region -- NewCertificate, Generate, Update ----------------------------------- private async Task <bool> NewCertificateAsync(AcmeStateStore state, bool force) { var notAfter = force ? DateTime.MinValue : GetCurrentCertifcateNotAfter(state.CommonName); if (notAfter < DateTime.Now || notAfter.AddDays(-10) < DateTime.Now) { // create a new order Log.Info("Start new Order."); await state.NewOrderAsync(); // wait one second await Task.Delay(1000); // start validation process await state.GetChallengeStateAsync(); return(true); } else { return(false); } } // proc NewCertificate