示例#1
0
        /// <summary>
        /// Test if the host fits to the binding
        /// 0: no match
        /// 100: default match
        /// 500: partial match (todo: make different levels for # of subdomains
        /// 1000: full match
        /// </summary>
        /// <param name=""></param>
        /// <param name=""></param>
        /// <returns></returns>
        private int Fits(string binding, string host, SSLFlags flags)
        {
            // The default (emtpy) binding matches with all hostnames.
            // But it's not supported with Central SSL
            if (string.IsNullOrEmpty(binding) && (!flags.HasFlag(SSLFlags.CentralSSL)))
            {
                return(10);
            }

            // Match sub.example.com with *.example.com
            if (binding.StartsWith("*."))
            {
                if (host.ToLower().EndsWith(binding.ToLower().Replace("*.", ".")))
                {
                    // If there is a binding for *.a.b.c.com (5) and one for *.c.com (3)
                    // then the hostname test.a.b.c.com (5) is a better (more specific)
                    // for the former than for the latter, so we prefer to use that.
                    var hostLevel    = host.Split('.').Count();
                    var bindingLevel = binding.Split('.').Count();
                    return(90 - (hostLevel - bindingLevel));
                }
                else
                {
                    return(0);
                }
            }

            // Full match
            return(string.Equals(binding, host, StringComparison.CurrentCultureIgnoreCase) ? 100 : 0);
        }
示例#2
0
 /// <summary>
 /// Make sure the flags are set correctly for updating the binding,
 /// because special conditions apply to the default binding
 /// </summary>
 /// <param name="host"></param>
 /// <param name="flags"></param>
 /// <returns></returns>
 private SSLFlags CheckFlags(bool newBinding, string host, SSLFlags flags)
 {
     // SSL flags are not supported at all by Windows 2008
     if (_client.Version.Major < 8)
     {
         return(SSLFlags.None);
     }
     // Do not allow CentralSSL flag to be set on the default binding
     if (string.IsNullOrEmpty(host))
     {
         if (flags.HasFlag(SSLFlags.CentralSSL))
         {
             throw new InvalidOperationException("Central SSL is not supported without a hostname");
         }
     }
     // Add SNI on Windows Server 2012+
     if (newBinding)
     {
         if (!string.IsNullOrEmpty(host) && _client.Version.Major >= 8)
         {
             flags = flags | SSLFlags.SNI;
         }
     }
     return(flags);
 }
示例#3
0
 /// <summary>
 /// Make sure the flags are set correctly for updating the binding,
 /// because special conditions apply to the default binding
 /// </summary>
 /// <param name="host"></param>
 /// <param name="flags"></param>
 /// <returns></returns>
 private SSLFlags CheckFlags(string host, SSLFlags flags)
 {
     // Remove SNI flag from empty binding
     if (string.IsNullOrEmpty(host))
     {
         if (flags.HasFlag(SSLFlags.CentralSSL))
         {
             throw new InvalidOperationException("Central SSL is not supported without a hostname");
         }
     }
     return(flags);
 }
示例#4
0
        /// <summary>
        /// Test if the host fits to the binding
        /// 100: full match
        /// 90: partial match (Certificate less specific, e.g. *.example.com cert for sub.example.com binding)
        /// 50,59,48,...: partial match (IIS less specific, e.g. sub.example.com cert for *.example.com binding)
        /// 10: default match (catch-all binding)
        /// 0: no match
        /// </summary>
        /// <param name=""></param>
        /// <param name=""></param>
        /// <returns></returns>
        private int Fits(IIISBinding iis, Identifier certificate, SSLFlags flags)
        {
            // The default (empty) binding matches with all hostnames.
            // But it's not supported with Central SSL
            if (string.IsNullOrEmpty(iis.Host) && (!flags.HasFlag(SSLFlags.CentralSsl)))
            {
                return(10);
            }

            // Match sub.example.com (certificate) with *.example.com (IIS)
            if (iis.Host.StartsWith("*.") && !certificate.Value.StartsWith("*."))
            {
                if (certificate.Value.ToLower().EndsWith(iis.Host.ToLower().Replace("*.", ".")))
                {
                    // If there is a binding for *.a.b.c.com (5) and one for *.c.com (3)
                    // then the hostname test.a.b.c.com (5) is a better (more specific)
                    // for the former than for the latter, so we prefer to use that.
                    var hostLevel    = certificate.Value.Split('.').Length;
                    var bindingLevel = iis.Host.Split('.').Length;
                    return(50 - (hostLevel - bindingLevel));
                }
                return(0);
            }

            // Match *.example.com (certificate) with sub.example.com (IIS)
            if (!iis.Host.StartsWith("*.") && certificate.Value.StartsWith("*."))
            {
                if (iis.Host.ToLower().EndsWith(certificate.Value.ToLower().Replace("*.", ".")))
                {
                    // But it should not match with another.sub.example.com.
                    var hostLevel    = certificate.Value.Split('.').Length;
                    var bindingLevel = iis.Host.Split('.').Length;
                    if (hostLevel == bindingLevel)
                    {
                        return(90);
                    }
                }
                else if (iis.Host.ToLower().Equals(certificate.Value.ToLower().Replace("*.", "")))
                {
                    if (iis.Host.Split('.').Length == 2)
                    {
                        return(89);
                    }
                }
                return(0);
            }

            // Full match
            return(string.Equals(iis.Host, certificate.Value, StringComparison.CurrentCultureIgnoreCase) ? 100 : 0);
        }
