ssl_tests.cpp 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. #include <gtest/gtest.h>
  2. #include <chrono>
  3. #include <string>
  4. #include <thread>
  5. #include <vector>
  6. #include <cpr/cprtypes.h>
  7. #include <cpr/filesystem.h>
  8. #include <cpr/ssl_options.h>
  9. #include "httpsServer.hpp"
  10. using namespace cpr;
  11. static HttpsServer* server;
  12. static std::string caCertPath;
  13. static std::string serverPubKeyPath;
  14. static std::string clientKeyPath;
  15. static std::string clientCertPath;
  16. std::string loadCertificateFromFile(const std::string certPath) {
  17. std::ifstream certFile(certPath);
  18. std::stringstream buffer;
  19. buffer << certFile.rdbuf();
  20. return buffer.str();
  21. }
  22. TEST(SslTests, HelloWorldTestSimpel) {
  23. std::this_thread::sleep_for(std::chrono::seconds(1));
  24. Url url{server->GetBaseUrl() + "/hello.html"};
  25. std::string baseDirPath{server->getBaseDirPath()};
  26. std::string crtPath{baseDirPath + "certificates/"};
  27. std::string keyPath{baseDirPath + "keys/"};
  28. SslOptions sslOpts = Ssl(ssl::CaPath{crtPath + "root-ca.crt"}, ssl::CertFile{crtPath + "client.crt"}, ssl::KeyFile{keyPath + "client.key"}, ssl::VerifyPeer{false}, ssl::PinnedPublicKey{keyPath + "server.pub"}, ssl::VerifyHost{false}, ssl::VerifyStatus{false});
  29. Response response = cpr::Get(url, sslOpts, Timeout{5000}, Verbose{});
  30. std::string expected_text = "Hello world!";
  31. EXPECT_EQ(expected_text, response.text);
  32. EXPECT_EQ(url, response.url);
  33. EXPECT_EQ(std::string{"text/html"}, response.header["content-type"]);
  34. EXPECT_EQ(200, response.status_code);
  35. EXPECT_EQ(ErrorCode::OK, response.error.code) << response.error.message;
  36. }
  37. TEST(SslTests, HelloWorldTestFull) {
  38. std::this_thread::sleep_for(std::chrono::seconds(1));
  39. Url url{server->GetBaseUrl() + "/hello.html"};
  40. std::string baseDirPath{server->getBaseDirPath()};
  41. std::string crtPath{baseDirPath + "certificates/"};
  42. std::string keyPath{baseDirPath + "keys/"};
  43. SslOptions sslOpts = Ssl(ssl::TLSv1{}, ssl::ALPN{false}, ssl::NPN{false}, ssl::CaPath{crtPath + "root-ca.crt"}, ssl::CertFile{crtPath + "client.crt"}, ssl::KeyFile{keyPath + "client.key"}, ssl::PinnedPublicKey{keyPath + "server.pub"}, ssl::VerifyPeer{false}, ssl::VerifyHost{false}, ssl::VerifyStatus{false});
  44. Response response = cpr::Get(url, sslOpts, Timeout{5000}, Verbose{});
  45. std::string expected_text = "Hello world!";
  46. EXPECT_EQ(expected_text, response.text);
  47. EXPECT_EQ(url, response.url);
  48. EXPECT_EQ(std::string{"text/html"}, response.header["content-type"]);
  49. EXPECT_EQ(200, response.status_code);
  50. EXPECT_EQ(ErrorCode::OK, response.error.code) << response.error.message;
  51. }
  52. TEST(SslTests, GetCertInfos) {
  53. std::this_thread::sleep_for(std::chrono::seconds(1));
  54. Url url{server->GetBaseUrl() + "/hello.html"};
  55. std::string baseDirPath{server->getBaseDirPath()};
  56. std::string crtPath{baseDirPath + "certificates/"};
  57. std::string keyPath{baseDirPath + "keys/"};
  58. SslOptions sslOpts = Ssl(ssl::CaPath{crtPath + "root-ca.crt"}, ssl::CertFile{crtPath + "client.crt"}, ssl::KeyFile{keyPath + "client.key"}, ssl::VerifyPeer{false}, ssl::VerifyHost{false}, ssl::VerifyStatus{false});
  59. Response response = cpr::Get(url, sslOpts, Timeout{5000}, Verbose{});
  60. std::vector<CertInfo> certInfos = response.GetCertInfos();
  61. std::string expected_text = "Hello world!";
  62. std::vector<CertInfo> expectedCertInfos{
  63. CertInfo{
  64. "Subject:CN = test-server",
  65. "Issuer:C = GB, O = Example, CN = Root CA",
  66. "Version:2",
  67. "Serial Number:28c252871ec62a626a98006b0bf2888f",
  68. "Signature Algorithm:ED25519",
  69. "Public Key Algorithm:ED25519",
  70. "X509v3 Subject Alternative Name:DNS:localhost, IP Address:127.0.0.1, IP Address:0:0:0:0:0:0:0:1",
  71. "X509v3 Subject Key Identifier:39:C1:81:38:01:DC:55:38:E5:2F:4E:7A:D0:4C:84:7B:B7:27:D3:AF",
  72. "X509v3 Authority Key Identifier:E4:F2:F3:85:0E:B7:85:75:84:76:E3:43:D1:B6:9D:14:B8:E2:A4:B7",
  73. "Start date:Jun 29 11:33:07 2022 GMT",
  74. "Expire date:Jun 28 11:33:07 2027 GMT",
  75. "Signature:2e:0d:a1:0d:f5:90:77:e9:eb:84:7d:80:63:63:4d:8a:eb:d9:23:57:1f:21:2a:ed:81:b4:a8:58:b9:00:1b:cb:5c:90:1b:33:6b:f6:ec:42:20:63:54:d6:60:ee:37:14:1b:1c:95:0b:33:ea:67:29:d4:cc:d9:7e:34:fd:47:04:",
  76. R"(Cert:-----BEGIN CERTIFICATE-----
  77. MIIBdTCCASegAwIBAgIQKMJShx7GKmJqmABrC/KIjzAFBgMrZXAwMTELMAkGA1UE
  78. BhMCR0IxEDAOBgNVBAoMB0V4YW1wbGUxEDAOBgNVBAMMB1Jvb3QgQ0EwHhcNMjIw
  79. NjI5MTEzMzA3WhcNMjcwNjI4MTEzMzA3WjAWMRQwEgYDVQQDDAt0ZXN0LXNlcnZl
  80. cjAqMAUGAytlcAMhAI64JU5RjfdEG1KQMxS5DQWkiGlKIQO7ye4mNFq9QleTo3Aw
  81. bjAsBgNVHREEJTAjgglsb2NhbGhvc3SHBH8AAAGHEAAAAAAAAAAAAAAAAAAAAAEw
  82. HQYDVR0OBBYEFDnBgTgB3FU45S9OetBMhHu3J9OvMB8GA1UdIwQYMBaAFOTy84UO
  83. t4V1hHbjQ9G2nRS44qS3MAUGAytlcANBAC4NoQ31kHfp64R9gGNjTYrr2SNXHyEq
  84. 7YG0qFi5ABvLXJAbM2v27EIgY1TWYO43FBsclQsz6mcp1MzZfjT9RwQ=
  85. -----END CERTIFICATE-----
  86. )",
  87. },
  88. };
  89. EXPECT_EQ(expected_text, response.text);
  90. EXPECT_EQ(url, response.url);
  91. EXPECT_EQ(std::string{"text/html"}, response.header["content-type"]);
  92. EXPECT_EQ(200, response.status_code);
  93. EXPECT_EQ(ErrorCode::OK, response.error.code) << response.error.message;
  94. EXPECT_EQ(1, certInfos.size());
  95. for (auto certInfo_it = certInfos.begin(), expectedCertInfo_it = expectedCertInfos.begin(); certInfo_it != certInfos.end() && expectedCertInfo_it != expectedCertInfos.end(); certInfo_it++, expectedCertInfo_it++) {
  96. 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++) {
  97. std::string search_string = "Identifier:keyid:";
  98. std::size_t search_index = (*entry_it).find(search_string);
  99. if (search_index != std::string::npos) {
  100. (*entry_it).replace(search_index, search_string.length(), "Identifier:");
  101. search_string = "\n";
  102. search_index = (*entry_it).find(search_string);
  103. if (search_index != std::string::npos) {
  104. (*entry_it).replace(search_index, search_string.length(), "");
  105. }
  106. }
  107. EXPECT_EQ(*expectedEntry_it, *entry_it);
  108. }
  109. std::cout << std::endl;
  110. }
  111. }
  112. #if SUPPORT_CURLOPT_SSL_CTX_FUNCTION
  113. TEST(SslTests, LoadCertFromBufferTestSimpel) {
  114. std::this_thread::sleep_for(std::chrono::seconds(1));
  115. Url url{server->GetBaseUrl() + "/hello.html"};
  116. std::string baseDirPath{server->getBaseDirPath()};
  117. std::string crtPath{baseDirPath + "certificates/"};
  118. std::string keyPath{baseDirPath + "keys/"};
  119. std::string certBuffer = loadCertificateFromFile(crtPath + "root-ca.crt");
  120. SslOptions sslOpts = Ssl(ssl::CaBuffer{std::move(certBuffer)}, ssl::CertFile{crtPath + "client.crt"}, ssl::KeyFile{keyPath + "client.key"}, ssl::VerifyPeer{false}, ssl::VerifyHost{false}, ssl::VerifyStatus{false});
  121. Response response = cpr::Get(url, sslOpts, Timeout{5000}, Verbose{});
  122. std::string expected_text = "Hello world!";
  123. EXPECT_EQ(expected_text, response.text);
  124. EXPECT_EQ(url, response.url);
  125. EXPECT_EQ(std::string{"text/html"}, response.header["content-type"]);
  126. EXPECT_EQ(200, response.status_code);
  127. EXPECT_EQ(ErrorCode::OK, response.error.code) << response.error.message;
  128. }
  129. #endif
  130. fs::path getBasePath(const std::string& execPath) {
  131. return fs::path(fs::path{execPath}.parent_path().string() + "/").make_preferred();
  132. }
  133. int main(int argc, char** argv) {
  134. ::testing::InitGoogleTest(&argc, argv);
  135. fs::path baseDirPath = fs::path{getBasePath(argv[0]).string() + "data/"};
  136. fs::path serverCertPath = fs::path{baseDirPath}.append("certificates/server.crt");
  137. fs::path serverKeyPath = fs::path{baseDirPath}.append("keys/server.key");
  138. server = new HttpsServer(std::move(baseDirPath), std::move(serverCertPath), std::move(serverKeyPath));
  139. ::testing::AddGlobalTestEnvironment(server);
  140. return RUN_ALL_TESTS();
  141. }