libfetch: Retry with proxy auth when server returns 407
PR: 220468 Submitted by: Egil Hasting <egil.hasting@higen.org> (based on) Reviewed by: kevans, kp Approved by: kp MFC after: 2 weeks Sponsored by: Rubicon Communications, LLC ("Netgate") Differential Revision: https://reviews.freebsd.org/D29533
This commit is contained in:
parent
9aef4e7c2b
commit
345c30a94f
@ -73,6 +73,7 @@ __FBSDID("$FreeBSD$");
|
|||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
#include <stdbool.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -1387,6 +1388,8 @@ http_connect(struct url *URL, struct url *purl, const char *flags)
|
|||||||
int verbose;
|
int verbose;
|
||||||
int af, val;
|
int af, val;
|
||||||
int serrno;
|
int serrno;
|
||||||
|
bool isproxyauth = false;
|
||||||
|
http_auth_challenges_t proxy_challenges;
|
||||||
|
|
||||||
#ifdef INET6
|
#ifdef INET6
|
||||||
af = AF_UNSPEC;
|
af = AF_UNSPEC;
|
||||||
@ -1404,18 +1407,58 @@ http_connect(struct url *URL, struct url *purl, const char *flags)
|
|||||||
|
|
||||||
curl = (purl != NULL) ? purl : URL;
|
curl = (purl != NULL) ? purl : URL;
|
||||||
|
|
||||||
|
retry:
|
||||||
if ((conn = fetch_connect(curl->host, curl->port, af, verbose)) == NULL)
|
if ((conn = fetch_connect(curl->host, curl->port, af, verbose)) == NULL)
|
||||||
/* fetch_connect() has already set an error code */
|
/* fetch_connect() has already set an error code */
|
||||||
return (NULL);
|
return (NULL);
|
||||||
init_http_headerbuf(&headerbuf);
|
init_http_headerbuf(&headerbuf);
|
||||||
if (strcmp(URL->scheme, SCHEME_HTTPS) == 0 && purl) {
|
if (strcmp(URL->scheme, SCHEME_HTTPS) == 0 && purl) {
|
||||||
http_cmd(conn, "CONNECT %s:%d HTTP/1.1",
|
init_http_auth_challenges(&proxy_challenges);
|
||||||
URL->host, URL->port);
|
http_cmd(conn, "CONNECT %s:%d HTTP/1.1", URL->host, URL->port);
|
||||||
http_cmd(conn, "Host: %s:%d",
|
http_cmd(conn, "Host: %s:%d", URL->host, URL->port);
|
||||||
URL->host, URL->port);
|
if (isproxyauth) {
|
||||||
|
http_auth_params_t aparams;
|
||||||
|
init_http_auth_params(&aparams);
|
||||||
|
if (*purl->user || *purl->pwd) {
|
||||||
|
aparams.user = strdup(purl->user);
|
||||||
|
aparams.password = strdup(purl->pwd);
|
||||||
|
} else if ((p = getenv("HTTP_PROXY_AUTH")) != NULL &&
|
||||||
|
*p != '\0') {
|
||||||
|
if (http_authfromenv(p, &aparams) < 0) {
|
||||||
|
http_seterr(HTTP_NEED_PROXY_AUTH);
|
||||||
|
fetch_syserr();
|
||||||
|
goto ouch;
|
||||||
|
}
|
||||||
|
} else if (fetch_netrc_auth(purl) == 0) {
|
||||||
|
aparams.user = strdup(purl->user);
|
||||||
|
aparams.password = strdup(purl->pwd);
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* No auth information found in system - exiting
|
||||||
|
* with warning.
|
||||||
|
*/
|
||||||
|
warnx("Missing username and/or password set");
|
||||||
|
fetch_syserr();
|
||||||
|
goto ouch;
|
||||||
|
}
|
||||||
|
http_authorize(conn, "Proxy-Authorization",
|
||||||
|
&proxy_challenges, &aparams, purl);
|
||||||
|
clean_http_auth_params(&aparams);
|
||||||
|
}
|
||||||
http_cmd(conn, "");
|
http_cmd(conn, "");
|
||||||
if (http_get_reply(conn) != HTTP_OK) {
|
/* Get reply from CONNECT Tunnel attempt */
|
||||||
http_seterr(conn->err);
|
int httpreply = http_get_reply(conn);
|
||||||
|
if (httpreply != HTTP_OK) {
|
||||||
|
http_seterr(httpreply);
|
||||||
|
/* If the error is a 407/HTTP_NEED_PROXY_AUTH */
|
||||||
|
if (httpreply == HTTP_NEED_PROXY_AUTH &&
|
||||||
|
! isproxyauth) {
|
||||||
|
/* Try again with authentication. */
|
||||||
|
clean_http_headerbuf(&headerbuf);
|
||||||
|
fetch_close(conn);
|
||||||
|
isproxyauth = true;
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
goto ouch;
|
goto ouch;
|
||||||
}
|
}
|
||||||
/* Read and discard the rest of the proxy response */
|
/* Read and discard the rest of the proxy response */
|
||||||
|
Loading…
Reference in New Issue
Block a user