public void WildcardOnlyMatchesNullServerNameDueToNoAlpn()
    {
        var sniDictionary = new Dictionary <string, SniConfig>
        {
            {
                "*",
                new SniConfig
                {
                    Certificate = new CertificateConfig
                    {
                        Path = "WildcardOnly"
                    }
                }
            }
        };

        var mockCertificateConfigLoader = new MockCertificateConfigLoader();
        var pathDictionary = mockCertificateConfigLoader.CertToPathDictionary;

        var sniOptionsSelector = new SniOptionsSelector(
            "TestEndpointName",
            sniDictionary,
            mockCertificateConfigLoader,
            fallbackHttpsOptions: new HttpsConnectionAdapterOptions(),
            fallbackHttpProtocols: HttpProtocols.Http1AndHttp2,
            logger: Mock.Of <ILogger <HttpsConnectionMiddleware> >());

        var(options, _) = sniOptionsSelector.GetOptions(new MockConnectionContext(), null);
        Assert.Equal("WildcardOnly", pathDictionary[options.ServerCertificate]);
    }
Esempio n. 2
0
        public void ServerNameMatchingIsCaseInsensitive()
        {
            var sniDictionary = new Dictionary <string, SniConfig>
            {
                {
                    "Www.Example.Org",
                    new SniConfig
                    {
                        Certificate = new CertificateConfig
                        {
                            Path = "Exact"
                        }
                    }
                },
                {
                    "*.Example.Org",
                    new SniConfig
                    {
                        Certificate = new CertificateConfig
                        {
                            Path = "WildcardPrefix"
                        }
                    }
                }
            };

            var mockCertificateConfigLoader = new MockCertificateConfigLoader();
            var pathDictionary = mockCertificateConfigLoader.CertToPathDictionary;

            var sniOptionsSelector = new SniOptionsSelector(
                "TestEndpointName",
                sniDictionary,
                mockCertificateConfigLoader,
                fallbackHttpsOptions: new HttpsConnectionAdapterOptions(),
                fallbackHttpProtocols: HttpProtocols.Http1AndHttp2,
                logger: Mock.Of <ILogger <HttpsConnectionMiddleware> >());

            var wwwSubdomainOptions = sniOptionsSelector.GetOptions(new MockConnectionContext(), "wWw.eXample.oRg");

            Assert.Equal("Exact", pathDictionary[wwwSubdomainOptions.ServerCertificate]);

            var baSubdomainOptions = sniOptionsSelector.GetOptions(new MockConnectionContext(), "B.a.eXample.oRg");

            Assert.Equal("WildcardPrefix", pathDictionary[baSubdomainOptions.ServerCertificate]);

            var aSubdomainOptions = sniOptionsSelector.GetOptions(new MockConnectionContext(), "A.eXample.oRg");

            Assert.Equal("WildcardPrefix", pathDictionary[aSubdomainOptions.ServerCertificate]);
        }
