Skip to content

Commit 2265481

Browse files
committed
http transport: prompt for proxy credentials
Teach the HTTP transport how to prompt for proxy credentials.
1 parent 0328eef commit 2265481

File tree

1 file changed

+37
-19
lines changed

1 file changed

+37
-19
lines changed

src/transports/http.c

Lines changed: 37 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ static const char *receive_pack_service_url = "/git-receive-pack";
3737
static const char *get_verb = "GET";
3838
static const char *post_verb = "POST";
3939

40+
#define SERVER_TYPE_REMOTE "remote"
41+
#define SERVER_TYPE_PROXY "proxy"
42+
4043
#define OWNING_SUBTRANSPORT(s) ((http_subtransport *)(s)->parent.subtransport)
4144

4245
#define PARSE_ERROR_GENERIC -1
@@ -97,6 +100,7 @@ typedef struct {
97100
/* Authentication */
98101
git_cred *cred;
99102
git_cred *url_cred;
103+
git_cred *proxy_cred;
100104
git_vector auth_contexts;
101105
} http_subtransport;
102106

@@ -353,10 +357,19 @@ static int on_header_value(http_parser *parser, const char *str, size_t len)
353357
return 0;
354358
}
355359

360+
GIT_INLINE(void) free_cred(git_cred **cred)
361+
{
362+
if (*cred) {
363+
git_cred_free(*cred);
364+
(*cred) = NULL;
365+
}
366+
}
367+
356368
static int on_auth_required(
357369
git_cred **creds,
358370
http_parser *parser,
359371
const char *url,
372+
const char *type,
360373
git_cred_acquire_cb callback,
361374
void *callback_payload,
362375
const char *username,
@@ -367,17 +380,13 @@ static int on_auth_required(
367380
int ret;
368381

369382
if (!allowed_types) {
370-
giterr_set(GITERR_NET, "remote did not prompt for authentication mechanisms");
383+
giterr_set(GITERR_NET, "%s requested authentication but did not negotiate mechanisms", type);
371384
t->parse_error = PARSE_ERROR_GENERIC;
372385
return t->parse_error;
373386
}
374387

375388
if (callback) {
376-
if (*creds) {
377-
(*creds)->free(*creds);
378-
*creds = NULL;
379-
}
380-
389+
free_cred(creds);
381390
ret = callback(creds, url, username, allowed_types, callback_payload);
382391

383392
if (ret == GIT_PASSTHROUGH) {
@@ -390,7 +399,7 @@ static int on_auth_required(
390399
assert(*creds);
391400

392401
if (!((*creds)->credtype & allowed_types)) {
393-
giterr_set(GITERR_NET, "credential provider returned an invalid cred type");
402+
giterr_set(GITERR_NET, "%s credential provider returned an invalid cred type", type);
394403
t->parse_error = PARSE_ERROR_GENERIC;
395404
return t->parse_error;
396405
}
@@ -401,7 +410,8 @@ static int on_auth_required(
401410
}
402411
}
403412

404-
giterr_set(GITERR_NET, "authentication required but no callback set");
413+
giterr_set(GITERR_NET, "%s authentication required but no callback set",
414+
type);
405415
t->parse_error = PARSE_ERROR_GENERIC;
406416
return t->parse_error;
407417
}
@@ -412,7 +422,7 @@ static int on_headers_complete(http_parser *parser)
412422
http_subtransport *t = ctx->t;
413423
http_stream *s = ctx->s;
414424
git_buf buf = GIT_BUF_INIT;
415-
int allowed_www_auth_types = 0;
425+
int allowed_proxy_auth_types = 0, allowed_www_auth_types = 0;
416426

417427
/* Both parse_header_name and parse_header_value are populated
418428
* and ready for consumption. */
@@ -425,15 +435,29 @@ static int on_headers_complete(http_parser *parser)
425435
* these may be 407/401 (authentication is not complete) or a 200
426436
* (informing us that auth has completed).
427437
*/
428-
if (parse_authenticate_response(&t->www_authenticate, t,
438+
if (parse_authenticate_response(&t->proxy_authenticate, t,
439+
&allowed_proxy_auth_types) < 0 ||
440+
parse_authenticate_response(&t->www_authenticate, t,
429441
&allowed_www_auth_types) < 0)
430442
return t->parse_error = PARSE_ERROR_GENERIC;
431443

444+
/* Check for a proxy authentication failure. */
445+
if (parser->status_code == 407 && get_verb == s->verb)
446+
return on_auth_required(&t->proxy_cred,
447+
parser,
448+
t->proxy.url,
449+
SERVER_TYPE_PROXY,
450+
t->proxy.credentials,
451+
t->proxy.payload,
452+
t->proxy_data.user,
453+
allowed_proxy_auth_types);
454+
432455
/* Check for an authentication failure. */
433456
if (parser->status_code == 401 && get_verb == s->verb)
434457
return on_auth_required(&t->cred,
435458
parser,
436459
t->owner->url,
460+
SERVER_TYPE_REMOTE,
437461
t->owner->cred_acquire_cb,
438462
t->owner->cred_acquire_payload,
439463
t->gitserver_data.user,
@@ -1131,15 +1155,9 @@ static int http_close(git_smart_subtransport *subtransport)
11311155
t->gitserver_stream = NULL;
11321156
}
11331157

1134-
if (t->cred) {
1135-
t->cred->free(t->cred);
1136-
t->cred = NULL;
1137-
}
1138-
1139-
if (t->url_cred) {
1140-
t->url_cred->free(t->url_cred);
1141-
t->url_cred = NULL;
1142-
}
1158+
free_cred(&t->cred);
1159+
free_cred(&t->url_cred);
1160+
free_cred(&t->proxy_cred);
11431161

11441162
git_vector_foreach(&t->auth_contexts, i, context) {
11451163
if (context->free)

0 commit comments

Comments
 (0)