共 10 个文件变更+158-77
@@ -810,8 +810,9 @@ static struct Curl_easy *h2_duphandle(struct Curl_cfilter *cf,
810 return second;810 return second;
811}811}
812 812 
813-static int set_transfer_url(struct Curl_easy *data,813+static int set_transfer_url(struct Curl_easy *newhandle,
814- struct curl_pushheaders *hp)814+ struct curl_pushheaders *hp,
815+ struct Curl_easy *data)
815{816{
816 const char *v;817 const char *v;
817 CURLUcode uc;818 CURLUcode uc;
@@ -849,6 +850,13 @@ static int set_transfer_url(struct Curl_easy *data,
849 }850 }
850 }851 }
851 852 
853+ /* We can only allow PUSH of resource from the same origin, e.g.
854+ * scheme + hostname + port */
855+ if(!Curl_url_same_origin(data->state.uh, u)) {
856+ rc = 1;
857+ goto fail;
858+ }
859+ 
852 uc = curl_url_get(u, CURLUPART_URL, &url, 0);860 uc = curl_url_get(u, CURLUPART_URL, &url, 0);
853 if(uc)861 if(uc)
854 rc = 4;862 rc = 4;
@@ -857,10 +865,11 @@ fail:
857 if(rc)865 if(rc)
858 return rc;866 return rc;
859 867 
860- if(data->state.url_alloc)868+ if(newhandle->state.url_alloc)
861- free(data->state.url);869+ free(newhandle->state.url);
862- data->state.url_alloc = TRUE;870+ newhandle->state.url_alloc = TRUE;
863- data->state.url = url;871+ newhandle->state.url = url;
872+ 
864 return 0;873 return 0;
865}874}
866 875 
@@ -911,7 +920,7 @@ static int push_promise(struct Curl_cfilter *cf,
911 heads.stream = stream;920 heads.stream = stream;
912 heads.frame = frame;921 heads.frame = frame;
913 922 
914- rv = set_transfer_url(newhandle, &heads);923+ rv = set_transfer_url(newhandle, &heads, data);
915 if(rv) {924 if(rv) {
916 discard_newhandle(cf, newhandle);925 discard_newhandle(cf, newhandle);
917 rv = CURL_PUSH_DENY;926 rv = CURL_PUSH_DENY;
@@ -53,6 +53,7 @@
53#include "tftp.h"53#include "tftp.h"
54#include "strdup.h"54#include "strdup.h"
55#include "escape.h"55#include "escape.h"
56+#include "vauth/vauth.h"
56 57 
57/* The last 3 #include files should be in this order */58/* The last 3 #include files should be in this order */
58#include "curl_printf.h"59#include "curl_printf.h"
@@ -180,6 +181,20 @@ static CURLcode protocol2num(const char *str, curl_prot_t *val)
180 return CURLE_OK;181 return CURLE_OK;
181}182}
182 183 
184+#ifndef CURL_DISABLE_PROXY
185+static CURLcode setproxy(struct Curl_easy *data, const char *proxy)
186+{
187+ if((data->set.str[STRING_PROXY] && proxy) &&
188+ /* there was one set, is this a new one? */
189+ !strcmp(data->set.str[STRING_PROXY], proxy))
190+ return CURLE_OK; /* same one as before */
191+ 
192+ Curl_auth_digest_cleanup(&data->state.proxydigest);
193+ memset(&data->state.authproxy, 0, sizeof(data->state.authproxy));
194+ return Curl_setstropt(&data->set.str[STRING_PROXY], proxy);
195+}
196+#endif
197+ 
183/*198/*
184 * Do not make Curl_vsetopt() static: it is called from199 * Do not make Curl_vsetopt() static: it is called from
185 * packages/OS400/ccsidcurl.c.200 * packages/OS400/ccsidcurl.c.
@@ -1121,8 +1136,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
1121 * Setting it to NULL, means no proxy but allows the environment variables1136 * Setting it to NULL, means no proxy but allows the environment variables
1122 * to decide for us (if CURLOPT_SOCKS_PROXY setting it to NULL).1137 * to decide for us (if CURLOPT_SOCKS_PROXY setting it to NULL).
1123 */1138 */
1124- result = Curl_setstropt(&data->set.str[STRING_PROXY],1139+ result = setproxy(data, va_arg(param, char *));
1125- va_arg(param, char *));
1126 break;1140 break;
1127 1141 
1128 case CURLOPT_PRE_PROXY:1142 case CURLOPT_PRE_PROXY:
@@ -462,9 +462,6 @@ static CURLcode smb_connect(struct Curl_easy *data, bool *done)
462 if(!smbc->send_buf)462 if(!smbc->send_buf)
463 return CURLE_OUT_OF_MEMORY;463 return CURLE_OUT_OF_MEMORY;
464 464 
465- /* Multiple requests are allowed with this connection */
466- connkeep(conn, "SMB default");
467- 
468 /* Parse the username, domain, and password */465 /* Parse the username, domain, and password */
469 slash = strchr(conn->user, '/');466 slash = strchr(conn->user, '/');
470 if(!slash)467 if(!slash)
@@ -559,6 +559,40 @@ void Curl_init_CONNECT(struct Curl_easy *data)
559 data->state.upload = (data->state.httpreq == HTTPREQ_PUT);559 data->state.upload = (data->state.httpreq == HTTPREQ_PUT);
560}560}
561 561 
562+/*
563+ * Restore the user credentials to those set in options.
564+ */
565+CURLcode Curl_reset_userpwd(struct Curl_easy *data)
566+{
567+ CURLcode result;
568+ if(data->set.str[STRING_USERNAME] || data->set.str[STRING_PASSWORD])
569+ data->state.creds_from = CREDS_OPTION;
570+ result = Curl_setstropt(&data->state.aptr.user,
571+ data->set.str[STRING_USERNAME]);
572+ if(!result)
573+ result = Curl_setstropt(&data->state.aptr.passwd,
574+ data->set.str[STRING_PASSWORD]);
575+ return result;
576+}
577+ 
578+/*
579+ * Restore the proxy credentials to those set in options.
580+ */
581+CURLcode Curl_reset_proxypwd(struct Curl_easy *data)
582+{
583+#ifndef CURL_DISABLE_PROXY
584+ CURLcode result = Curl_setstropt(&data->state.aptr.proxyuser,
585+ data->set.str[STRING_PROXYUSERNAME]);
586+ if(!result)
587+ result = Curl_setstropt(&data->state.aptr.proxypasswd,
588+ data->set.str[STRING_PROXYPASSWORD]);
589+ return result;
590+#else
591+ (void)data;
592+ return CURLE_OK;
593+#endif
594+}
595+ 
562/*596/*
563 * Curl_pretransfer() is called immediately before a transfer starts, and only597 * Curl_pretransfer() is called immediately before a transfer starts, and only
564 * once for one transfer no matter if it has redirects or do multi-pass598 * once for one transfer no matter if it has redirects or do multi-pass
@@ -707,18 +741,10 @@ CURLcode Curl_pretransfer(struct Curl_easy *data)
707 }741 }
708 742 
709 if(!result)743 if(!result)
710- result = Curl_setstropt(&data->state.aptr.user,744+ result = Curl_reset_userpwd(data);
711- data->set.str[STRING_USERNAME]);
712- if(!result)
713- result = Curl_setstropt(&data->state.aptr.passwd,
714- data->set.str[STRING_PASSWORD]);
715#ifndef CURL_DISABLE_PROXY745#ifndef CURL_DISABLE_PROXY
716 if(!result)746 if(!result)
717- result = Curl_setstropt(&data->state.aptr.proxyuser,747+ result = Curl_reset_proxypwd(data);
718- data->set.str[STRING_PROXYUSERNAME]);
719- if(!result)
720- result = Curl_setstropt(&data->state.aptr.proxypasswd,
721- data->set.str[STRING_PROXYPASSWORD]);
722#endif748#endif
723 749 
724 data->req.headerbytecount = 0;750 data->req.headerbytecount = 0;
@@ -847,56 +873,38 @@ CURLcode Curl_follow(struct Curl_easy *data,
847 return CURLE_OUT_OF_MEMORY;873 return CURLE_OUT_OF_MEMORY;
848 }874 }
849 else {875 else {
850- uc = curl_url_get(data->state.uh, CURLUPART_URL, &newurl, 0);876+ bool same_origin;
851- if(uc)877+ CURLcode result;
878+ CURLU *u = curl_url();
879+ if(!u)
880+ return CURLE_OUT_OF_MEMORY;
881+ uc = curl_url_set(u, CURLUPART_URL,
882+ data->state.url,
883+ CURLU_URLENCODE | CURLU_ALLOW_SPACE);
884+ if(!uc)
885+ uc = curl_url_get(data->state.uh, CURLUPART_URL, &newurl, 0);
886+ if(uc) {
887+ curl_url_cleanup(u);
852 return Curl_uc_to_curlcode(uc);888 return Curl_uc_to_curlcode(uc);
889+ }
853 890 
854- /* Clear auth if this redirects to a different port number or protocol,891+ same_origin = Curl_url_same_origin(u, data->state.uh);
855- unless permitted */892+ curl_url_cleanup(u);
856- if(!data->set.allow_auth_to_other_hosts && (type != FOLLOW_FAKE)) {
857- char *portnum;
858- int port;
859- bool clear = FALSE;
860 893 
861- if(data->set.use_port && data->state.allow_port)894+ if((!same_origin && !data->set.allow_auth_to_other_hosts) ||
862- /* a custom port is used */895+ !data->set.str[STRING_USERNAME]) {
863- port = (int)data->set.use_port;896+ result = Curl_reset_userpwd(data);
864- else {897+ if(result) {
865- uc = curl_url_get(data->state.uh, CURLUPART_PORT, &portnum,898+ free(newurl);
866- CURLU_DEFAULT_PORT);899+ return result;
867- if(uc) {
868- free(newurl);
869- return Curl_uc_to_curlcode(uc);
870- }
871- port = atoi(portnum);
872- free(portnum);
873- }
874- if(port != data->info.conn_remote_port) {
875- infof(data, "Clear auth, redirects to port from %u to %u",
876- data->info.conn_remote_port, port);
877- clear = TRUE;
878- }
879- else {
880- char *scheme;
881- const struct Curl_handler *p;
882- uc = curl_url_get(data->state.uh, CURLUPART_SCHEME, &scheme, 0);
883- if(uc) {
884- free(newurl);
885- return Curl_uc_to_curlcode(uc);
886- }
887- 
888- p = Curl_get_scheme_handler(scheme);
889- if(p && (p->protocol != data->info.conn_protocol)) {
890- infof(data, "Clear auth, redirects scheme from %s to %s",
891- data->info.conn_scheme, scheme);
892- clear = TRUE;
893- }
894- free(scheme);
895- }
896- if(clear) {
897- Curl_safefree(data->state.aptr.user);
898- Curl_safefree(data->state.aptr.passwd);
899 }900 }
901+ Curl_safefree(data->state.aptr.user);
902+ Curl_safefree(data->state.aptr.passwd);
903+ }
904+ result = Curl_reset_proxypwd(data);
905+ if(result) {
906+ free(newurl);
907+ return result;
900 }908 }
901 }909 }
902 910 
@@ -31,6 +31,8 @@ char *Curl_checkheaders(const struct Curl_easy *data,
31 31 
32void Curl_init_CONNECT(struct Curl_easy *data);32void Curl_init_CONNECT(struct Curl_easy *data);
33 33 
34+CURLcode Curl_reset_userpwd(struct Curl_easy *data);
35+CURLcode Curl_reset_proxypwd(struct Curl_easy *data);
34CURLcode Curl_pretransfer(struct Curl_easy *data);36CURLcode Curl_pretransfer(struct Curl_easy *data);
35CURLcode Curl_posttransfer(struct Curl_easy *data);37CURLcode Curl_posttransfer(struct Curl_easy *data);
36 38 
Mlib/url.c+15-9
@@ -1212,6 +1212,11 @@ ConnectionExists(struct Curl_easy *data,
1212 (get_protocol_family(check->handler) !=1212 (get_protocol_family(check->handler) !=
1213 needle->handler->protocol || !check->bits.tls_upgraded))1213 needle->handler->protocol || !check->bits.tls_upgraded))
1214 continue;1214 continue;
1215+ else if (!(needle->handler->flags & PROTOPT_SSL) &&
1216+ !check->bits.tls_upgraded &&
1217+ data->set.use_ssl >= CURLUSESSL_CONTROL)
1218+ /* do not reuse a non-TLS STARTTLS connection if TLS is required */
1219+ continue;
1215 1220 
1216 /* If needle has "conn_to_*" set, check must match this */1221 /* If needle has "conn_to_*" set, check must match this */
1217 if((needle->bits.conn_to_host && !strcasecompare(1222 if((needle->bits.conn_to_host && !strcasecompare(
@@ -1978,10 +1983,10 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
1978 return result;1983 return result;
1979 1984 
1980 /*1985 /*
1981- * User name and password set with their own options override the1986+ * username and password set with their own options override the credentials
1982- * credentials possibly set in the URL.1987+ * possibly set in the URL, but netrc does not.
1983 */1988 */
1984- if(!data->set.str[STRING_PASSWORD]) {1989+ if(!data->state.aptr.passwd || (data->state.creds_from != CREDS_OPTION)) {
1985 uc = curl_url_get(uh, CURLUPART_PASSWORD, &data->state.up.password, 0);1990 uc = curl_url_get(uh, CURLUPART_PASSWORD, &data->state.up.password, 0);
1986 if(!uc) {1991 if(!uc) {
1987 char *decoded;1992 char *decoded;
@@ -1994,12 +1999,13 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
1994 result = Curl_setstropt(&data->state.aptr.passwd, decoded);1999 result = Curl_setstropt(&data->state.aptr.passwd, decoded);
1995 if(result)2000 if(result)
1996 return result;2001 return result;
2002+ data->state.creds_from = CREDS_URL;
1997 }2003 }
1998 else if(uc != CURLUE_NO_PASSWORD)2004 else if(uc != CURLUE_NO_PASSWORD)
1999 return Curl_uc_to_curlcode(uc);2005 return Curl_uc_to_curlcode(uc);
2000 }2006 }
2001 2007 
2002- if(!data->set.str[STRING_USERNAME]) {2008+ if(!data->state.aptr.user || (data->state.creds_from != CREDS_OPTION)) {
2003 /* we don't use the URL API's URL decoder option here since it rejects2009 /* we don't use the URL API's URL decoder option here since it rejects
2004 control codes and we want to allow them for some schemes in the user2010 control codes and we want to allow them for some schemes in the user
2005 and password fields */2011 and password fields */
@@ -2013,13 +2019,10 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
2013 return result;2019 return result;
2014 conn->user = decoded;2020 conn->user = decoded;
2015 result = Curl_setstropt(&data->state.aptr.user, decoded);2021 result = Curl_setstropt(&data->state.aptr.user, decoded);
2022+ data->state.creds_from = CREDS_URL;
2016 }2023 }
2017 else if(uc != CURLUE_NO_USER)2024 else if(uc != CURLUE_NO_USER)
2018 return Curl_uc_to_curlcode(uc);2025 return Curl_uc_to_curlcode(uc);
2019- else if(data->state.aptr.passwd) {
2020- /* no user was set but a password, set a blank user */
2021- result = Curl_setstropt(&data->state.aptr.user, "");
2022- }
2023 if(result)2026 if(result)
2024 return result;2027 return result;
2025 }2028 }
@@ -2789,7 +2792,8 @@ static CURLcode override_login(struct Curl_easy *data,
2789 int ret;2792 int ret;
2790 bool url_provided = FALSE;2793 bool url_provided = FALSE;
2791 2794 
2792- if(data->state.aptr.user) {2795+ if(data->state.aptr.user &&
2796+ (data->state.creds_from != CREDS_NETRC)) {
2793 /* there was a username with a length in the URL. Use the URL decoded2797 /* there was a username with a length in the URL. Use the URL decoded
2794 version */2798 version */
2795 userp = &data->state.aptr.user;2799 userp = &data->state.aptr.user;
@@ -2848,6 +2852,7 @@ static CURLcode override_login(struct Curl_easy *data,
2848 result = Curl_setstropt(&data->state.aptr.user, *userp);2852 result = Curl_setstropt(&data->state.aptr.user, *userp);
2849 if(result)2853 if(result)
2850 return result;2854 return result;
2855+ data->state.creds_from = CREDS_NETRC;
2851 }2856 }
2852 }2857 }
2853 if(data->state.aptr.user) {2858 if(data->state.aptr.user) {
@@ -2865,6 +2870,7 @@ static CURLcode override_login(struct Curl_easy *data,
2865 CURLcode result = Curl_setstropt(&data->state.aptr.passwd, *passwdp);2870 CURLcode result = Curl_setstropt(&data->state.aptr.passwd, *passwdp);
2866 if(result)2871 if(result)
2867 return result;2872 return result;
2873+ data->state.creds_from = CREDS_NETRC;
2868 }2874 }
2869 if(data->state.aptr.passwd) {2875 if(data->state.aptr.passwd) {
2870 uc = curl_url_set(data->state.uh, CURLUPART_PASSWORD,2876 uc = curl_url_set(data->state.uh, CURLUPART_PASSWORD,
@@ -35,4 +35,6 @@ CURLUcode Curl_parse_port(struct Curl_URL *u, struct dynbuf *host,
35 bool has_scheme);35 bool has_scheme);
36#endif36#endif
37 37 
38+bool Curl_url_same_origin(CURLU *base, CURLU *href);
39+ 
38#endif /* HEADER_CURL_URLAPI_INT_H */40#endif /* HEADER_CURL_URLAPI_INT_H */
@@ -1993,3 +1993,36 @@ nomem:
1993 }1993 }
1994 return CURLUE_OK;1994 return CURLUE_OK;
1995}1995}
1996+ 
1997+bool Curl_url_same_origin(CURLU *base, CURLU *href)
1998+{
1999+ const struct Curl_handler *s = NULL;
2000+ 
2001+ /* base must be an absolute URL */
2002+ if(!base->scheme || !base->host)
2003+ return FALSE;
2004+ if(href->scheme && !curl_strequal(base->scheme, href->scheme))
2005+ return FALSE;
2006+ if(href->host) {
2007+ if(!curl_strequal(base->host, href->host))
2008+ return FALSE;
2009+ if(!curl_strequal(base->port, href->port)) {
2010+ /* This may still match if only one has an explicit port
2011+ * and it is the default for the scheme. */
2012+ if(base->port && href->port)
2013+ return FALSE;
2014+ 
2015+ s = Curl_get_scheme_handler(base->scheme);
2016+ if(!s) /* Cannot match default port for unknown scheme */
2017+ return FALSE;
2018+ 
2019+ /* The port which is set must be the default one */
2020+ if((base->port && (base->portnum != s->defport)) ||
2021+ (href->port && (href->portnum != s->defport)))
2022+ return FALSE;
2023+ }
2024+ }
2025+ else if(href->port) /* no host in href, then there must be no port */
2026+ return FALSE;
2027+ return TRUE;
2028+}
@@ -1228,6 +1228,11 @@ struct urlpieces {
1228 char *query;1228 char *query;
1229};1229};
1230 1230 
1231+#define CREDS_NONE 0
1232+#define CREDS_URL 1 /* from URL */
1233+#define CREDS_OPTION 2 /* set with a CURLOPT_ */
1234+#define CREDS_NETRC 3 /* found in netrc */
1235+ 
1231struct UrlState {1236struct UrlState {
1232 /* Points to the connection cache */1237 /* Points to the connection cache */
1233 struct conncache *conn_cache;1238 struct conncache *conn_cache;
@@ -1381,6 +1386,9 @@ struct UrlState {
1381 unsigned char select_bits; /* != 0 -> bitmask of socket events for this1386 unsigned char select_bits; /* != 0 -> bitmask of socket events for this
1382 transfer overriding anything the socket may1387 transfer overriding anything the socket may
1383 report */1388 report */
1389+ unsigned int creds_from:2; /* where is the server credentials originating
1390+ from, see the CREDS_* defines above */
1391+ 
1384#ifdef CURLDEBUG1392#ifdef CURLDEBUG
1385 BIT(conncache_lock);1393 BIT(conncache_lock);
1386#endif1394#endif
@@ -117,6 +117,8 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data,
117 117 
118/* This is used to clean up the digest specific data */118/* This is used to clean up the digest specific data */
119void Curl_auth_digest_cleanup(struct digestdata *digest);119void Curl_auth_digest_cleanup(struct digestdata *digest);
120+#else
121+#define Curl_auth_digest_cleanup(x)
120#endif /* !CURL_DISABLE_DIGEST_AUTH */122#endif /* !CURL_DISABLE_DIGEST_AUTH */
121 123 
122#ifdef USE_GSASL124#ifdef USE_GSASL