QuerySslSniInfo() public static method

public static QuerySslSniInfo ( int>.Tuple binding ) : SslSniInfo
binding int>.Tuple
return SslSniInfo
Example #1
0
        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.
        }
Example #2
0
        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;
            }
        }
Example #3
0
        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;
        }
Example #4
0
        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);
        }