diff --git a/test/Makefile b/test/Makefile index 0a72252..fe866a6 100644 --- a/test/Makefile +++ b/test/Makefile @@ -15,6 +15,11 @@ test : test.cc ../httplib.h Makefile cert.pem cert.pem: openssl genrsa 2048 > key.pem openssl req -new -batch -config test.conf -key key.pem | openssl x509 -days 3650 -req -signkey key.pem > cert.pem + openssl genrsa 2048 > rootCA.key.pem + openssl req -x509 -new -batch -config test.rootCA.conf -key rootCA.key.pem -days 1024 > rootCA.cert.pem + openssl genrsa 2048 > client.key.pem + openssl req -new -batch -config test.conf -key client.key.pem | openssl x509 -days 370 -req -CA rootCA.cert.pem -CAkey rootCA.key.pem -CAcreateserial > client.cert.pem + c_rehash . clean: - rm -f test *.pem + rm -f test *.pem *.0 *.1 *.srl diff --git a/test/test.cc b/test/test.cc index afa1363..3637d69 100644 --- a/test/test.cc +++ b/test/test.cc @@ -5,6 +5,10 @@ #define SERVER_CERT_FILE "./cert.pem" #define SERVER_PRIVATE_KEY_FILE "./key.pem" #define CA_CERT_FILE "./ca-bundle.crt" +#define CLIENT_CA_CERT_FILE "./rootCA.cert.pem" +#define CLIENT_CERT_FILE "./client.cert.pem" +#define CLIENT_PRIVATE_KEY_FILE "./client.key.pem" +#define TRUST_CERT_DIR "." #ifdef _WIN32 #include @@ -1374,6 +1378,70 @@ TEST(SSLClientTest, WildcardHostNameMatch) { ASSERT_TRUE(res != nullptr); ASSERT_EQ(200, res->status); } + +TEST(SSLClientServerTest, ClientCertPresent) { + SSLServer svr(SERVER_CERT_FILE, SERVER_PRIVATE_KEY_FILE, CLIENT_CA_CERT_FILE, TRUST_CERT_DIR); + ASSERT_TRUE(svr.is_valid()); + + svr.Get("/test", [&](const Request &, Response &res){ + res.set_content("test", "text/plain"); + svr.stop(); + }); + + thread t = thread([&]() { ASSERT_TRUE(svr.listen(HOST, PORT)); }); + + httplib::SSLClient cli(HOST, PORT, 30, CLIENT_CERT_FILE, CLIENT_PRIVATE_KEY_FILE); + auto res = cli.Get("/test"); + ASSERT_TRUE(res != nullptr); + ASSERT_EQ(200, res->status); + + t.join(); +} + +TEST(SSLClientServerTest, ClientCertMissing) { + SSLServer svr(SERVER_CERT_FILE, SERVER_PRIVATE_KEY_FILE, CLIENT_CA_CERT_FILE, TRUST_CERT_DIR); + ASSERT_TRUE(svr.is_valid()); + + svr.Get("/test", [&](const Request &, Response &res){ + res.set_content("test", "text/plain"); + svr.stop(); + }); + + thread t = thread([&]() { ASSERT_TRUE(svr.listen(HOST, PORT)); }); + + httplib::SSLClient cli(HOST, PORT, 30); + auto res = cli.Get("/test"); + ASSERT_TRUE(res == nullptr); + + svr.stop(); + + t.join(); +} + +TEST(SSLClientServerTest, TrustDirOptional) { + SSLServer svr(SERVER_CERT_FILE, SERVER_PRIVATE_KEY_FILE, CLIENT_CA_CERT_FILE); + ASSERT_TRUE(svr.is_valid()); + + svr.Get("/test", [&](const Request &, Response &res){ + res.set_content("test", "text/plain"); + svr.stop(); + }); + + thread t = thread([&]() { ASSERT_TRUE(svr.listen(HOST, PORT)); }); + + httplib::SSLClient cli(HOST, PORT, 30, CLIENT_CERT_FILE, CLIENT_PRIVATE_KEY_FILE); + auto res = cli.Get("/test"); + ASSERT_TRUE(res != nullptr); + ASSERT_EQ(200, res->status); + + t.join(); +} + +/* Cannot test this case as there is no external access to SSL object to check SSL_get_peer_certificate() == NULL +TEST(SSLClientServerTest, ClientCAPathRequired) { + SSLServer svr(SERVER_CERT_FILE, SERVER_PRIVATE_KEY_FILE, nullptr, TRUST_CERT_DIR); +} +*/ #endif #ifdef _WIN32 diff --git a/test/test.rootCA.conf b/test/test.rootCA.conf new file mode 100644 index 0000000..9d7037d --- /dev/null +++ b/test/test.rootCA.conf @@ -0,0 +1,18 @@ +[req] +default_bits = 2048 +distinguished_name = req_distinguished_name +attributes = req_attributes +prompt = no +output_password = mypass + +[req_distinguished_name] +C = US +ST = Test State or Province +L = Test Locality +O = Organization Name +OU = Organizational Unit Name +CN = Root CA Name +emailAddress = test@email.address + +[req_attributes] +challengePassword = 1234