7070#include <locale.h>
7171#include <netdb.h>
7272#include <stdarg.h>
73+ #include <stdbool.h>
7374#include <stdio.h>
7475#include <stdlib.h>
7576#include <string.h>
@@ -1310,8 +1311,7 @@ http_digest_auth(conn_t *conn, const char *hdr, http_auth_challenge_t *c,
13101311 http_auth_params_t * parms , struct url * url )
13111312{
13121313 HASHHEX HA1 ;
1313- HASHHEX digest ;
1314- HASHHEX empty = {0 };
1314+ HASHHEX digest , null ;
13151315 int r ;
13161316 char noncecount [10 ];
13171317 char cnonce [40 ];
@@ -1343,8 +1343,9 @@ http_digest_auth(conn_t *conn, const char *hdr, http_auth_challenge_t *c,
13431343 DigestCalcHA1 (c -> algo , parms -> user , c -> realm ,
13441344 parms -> password , c -> nonce , cnonce , HA1 );
13451345 DEBUGF ("HA1: [%s]\n" , HA1 );
1346+ memset (null , 0 , sizeof (null ));
13461347 DigestCalcResponse (HA1 , c -> nonce , noncecount , cnonce , c -> qop ,
1347- "GET" , url -> doc , empty , digest );
1348+ "GET" , url -> doc , null , digest );
13481349
13491350 if (c -> qop [0 ]) {
13501351 r = http_cmd (conn , "%s: Digest username=\"%s\",realm=\"%s\","
@@ -1449,6 +1450,8 @@ http_connect(struct url *URL, struct url *purl, const char *flags)
14491450 int val ;
14501451#endif
14511452 int serrno ;
1453+ bool isproxyauth = false;
1454+ http_auth_challenges_t proxy_challenges ;
14521455
14531456#ifdef INET6
14541457 af = AF_UNSPEC ;
@@ -1466,21 +1469,63 @@ http_connect(struct url *URL, struct url *purl, const char *flags)
14661469
14671470 curl = (purl != NULL ) ? purl : URL ;
14681471
1472+
14691473 if ((conn = fetch_cache_get (curl , af )) != NULL )
14701474 return (conn );
14711475
1476+ retry :
14721477 if ((conn = fetch_connect (curl , af , verbose )) == NULL )
14731478 /* fetch_connect() has already set an error code */
14741479 return (NULL );
14751480 init_http_headerbuf (& headerbuf );
14761481 if (strcmp (URL -> scheme , SCHEME_HTTPS ) == 0 && purl ) {
1477- http_cmd (conn , "CONNECT %s:%d HTTP/1.1" ,
1478- URL -> host , URL -> port );
1479- http_cmd (conn , "Host: %s:%d" ,
1480- URL -> host , URL -> port );
1482+ int httpreply ;
1483+ init_http_auth_challenges (& proxy_challenges );
1484+ http_cmd (conn , "CONNECT %s:%d HTTP/1.1" , URL -> host , URL -> port );
1485+ http_cmd (conn , "Host: %s:%d" , URL -> host , URL -> port );
1486+ if (isproxyauth ) {
1487+ http_auth_params_t aparams ;
1488+ init_http_auth_params (& aparams );
1489+ if (* purl -> user || * purl -> pwd ) {
1490+ aparams .user = strdup (purl -> user );
1491+ aparams .password = strdup (purl -> pwd );
1492+ } else if ((p = getenv ("HTTP_PROXY_AUTH" )) != NULL &&
1493+ * p != '\0' ) {
1494+ if (http_authfromenv (p , & aparams ) < 0 ) {
1495+ http_seterr (HTTP_NEED_PROXY_AUTH );
1496+ fetch_syserr ();
1497+ goto ouch ;
1498+ }
1499+ } else if (fetch_netrc_auth (purl ) == 0 ) {
1500+ aparams .user = strdup (purl -> user );
1501+ aparams .password = strdup (purl -> pwd );
1502+ } else {
1503+ /*
1504+ * No auth information found in system - exiting
1505+ * with warning.
1506+ */
1507+ http_seterr (HTTP_NEED_PROXY_AUTH );
1508+ fetch_syserr ();
1509+ goto ouch ;
1510+ }
1511+ http_authorize (conn , "Proxy-Authorization" ,
1512+ & proxy_challenges , & aparams , purl );
1513+ clean_http_auth_params (& aparams );
1514+ }
14811515 http_cmd (conn , "%s" , "" );
1482- if (http_get_reply (conn , NULL ) != HTTP_OK ) {
1483- http_seterr (conn -> err );
1516+ /* Get reply from CONNECT Tunnel attempt */
1517+ httpreply = http_get_reply (conn , NULL );
1518+ if (httpreply != HTTP_OK ) {
1519+ http_seterr (httpreply );
1520+ /* If the error is a 407/HTTP_NEED_PROXY_AUTH */
1521+ if (httpreply == HTTP_NEED_PROXY_AUTH &&
1522+ ! isproxyauth ) {
1523+ /* Try again with authentication. */
1524+ clean_http_headerbuf (& headerbuf );
1525+ fetch_close (conn );
1526+ isproxyauth = true;
1527+ goto retry ;
1528+ }
14841529 goto ouch ;
14851530 }
14861531 /* Read and discard the rest of the proxy response */
0 commit comments