diff -up curl-7.10.6/docs/libcurl/curl_easy_setopt.3.CVE-2009-0037 curl-7.10.6/docs/libcurl/curl_easy_setopt.3 --- curl-7.10.6/docs/libcurl/curl_easy_setopt.3.CVE-2009-0037 2003-07-16 00:44:48.000000000 +0200 +++ curl-7.10.6/docs/libcurl/curl_easy_setopt.3 2009-03-02 14:52:50.000000000 +0100 @@ -234,6 +234,26 @@ you tunnel through the HTTP proxy. Such \fBNOTE2:\fP libcurl respects the environment variables \fBhttp_proxy\fP, \fBftp_proxy\fP, \fBall_proxy\fP etc, if any of those is set. + +\fICURLOPT_PROTOCOLS\fP can be used to limit what protocols libcurl will use +for this transfer, independent of what libcurl has been compiled to +support. That may be useful if you accept the URL from an external source and +want to limit the accessibility. +.IP CURLOPT_PROTOCOLS +Pass a long that holds a bitmask of CURLPROTO_* defines. If used, this bitmask +limits what protocols libcurl may use in the transfer. This allows you to have +a libcurl built to support a wide range of protocols but still limit specific +transfers to only be allowed to use a subset of them. By default libcurl will +accept all protocols it supports. See also +\fICURLOPT_REDIR_PROTOCOLS\fP. (Added in 7.19.4) +.IP CURLOPT_REDIR_PROTOCOLS +Pass a long that holds a bitmask of CURLPROTO_* defines. If used, this bitmask +limits what protocols libcurl may use in a transfer that it follows to in a +redirect when \fICURLOPT_FOLLOWLOCATION\fP is enabled. This allows you to +limit specific transfers to only be allowed to use a subset of protocols in +redirections. By default libcurl will allow all protocols except for FILE. +This is a difference compared to pre-7.19.4 versions which +unconditionally would follow to all protocols supported. (Added in 7.19.4) .TP .B CURLOPT_PROXYPORT Pass a long with this option to set the proxy port to connect to unless it is @@ -410,6 +430,10 @@ that this is meaningful only when settin .B CURLOPT_MAXREDIRS Pass a long. The set number will be the redirection limit. If that many redirections have been followed, the next redirect will cause an error + +NOTE: since 7.19.4, libcurl can limit to what protocols it will automatically +follow. The accepted protocols are set with \fICURLOPT_REDIR_PROTOCOLS\fP and +it excludes the FILE protocol by default. (\fICURLE_TOO_MANY_REDIRECTS\fP). This option only makes sense if the \fICURLOPT_FOLLOWLOCATION\fP is used at the same time. (Added in 7.5) .TP diff -up curl-7.10.6/include/curl/curl.h.CVE-2009-0037 curl-7.10.6/include/curl/curl.h --- curl-7.10.6/include/curl/curl.h.CVE-2009-0037 2003-07-28 14:10:01.000000000 +0200 +++ curl-7.10.6/include/curl/curl.h 2009-03-02 14:52:50.000000000 +0100 @@ -254,6 +254,18 @@ typedef enum { #define CURL_ERROR_SIZE 256 +/* CURLPROTO_ defines are for the CURLOPT_*PROTOCOLS options */ +#define CURLPROTO_HTTP (1<<0) +#define CURLPROTO_HTTPS (1<<1) +#define CURLPROTO_FTP (1<<2) +#define CURLPROTO_FTPS (1<<3) +#define CURLPROTO_TELNET (1<<6) +#define CURLPROTO_LDAP (1<<7) +#define CURLPROTO_LDAPS (1<<8) +#define CURLPROTO_DICT (1<<9) +#define CURLPROTO_FILE (1<<10) +#define CURLPROTO_ALL (~0) /* enable everything */ + /* long may be 32 or 64 bits, but we should never depend on anything else but 32 */ #define CURLOPTTYPE_LONG 0 @@ -669,6 +681,18 @@ typedef enum { argument */ CINIT(SSL_CTX_DATA, OBJECTPOINT, 109), + /* set the bitmask for the protocols that are allowed to be used for the + transfer, which thus helps the app which takes URLs from users or other + external inputs and want to restrict what protocol(s) to deal + with. Defaults to CURLPROTO_ALL. */ + CINIT(PROTOCOLS, LONG, 181), + + /* set the bitmask for the protocols that libcurl is allowed to follow to, + as a subset of the CURLOPT_PROTOCOLS ones. That means the protocol needs + to be set in both bitmasks to be allowed to get redirected to. Defaults + to CURLPROTO_ALL & ~CURLPROTO_FILE. */ + CINIT(REDIR_PROTOCOLS, LONG, 182), + CURLOPT_LASTENTRY /* the last unused */ } CURLoption; diff -up curl-7.10.6/lib/url.c.CVE-2009-0037 curl-7.10.6/lib/url.c --- curl-7.10.6/lib/url.c.CVE-2009-0037 2003-07-25 10:30:58.000000000 +0200 +++ curl-7.10.6/lib/url.c 2009-03-02 14:52:50.000000000 +0100 @@ -303,6 +303,13 @@ CURLcode Curl_open(struct SessionHandle data->set.proxytype = CURLPROXY_HTTP; /* defaults to HTTP proxy */ + /* for the *protocols fields we don't use the CURLPROTO_ALL convenience + define since we internally only use the lower 16 bits for the passed + in bitmask to not conflict with the private bits */ + data->set.allowed_protocols = PROT_EXTMASK | PROT_GOPHER; + data->set.redir_protocols = + (PROT_EXTMASK & ~CURLPROTO_FILE) | PROT_GOPHER; /* not FILE */ + /* create an array with connection data struct pointers */ data->state.numconnects = 5; /* hard-coded right now */ data->state.connects = (struct connectdata **) @@ -1200,6 +1207,22 @@ CURLcode Curl_setopt(struct SessionHandl data->set.http200aliases = va_arg(param, struct curl_slist *); break; + case CURLOPT_PROTOCOLS: + /* set the bitmask for the protocols that are allowed to be used for the + transfer, which thus helps the app which takes URLs from users or other + external inputs and want to restrict what protocol(s) to deal + with. Defaults to CURLPROTO_ALL. */ + data->set.allowed_protocols = va_arg(param, long) & PROT_EXTMASK; + break; + + case CURLOPT_REDIR_PROTOCOLS: + /* set the bitmask for the protocols that libcurl is allowed to follow to, + as a subset of the CURLOPT_PROTOCOLS ones. That means the protocol needs + to be set in both bitmasks to be allowed to get redirected to. Defaults + to CURLPROTO_ALL & ~CURLPROTO_FILE. */ + data->set.redir_protocols = va_arg(param, long) & PROT_EXTMASK; + break; + default: /* unknown tag and its companion, just ignore: */ return CURLE_FAILED_INIT; /* correct this */ @@ -2474,8 +2497,6 @@ static CURLcode CreateConnection(struct result = Curl_Transfer(conn, -1, -1, FALSE, NULL, /* no download */ -1, NULL); /* no upload */ } - - return result; #else failf(data, LIBCURL_NAME " was built with FILE disabled!"); @@ -2487,6 +2508,18 @@ static CURLcode CreateConnection(struct failf(data, "Unsupported protocol: %s", conn->protostr); return CURLE_UNSUPPORTED_PROTOCOL; } + /* Protocol found. Check if allowed */ + if(!(data->set.allowed_protocols & conn->protocol) || + /* it is allowed for "normal" request, now do an extra check if this is + the result of a redirect */ + (data->state.this_is_a_follow && + !(data->set.redir_protocols & conn->protocol))) { + failf(data, "Unsupported protocol: %s", conn->protostr); + return CURLE_UNSUPPORTED_PROTOCOL; + } + if (conn->protocol & PROT_FILE) + return result; + /************************************************************* * Figure out the remote port number diff -up curl-7.10.6/lib/urldata.h.CVE-2009-0037 curl-7.10.6/lib/urldata.h --- curl-7.10.6/lib/urldata.h.CVE-2009-0037 2003-07-22 11:58:18.000000000 +0200 +++ curl-7.10.6/lib/urldata.h 2009-03-02 14:52:50.000000000 +0100 @@ -375,17 +375,27 @@ struct connectdata { struct has */ long protocol; /* PROT_* flags concerning the protocol set */ -#define PROT_MISSING (1<<0) -#define PROT_GOPHER (1<<1) -#define PROT_HTTP (1<<2) -#define PROT_HTTPS (1<<3) -#define PROT_FTP (1<<4) -#define PROT_TELNET (1<<5) -#define PROT_DICT (1<<6) -#define PROT_LDAP (1<<7) -#define PROT_FILE (1<<8) -#define PROT_FTPS (1<<9) -#define PROT_SSL (1<<10) /* protocol requires SSL */ +#define PROT_HTTP CURLPROTO_HTTP +#define PROT_HTTPS CURLPROTO_HTTPS +#define PROT_FTP CURLPROTO_FTP +#define PROT_TELNET CURLPROTO_TELNET +#define PROT_DICT CURLPROTO_DICT +#define PROT_LDAP CURLPROTO_LDAP +#define PROT_FILE CURLPROTO_FILE +#define PROT_FTPS CURLPROTO_FTPS +/* CURLPROTO_TFTP (1<<11) is currently the highest used bit in the public + bitmask. We make sure we use "private bits" above the first 16 to make + things easier. */ + +#define PROT_EXTMASK 0xfff + +#define PROT_SSL (1<<22) /* protocol requires SSL */ +#define PROT_MISSING (1<<23) +/* CURLPROTO_GOPHER is not defined in the 7.19.4 headers, as gopher + support has been dropped long ago. Apps won't be able to explicitly + allow gopher, but that's probably not going to be an issue */ +#define PROT_GOPHER (1<<24) + /* the particular host we use, in two different ways */ struct Curl_dns_entry *connect_addr; @@ -818,6 +828,8 @@ struct UserDefined { bool no_signal; /* do not use any signal/alarm handler */ bool global_dns_cache; + long allowed_protocols; + long redir_protocols; }; /*