Skip to content

Commit c121ee0

Browse files
authored
Merge pull request #1181 from simue/fix/proxy-authentication-segfault
Fix Seg-fault when setting proxy username + password
2 parents bc4f169 + 245affc commit c121ee0

File tree

6 files changed

+47
-17
lines changed

6 files changed

+47
-17
lines changed

cpr/curlholder.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
#include "cpr/curlholder.h"
2+
#include "cpr/secure_string.h"
23
#include <cassert>
34
#include <curl/curl.h>
45
#include <curl/easy.h>
56
#include <string_view>
6-
#include "cpr/secure_string.h"
77

88
namespace cpr {
99
CurlHolder::CurlHolder() {

cpr/proxyauth.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include "cpr/proxyauth.h"
22
#include <string>
33
#include <string_view>
4+
#include "cpr/secure_string.h"
45

56
namespace cpr {
67

@@ -12,6 +13,14 @@ std::string_view EncodedAuthentication::GetPassword() const {
1213
return password;
1314
}
1415

16+
const util::SecureString& EncodedAuthentication::GetUsernameUnderlying() const {
17+
return username;
18+
}
19+
20+
const util::SecureString& EncodedAuthentication::GetPasswordUnderlying() const {
21+
return password;
22+
}
23+
1524
bool ProxyAuthentication::has(const std::string& protocol) const {
1625
return proxyAuth_.count(protocol) > 0;
1726
}
@@ -24,4 +33,12 @@ std::string_view ProxyAuthentication::GetPassword(const std::string& protocol) {
2433
return proxyAuth_[protocol].GetPassword();
2534
}
2635

36+
const util::SecureString& ProxyAuthentication::GetUsernameUnderlying(const std::string& protocol) const {
37+
return proxyAuth_.at(protocol).GetUsernameUnderlying();
38+
}
39+
40+
const util::SecureString& ProxyAuthentication::GetPasswordUnderlying(const std::string& protocol) const {
41+
return proxyAuth_.at(protocol).GetPasswordUnderlying();
42+
}
43+
2744
} // namespace cpr

cpr/session.cpp

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,17 @@ void Session::prepareHeader() {
116116
curl_->chunk = chunk;
117117
}
118118

119+
void Session::prepareProxy() {
120+
const std::string protocol = url_.str().substr(0, url_.str().find(':'));
121+
if (proxies_.has(protocol)) {
122+
curl_easy_setopt(curl_->handle, CURLOPT_PROXY, proxies_[protocol].c_str());
123+
if (proxyAuth_.has(protocol)) {
124+
curl_easy_setopt(curl_->handle, CURLOPT_PROXYUSERNAME, proxyAuth_.GetUsernameUnderlying(protocol).c_str());
125+
curl_easy_setopt(curl_->handle, CURLOPT_PROXYPASSWORD, proxyAuth_.GetPasswordUnderlying(protocol).c_str());
126+
}
127+
}
128+
}
129+
119130
// Only supported with libcurl >= 7.61.0.
120131
// As an alternative use SetHeader and add the token manually.
121132
#if LIBCURL_VERSION_NUM >= 0x073D00
@@ -173,14 +184,8 @@ void Session::prepareCommonShared() {
173184
}
174185

175186
// Proxy:
176-
const std::string protocol = url_.str().substr(0, url_.str().find(':'));
177-
if (proxies_.has(protocol)) {
178-
curl_easy_setopt(curl_->handle, CURLOPT_PROXY, proxies_[protocol].c_str());
179-
if (proxyAuth_.has(protocol)) {
180-
curl_easy_setopt(curl_->handle, CURLOPT_PROXYUSERNAME, proxyAuth_.GetUsername(protocol));
181-
curl_easy_setopt(curl_->handle, CURLOPT_PROXYPASSWORD, proxyAuth_.GetPassword(protocol));
182-
}
183-
}
187+
prepareProxy();
188+
184189
// handle NO_PROXY override passed through Proxies object
185190
// Example: Proxies{"no_proxy": ""} will override environment variable definition with an empty list
186191
const std::array<std::string, 2> no_proxy{"no_proxy", "NO_PROXY"};
@@ -658,14 +663,7 @@ cpr_off_t Session::GetDownloadFileLength() {
658663
cpr_off_t downloadFileLength = -1;
659664
curl_easy_setopt(curl_->handle, CURLOPT_URL, url_.c_str());
660665

661-
const std::string protocol = url_.str().substr(0, url_.str().find(':'));
662-
if (proxies_.has(protocol)) {
663-
curl_easy_setopt(curl_->handle, CURLOPT_PROXY, proxies_[protocol].c_str());
664-
if (proxyAuth_.has(protocol)) {
665-
curl_easy_setopt(curl_->handle, CURLOPT_PROXYUSERNAME, proxyAuth_.GetUsername(protocol));
666-
curl_easy_setopt(curl_->handle, CURLOPT_PROXYPASSWORD, proxyAuth_.GetPassword(protocol));
667-
}
668-
}
666+
prepareProxy();
669667

670668
curl_easy_setopt(curl_->handle, CURLOPT_HTTPGET, 1);
671669
curl_easy_setopt(curl_->handle, CURLOPT_NOBODY, 1);

include/cpr/proxyauth.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ class EncodedAuthentication {
2727

2828
[[nodiscard]] std::string_view GetUsername() const;
2929
[[nodiscard]] std::string_view GetPassword() const;
30+
[[nodiscard]] const util::SecureString& GetUsernameUnderlying() const;
31+
[[nodiscard]] const util::SecureString& GetPasswordUnderlying() const;
3032

3133
private:
3234
util::SecureString username;
@@ -42,6 +44,8 @@ class ProxyAuthentication {
4244
[[nodiscard]] bool has(const std::string& protocol) const;
4345
[[nodiscard]] std::string_view GetUsername(const std::string& protocol);
4446
[[nodiscard]] std::string_view GetPassword(const std::string& protocol);
47+
[[nodiscard]] const util::SecureString& GetUsernameUnderlying(const std::string& protocol) const;
48+
[[nodiscard]] const util::SecureString& GetPasswordUnderlying(const std::string& protocol) const;
4549

4650
private:
4751
std::map<std::string, EncodedAuthentication> proxyAuth_;

include/cpr/session.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,7 @@ class Session : public std::enable_shared_from_this<Session> {
296296
**/
297297
void prepareCommonDownload();
298298
void prepareHeader();
299+
void prepareProxy();
299300
CURLcode DoEasyPerform();
300301
void prepareBodyPayloadOrMultipart() const;
301302
/**

test/proxy_auth_tests.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,16 @@ using namespace cpr;
1717

1818
static HttpServer* server = new HttpServer();
1919

20+
TEST(ProxyAuthTests, SetProxyCredentials) {
21+
Url url{server->GetBaseUrl() + "/hello.html"};
22+
Session session;
23+
session.SetUrl(url);
24+
session.SetProxies(Proxies{{"http", HTTP_PROXY}, {"https", HTTPS_PROXY}});
25+
session.SetProxyAuth({{"http", EncodedAuthentication{PROXY_USER, PROXY_PASS}}, {"https", EncodedAuthentication{PROXY_USER, PROXY_PASS}}});
26+
session.PrepareGet();
27+
EXPECT_TRUE(true);
28+
}
29+
2030
// TODO: These should be fixed after a source code implementation of a proxy
2131
#if defined(false)
2232
TEST(ProxyAuthTests, SingleProxyTest) {

0 commit comments

Comments
 (0)