internal bool DetectConflicts() { if (SslFlags == SslFlags.Sni) { var sni = NativeMethods.QuerySslSniInfo(new Tuple <string, int>(_host, _endPoint.Port)); return(sni != null); // true if detect existing SNI mapping. } var certificate = NativeMethods.QuerySslCertificateInfo(_endPoint); return(certificate != null); // true if detect existing IP mapping. }
private void Initialize() { if (_initialized) { return; } _initialized = true; var value = (string)this["bindingInformation"]; var last = value.LastIndexOf(':'); _host = value.Substring(last + 1); var next = value.LastIndexOf(':', last - 1); var port = value.Substring(next + 1, last - next - 1); var address = value.Substring(0, next); _endPoint = new IPEndPoint(address.DisplayToAddress(), Int32.Parse(port)); if (Protocol != "https" || CertificateHash != null) { return; } if (Helper.IsRunningOnMono()) { // TODO: how to do it on Mono? return; } if (this.GetIsSni()) { var sni = NativeMethods.QuerySslSniInfo(new Tuple <string, int>(_host, _endPoint.Port)); if (sni != null) { this.CertificateHash = sni.Hash; this.CertificateStoreName = sni.StoreName; return; } } var certificate = NativeMethods.QuerySslCertificateInfo(_endPoint); if (certificate != null) { CertificateHash = certificate.Hash; CertificateStoreName = certificate.StoreName; } }
public void RefreshCertificate() { if (Parent.Parent.Server.SupportsSni) { if (this.GetIsSni()) { try { var sni = NativeMethods.QuerySslSniInfo(new Tuple <string, int>(_host, _endPoint.Port)); if (sni == null) { CertificateHash = null; CertificateStoreName = string.Empty; SslFlags = SslFlags.Sni; return; } else { CertificateHash = sni.Hash; CertificateStoreName = sni.StoreName; SslFlags = SslFlags.Sni; return; } } catch (Win32Exception) { CertificateHash = null; CertificateStoreName = string.Empty; SslFlags = SslFlags.Sni; return; } } } var certificate = NativeMethods.QuerySslCertificateInfo(_endPoint); if (certificate == null) { CertificateHash = null; CertificateStoreName = string.Empty; return; } CertificateHash = certificate.Hash; CertificateStoreName = certificate.StoreName; }
internal static string FixCertificateMapping(this Binding binding, X509Certificate2 certificate2) { if (binding.Protocol == "http") { return(string.Empty); } if (binding.Parent.Parent.Server.SupportsSni) { if (binding.GetIsSni()) { if (certificate2.GetNameInfo(X509NameType.DnsName, false) != binding.Host) { return("SNI mode requires host name matches common name of the certificate"); } // handle SNI var sni = NativeMethods.QuerySslSniInfo(new Tuple <string, int>(binding.Host, binding.EndPoint.Port)); if (sni == null) { try { // register mapping using (var process = new Process()) { var start = process.StartInfo; start.Verb = "runas"; start.FileName = "cmd"; start.Arguments = $"/c \"\"{Path.Combine(Environment.CurrentDirectory, "certificateinstaller.exe")}\" /h:\"{Hex.ToHexString(binding.CertificateHash)}\" /s:{binding.CertificateStoreName}\" /i:{AppIdIisExpress} /a:{binding.EndPoint.Address} /o:{binding.EndPoint.Port} /x:{binding.Host}"; start.CreateNoWindow = true; start.WindowStyle = ProcessWindowStyle.Hidden; process.Start(); process.WaitForExit(); if (process.ExitCode != 0) { return("Register new certificate failed: access is denied"); } return(string.Empty); } } catch (Win32Exception ex) { // elevation is cancelled. if (ex.NativeErrorCode != NativeMethods.ErrorCancelled) { Rollbar.Report(ex, ErrorLevel.Error, new Dictionary <string, object> { { "native", ex.NativeErrorCode } }); return($"Register new certificate failed: unknown (native {ex.NativeErrorCode})"); } return("Register new certificate failed: operation is cancelled"); } catch (Exception ex) { Rollbar.Report(ex, ErrorLevel.Error); return($"Register new certificate failed: unknown ({ex.Message})"); } } if (!sni.Hash.SequenceEqual(binding.CertificateHash)) { // TODO: fix the error message. var result = MessageBox.Show( "At least one other site is using the same HTTPS binding and the binding is configured with a different certificate. Are you sure that you want to reuse this HTTPS binding and reassign the other site or sites to use the new certificate?", "TODO", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1); if (result != DialogResult.Yes) { return ("Certificate hash does not match. Please use the certificate that matches HTTPS binding"); } try { // register mapping using (var process = new Process()) { var start = process.StartInfo; start.Verb = "runas"; start.FileName = "cmd"; start.Arguments = $"/c \"\"{Path.Combine(Environment.CurrentDirectory, "certificateinstaller.exe")}\" /h:\"{Hex.ToHexString(binding.CertificateHash)}\" /s:{binding.CertificateStoreName}\" /i:{AppIdIisExpress} /a:{binding.EndPoint.Address} /o:{binding.EndPoint.Port} /x:{binding.Host}"; start.CreateNoWindow = true; start.WindowStyle = ProcessWindowStyle.Hidden; process.Start(); process.WaitForExit(); if (process.ExitCode != 0) { return("Register new certificate failed: access is denied"); } return(string.Empty); } } catch (Win32Exception ex) { // elevation is cancelled. if (ex.NativeErrorCode != NativeMethods.ErrorCancelled) { Rollbar.Report(ex, ErrorLevel.Error, new Dictionary <string, object> { { "native", ex.NativeErrorCode } }); return($"Register new certificate failed: unknown (native {ex.NativeErrorCode})"); } return("Register new certificate failed: operation is cancelled"); } catch (Exception ex) { Rollbar.Report(ex, ErrorLevel.Error); return($"Register new certificate failed: unknown ({ex.Message})"); } } if (!string.Equals(sni.StoreName, binding.CertificateStoreName, StringComparison.OrdinalIgnoreCase)) { // TODO: can this happen? return ("Certificate store name does not match. Please use the certificate that matches HTTPS binding"); } return(string.Empty); } } // handle IP based var certificate = NativeMethods.QuerySslCertificateInfo(binding.EndPoint); if (certificate == null) { try { // register mapping using (var process = new Process()) { var start = process.StartInfo; start.Verb = "runas"; start.FileName = "cmd"; start.Arguments = $"/c \"\"{Path.Combine(Environment.CurrentDirectory, "certificateinstaller.exe")}\" /h:\"{Hex.ToHexString(binding.CertificateHash)}\" /s:{binding.CertificateStoreName}\" /i:{AppIdIisExpress} /a:{binding.EndPoint.Address} /o:{binding.EndPoint.Port}"; start.CreateNoWindow = true; start.WindowStyle = ProcessWindowStyle.Hidden; process.Start(); process.WaitForExit(); if (process.ExitCode != 0) { return("Register new certificate failed: access is denied"); } return(string.Empty); } } catch (Win32Exception ex) { // elevation is cancelled. if (ex.NativeErrorCode != NativeMethods.ErrorCancelled) { Rollbar.Report(ex, ErrorLevel.Error, new Dictionary <string, object> { { "native", ex.NativeErrorCode } }); return($"Register new certificate failed: unknown (native {ex.NativeErrorCode})"); } return("Register new certificate failed: operation is cancelled"); } catch (Exception ex) { Rollbar.Report(ex, ErrorLevel.Error); return($"Register new certificate failed: unknown ({ex.Message})"); } } if (!certificate.Hash.SequenceEqual(binding.CertificateHash)) { var result = MessageBox.Show( "At least one other site is using the same HTTPS binding and the binding is configured with a different certificate. Are you sure that you want to reuse this HTTPS binding and reassign the other site or sites to use the new certificate?", "TODO", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1); if (result != DialogResult.Yes) { return("Certificate hash does not match. Please use the certificate that matches HTTPS binding"); } try { // register mapping using (var process = new Process()) { var start = process.StartInfo; start.Verb = "runas"; start.FileName = "cmd"; start.Arguments = $"/c \"\"{Path.Combine(Environment.CurrentDirectory, "certificateinstaller.exe")}\" /h:\"{Hex.ToHexString(binding.CertificateHash)}\" /s:{binding.CertificateStoreName}\" /i:{AppIdIisExpress} /a:{binding.EndPoint.Address} /o:{binding.EndPoint.Port}"; start.CreateNoWindow = true; start.WindowStyle = ProcessWindowStyle.Hidden; process.Start(); process.WaitForExit(); if (process.ExitCode != 0) { return("Register new certificate failed: access is denied"); } return(string.Empty); } } catch (Win32Exception ex) { // elevation is cancelled. if (ex.NativeErrorCode != NativeMethods.ErrorCancelled) { Rollbar.Report(ex, ErrorLevel.Error, new Dictionary <string, object> { { "native", ex.NativeErrorCode } }); return($"Register new certificate failed: unknown (native {ex.NativeErrorCode})"); } return("Register new certificate failed: operation is cancelled"); } catch (Exception ex) { Rollbar.Report(ex, ErrorLevel.Error); return($"Register new certificate failed: unknown ({ex.Message})"); } } if (!string.Equals(certificate.StoreName, binding.CertificateStoreName, StringComparison.OrdinalIgnoreCase)) { // TODO: can this happen? return ("Certificate store name does not match. Please use the certificate that matches HTTPS binding"); } return(string.Empty); }