示例#5
0
        /// <summary>
        /// Make sure the flags are set correctly for updating the binding,
        /// because special conditions apply to the default binding
        /// </summary>
        /// <param name="host"></param>
        /// <param name="flags"></param>
        /// <returns></returns>
        private SSLFlags CheckFlags(bool newBinding, string host, SSLFlags flags)
        {
            // SSL flags are not supported at all by Windows 2008
            if (_client.Version.Major < 8)
            {
                return(SSLFlags.None);
            }

            // Add SNI on Windows Server 2012+ for new bindings
            if (newBinding &&
                !string.IsNullOrEmpty(host) &&
                _client.Version.Major >= 8)
            {
                flags |= SSLFlags.SNI;
            }

            // Modern flags are not supported by IIS versions lower than 10.
            // In fact they are not even supported by all versions of IIS 10,
            // but so far we don't know how to check for these features
            // availability (IIS reports its version as 10.0.0 even on
            // Server 2019).
            if (_client.Version.Major < 10)
            {
                flags &= ~SSLFlags.IIS10_Flags;
            }

            // Some flags cannot be used together with the CentralSsl flag,
            // because when using CentralSsl they are supposedly configured at
            // the server level instead of at the binding level (though the IIS
            // Manager doesn't seem to expose these options).
            if (flags.HasFlag(SSLFlags.CentralSsl))
            {
                // Do not allow CentralSSL flag to be set on the default binding
                // Logic elsewhere in the program should prevent this
                // from happening. This is merely a sanity check
                if (string.IsNullOrEmpty(host))
                {
                    throw new InvalidOperationException("Central SSL is not supported without a hostname");
                }
                flags &= ~SSLFlags.NotWithCentralSsl;
            }

            // All checks passed, return flags
            return(flags);
        }
示例#6
0
        public void UpdateWildcardFuzzy(string storeName, string bindingIp, int bindingPort, SSLFlags inputFlags, SSLFlags expectedFlags)
        {
            var originalBindings = new List <MockBinding> {
                new MockBinding()
                {
                    IP              = DefaultIP,
                    Port            = DefaultPort,
                    Host            = "site1.example.com",
                    Protocol        = "https",
                    CertificateHash = scopeCert
                }
            };
            var site = new MockSite()
            {
                Id       = httpOnlyId,
                Bindings = originalBindings.ToList()
            };
            var iis = new MockIISClient(log)
            {
                MockSites = new[] { site }
            };
            var bindingOptions = new BindingOptions().
                                 WithSiteId(httpOnlyId).
                                 WithIP(bindingIp).
                                 WithPort(bindingPort).
                                 WithStore(storeName).
                                 WithFlags(inputFlags).
                                 WithThumbprint(newCert);

            iis.AddOrUpdateBindings(new[] { "*.example.com" }, bindingOptions, oldCert1);

            var expectedBindings = inputFlags.HasFlag(SSLFlags.CentralSSL) ? 2 : 1;

            Assert.AreEqual(expectedBindings, site.Bindings.Count);
            foreach (var newBinding in site.Bindings.Except(originalBindings))
            {
                Assert.AreEqual("https", newBinding.Protocol);
                Assert.AreEqual(storeName, newBinding.CertificateStoreName);
                Assert.AreEqual(newCert, newBinding.CertificateHash);
                Assert.AreEqual(DefaultPort, newBinding.Port);
                Assert.AreEqual(DefaultIP, newBinding.IP);
                Assert.AreEqual(expectedFlags, newBinding.SSLFlags);
            }
        }