From 289cc25709b081cd112d47db66c4f2fbf4609583 Mon Sep 17 00:00:00 2001 From: René Korthaus Date: Thu, 20 Apr 2017 09:54:19 +0200 Subject: Complete wildcard handling for X.509 certificates Hostname validation is used to make sure the certificate hostname matches the hostname of the connected host. RFC 6125 allows one wildcard in the left-most label of a hostname. Up to now, we only supported only the wildcard as the left-most label, e.g., www.example.com would match *.example.com, but www.example.com would not match www*.example.com, although it is permitted. Also adds test vectors from RFC 6125 as well as the OpenSSL test suite. --- src/tests/data/hostnames.vec | 66 ++++++++++++++++++++++++++++++++++++++++++++ src/tests/test_utils.cpp | 28 +++++++++++++++++++ 2 files changed, 94 insertions(+) create mode 100644 src/tests/data/hostnames.vec (limited to 'src/tests') diff --git a/src/tests/data/hostnames.vec b/src/tests/data/hostnames.vec new file mode 100644 index 000000000..91296d2d8 --- /dev/null +++ b/src/tests/data/hostnames.vec @@ -0,0 +1,66 @@ +# Test vectors derived from from RFC 6125 and OpenSSL test suite +# https://github.com/openssl/openssl/blob/master/test/v3nametest.c + +Issued = example +Hostname = example + +Issued = example.com +Hostname = example.com + +Issued = a.example.com +Hostname = a.example.com + +Issued = test.www.example.com +Hostname = test.www.example.com + +Issued = *.example.com +Hostname = foo.example.com + +Issued = baz*.example.net +Hostname = baz1.example.net + +Issued = baz*.example.net +Hostname = baz.example.net + +Issued = *baz.example.net +Hostname = foobaz.example.net + +Issued = *baz.example.net +Hostname = baz.example.net + +Issued = b*z.example.net +Hostname = buzz.example.net + +Issued = foo*bar.example.net +Hostname = foobar.example.net + +Issued = *.www.example.com +Hostname = test.www.example.com + +Issued = *www.example.com +Hostname = www.example.com + +[Invalid] +Issued = example.com +Hostname = www.example.com + +Issued = www.example.com +Hostname = example.com + +Issued = bar.*.example.net +Hostname = bar.foo.example.net + +Issued = *.example.com +Hostname = bar.foo.example.com + +Issued = *.example.com +Hostname = example.com + +Issued = foo*foo.example.com +Hostname = foo.example.com + +Issued = **.example.com +Hostname = foo.example.com + +Issued = *.*.example.com +Hostname = foo.bar.example.com diff --git a/src/tests/test_utils.cpp b/src/tests/test_utils.cpp index a2601722d..8c1d353b4 100644 --- a/src/tests/test_utils.cpp +++ b/src/tests/test_utils.cpp @@ -1,6 +1,7 @@ /* * (C) 2015 Jack Lloyd * (C) 2016 Daniel Neus, Rohde & Schwarz Cybersecurity +* (C) 2017 René Korthaus, Rohde & Schwarz Cybersecurity * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -12,6 +13,7 @@ #include #include #include +#include #if defined(BOTAN_HAS_BASE64_CODEC) #include @@ -454,6 +456,32 @@ class Charset_Tests : public Text_Based_Test BOTAN_REGISTER_TEST("charset", Charset_Tests); +class Hostname_Tests : public Text_Based_Test + { + public: + Hostname_Tests() : Text_Based_Test("hostnames.vec", "Issued,Hostname") + {} + + Test::Result run_one_test(const std::string& type, const VarMap& vars) override + { + using namespace Botan; + + Test::Result result("Hostname"); + + const std::string issued = get_req_str(vars, "Issued"); + const std::string hostname = get_req_str(vars, "Hostname"); + const bool expected = (type == "Invalid") ? false : true; + + const std::string what = hostname + ((expected == true) ? + " matches " : " does not match ") + issued; + result.test_eq(what, Botan::host_wildcard_match(issued, hostname), expected); + + return result; + } + }; + +BOTAN_REGISTER_TEST("hostname", Hostname_Tests); + } } -- cgit v1.2.3