summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/http/mutual_tls.cpp174
1 files changed, 174 insertions, 0 deletions
diff --git a/test/http/mutual_tls.cpp b/test/http/mutual_tls.cpp
new file mode 100644
index 0000000000..b1b7878586
--- /dev/null
+++ b/test/http/mutual_tls.cpp
@@ -0,0 +1,174 @@
+#include "mutual_tls.hpp"
+
+#include <boost/asio/ip/address.hpp>
+#include <boost/asio/ssl/verify_context.hpp>
+
+#include <memory>
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h> // IWYU pragma: keep
+
+using ::testing::IsNull;
+using ::testing::NotNull;
+
+namespace
+{
+class OSSLX509
+{
+ X509* ptr = X509_new();
+
+ public:
+ OSSLX509& operator=(const OSSLX509&) = delete;
+ OSSLX509& operator=(OSSLX509&&) = delete;
+
+ OSSLX509(const OSSLX509&) = delete;
+ OSSLX509(OSSLX509&&) = delete;
+
+ OSSLX509() = default;
+ X509* get()
+ {
+ return ptr;
+ }
+ ~OSSLX509()
+ {
+ X509_free(ptr);
+ }
+};
+
+class OSSLX509StoreCTX
+{
+ X509_STORE_CTX* ptr = X509_STORE_CTX_new();
+
+ public:
+ OSSLX509StoreCTX& operator=(const OSSLX509StoreCTX&) = delete;
+ OSSLX509StoreCTX& operator=(OSSLX509StoreCTX&&) = delete;
+
+ OSSLX509StoreCTX(const OSSLX509StoreCTX&) = delete;
+ OSSLX509StoreCTX(OSSLX509StoreCTX&&) = delete;
+
+ OSSLX509StoreCTX() = default;
+ X509_STORE_CTX* get()
+ {
+ return ptr;
+ }
+ ~OSSLX509StoreCTX()
+ {
+ X509_STORE_CTX_free(ptr);
+ }
+};
+
+TEST(MutualTLS, GoodCert)
+{
+ OSSLX509 x509;
+
+ X509_NAME* name = X509_get_subject_name(x509.get());
+ std::array<unsigned char, 5> user = {'u', 's', 'e', 'r', '\0'};
+ X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, user.data(), -1, -1,
+ 0);
+
+ X509_EXTENSION* ex = X509V3_EXT_conf_nid(nullptr, nullptr, NID_key_usage,
+ "digitalSignature, keyAgreement");
+ ASSERT_THAT(ex, NotNull());
+ ASSERT_EQ(X509_add_ext(x509.get(), ex, -1), 1);
+ X509_EXTENSION_free(ex);
+ ex = X509V3_EXT_conf_nid(nullptr, nullptr, NID_ext_key_usage, "clientAuth");
+ ASSERT_THAT(ex, NotNull());
+ ASSERT_EQ(X509_add_ext(x509.get(), ex, -1), 1);
+ X509_EXTENSION_free(ex);
+
+ OSSLX509StoreCTX x509Store;
+ X509_STORE_CTX_set_current_cert(x509Store.get(), x509.get());
+
+ boost::asio::ip::address ip;
+ boost::asio::ssl::verify_context ctx(x509Store.get());
+ std::shared_ptr<persistent_data::UserSession> session = verifyMtlsUser(ip,
+ ctx);
+ ASSERT_THAT(session, NotNull());
+ EXPECT_THAT(session->username, "user");
+}
+
+TEST(MutualTLS, MissingSubject)
+{
+ OSSLX509 x509;
+
+ X509_EXTENSION* ex = X509V3_EXT_conf_nid(nullptr, nullptr, NID_key_usage,
+ "digitalSignature, keyAgreement");
+ ASSERT_THAT(ex, NotNull());
+ ASSERT_EQ(X509_add_ext(x509.get(), ex, -1), 1);
+ X509_EXTENSION_free(ex);
+ ex = X509V3_EXT_conf_nid(nullptr, nullptr, NID_ext_key_usage, "clientAuth");
+ ASSERT_THAT(ex, NotNull());
+ ASSERT_EQ(X509_add_ext(x509.get(), ex, -1), 1);
+ X509_EXTENSION_free(ex);
+
+ OSSLX509StoreCTX x509Store;
+ X509_STORE_CTX_set_current_cert(x509Store.get(), x509.get());
+
+ boost::asio::ip::address ip;
+ boost::asio::ssl::verify_context ctx(x509Store.get());
+ std::shared_ptr<persistent_data::UserSession> session = verifyMtlsUser(ip,
+ ctx);
+ ASSERT_THAT(session, IsNull());
+}
+
+TEST(MutualTLS, MissingKeyUsage)
+{
+ for (const char* usageString : {"digitalSignature", "keyAgreement"})
+ {
+ OSSLX509 x509;
+
+ X509_EXTENSION* ex = X509V3_EXT_conf_nid(nullptr, nullptr,
+ NID_key_usage, usageString);
+
+ ASSERT_THAT(ex, NotNull());
+ ASSERT_EQ(X509_add_ext(x509.get(), ex, -1), 1);
+ X509_EXTENSION_free(ex);
+ ex = X509V3_EXT_conf_nid(nullptr, nullptr, NID_ext_key_usage,
+ "clientAuth");
+ ASSERT_THAT(ex, NotNull());
+ ASSERT_EQ(X509_add_ext(x509.get(), ex, -1), 1);
+ X509_EXTENSION_free(ex);
+
+ OSSLX509StoreCTX x509Store;
+ X509_STORE_CTX_set_current_cert(x509Store.get(), x509.get());
+
+ boost::asio::ip::address ip;
+ boost::asio::ssl::verify_context ctx(x509Store.get());
+ std::shared_ptr<persistent_data::UserSession> session =
+ verifyMtlsUser(ip, ctx);
+ ASSERT_THAT(session, IsNull());
+ }
+}
+
+TEST(MutualTLS, MissingExtKeyUsage)
+{
+ OSSLX509 x509;
+
+ X509_EXTENSION* ex = X509V3_EXT_conf_nid(nullptr, nullptr, NID_key_usage,
+ "digitalSignature, keyAgreement");
+
+ ASSERT_THAT(ex, NotNull());
+ ASSERT_EQ(X509_add_ext(x509.get(), ex, -1), 1);
+ X509_EXTENSION_free(ex);
+
+ OSSLX509StoreCTX x509Store;
+ X509_STORE_CTX_set_current_cert(x509Store.get(), x509.get());
+
+ boost::asio::ip::address ip;
+ boost::asio::ssl::verify_context ctx(x509Store.get());
+ std::shared_ptr<persistent_data::UserSession> session = verifyMtlsUser(ip,
+ ctx);
+ ASSERT_THAT(session, IsNull());
+}
+
+TEST(MutualTLS, MissingCert)
+{
+ OSSLX509StoreCTX x509Store;
+
+ boost::asio::ip::address ip;
+ boost::asio::ssl::verify_context ctx(x509Store.get());
+ std::shared_ptr<persistent_data::UserSession> session = verifyMtlsUser(ip,
+ ctx);
+ ASSERT_THAT(session, IsNull());
+}
+} // namespace