Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions cpr/session.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,20 @@ void Session::SetSslOptions(const SslOptions& options) {
curl_easy_setopt(curl_->handle, CURLOPT_SSLCERTTYPE, options.cert_type.c_str());
}
}
#if SUPPORT_CURLOPT_SSLCERT_BLOB
else if(!options.cert_blob.empty()) {
std::string cert_blob(options.cert_blob);
curl_blob blob{};
// NOLINTNEXTLINE (readability-container-data-pointer)
blob.data = &cert_blob[0];
blob.len = cert_blob.length();
blob.flags = CURL_BLOB_COPY;
curl_easy_setopt(curl_->handle, CURLOPT_SSLCERT_BLOB, &blob);
if (!options.cert_type.empty()) {
curl_easy_setopt(curl_->handle, CURLOPT_SSLCERTTYPE, options.cert_type.c_str());
}
}
#endif
if (!options.key_file.empty()) {
curl_easy_setopt(curl_->handle, CURLOPT_SSLKEY, options.key_file.c_str());
if (!options.key_type.empty()) {
Expand Down
44 changes: 44 additions & 0 deletions include/cpr/ssl_options.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@
#ifndef SUPPORT_CURLOPT_CAINFO_BLOB
#define SUPPORT_CURLOPT_CAINFO_BLOB LIBCURL_VERSION_NUM >= 0x074D00 // 7.77.0
#endif
#ifndef SUPPORT_CURLOPT_SSLCERT_BLOB
#define SUPPORT_CURLOPT_SSLCERT_BLOB LIBCURL_VERSION_NUM >= 0x074700 // 7.71.0
#endif

namespace cpr {

Expand Down Expand Up @@ -117,6 +120,38 @@ class DerCert : public CertFile {
}
};


#if SUPPORT_CURLOPT_SSLCERT_BLOB
class CertBlob {
public:
// NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions)
CertBlob(std::string&& p_blob) : blob(std::move(p_blob)) {}

virtual ~CertBlob() = default;

std::string blob;

virtual const char* GetCertType() const {
return "PEM";
}
};

using PemBlob = CertBlob;

class DerBlob : public CertBlob {
public:
template <typename BlobType>
// NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions)
DerBlob(BlobType&& p_blob) : CertBlob(std::move(p_blob)) {}

~DerBlob() override = default;

const char* GetCertType() const override {
return "DER";
}
};
#endif

// specify private keyfile for TLS and SSL client cert
class KeyFile {
public:
Expand Down Expand Up @@ -423,6 +458,9 @@ class NoRevoke {
struct SslOptions {
// We don't use fs::path here, as this leads to problems using windows
std::string cert_file;
#if SUPPORT_CURLOPT_SSLCERT_BLOB
util::SecureString cert_blob;
#endif
std::string cert_type;
// We don't use fs::path here, as this leads to problems using windows
std::string key_file;
Expand Down Expand Up @@ -472,6 +510,12 @@ struct SslOptions {
cert_file = opt.filename.string();
cert_type = opt.GetCertType();
}
#if SUPPORT_CURLOPT_SSLCERT_BLOB
void SetOption(const ssl::CertBlob& opt) {
cert_blob = opt.blob;
cert_type = opt.GetCertType();
}
#endif
void SetOption(const ssl::KeyFile& opt) {
key_file = opt.filename.string();
key_type = opt.GetKeyType();
Expand Down
21 changes: 21 additions & 0 deletions test/ssl_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,27 @@ TEST(SslTests, LoadCertFromBufferTestSimpel) {
}
#endif

#if SUPPORT_CURLOPT_SSLCERT_BLOB
TEST(SslTests, LoadCertFromBlobTestSimpel) {
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 crtBuffer = loadFileContent(crtPath + "client.crt");
SslOptions sslOpts = Ssl(ssl::CaInfo{crtPath + "ca-bundle.crt"}, ssl::CertBlob{std::move(crtBuffer)}, 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));
Expand Down
Loading