- David Kierznowski notified us about a security flaw
(http://curl.haxx.se/docs/adv_20090303.html also known as CVE-2009-0037) in which previous libcurl versions (by design) can be tricked to access an arbitrary local/different file instead of a remote one when CURLOPT_FOLLOWLOCATION is enabled. This flaw is now fixed in this release together this the addition of two new setopt options for controlling this new behavior: o CURLOPT_REDIR_PROTOCOLS controls what protocols libcurl is allowed to follow to when CURLOPT_FOLLOWLOCATION is enabled. By default, this option excludes the FILE and SCP protocols and thus you nee to explicitly allow them in your app if you really want that behavior. o CURLOPT_PROTOCOLS controls what protocol(s) libcurl is allowed to fetch using the primary URL option. This is useful if you want to allow a user or other outsiders control what URL to pass to libcurl and yet not allow all protocols libcurl may have been built to support.
This commit is contained in:
		
							
								
								
									
										21
									
								
								CHANGES
									
									
									
									
									
								
							
							
						
						
									
										21
									
								
								CHANGES
									
									
									
									
									
								
							@@ -6,6 +6,27 @@
 | 
			
		||||
 | 
			
		||||
                                  Changelog
 | 
			
		||||
 | 
			
		||||
Version 7.19.4 (3 March 2009)
 | 
			
		||||
 | 
			
		||||
Daniel Stenberg (3 Mar 2009)
 | 
			
		||||
- David Kierznowski notified us about a security flaw
 | 
			
		||||
  (http://curl.haxx.se/docs/adv_20090303.html also known as CVE-2009-0037) in
 | 
			
		||||
  which previous libcurl versions (by design) can be tricked to access an
 | 
			
		||||
  arbitrary local/different file instead of a remote one when
 | 
			
		||||
  CURLOPT_FOLLOWLOCATION is enabled. This flaw is now fixed in this release
 | 
			
		||||
  together this the addition of two new setopt options for controlling this
 | 
			
		||||
  new behavior:
 | 
			
		||||
 | 
			
		||||
  o CURLOPT_REDIR_PROTOCOLS controls what protocols libcurl is allowed to
 | 
			
		||||
  follow to when CURLOPT_FOLLOWLOCATION is enabled. By default, this option
 | 
			
		||||
  excludes the FILE and SCP protocols and thus you nee to explicitly allow
 | 
			
		||||
  them in your app if you really want that behavior.
 | 
			
		||||
 | 
			
		||||
  o CURLOPT_PROTOCOLS controls what protocol(s) libcurl is allowed to fetch
 | 
			
		||||
  using the primary URL option. This is useful if you want to allow a user or
 | 
			
		||||
  other outsiders control what URL to pass to libcurl and yet not allow all
 | 
			
		||||
  protocols libcurl may have been built to support.
 | 
			
		||||
 | 
			
		||||
Daniel Stenberg (27 Feb 2009)
 | 
			
		||||
- Senthil Raja Velu reported a problem when CURLOPT_INTERFACE and
 | 
			
		||||
  CURLOPT_LOCALPORT were used together (the local port bind failed), and
 | 
			
		||||
 
 | 
			
		||||
@@ -2,11 +2,16 @@ Curl and libcurl 7.19.4
 | 
			
		||||
 | 
			
		||||
 Public curl releases:         110
 | 
			
		||||
 Command line options:         132
 | 
			
		||||
 curl_easy_setopt() options:   161
 | 
			
		||||
 curl_easy_setopt() options:   163
 | 
			
		||||
 Public functions in libcurl:  58
 | 
			
		||||
 Known libcurl bindings:       38
 | 
			
		||||
 Contributors:                 700
 | 
			
		||||
 | 
			
		||||
This release includes the following security-related fix:
 | 
			
		||||
 | 
			
		||||
 o CVE-2009-0037 with the curl advisory here:
 | 
			
		||||
   http://curl.haxx.se/docs/adv_20090303.html
 | 
			
		||||
 | 
			
		||||
This release includes the following changes:
 | 
			
		||||
 | 
			
		||||
 o Added CURLOPT_NOPROXY and the corresponding --noproxy
 | 
			
		||||
@@ -24,6 +29,7 @@ This release includes the following changes:
 | 
			
		||||
 o CURLOPT_FTP_CREATE_MISSING_DIRS can now be set to 2 to retry the CWD even
 | 
			
		||||
   when MKD fails
 | 
			
		||||
 o GnuTLS initing moved to curl_global_init()
 | 
			
		||||
 o Added CURLOPT_REDIR_PROTOCOLS and CURLOPT_PROTOCOLS
 | 
			
		||||
 | 
			
		||||
This release includes the following bugfixes:
 | 
			
		||||
 | 
			
		||||
@@ -59,6 +65,6 @@ advice from friends like these:
 | 
			
		||||
 Patrick Scott, Hidemoto Nakada, Jocelyn Jaubert, Andre Guibert de Bruet,
 | 
			
		||||
 Kamil Dudka, Patrik Thunstrom, Linus Nielsen Feltzing, Mark Incley,
 | 
			
		||||
 Daniel Johnson, James Cheng, Brian J. Murrell, Senthil Raja Velu,
 | 
			
		||||
 Markus Koetter
 | 
			
		||||
 Markus Koetter, David Kierznowski, Michal Marek
 | 
			
		||||
 | 
			
		||||
        Thanks! (and sorry if I forgot to mention someone)
 | 
			
		||||
 
 | 
			
		||||
@@ -440,6 +440,26 @@ The string given to CURLOPT_URL must be url-encoded and follow RFC 2396
 | 
			
		||||
 | 
			
		||||
\fICURLOPT_URL\fP is the only option that \fBmust\fP be set before
 | 
			
		||||
\fIcurl_easy_perform(3)\fP is called.
 | 
			
		||||
 | 
			
		||||
\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 and
 | 
			
		||||
SCP. This is a difference compared to pre-7.19.4 versions which
 | 
			
		||||
unconditionally would follow to all protocols supported. (Added in 7.19.4)
 | 
			
		||||
.IP CURLOPT_PROXY
 | 
			
		||||
Set HTTP proxy to use. The parameter should be a char * to a zero terminated
 | 
			
		||||
string holding the host name or dotted IP address. To specify port number in
 | 
			
		||||
@@ -743,6 +763,10 @@ This means that the library will re-send the same request on the new location
 | 
			
		||||
and follow new Location: headers all the way until no more such headers are
 | 
			
		||||
returned. \fICURLOPT_MAXREDIRS\fP can be used to limit the number of redirects
 | 
			
		||||
libcurl will follow.
 | 
			
		||||
 | 
			
		||||
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.
 | 
			
		||||
.IP CURLOPT_UNRESTRICTED_AUTH
 | 
			
		||||
A parameter set to 1 tells the library it can continue to send authentication
 | 
			
		||||
(user+password) when following locations, even when hostname changed. This
 | 
			
		||||
 
 | 
			
		||||
@@ -191,6 +191,7 @@ CURLOPT_PRIVATE                 7.10.3
 | 
			
		||||
CURLOPT_PROGRESSDATA            7.1
 | 
			
		||||
CURLOPT_PROGRESSFUNCTION        7.1
 | 
			
		||||
CURLOPT_PROGRESSMODE            7.1           -           7.9.2
 | 
			
		||||
CURLOPT_PROTOCOLS               7.19.4
 | 
			
		||||
CURLOPT_PROXY                   7.1
 | 
			
		||||
CURLOPT_PROXYAUTH               7.10.7
 | 
			
		||||
CURLOPT_PROXYPASSWORD           7.19.1
 | 
			
		||||
@@ -205,6 +206,7 @@ CURLOPT_RANDOM_FILE             7.7
 | 
			
		||||
CURLOPT_RANGE                   7.1
 | 
			
		||||
CURLOPT_READDATA                7.9.7
 | 
			
		||||
CURLOPT_READFUNCTION            7.1
 | 
			
		||||
CURLOPT_REDIR_PROTOCOLS         7.19.4
 | 
			
		||||
CURLOPT_REFERER                 7.1
 | 
			
		||||
CURLOPT_RESUME_FROM             7.1
 | 
			
		||||
CURLOPT_RESUME_FROM_LARGE       7.11.0
 | 
			
		||||
@@ -261,6 +263,19 @@ CURLOPT_VERBOSE                 7.1
 | 
			
		||||
CURLOPT_WRITEDATA               7.9.7
 | 
			
		||||
CURLOPT_WRITEFUNCTION           7.1
 | 
			
		||||
CURLOPT_WRITEHEADER             7.1
 | 
			
		||||
CURLPROTO_ALL                   7.19.4
 | 
			
		||||
CURLPROTO_DICT                  7.19.4
 | 
			
		||||
CURLPROTO_FILE                  7.19.4
 | 
			
		||||
CURLPROTO_FTP                   7.19.4
 | 
			
		||||
CURLPROTO_FTPS                  7.19.4
 | 
			
		||||
CURLPROTO_HTTP                  7.19.4
 | 
			
		||||
CURLPROTO_HTTPS                 7.19.4
 | 
			
		||||
CURLPROTO_LDAP                  7.19.4
 | 
			
		||||
CURLPROTO_LDAPS                 7.19.4
 | 
			
		||||
CURLPROTO_SCP                   7.19.4
 | 
			
		||||
CURLPROTO_SFTP                  7.19.4
 | 
			
		||||
CURLPROTO_TELNET                7.19.4
 | 
			
		||||
CURLPROTO_TFTP                  7.19.4
 | 
			
		||||
CURLPROXY_HTTP                  7.10
 | 
			
		||||
CURLPROXY_HTTP_1_0              7.19.4
 | 
			
		||||
CURLPROXY_SOCKS4                7.10
 | 
			
		||||
 
 | 
			
		||||
@@ -550,6 +550,21 @@ typedef enum {
 | 
			
		||||
  CURLFTPMETHOD_LAST       /* not an option, never use */
 | 
			
		||||
} curl_ftpmethod;
 | 
			
		||||
 | 
			
		||||
/* 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_SCP    (1<<4)
 | 
			
		||||
#define CURLPROTO_SFTP   (1<<5)
 | 
			
		||||
#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_TFTP   (1<<11)
 | 
			
		||||
#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
 | 
			
		||||
@@ -1185,6 +1200,18 @@ typedef enum {
 | 
			
		||||
  /* Socks Service */
 | 
			
		||||
  CINIT(SOCKS5_GSSAPI_NEC, LONG, 180),
 | 
			
		||||
 | 
			
		||||
  /* 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 all protocols except FILE and SCP. */
 | 
			
		||||
  CINIT(REDIR_PROTOCOLS, LONG, 182),
 | 
			
		||||
 | 
			
		||||
  CURLOPT_LASTENTRY /* the last unused */
 | 
			
		||||
} CURLoption;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										36
									
								
								lib/url.c
									
									
									
									
									
								
							
							
						
						
									
										36
									
								
								lib/url.c
									
									
									
									
									
								
							@@ -683,6 +683,12 @@ CURLcode Curl_init_userdefined(struct UserDefined *set)
 | 
			
		||||
  set->new_file_perms = 0644;    /* Default permissions */
 | 
			
		||||
  set->new_directory_perms = 0755; /* Default permissions */
 | 
			
		||||
 | 
			
		||||
  /* 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 */
 | 
			
		||||
  set->allowed_protocols = PROT_EXTMASK;
 | 
			
		||||
  set->redir_protocols =
 | 
			
		||||
    PROT_EXTMASK & ~(CURLPROTO_FILE|CURLPROTO_SCP); /* not FILE or SCP */
 | 
			
		||||
 | 
			
		||||
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
 | 
			
		||||
  /*
 | 
			
		||||
@@ -2217,6 +2223,22 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
 | 
			
		||||
    data->set.scope = (unsigned int) va_arg(param, long);
 | 
			
		||||
    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 all protocols except FILE and SCP. */
 | 
			
		||||
    data->set.redir_protocols = va_arg(param, long) & PROT_EXTMASK;
 | 
			
		||||
    break;
 | 
			
		||||
 | 
			
		||||
  default:
 | 
			
		||||
    /* unknown tag and its companion, just ignore: */
 | 
			
		||||
    result = CURLE_FAILED_INIT; /* correct this */
 | 
			
		||||
@@ -3371,7 +3393,19 @@ static CURLcode setup_connection_internals(struct SessionHandle *data,
 | 
			
		||||
 | 
			
		||||
  for (pp = protocols; (p = *pp) != NULL; pp++)
 | 
			
		||||
    if(Curl_raw_equal(p->scheme, conn->protostr)) {
 | 
			
		||||
      /* Protocol found in table. Perform setup complement if some. */
 | 
			
		||||
      /* Protocol found in table. Check if allowed */
 | 
			
		||||
      if(!(data->set.allowed_protocols & p->protocol))
 | 
			
		||||
        /* nope, get out */
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
      /* it is allowed for "normal" request, now do an extra check if this is
 | 
			
		||||
         the result of a redirect */
 | 
			
		||||
      if(data->state.this_is_a_follow &&
 | 
			
		||||
         !(data->set.redir_protocols & p->protocol))
 | 
			
		||||
        /* nope, get out */
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
      /* Perform setup complement if some. */
 | 
			
		||||
      conn->handler = p;
 | 
			
		||||
 | 
			
		||||
      if(p->setup_connection) {
 | 
			
		||||
 
 | 
			
		||||
@@ -891,19 +891,26 @@ struct connectdata {
 | 
			
		||||
  long connectindex; /* what index in the connection cache connects index this
 | 
			
		||||
                        particular struct has */
 | 
			
		||||
  long protocol; /* PROT_* flags concerning the protocol set */
 | 
			
		||||
#define PROT_MISSING (1<<0)
 | 
			
		||||
#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_TFTP    (1<<11)
 | 
			
		||||
#define PROT_SCP     (1<<12)
 | 
			
		||||
#define PROT_SFTP    (1<<13)
 | 
			
		||||
#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
 | 
			
		||||
#define PROT_TFTP    CURLPROTO_TFTP
 | 
			
		||||
#define PROT_SCP     CURLPROTO_SCP
 | 
			
		||||
#define PROT_SFTP    CURLPROTO_SFTP
 | 
			
		||||
 | 
			
		||||
/* 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 0xffff
 | 
			
		||||
 | 
			
		||||
#define PROT_SSL     (1<<22) /* protocol requires SSL */
 | 
			
		||||
#define PROT_MISSING (1<<23)
 | 
			
		||||
 | 
			
		||||
#define PROT_CLOSEACTION PROT_FTP /* these ones need action before socket
 | 
			
		||||
                                     close */
 | 
			
		||||
@@ -1533,6 +1540,8 @@ struct UserDefined {
 | 
			
		||||
                               via an HTTP proxy */
 | 
			
		||||
  char *str[STRING_LAST]; /* array of strings, pointing to allocated memory */
 | 
			
		||||
  unsigned int scope;    /* address scope for IPv6 */
 | 
			
		||||
  long allowed_protocols;
 | 
			
		||||
  long redir_protocols;
 | 
			
		||||
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
 | 
			
		||||
  long socks5_gssapi_nec; /* flag to support nec socks5 server */
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user