/// <summary> /// Prepares IIS to respond to a tls-sni-01 challenge /// </summary> /// <returns> /// A Boolean-returning Func. Invoke the Func to test the challenge response locally. /// </returns> private Func <bool> PrepareChallengeResponse_TlsSni01(ICertifiedServer iisManager, string domain, ManagedSite managedSite, PendingAuthorization pendingAuth) { var requestConfig = managedSite.RequestConfig; var tlsSniChallenge = pendingAuth.Challenges.FirstOrDefault(c => c.ChallengeType == SupportedChallengeTypes.CHALLENGE_TYPE_SNI); if (tlsSniChallenge == null) { this.LogAction($"No tls-sni-01 challenge to complete for {managedSite.Name}. Request cannot continue."); return(() => false); } var sha256 = System.Security.Cryptography.SHA256.Create(); var z = new byte[tlsSniChallenge.HashIterationCount][]; // compute n sha256 hashes, where n=challengedata.iterationcount z[0] = sha256.ComputeHash(Encoding.UTF8.GetBytes(tlsSniChallenge.Value)); for (int i = 1; i < z.Length; i++) { z[i] = sha256.ComputeHash(z[i - 1]); } // generate certs and install iis bindings var cleanupQueue = new List <Action>(); var checkQueue = new List <Func <bool> >(); foreach (string hex in z.Select(b => BitConverter.ToString(b).Replace("-", "").ToLower())) { string sni = $"{hex.Substring(0, 32)}.{hex.Substring(32)}.acme.invalid"; this.LogAction($"Preparing binding at: https://{domain}, sni: {sni}"); var x509 = CertificateManager.GenerateTlsSni01Certificate(sni); CertificateManager.StoreCertificate(x509); var certStoreName = CertificateManager.GetDefaultStore().Name; iisManager.InstallCertificateforBinding(certStoreName, x509.GetCertHash(), managedSite, sni); // add check to the queue checkQueue.Add(() => _netUtil.CheckSNI(domain, sni)); // add cleanup actions to queue cleanupQueue.Add(() => iisManager.RemoveHttpsBinding(managedSite, sni)); cleanupQueue.Add(() => CertificateManager.RemoveCertificate(x509)); } // configure cleanup to execute the cleanup queue pendingAuth.Cleanup = () => cleanupQueue.ForEach(a => a()); // perform our own config checks return(() => checkQueue.All(check => check())); }
/// <summary> /// Prepares IIS to respond to a tls-sni-01 challenge /// </summary> /// <returns> /// A Boolean-returning Func. Invoke the Func to test the challenge response locally. /// </returns> private Func <bool> PrepareChallengeResponse_TlsSni01(IISManager iisManager, string domain, ManagedSite managedSite, PendingAuthorization pendingAuth) { var requestConfig = managedSite.RequestConfig; var tlsSniChallenge = (ACMESharp.ACME.TlsSniChallenge)pendingAuth.Challenge.ChallengeData; var tlsSniAnswer = (ACMESharp.ACME.TlsSniChallengeAnswer)tlsSniChallenge.Answer; var sha256 = System.Security.Cryptography.SHA256.Create(); var z = new byte[tlsSniChallenge.IterationCount][]; // compute n sha256 hashes, where n=challengedata.iterationcount z[0] = sha256.ComputeHash(Encoding.UTF8.GetBytes(tlsSniAnswer.KeyAuthorization)); for (int i = 1; i < z.Length; i++) { z[i] = sha256.ComputeHash(z[i - 1]); } // generate certs and install iis bindings var cleanupQueue = new List <Action>(); var checkQueue = new List <Func <bool> >(); foreach (string hex in z.Select(b => BitConverter.ToString(b).Replace("-", "").ToLower())) { string sni = $"{hex.Substring(0, 32)}.{hex.Substring(32)}.acme.invalid"; this.LogAction($"Preparing binding at: https://{domain}, sni: {sni}"); var x509 = CertificateManager.GenerateTlsSni01Certificate(sni); CertificateManager.StoreCertificate(x509); iisManager.InstallCertificateforBinding(managedSite, x509, sni); // add check to the queue checkQueue.Add(() => NetUtil.CheckSNI(domain, sni)); // add cleanup actions to queue cleanupQueue.Add(() => iisManager.RemoveHttpsBinding(managedSite, sni)); cleanupQueue.Add(() => CertificateManager.RemoveCertificate(x509)); } // configure cleanup to execute the cleanup queue pendingAuth.Cleanup = () => cleanupQueue.ForEach(a => a()); // perform our own config checks pendingAuth.TlsSniConfigCheckedOK = true; return(() => checkQueue.All(check => check())); }