1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
|
#include <gtest/gtest.h>
#include <chrono>
#include <string>
#include <thread>
#include <vector>
#include "cpr/cprtypes.h"
#include "cpr/filesystem.h"
#include "cpr/ssl_options.h"
#include "httpsServer.hpp"
using namespace cpr;
static HttpsServer* server;
static std::string caCertPath;
static std::string serverPubKeyPath;
static std::string clientKeyPath;
static std::string clientCertPath;
std::string loadFileContent(const std::string filePath) {
std::ifstream file(filePath);
std::stringstream buffer;
buffer << file.rdbuf();
return buffer.str();
}
TEST(SslTests, HelloWorldTestSimpel) {
std::this_thread::sleep_for(std::chrono::seconds(1));
Url url{server->GetBaseUrl() + "/hello.html"};
std::string baseDirPath{server->getBaseDirPath()};
std::string crtPath{baseDirPath + "certificates/"};
std::string keyPath{baseDirPath + "keys/"};
SslOptions sslOpts = Ssl(ssl::CaInfo{crtPath + "ca-bundle.crt"}, ssl::CertFile{crtPath + "client.crt"}, ssl::KeyFile{keyPath + "client.key"}, ssl::VerifyPeer{true}, ssl::PinnedPublicKey{keyPath + "server.pub"}, ssl::VerifyHost{true}, ssl::VerifyStatus{false});
Response response = cpr::Get(url, sslOpts, Timeout{5000}, Verbose{});
std::string expected_text = "Hello world!";
EXPECT_EQ(expected_text, response.text);
EXPECT_EQ(url, response.url);
EXPECT_EQ(std::string{"text/html"}, response.header["content-type"]);
EXPECT_EQ(200, response.status_code);
EXPECT_EQ(ErrorCode::OK, response.error.code) << response.error.message;
}
TEST(SslTests, HelloWorldTestFull) {
std::this_thread::sleep_for(std::chrono::seconds(1));
Url url{server->GetBaseUrl() + "/hello.html"};
std::string baseDirPath{server->getBaseDirPath()};
std::string crtPath{baseDirPath + "certificates/"};
std::string keyPath{baseDirPath + "keys/"};
SslOptions sslOpts = Ssl(ssl::TLSv1{}, ssl::ALPN{false},
#if SUPPORT_NPN
ssl::NPN{false},
#endif // DEBUG
ssl::CaInfo{crtPath + "ca-bundle.crt"}, ssl::CertFile{crtPath + "client.crt"}, ssl::KeyFile{keyPath + "client.key"}, ssl::PinnedPublicKey{keyPath + "server.pub"}, ssl::VerifyPeer{true}, ssl::VerifyHost{true}, ssl::VerifyStatus{false});
Response response = cpr::Get(url, sslOpts, Timeout{5000}, Verbose{});
std::string expected_text = "Hello world!";
EXPECT_EQ(expected_text, response.text);
EXPECT_EQ(url, response.url);
EXPECT_EQ(std::string{"text/html"}, response.header["content-type"]);
EXPECT_EQ(200, response.status_code);
EXPECT_EQ(ErrorCode::OK, response.error.code) << response.error.message;
}
TEST(SslTests, GetCertInfos) {
std::this_thread::sleep_for(std::chrono::seconds(1));
Url url{server->GetBaseUrl() + "/hello.html"};
std::string baseDirPath{server->getBaseDirPath()};
std::string crtPath{baseDirPath + "certificates/"};
std::string keyPath{baseDirPath + "keys/"};
SslOptions sslOpts = Ssl(ssl::CaInfo{crtPath + "ca-bundle.crt"}, ssl::CertFile{crtPath + "client.crt"}, ssl::KeyFile{keyPath + "client.key"}, ssl::VerifyPeer{true}, ssl::VerifyHost{true}, ssl::VerifyStatus{false});
Response response = cpr::Get(url, sslOpts, Timeout{5000}, Verbose{});
std::vector<CertInfo> certInfos = response.GetCertInfos();
std::string expected_text = "Hello world!";
std::vector<CertInfo> expectedCertInfos{
CertInfo{
"Subject:CN = test-server",
"Issuer:C = GB, O = Example, CN = Sub CA",
"Version:2",
"Serial Number:acbefc2cde5b900b55548396556765d4",
"Signature Algorithm:ED25519",
"Public Key Algorithm:ED25519",
"X509v3 Authority Key Identifier:9B:B1:9B:21:61:DC:66:2B:3A:AD:ED:84:F1:05:B6:CE:99:82:C1:FC",
"X509v3 Basic Constraints:CA:FALSE",
"X509v3 Extended Key Usage:TLS Web Client Authentication, TLS Web Server Authentication",
"X509v3 Key Usage:Digital Signature, Key Encipherment",
"X509v3 Subject Key Identifier:66:47:54:F8:25:97:56:9A:52:56:35:B4:A7:52:60:0C:E7:4F:33:09",
"X509v3 Subject Alternative Name:DNS:localhost, IP Address:127.0.0.1, IP Address:0:0:0:0:0:0:0:1",
"Start date:May 7 10:18:22 2024 GMT",
"Expire date:May 6 10:18:22 2029 GMT",
"Signature:6d:63:d9:11:a3:9b:c7:9f:b6:23:12:27:e9:34:e0:a1:a3:20:be:fb:df:80:fe:53:08:9d:8c:e4:82:42:76:c2:55:13:e8:7c:86:83:33:0b:9a:9f:92:2a:3f:de:e9:32:78:c0:b1:bc:3f:42:e9:17:f9:9f:6c:15:35:a3:01:09:",
R"(Cert:-----BEGIN CERTIFICATE-----
MIIBtDCCAWagAwIBAgIRAKy+/CzeW5ALVVSDllVnZdQwBQYDK2VwMDAxCzAJBgNV
BAYTAkdCMRAwDgYDVQQKDAdFeGFtcGxlMQ8wDQYDVQQDDAZTdWIgQ0EwHhcNMjQw
NTA3MTAxODIyWhcNMjkwNTA2MTAxODIyWjAWMRQwEgYDVQQDDAt0ZXN0LXNlcnZl
cjAqMAUGAytlcAMhACdLUqJFSyspgGKJiXNlnOLU2dO/TLV+b8aIZNAX7EuVo4Gu
MIGrMB8GA1UdIwQYMBaAFJuxmyFh3GYrOq3thPEFts6ZgsH8MAwGA1UdEwEB/wQC
MAAwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMA4GA1UdDwEB/wQEAwIF
oDAdBgNVHQ4EFgQUZkdU+CWXVppSVjW0p1JgDOdPMwkwLAYDVR0RBCUwI4IJbG9j
YWxob3N0hwR/AAABhxAAAAAAAAAAAAAAAAAAAAABMAUGAytlcANBAG1j2RGjm8ef
tiMSJ+k04KGjIL7734D+UwidjOSCQnbCVRPofIaDMwuan5IqP97pMnjAsbw/QukX
+Z9sFTWjAQk=
-----END CERTIFICATE-----
)",
},
};
EXPECT_EQ(expected_text, response.text);
EXPECT_EQ(url, response.url);
EXPECT_EQ(std::string{"text/html"}, response.header["content-type"]);
EXPECT_EQ(200, response.status_code);
EXPECT_EQ(ErrorCode::OK, response.error.code) << response.error.message;
EXPECT_EQ(1, certInfos.size());
for (auto certInfo_it = certInfos.begin(), expectedCertInfo_it = expectedCertInfos.begin(); certInfo_it != certInfos.end() && expectedCertInfo_it != expectedCertInfos.end(); certInfo_it++, expectedCertInfo_it++) {
for (auto entry_it = (*certInfo_it).begin(), expectedEntry_it = (*expectedCertInfo_it).begin(); entry_it != (*certInfo_it).end() && expectedEntry_it != (*expectedCertInfo_it).end(); entry_it++, expectedEntry_it++) {
std::string search_string = "Identifier:keyid:";
std::size_t search_index = (*entry_it).find(search_string);
if (search_index != std::string::npos) {
(*entry_it).replace(search_index, search_string.length(), "Identifier:");
search_string = "\n";
search_index = (*entry_it).find(search_string);
if (search_index != std::string::npos) {
(*entry_it).replace(search_index, search_string.length(), "");
}
}
EXPECT_EQ(*expectedEntry_it, *entry_it);
}
std::cout << '\n';
}
}
#if SUPPORT_CURLOPT_SSL_CTX_FUNCTION
TEST(SslTests, LoadCertFromBufferTestSimpel) {
std::this_thread::sleep_for(std::chrono::seconds(1));
Url url{server->GetBaseUrl() + "/hello.html"};
std::string baseDirPath{server->getBaseDirPath()};
std::string crtPath{baseDirPath + "certificates/"};
std::string keyPath{baseDirPath + "keys/"};
std::string certBuffer = loadFileContent(crtPath + "ca-bundle.crt");
SslOptions sslOpts = Ssl(ssl::CaBuffer{std::move(certBuffer)}, ssl::CertFile{crtPath + "client.crt"}, ssl::KeyFile{keyPath + "client.key"}, ssl::VerifyPeer{true}, ssl::VerifyHost{true}, ssl::VerifyStatus{false});
Response response = cpr::Get(url, sslOpts, Timeout{5000}, Verbose{});
std::string expected_text = "Hello world!";
EXPECT_EQ(expected_text, response.text);
EXPECT_EQ(url, response.url);
EXPECT_EQ(std::string{"text/html"}, response.header["content-type"]);
EXPECT_EQ(200, response.status_code);
EXPECT_EQ(ErrorCode::OK, response.error.code) << response.error.message;
}
#endif
#if SUPPORT_CURLOPT_SSLKEY_BLOB
TEST(SslTests, LoadKeyFromBlobTestSimpel) {
std::this_thread::sleep_for(std::chrono::seconds(1));
Url url{server->GetBaseUrl() + "/hello.html"};
std::string baseDirPath{server->getBaseDirPath()};
std::string crtPath{baseDirPath + "certificates/"};
std::string keyPath{baseDirPath + "keys/"};
std::string keyBuffer = loadFileContent(keyPath + "client.key");
SslOptions sslOpts = Ssl(ssl::CaInfo{crtPath + "ca-bundle.crt"}, ssl::CertFile{crtPath + "client.crt"}, ssl::KeyBlob{std::move(keyBuffer)}, ssl::VerifyPeer{true}, ssl::VerifyHost{true}, ssl::VerifyStatus{false});
Response response = cpr::Get(url, sslOpts, Timeout{5000}, Verbose{});
std::string expected_text = "Hello world!";
EXPECT_EQ(expected_text, response.text);
EXPECT_EQ(url, response.url);
EXPECT_EQ(std::string{"text/html"}, response.header["content-type"]);
EXPECT_EQ(200, response.status_code);
EXPECT_EQ(ErrorCode::OK, response.error.code) << response.error.message;
}
#endif
fs::path GetBasePath(const std::string& execPath) {
return fs::path(fs::path{execPath}.parent_path().string() + "/").make_preferred();
}
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
fs::path baseDirPath = fs::path{GetBasePath(argv[0]).string() + "data/"};
fs::path serverCertPath = fs::path{baseDirPath}.append("certificates/server.crt");
fs::path serverKeyPath = fs::path{baseDirPath}.append("keys/server.key");
server = new HttpsServer(std::move(baseDirPath), std::move(serverCertPath), std::move(serverKeyPath));
::testing::AddGlobalTestEnvironment(server);
return RUN_ALL_TESTS();
}
|