Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Replaced the secureStringClear mechanism with a SecureString class #1170

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
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
1 change: 0 additions & 1 deletion cpr/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ add_library(cpr
accept_encoding.cpp
async.cpp
auth.cpp
bearer.cpp
callback.cpp
cert_info.cpp
cookies.cpp
Expand Down
5 changes: 0 additions & 5 deletions cpr/auth.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#include "cpr/auth.h"
#include "cpr/util.h"

#include <string_view>

Expand All @@ -12,10 +11,6 @@ Authentication::Authentication(std::string_view username, std::string_view passw
auth_string_ += password;
}

Authentication::~Authentication() noexcept {
util::secureStringClear(auth_string_);
}

const char* Authentication::GetAuthString() const noexcept {
return auth_string_.c_str();
}
Expand Down
17 changes: 0 additions & 17 deletions cpr/bearer.cpp

This file was deleted.

5 changes: 3 additions & 2 deletions cpr/cookies.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <iomanip>
#include <sstream>
#include <string>
#include <string_view>

namespace cpr {
const std::string Cookie::GetDomain() const {
Expand Down Expand Up @@ -53,15 +54,15 @@ const std::string Cookies::GetEncoded(const CurlHolder& holder) const {
std::stringstream stream;
for (const cpr::Cookie& item : cookies_) {
// Depending on if encoding is set to "true", we will URL-encode cookies
stream << (encode ? holder.urlEncode(item.GetName()) : item.GetName()) << "=";
stream << (encode ? std::string_view{holder.urlEncode(item.GetName())} : std::string_view{item.GetName()}) << "=";

// special case version 1 cookies, which can be distinguished by
// beginning and trailing quotes
if (!item.GetValue().empty() && item.GetValue().front() == '"' && item.GetValue().back() == '"') {
stream << item.GetValue();
} else {
// Depending on if encoding is set to "true", we will URL-encode cookies
stream << (encode ? holder.urlEncode(item.GetValue()) : item.GetValue());
stream << (encode ? std::string_view{holder.urlEncode(item.GetValue())} : std::string_view{item.GetValue()});
}
stream << "; ";
}
Expand Down
6 changes: 3 additions & 3 deletions cpr/curl_container.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@ const std::string CurlContainer<Parameter>::GetContent(const CurlHolder& holder)
content += "&";
}

const std::string escapedKey = encode ? holder.urlEncode(parameter.key) : parameter.key;
const std::string escapedKey = encode ? std::string{holder.urlEncode(parameter.key)} : parameter.key;
if (parameter.value.empty()) {
content += escapedKey;
} else {
const std::string escapedValue = encode ? holder.urlEncode(parameter.value) : parameter.value;
const std::string escapedValue = encode ? std::string{holder.urlEncode(parameter.value)} : parameter.value;
content += escapedKey + "=";
content += escapedValue;
}
Expand All @@ -47,7 +47,7 @@ const std::string CurlContainer<Pair>::GetContent(const CurlHolder& holder) cons
if (!content.empty()) {
content += "&";
}
const std::string escaped = encode ? holder.urlEncode(element.value) : element.value;
const std::string escaped = encode ? std::string{holder.urlEncode(element.value)} : element.value;
content += element.key + "=" + escaped;
}

Expand Down
15 changes: 8 additions & 7 deletions cpr/curlholder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
#include <cassert>
#include <curl/curl.h>
#include <curl/easy.h>
#include <string>
#include <string_view>
#include "cpr/secure_string.h"

namespace cpr {
CurlHolder::CurlHolder() {
Expand All @@ -28,22 +29,22 @@ CurlHolder::~CurlHolder() {
curl_easy_cleanup(handle);
}

std::string CurlHolder::urlEncode(const std::string& s) const {
util::SecureString CurlHolder::urlEncode(std::string_view s) const {
assert(handle);
char* output = curl_easy_escape(handle, s.c_str(), static_cast<int>(s.length()));
char* output = curl_easy_escape(handle, s.data(), static_cast<int>(s.length()));
if (output) {
std::string result = output;
util::SecureString result = output;
curl_free(output);
return result;
}
return "";
}

std::string CurlHolder::urlDecode(const std::string& s) const {
util::SecureString CurlHolder::urlDecode(std::string_view s) const {
assert(handle);
char* output = curl_easy_unescape(handle, s.c_str(), static_cast<int>(s.length()), nullptr);
char* output = curl_easy_unescape(handle, s.data(), static_cast<int>(s.length()), nullptr);
if (output) {
std::string result = output;
util::SecureString result = output;
curl_free(output);
return result;
}
Expand Down
6 changes: 1 addition & 5 deletions cpr/file.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,7 @@

namespace cpr {

Files::Files(const std::initializer_list<std::string>& p_filepaths) {
for (const std::string& filepath : p_filepaths) {
files.emplace_back(filepath);
}
}
Files::Files(const std::initializer_list<std::string>& p_filepaths) : files(p_filepaths.begin(), p_filepaths.end()) {}

Files::iterator Files::begin() {
return files.begin();
Expand Down
16 changes: 6 additions & 10 deletions cpr/proxyauth.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,25 @@
#include <string>

namespace cpr {
EncodedAuthentication::~EncodedAuthentication() noexcept {
util::secureStringClear(username);
util::secureStringClear(password);
}

const std::string& EncodedAuthentication::GetUsername() const {
std::string_view EncodedAuthentication::GetUsername() const {
return username;
}

const std::string& EncodedAuthentication::GetPassword() const {
std::string_view EncodedAuthentication::GetPassword() const {
return password;
}

bool ProxyAuthentication::has(const std::string& protocol) const {
return proxyAuth_.count(protocol) > 0;
}

const char* ProxyAuthentication::GetUsername(const std::string& protocol) {
return proxyAuth_[protocol].username.c_str();
std::string_view ProxyAuthentication::GetUsername(const std::string& protocol) {
return proxyAuth_[protocol].GetUsername();
}

const char* ProxyAuthentication::GetPassword(const std::string& protocol) {
return proxyAuth_[protocol].password.c_str();
std::string_view ProxyAuthentication::GetPassword(const std::string& protocol) {
return proxyAuth_[protocol].GetPassword();
}

} // namespace cpr
2 changes: 1 addition & 1 deletion cpr/session.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -903,7 +903,7 @@ const std::optional<Response> Session::intercept() {
if (current_interceptor_ == interceptors_.end()) {
current_interceptor_ = first_interceptor_;
} else {
current_interceptor_++;
++current_interceptor_;
}

if (current_interceptor_ != interceptors_.end()) {
Expand Down
52 changes: 7 additions & 45 deletions cpr/util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <curl/curl.h>
#include <fstream>
#include <ios>
#include <iterator>
#include <sstream>
#include <string>
#include <type_traits>
Expand Down Expand Up @@ -166,7 +167,7 @@ int debugUserFunction(CURL* /*handle*/, curl_infotype type, char* data, size_t s
* std::string input = "Hello World!";
* std::string result = holder.urlEncode(input);
**/
std::string urlEncode(const std::string& s) {
util::SecureString urlEncode(std::string_view s) {
const CurlHolder holder; // Create a temporary new holder for URL encoding
return holder.urlEncode(s);
}
Expand All @@ -181,55 +182,16 @@ std::string urlEncode(const std::string& s) {
* std::string input = "Hello%20World%21";
* std::string result = holder.urlDecode(input);
**/
std::string urlDecode(const std::string& s) {
util::SecureString urlDecode(std::string_view s) {
const CurlHolder holder; // Create a temporary new holder for URL decoding
return holder.urlDecode(s);
}

#if defined(__STDC_LIB_EXT1__)
void secureStringClear(std::string& s) {
if (s.empty()) {
return;
}
memset_s(&s.front(), s.length(), 0, s.length());
s.clear();
}
#elif defined(_WIN32)
void secureStringClear(std::string& s) {
if (s.empty()) {
return;
}
SecureZeroMemory(&s.front(), s.length());
s.clear();
}
#else
#if defined(__clang__)
#pragma clang optimize off // clang
#elif defined(__GNUC__) || defined(__MINGW32__) || defined(__MINGW32__) || defined(__MINGW64__)
#pragma GCC push_options // g++
#pragma GCC optimize("O0") // g++
#endif
void secureStringClear(std::string& s) {
if (s.empty()) {
return;
}
// NOLINTNEXTLINE (readability-container-data-pointer)
char* ptr = &(s[0]);
memset(ptr, '\0', s.length());
s.clear();
}

#if defined(__clang__)
#pragma clang optimize on // clang
#elif defined(__GNUC__) || defined(__MINGW32__) || defined(__MINGW32__) || defined(__MINGW64__)
#pragma GCC pop_options // g++
#endif
#endif

bool isTrue(const std::string& s) {
std::string temp_string{s};
std::transform(temp_string.begin(), temp_string.end(), temp_string.begin(), [](unsigned char c) { return static_cast<unsigned char>(std::tolower(c)); });
return temp_string == "true";
constexpr std::string_view tmp = "true";
auto [s_it, tmp_it] = std::mismatch(s.begin(), s.end(), tmp.begin(), tmp.end(),
[](auto s_c, auto t_c) { return std::tolower(s_c) == t_c; });
return s_it == s.end() && tmp_it == tmp.end();
}

time_t sTimestampToT(const std::string& st) {
Expand Down
1 change: 1 addition & 0 deletions include/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ target_sources(cpr PRIVATE
cpr/proxies.h
cpr/proxyauth.h
cpr/response.h
cpr/secure_string.h
cpr/session.h
cpr/singleton.h
cpr/ssl_ctx.h
Expand Down
8 changes: 3 additions & 5 deletions include/cpr/auth.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,21 @@
#include <string>
#include <string_view>

#include "cpr/util.h"

namespace cpr {

enum class AuthMode { BASIC, DIGEST, NTLM, NEGOTIATE };

class Authentication {
public:
Authentication(std::string_view username, std::string_view password, AuthMode auth_mode);
Authentication(const Authentication& other) = default;
~Authentication() noexcept;

Authentication& operator=(const Authentication& other) = default;

const char* GetAuthString() const noexcept;
AuthMode GetAuthMode() const noexcept;

private:
std::string auth_string_;
util::SecureString auth_string_;
AuthMode auth_mode_;
};

Expand Down
12 changes: 8 additions & 4 deletions include/cpr/bearer.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

#include <utility>

#include "cpr/util.h"

namespace cpr {

// Only supported with libcurl >= 7.61.0.
Expand All @@ -14,18 +16,20 @@ namespace cpr {
class Bearer {
public:
// NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions)
Bearer(std::string token) : token_string_{std::move(token)} {}
Bearer(std::string_view token) : token_string_{token} {}
Bearer(const Bearer& other) = default;
Bearer(Bearer&& old) noexcept = default;
virtual ~Bearer() noexcept;
virtual ~Bearer() noexcept = default;

Bearer& operator=(Bearer&& old) noexcept = default;
Bearer& operator=(const Bearer& other) = default;

virtual const char* GetToken() const noexcept;
virtual const char* GetToken() const noexcept {
return token_string_.c_str();
}

protected:
std::string token_string_;
util::SecureString token_string_;
};
#endif

Expand Down
7 changes: 5 additions & 2 deletions include/cpr/curlholder.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
#include <mutex>
#include <string>

#include "cpr/secure_string.h"

namespace cpr {

struct CurlHolder {
private:
/**
Expand Down Expand Up @@ -41,12 +44,12 @@ struct CurlHolder {
/**
* Uses curl_easy_escape(...) for escaping the given string.
**/
[[nodiscard]] std::string urlEncode(const std::string& s) const;
[[nodiscard]] util::SecureString urlEncode(std::string_view s) const;

/**
* Uses curl_easy_unescape(...) for unescaping the given string.
**/
[[nodiscard]] std::string urlDecode(const std::string& s) const;
[[nodiscard]] util::SecureString urlDecode(std::string_view s) const;
};
} // namespace cpr

Expand Down
Loading