Skip to content

Commit 10896fd

Browse files
committed
Enable automatic proxy logon with implicit credentials.
Fixes #248
1 parent 32c2730 commit 10896fd

File tree

2 files changed

+39
-10
lines changed

2 files changed

+39
-10
lines changed

src/_native/bits.cpp

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -229,12 +229,17 @@ static HRESULT _job_setproxy(IBackgroundCopyJob *job) {
229229
}
230230

231231

232-
static HRESULT _job_setcredentials(IBackgroundCopyJob *job, wchar_t *username, wchar_t *password) {
232+
static HRESULT _job_setcredentials(
233+
IBackgroundCopyJob *job,
234+
BG_AUTH_TARGET target,
235+
wchar_t *username,
236+
wchar_t *password
237+
) {
233238
IBackgroundCopyJob2 *job2 = NULL;
234239
HRESULT hr;
235240
BG_AUTH_CREDENTIALS creds = {
236-
.Target = BG_AUTH_TARGET_SERVER,
237-
.Scheme = BG_AUTH_SCHEME_BASIC,
241+
.Target = target,
242+
.Scheme = username ? BG_AUTH_SCHEME_BASIC : BG_AUTH_SCHEME_NEGOTIATE,
238243
.Credentials = {
239244
.Basic = {
240245
.UserName = username,
@@ -243,10 +248,6 @@ static HRESULT _job_setcredentials(IBackgroundCopyJob *job, wchar_t *username, w
243248
}
244249
};
245250

246-
if (!username && !password) {
247-
return S_OK;
248-
}
249-
250251
if (FAILED(hr = _inject_hr[3])
251252
|| FAILED(hr = job->QueryInterface(__uuidof(IBackgroundCopyJob2), (void **)&job2))) {
252253
return hr;
@@ -285,7 +286,14 @@ PyObject *bits_begin(PyObject *, PyObject *args, PyObject *kwargs) {
285286
error_from_bits_hr(bcm, hr, "Setting proxy");
286287
goto done;
287288
}
288-
if ((username || password) && FAILED(hr = _job_setcredentials(job, username, password))) {
289+
// Setting proxy credentials to NULL will automatically infer credentials
290+
// if needed. It's a good default (provided users have not configured a
291+
// malicious proxy server, which we can't do anything about here anyway).
292+
if (FAILED(hr = _job_setcredentials(job, BG_AUTH_TARGET_PROXY, NULL, NULL))) {
293+
error_from_bits_hr(bcm, hr, "Setting proxy credentials");
294+
goto done;
295+
}
296+
if (FAILED(hr = _job_setcredentials(job, BG_AUTH_TARGET_SERVER, username, password))) {
289297
error_from_bits_hr(bcm, hr, "Adding basic credentials to download job");
290298
goto done;
291299
}
@@ -387,7 +395,7 @@ PyObject *bits_retry_with_auth(PyObject *, PyObject *args, PyObject *kwargs) {
387395
HRESULT hr;
388396
PyObject *r = NULL;
389397

390-
if (FAILED(hr = _job_setcredentials(job, username, password))) {
398+
if (FAILED(hr = _job_setcredentials(job, BG_AUTH_TARGET_SERVER, username, password))) {
391399
error_from_bits_hr(bcm, hr, "Adding basic credentials to download job");
392400
goto done;
393401
}

src/_native/winhttp.cpp

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,16 @@ static bool winhttp_apply_proxy(HINTERNET hSession, HINTERNET hRequest, const wc
190190
// Now resolve the proxy required for the specified URL
191191
CHECK_WINHTTP(WinHttpGetProxyForUrl(hSession, url, &proxy_opt, &proxy_info));
192192

193+
// Enable proxy servers to automatically login with implicit credentials
194+
// This is only used if the proxy sends a 407 response, otherwise, they are
195+
// ignored.
196+
CHECK_WINHTTP(WinHttpSetCredentials(
197+
hRequest,
198+
WINHTTP_AUTH_TARGET_PROXY,
199+
WINHTTP_AUTH_SCHEME_NEGOTIATE,
200+
NULL, NULL, NULL
201+
));
202+
193203
// Apply the proxy settings to the request
194204
CHECK_WINHTTP(WinHttpSetOption(
195205
hRequest,
@@ -285,6 +295,17 @@ PyObject *winhttp_urlopen(PyObject *, PyObject *args, PyObject *kwargs) {
285295
0
286296
);
287297
}
298+
299+
// Allow proxies to automatically log in (we'll set the default credentials
300+
// in winhttp_apply_proxy(), but this setting has to go on the session).
301+
opt = WINHTTP_AUTOLOGON_SECURITY_LEVEL_LOW;
302+
CHECK_WINHTTP(WinHttpSetOption(
303+
hSession,
304+
WINHTTP_OPTION_AUTOLOGON_POLICY,
305+
&opt,
306+
sizeof(opt)
307+
));
308+
288309
CHECK_WINHTTP(hSession);
289310

290311
hConnection = WinHttpConnect(
@@ -456,7 +477,7 @@ PyObject *winhttp_urlopen(PyObject *, PyObject *args, PyObject *kwargs) {
456477
PyObject *winhttp_isconnected(PyObject *, PyObject *, PyObject *) {
457478
INetworkListManager *nlm = NULL;
458479
VARIANT_BOOL connected;
459-
480+
460481
HRESULT hr = CoCreateInstance(
461482
CLSID_NetworkListManager,
462483
NULL,

0 commit comments

Comments
 (0)