已合并
fix curl6 #406
fix curl6 #406
已合并
hhd227创建于 5月21日
共 10 个文件变更+158-77
@@ -814,8 +814,9 @@ static struct Curl_easy *h2_duphandle(struct Curl_cfilter *cf,
814 return second;814 return second;
815}815}
816 816 
817-static int set_transfer_url(struct Curl_easy *data,817+static int set_transfer_url(struct Curl_easy *newhandle,
818- struct curl_pushheaders *hp)818+ struct curl_pushheaders *hp,
819+ struct Curl_easy *data)
819{820{
820 const char *v;821 const char *v;
821 CURLUcode uc;822 CURLUcode uc;
@@ -853,6 +854,13 @@ static int set_transfer_url(struct Curl_easy *data,
853 }854 }
854 }855 }
855 856 
857+ /* We can only allow PUSH of resource from the same origin, e.g.
858+ * scheme + hostname + port */
859+ if(!Curl_url_same_origin(data->state.uh, u)) {
860+ rc = 1;
861+ goto fail;
862+ }
863+ 
856 uc = curl_url_get(u, CURLUPART_URL, &url, 0);864 uc = curl_url_get(u, CURLUPART_URL, &url, 0);
857 if(uc)865 if(uc)
858 rc = 4;866 rc = 4;
@@ -861,10 +869,11 @@ fail:
861 if(rc)869 if(rc)
862 return rc;870 return rc;
863 871 
864- if(data->state.url_alloc)872+ if(newhandle->state.url_alloc)
865- free(data->state.url);873+ free(newhandle->state.url);
866- data->state.url_alloc = TRUE;874+ newhandle->state.url_alloc = TRUE;
867- data->state.url = url;875+ newhandle->state.url = url;
876+ 
868 return 0;877 return 0;
869}878}
870 879 
@@ -915,7 +924,7 @@ static int push_promise(struct Curl_cfilter *cf,
915 heads.stream = stream;924 heads.stream = stream;
916 heads.frame = frame;925 heads.frame = frame;
917 926 
918- rv = set_transfer_url(newhandle, &heads);927+ rv = set_transfer_url(newhandle, &heads, data);
919 if(rv) {928 if(rv) {
920 discard_newhandle(cf, newhandle);929 discard_newhandle(cf, newhandle);
921 rv = CURL_PUSH_DENY;930 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.
@@ -1122,8 +1137,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
1122 * Setting it to NULL, means no proxy but allows the environment variables1137 * Setting it to NULL, means no proxy but allows the environment variables
1123 * to decide for us (if CURLOPT_SOCKS_PROXY setting it to NULL).1138 * to decide for us (if CURLOPT_SOCKS_PROXY setting it to NULL).
1124 */1139 */
1125- result = Curl_setstropt(&data->set.str[STRING_PROXY],1140+ result = setproxy(data, va_arg(param, char *));
1126- va_arg(param, char *));
1127 break;1141 break;
1128 1142 
1129 case CURLOPT_PRE_PROXY:1143 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)
@@ -558,6 +558,40 @@ void Curl_init_CONNECT(struct Curl_easy *data)
558 data->state.upload = (data->state.httpreq == HTTPREQ_PUT);558 data->state.upload = (data->state.httpreq == HTTPREQ_PUT);
559}559}
560 560 
561+/*
562+ * Restore the user credentials to those set in options.
563+ */
564+CURLcode Curl_reset_userpwd(struct Curl_easy *data)
565+{
566+ CURLcode result;
567+ if(data->set.str[STRING_USERNAME] || data->set.str[STRING_PASSWORD])
568+ data->state.creds_from = CREDS_OPTION;
569+ result = Curl_setstropt(&data->state.aptr.user,
570+ data->set.str[STRING_USERNAME]);
571+ if(!result)
572+ result = Curl_setstropt(&data->state.aptr.passwd,
573+ data->set.str[STRING_PASSWORD]);
574+ return result;
575+}
576+ 
577+/*
578+ * Restore the proxy credentials to those set in options.
579+ */
580+CURLcode Curl_reset_proxypwd(struct Curl_easy *data)
581+{
582+#ifndef CURL_DISABLE_PROXY
583+ CURLcode result = Curl_setstropt(&data->state.aptr.proxyuser,
584+ data->set.str[STRING_PROXYUSERNAME]);
585+ if(!result)
586+ result = Curl_setstropt(&data->state.aptr.proxypasswd,
587+ data->set.str[STRING_PROXYPASSWORD]);
588+ return result;
589+#else
590+ (void)data;
591+ return CURLE_OK;
592+#endif
593+}
594+ 
561/*595/*
562 * Curl_pretransfer() is called immediately before a transfer starts, and only596 * Curl_pretransfer() is called immediately before a transfer starts, and only
563 * once for one transfer no matter if it has redirects or do multi-pass597 * once for one transfer no matter if it has redirects or do multi-pass
@@ -706,18 +740,10 @@ CURLcode Curl_pretransfer(struct Curl_easy *data)
706 }740 }
707 741 
708 if(!result)742 if(!result)
709- result = Curl_setstropt(&data->state.aptr.user,743+ result = Curl_reset_userpwd(data);
710- data->set.str[STRING_USERNAME]);
711- if(!result)
712- result = Curl_setstropt(&data->state.aptr.passwd,
713- data->set.str[STRING_PASSWORD]);
714#ifndef CURL_DISABLE_PROXY744#ifndef CURL_DISABLE_PROXY
715 if(!result)745 if(!result)
716- result = Curl_setstropt(&data->state.aptr.proxyuser,746+ result = Curl_reset_proxypwd(data);
717- data->set.str[STRING_PROXYUSERNAME]);
718- if(!result)
719- result = Curl_setstropt(&data->state.aptr.proxypasswd,
720- data->set.str[STRING_PROXYPASSWORD]);
721#endif747#endif
722 748 
723 data->req.headerbytecount = 0;749 data->req.headerbytecount = 0;
@@ -846,56 +872,38 @@ CURLcode Curl_follow(struct Curl_easy *data,
846 return CURLE_OUT_OF_MEMORY;872 return CURLE_OUT_OF_MEMORY;
847 }873 }
848 else {874 else {
849- uc = curl_url_get(data->state.uh, CURLUPART_URL, &newurl, 0);875+ bool same_origin;
850- if(uc)876+ CURLcode result;
877+ CURLU *u = curl_url();
878+ if(!u)
879+ return CURLE_OUT_OF_MEMORY;
880+ uc = curl_url_set(u, CURLUPART_URL,
881+ data->state.url,
882+ CURLU_URLENCODE | CURLU_ALLOW_SPACE);
883+ if(!uc)
884+ uc = curl_url_get(data->state.uh, CURLUPART_URL, &newurl, 0);
885+ if(uc) {
886+ curl_url_cleanup(u);
851 return Curl_uc_to_curlcode(uc);887 return Curl_uc_to_curlcode(uc);
888+ }
852 889 
853- /* Clear auth if this redirects to a different port number or protocol,890+ same_origin = Curl_url_same_origin(u, data->state.uh);
854- unless permitted */891+ curl_url_cleanup(u);
855- if(!data->set.allow_auth_to_other_hosts && (type != FOLLOW_FAKE)) {
856- char *portnum;
857- int port;
858- bool clear = FALSE;
859 892 
860- if(data->set.use_port && data->state.allow_port)893+ if((!same_origin && !data->set.allow_auth_to_other_hosts) ||
861- /* a custom port is used */894+ !data->set.str[STRING_USERNAME]) {
862- port = (int)data->set.use_port;895+ result = Curl_reset_userpwd(data);
863- else {896+ if(result) {
864- uc = curl_url_get(data->state.uh, CURLUPART_PORT, &portnum,897+ free(newurl);
865- CURLU_DEFAULT_PORT);898+ return result;
866- if(uc) {
867- free(newurl);
868- return Curl_uc_to_curlcode(uc);
869- }
870- port = atoi(portnum);
871- free(portnum);
872- }
873- if(port != data->info.conn_remote_port) {
874- infof(data, "Clear auth, redirects to port from %u to %u",
875- data->info.conn_remote_port, port);
876- clear = TRUE;
877- }
878- else {
879- char *scheme;
880- const struct Curl_handler *p;
881- uc = curl_url_get(data->state.uh, CURLUPART_SCHEME, &scheme, 0);
882- if(uc) {
883- free(newurl);
884- return Curl_uc_to_curlcode(uc);
885- }
886- 
887- p = Curl_get_scheme_handler(scheme);
888- if(p && (p->protocol != data->info.conn_protocol)) {
889- infof(data, "Clear auth, redirects scheme from %s to %s",
890- data->info.conn_scheme, scheme);
891- clear = TRUE;
892- }
893- free(scheme);
894- }
895- if(clear) {
896- Curl_safefree(data->state.aptr.user);
897- Curl_safefree(data->state.aptr.passwd);
898 }899 }
900+ Curl_safefree(data->state.aptr.user);
901+ Curl_safefree(data->state.aptr.passwd);
902+ }
903+ result = Curl_reset_proxypwd(data);
904+ if(result) {
905+ free(newurl);
906+ return result;
899 }907 }
900 }908 }
901 909 
@@ -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
@@ -1220,6 +1220,11 @@ ConnectionExists(struct Curl_easy *data,
1220 (get_protocol_family(check->handler) !=1220 (get_protocol_family(check->handler) !=
1221 needle->handler->protocol || !check->bits.tls_upgraded))1221 needle->handler->protocol || !check->bits.tls_upgraded))
1222 continue;1222 continue;
1223+ else if (!(needle->handler->flags & PROTOPT_SSL) &&
1224+ !check->bits.tls_upgraded &&
1225+ data->set.use_ssl >= CURLUSESSL_CONTROL)
1226+ /* do not reuse a non-TLS STARTTLS connection if TLS is required */
1227+ continue;
1223 1228 
1224 /* If needle has "conn_to_*" set, check must match this */1229 /* If needle has "conn_to_*" set, check must match this */
1225 if((needle->bits.conn_to_host && !strcasecompare(1230 if((needle->bits.conn_to_host && !strcasecompare(
@@ -1986,10 +1991,10 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
1986 return result;1991 return result;
1987 1992 
1988 /*1993 /*
1989- * User name and password set with their own options override the1994+ * username and password set with their own options override the credentials
1990- * credentials possibly set in the URL.1995+ * possibly set in the URL, but netrc does not.
1991 */1996 */
1992- if(!data->set.str[STRING_PASSWORD]) {1997+ if(!data->state.aptr.passwd || (data->state.creds_from != CREDS_OPTION)) {
1993 uc = curl_url_get(uh, CURLUPART_PASSWORD, &data->state.up.password, 0);1998 uc = curl_url_get(uh, CURLUPART_PASSWORD, &data->state.up.password, 0);
1994 if(!uc) {1999 if(!uc) {
1995 char *decoded;2000 char *decoded;
@@ -2002,12 +2007,13 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
2002 result = Curl_setstropt(&data->state.aptr.passwd, decoded);2007 result = Curl_setstropt(&data->state.aptr.passwd, decoded);
2003 if(result)2008 if(result)
2004 return result;2009 return result;
2010+ data->state.creds_from = CREDS_URL;
2005 }2011 }
2006 else if(uc != CURLUE_NO_PASSWORD)2012 else if(uc != CURLUE_NO_PASSWORD)
2007 return Curl_uc_to_curlcode(uc);2013 return Curl_uc_to_curlcode(uc);
2008 }2014 }
2009 2015 
2010- if(!data->set.str[STRING_USERNAME]) {2016+ if(!data->state.aptr.user || (data->state.creds_from != CREDS_OPTION)) {
2011 /* we don't use the URL API's URL decoder option here since it rejects2017 /* we don't use the URL API's URL decoder option here since it rejects
2012 control codes and we want to allow them for some schemes in the user2018 control codes and we want to allow them for some schemes in the user
2013 and password fields */2019 and password fields */
@@ -2021,13 +2027,10 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
2021 return result;2027 return result;
2022 conn->user = decoded;2028 conn->user = decoded;
2023 result = Curl_setstropt(&data->state.aptr.user, decoded);2029 result = Curl_setstropt(&data->state.aptr.user, decoded);
2030+ data->state.creds_from = CREDS_URL;
2024 }2031 }
2025 else if(uc != CURLUE_NO_USER)2032 else if(uc != CURLUE_NO_USER)
2026 return Curl_uc_to_curlcode(uc);2033 return Curl_uc_to_curlcode(uc);
2027- else if(data->state.aptr.passwd) {
2028- /* no user was set but a password, set a blank user */
2029- result = Curl_setstropt(&data->state.aptr.user, "");
2030- }
2031 if(result)2034 if(result)
2032 return result;2035 return result;
2033 }2036 }
@@ -2797,7 +2800,8 @@ static CURLcode override_login(struct Curl_easy *data,
2797 int ret;2800 int ret;
2798 bool url_provided = FALSE;2801 bool url_provided = FALSE;
2799 2802 
2800- if(data->state.aptr.user) {2803+ if(data->state.aptr.user &&
2804+ (data->state.creds_from != CREDS_NETRC)) {
2801 /* there was a username with a length in the URL. Use the URL decoded2805 /* there was a username with a length in the URL. Use the URL decoded
2802 version */2806 version */
2803 userp = &data->state.aptr.user;2807 userp = &data->state.aptr.user;
@@ -2856,6 +2860,7 @@ static CURLcode override_login(struct Curl_easy *data,
2856 result = Curl_setstropt(&data->state.aptr.user, *userp);2860 result = Curl_setstropt(&data->state.aptr.user, *userp);
2857 if(result)2861 if(result)
2858 return result;2862 return result;
2863+ data->state.creds_from = CREDS_NETRC;
2859 }2864 }
2860 }2865 }
2861 if(data->state.aptr.user) {2866 if(data->state.aptr.user) {
@@ -2873,6 +2878,7 @@ static CURLcode override_login(struct Curl_easy *data,
2873 CURLcode result = Curl_setstropt(&data->state.aptr.passwd, *passwdp);2878 CURLcode result = Curl_setstropt(&data->state.aptr.passwd, *passwdp);
2874 if(result)2879 if(result)
2875 return result;2880 return result;
2881+ data->state.creds_from = CREDS_NETRC;
2876 }2882 }
2877 if(data->state.aptr.passwd) {2883 if(data->state.aptr.passwd) {
2878 uc = curl_url_set(data->state.uh, CURLUPART_PASSWORD,2884 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 */
@@ -1994,3 +1994,36 @@ nomem:
1994 }1994 }
1995 return CURLUE_OK;1995 return CURLUE_OK;
1996}1996}
1997+ 
1998+bool Curl_url_same_origin(CURLU *base, CURLU *href)
1999+{
2000+ const struct Curl_handler *s = NULL;
2001+ 
2002+ /* base must be an absolute URL */
2003+ if(!base->scheme || !base->host)
2004+ return FALSE;
2005+ if(href->scheme && !curl_strequal(base->scheme, href->scheme))
2006+ return FALSE;
2007+ if(href->host) {
2008+ if(!curl_strequal(base->host, href->host))
2009+ return FALSE;
2010+ if(!curl_strequal(base->port, href->port)) {
2011+ /* This may still match if only one has an explicit port
2012+ * and it is the default for the scheme. */
2013+ if(base->port && href->port)
2014+ return FALSE;
2015+ 
2016+ s = Curl_get_scheme_handler(base->scheme);
2017+ if(!s) /* Cannot match default port for unknown scheme */
2018+ return FALSE;
2019+ 
2020+ /* The port which is set must be the default one */
2021+ if((base->port && (base->portnum != s->defport)) ||
2022+ (href->port && (href->portnum != s->defport)))
2023+ return FALSE;
2024+ }
2025+ }
2026+ else if(href->port) /* no host in href, then there must be no port */
2027+ return FALSE;
2028+ return TRUE;
2029+}
@@ -1235,6 +1235,11 @@ struct urlpieces {
1235 char *query;1235 char *query;
1236};1236};
1237 1237 
1238+#define CREDS_NONE 0
1239+#define CREDS_URL 1 /* from URL */
1240+#define CREDS_OPTION 2 /* set with a CURLOPT_ */
1241+#define CREDS_NETRC 3 /* found in netrc */
1242+ 
1238struct UrlState {1243struct UrlState {
1239 /* Points to the connection cache */1244 /* Points to the connection cache */
1240 struct conncache *conn_cache;1245 struct conncache *conn_cache;
@@ -1388,6 +1393,9 @@ struct UrlState {
1388 unsigned char select_bits; /* != 0 -> bitmask of socket events for this1393 unsigned char select_bits; /* != 0 -> bitmask of socket events for this
1389 transfer overriding anything the socket may1394 transfer overriding anything the socket may
1390 report */1395 report */
1396+ unsigned int creds_from:2; /* where is the server credentials originating
1397+ from, see the CREDS_* defines above */
1398+ 
1391#ifdef CURLDEBUG1399#ifdef CURLDEBUG
1392 BIT(conncache_lock);1400 BIT(conncache_lock);
1393#endif1401#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