aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRenato Botelho <garga@FreeBSD.org>2021-04-01 21:02:57 +0000
committerRenato Botelho <garga@FreeBSD.org>2021-04-01 21:02:57 +0000
commit345c30a94f6425954163f1e0b075a75f603d27cd (patch)
treefc04b6df5c267170349520907e91239eeda0e420
parent9aef4e7c2bd4371e526e4e3feb26064d361ad8ce (diff)
downloadsrc-345c30a94f6425954163f1e0b075a75f603d27cd.tar.gz
src-345c30a94f6425954163f1e0b075a75f603d27cd.zip
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
-rw-r--r--lib/libfetch/http.c55
1 files changed, 49 insertions, 6 deletions
diff --git a/lib/libfetch/http.c b/lib/libfetch/http.c
index 7f37b7d67197..e61e23b1425a 100644
--- a/lib/libfetch/http.c
+++ b/lib/libfetch/http.c
@@ -73,6 +73,7 @@ __FBSDID("$FreeBSD$");
#include <locale.h>
#include <netdb.h>
#include <stdarg.h>
+#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -1387,6 +1388,8 @@ http_connect(struct url *URL, struct url *purl, const char *flags)
int verbose;
int af, val;
int serrno;
+ bool isproxyauth = false;
+ http_auth_challenges_t proxy_challenges;
#ifdef INET6
af = AF_UNSPEC;
@@ -1404,18 +1407,58 @@ http_connect(struct url *URL, struct url *purl, const char *flags)
curl = (purl != NULL) ? purl : URL;
+retry:
if ((conn = fetch_connect(curl->host, curl->port, af, verbose)) == NULL)
/* fetch_connect() has already set an error code */
return (NULL);
init_http_headerbuf(&headerbuf);
if (strcmp(URL->scheme, SCHEME_HTTPS) == 0 && purl) {
- http_cmd(conn, "CONNECT %s:%d HTTP/1.1",
- URL->host, URL->port);
- http_cmd(conn, "Host: %s:%d",
- URL->host, URL->port);
+ init_http_auth_challenges(&proxy_challenges);
+ http_cmd(conn, "CONNECT %s:%d HTTP/1.1", URL->host, URL->port);
+ http_cmd(conn, "Host: %s:%d", 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, "");
- if (http_get_reply(conn) != HTTP_OK) {
- http_seterr(conn->err);
+ /* Get reply from CONNECT Tunnel attempt */
+ 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;
}
/* Read and discard the rest of the proxy response */