Esempio n. 3
0
        public void PerfersLongerWildcardPrefixOverShorterWildcardPrefix()
        {
            var sniDictionary = new Dictionary <string, SniConfig>
            {
                {
                    "*.a.example.org",
                    new SniConfig
                    {
                        Certificate = new CertificateConfig
                        {
                            Path = "Long"
                        }
                    }
                },
                {
                    "*.example.org",
                    new SniConfig
                    {
                        Certificate = new CertificateConfig
                        {
                            Path = "Short"
                        }
                    }
                }
            };

            var mockCertificateConfigLoader = new MockCertificateConfigLoader();
            var pathDictionary = mockCertificateConfigLoader.CertToPathDictionary;

            var sniOptionsSelector = new SniOptionsSelector(
                "TestEndpointName",
                sniDictionary,
                mockCertificateConfigLoader,
                fallbackHttpsOptions: new HttpsConnectionAdapterOptions(),
                fallbackHttpProtocols: HttpProtocols.Http1AndHttp2,
                logger: Mock.Of <ILogger <HttpsConnectionMiddleware> >());

            var baSubdomainOptions = sniOptionsSelector.GetOptions(new MockConnectionContext(), "b.a.example.org");

            Assert.Equal("Long", pathDictionary[baSubdomainOptions.ServerCertificate]);

            // "*.a.example.org" is preferred over "*.example.org", but "a.example.org" doesn't match "*.a.example.org".
            var aSubdomainOptions = sniOptionsSelector.GetOptions(new MockConnectionContext(), "a.example.org");

            Assert.Equal("Short", pathDictionary[aSubdomainOptions.ServerCertificate]);
        }
    public void MultipleWildcardPrefixServerNamesOfSameLengthAreAllowed()
    {
        var sniDictionary = new Dictionary <string, SniConfig>
        {
            {
                "*.a.example.org",
                new SniConfig
                {
                    Certificate = new CertificateConfig
                    {
                        Path = "a"
                    }
                }
            },
            {
                "*.b.example.org",
                new SniConfig
                {
                    Certificate = new CertificateConfig
                    {
                        Path = "b"
                    }
                }
            }
        };

        var mockCertificateConfigLoader = new MockCertificateConfigLoader();
        var pathDictionary = mockCertificateConfigLoader.CertToPathDictionary;

        var sniOptionsSelector = new SniOptionsSelector(
            "TestEndpointName",
            sniDictionary,
            mockCertificateConfigLoader,
            fallbackHttpsOptions: new HttpsConnectionAdapterOptions(),
            fallbackHttpProtocols: HttpProtocols.Http1AndHttp2,
            logger: Mock.Of <ILogger <HttpsConnectionMiddleware> >());

        var(aSubdomainOptions, _) = sniOptionsSelector.GetOptions(new MockConnectionContext(), "c.a.example.org");
        Assert.Equal("a", pathDictionary[aSubdomainOptions.ServerCertificate]);

        var(bSubdomainOptions, _) = sniOptionsSelector.GetOptions(new MockConnectionContext(), "c.b.example.org");
        Assert.Equal("b", pathDictionary[bSubdomainOptions.ServerCertificate]);
    }
    public void DuplicateWildcardPrefixServerNamesThrowsArgumentException()
    {
        var sniDictionary = new Dictionary <string, SniConfig>
        {
            {
                "*.example.org",
                new SniConfig
                {
                    Certificate = new CertificateConfig
                    {
                        Path = "a"
                    }
                }
            },
            {
                "*.EXAMPLE.org",
                new SniConfig
                {
                    Certificate = new CertificateConfig
                    {
                        Path = "b"
                    }
                }
            }
        };

        var mockCertificateConfigLoader = new MockCertificateConfigLoader();
        var pathDictionary = mockCertificateConfigLoader.CertToPathDictionary;

        var exception = Assert.Throws <ArgumentException>(() => new SniOptionsSelector(
                                                              "TestEndpointName",
                                                              sniDictionary,
                                                              mockCertificateConfigLoader,
                                                              fallbackHttpsOptions: new HttpsConnectionAdapterOptions(),
                                                              fallbackHttpProtocols: HttpProtocols.Http1AndHttp2,
                                                              logger: Mock.Of <ILogger <HttpsConnectionMiddleware> >()));

        Assert.Equal("An item with the same key has already been added. Key: .EXAMPLE.org (Parameter 'key')", exception.Message);
    }
    public void PrefersExactMatchOverWildcardPrefixOverWildcardOnly()
    {
        var sniDictionary = new Dictionary <string, SniConfig>
        {
            {
                "www.example.org",
                new SniConfig
                {
                    Certificate = new CertificateConfig
                    {
                        Path = "Exact"
                    }
                }
            },
            {
                "*.example.org",
                new SniConfig
                {
                    Certificate = new CertificateConfig
                    {
                        Path = "WildcardPrefix"
                    }
                }
            },
            {
                "*",
                new SniConfig
                {
                    Certificate = new CertificateConfig
                    {
                        Path = "WildcardOnly"
                    }
                }
            }
        };

        var mockCertificateConfigLoader = new MockCertificateConfigLoader();
        var pathDictionary = mockCertificateConfigLoader.CertToPathDictionary;

        var sniOptionsSelector = new SniOptionsSelector(
            "TestEndpointName",
            sniDictionary,
            mockCertificateConfigLoader,
            fallbackHttpsOptions: new HttpsConnectionAdapterOptions(),
            fallbackHttpProtocols: HttpProtocols.Http1AndHttp2,
            logger: Mock.Of <ILogger <HttpsConnectionMiddleware> >());

        var(wwwSubdomainOptions, _) = sniOptionsSelector.GetOptions(new MockConnectionContext(), "www.example.org");
        Assert.Equal("Exact", pathDictionary[wwwSubdomainOptions.ServerCertificate]);

        var(baSubdomainOptions, _) = sniOptionsSelector.GetOptions(new MockConnectionContext(), "b.a.example.org");
        Assert.Equal("WildcardPrefix", pathDictionary[baSubdomainOptions.ServerCertificate]);

        var(aSubdomainOptions, _) = sniOptionsSelector.GetOptions(new MockConnectionContext(), "a.example.org");
        Assert.Equal("WildcardPrefix", pathDictionary[aSubdomainOptions.ServerCertificate]);

        // "*.example.org" is preferred over "*", but "*.example.org" doesn't match "example.org".
        // REVIEW: Are we OK with "example.org" matching "*" instead of "*.example.org"? It feels annoying to me to have to configure example.org twice.
        // Unfortunately, the alternative would have "a.example.org" match "*.a.example.org" before "*.example.org", and that just seems wrong.
        var(noSubdomainOptions, _) = sniOptionsSelector.GetOptions(new MockConnectionContext(), "example.org");
        Assert.Equal("WildcardOnly", pathDictionary[noSubdomainOptions.ServerCertificate]);

        var(anotherTldOptions, _) = sniOptionsSelector.GetOptions(new MockConnectionContext(), "dot.net");
        Assert.Equal("WildcardOnly", pathDictionary[anotherTldOptions.ServerCertificate]);
    }
    public void FullChainCertsCanBeLoaded()
    {
        var sniDictionary = new Dictionary <string, SniConfig>
        {
            {
                "Www.Example.Org",
                new SniConfig
                {
                    Certificate = new CertificateConfig
                    {
                        Path = "Exact"
                    }
                }
            },
            {
                "*.Example.Org",
                new SniConfig
                {
                    Certificate = new CertificateConfig
                    {
                        Path = "WildcardPrefix"
                    }
                }
            }
        };

        var mockCertificateConfigLoader = new MockCertificateConfigLoader();
        var pathDictionary      = mockCertificateConfigLoader.CertToPathDictionary;
        var fullChainDictionary = mockCertificateConfigLoader.CertToFullChain;

        var sniOptionsSelector = new SniOptionsSelector(
            "TestEndpointName",
            sniDictionary,
            mockCertificateConfigLoader,
            fallbackHttpsOptions: new HttpsConnectionAdapterOptions(),
            fallbackHttpProtocols: HttpProtocols.Http1AndHttp2,
            logger: Mock.Of <ILogger <HttpsConnectionMiddleware> >());

        var(wwwSubdomainOptions, _) = sniOptionsSelector.GetOptions(new MockConnectionContext(), "wWw.eXample.oRg");
        Assert.Equal("Exact", pathDictionary[wwwSubdomainOptions.ServerCertificate]);

        var(baSubdomainOptions, _) = sniOptionsSelector.GetOptions(new MockConnectionContext(), "B.a.eXample.oRg");
        Assert.Equal("WildcardPrefix", pathDictionary[baSubdomainOptions.ServerCertificate]);

        var(aSubdomainOptions, _) = sniOptionsSelector.GetOptions(new MockConnectionContext(), "A.eXample.oRg");
        Assert.Equal("WildcardPrefix", pathDictionary[aSubdomainOptions.ServerCertificate]);

        /*
         * Chain test certs were created using smallstep cli: https://github.com/smallstep/cli
         * root_ca(pwd: testroot) ->
         * intermediate_ca 1(pwd: inter) ->
         * intermediate_ca 2(pwd: inter) ->
         * leaf.com(pwd: leaf) (bundled)
         */
        var fullChain = fullChainDictionary[aSubdomainOptions.ServerCertificate];

        // Expect intermediate 2 cert and leaf.com
        Assert.Equal(2, fullChain.Count);
        Assert.Equal("CN=leaf.com", fullChain[0].Subject);
        Assert.Equal("CN=Test Intermediate CA 2", fullChain[0].IssuerName.Name);
        Assert.Equal("CN=Test Intermediate CA 2", fullChain[1].Subject);
        Assert.Equal("CN=Test Intermediate CA 1", fullChain[1].IssuerName.Name);
    }