bagder: curl-www/CVE-2009-0037 curl-7.11.0-CVE-2009-0037.patch, NONE, 1.1 curl-7.15.1-CVE-2009-0037.patch, NONE, 1.1 curl-7.16.4-CVE-2009-0037.patch, NONE, 1.1 curl-7.18.1-CVE-2009-0037.patch, NONE, 1.1 curl-7.18.2-CVE-2009-0037.patch, NONE, 1.1 curl-7.19.0-CVE-2009-0037.patch, NONE, 1.1 curl-CVSHEAD-CVE-2009-0037.patch, NONE, 1.1

[email protected] Mon, 02 Mar 2009 23:06:28 +0000
Newsgroups gmane.comp.web.curl.www.cvs
Message-ID <[email protected]>
Update of /cvsroot/curl/curl-www/CVE-2009-0037
In directory labb:/tmp/cvs-serv10700/CVE-2009-0037

Added Files:
	curl-7.11.0-CVE-2009-0037.patch 
	curl-7.15.1-CVE-2009-0037.patch 
	curl-7.16.4-CVE-2009-0037.patch 
	curl-7.18.1-CVE-2009-0037.patch 
	curl-7.18.2-CVE-2009-0037.patch 
	curl-7.19.0-CVE-2009-0037.patch 
	curl-CVSHEAD-CVE-2009-0037.patch 
Log Message:
new release (in a few secs) and advisory stuff


--- NEW FILE: curl-7.16.4-CVE-2009-0037.patch ---
Index: docs/libcurl/curl_easy_setopt.3
===================================================================
--- docs/libcurl/curl_easy_setopt.3.orig
+++ docs/libcurl/curl_easy_setopt.3
@@ -370,6 +370,26 @@ The string given to CURLOPT_URL must be
 
 \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
@@ -601,6 +621,10 @@ This means that the library will re-send
 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 non-zero parameter tells the library it can continue to send authentication
 (user+password) when following locations, even when hostname changed. This
Index: include/curl/curl.h
===================================================================
--- include/curl/curl.h.orig
+++ include/curl/curl.h
@@ -495,6 +495,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
@@ -1083,6 +1098,18 @@ typedef enum {
   CINIT(NEW_FILE_PERMS, LONG, 159),
   CINIT(NEW_DIRECTORY_PERMS, LONG, 160),
 
+  /* 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;
 
Index: lib/url.c
===================================================================
--- lib/url.c.orig
+++ lib/url.c
@@ -595,6 +595,13 @@ CURLcode Curl_open(struct SessionHandle
     data->set.new_file_perms = 0644;    /* Default permissions */
     data->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 */
+    data->set.allowed_protocols = PROT_EXTMASK;
+    data->set.redir_protocols =
+      PROT_EXTMASK & ~(CURLPROTO_FILE|CURLPROTO_SCP); /* not FILE or SCP */
+
     /* most recent connection is not yet defined */
     data->state.lastconnect = -1;
 
@@ -1773,6 +1780,22 @@ CURLcode Curl_setopt(struct SessionHandl
     data->set.new_directory_perms = 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 CURLPROTO_ALL & ~CURLPROTO_FILE. */
+    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 */
@@ -3390,6 +3413,15 @@ else {
     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(proxy && *proxy) {
     /* If this is supposed to use a proxy, we need to figure out the proxy
Index: lib/urldata.h
===================================================================
--- lib/urldata.h.orig
+++ lib/urldata.h
@@ -758,19 +758,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 0xfff
+
+#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 */
@@ -1360,6 +1367,8 @@ struct UserDefined {
                             content-encoded (chunked, compressed) */
   long new_file_perms;    /* Permissions to use when creating remote files */
   long new_directory_perms; /* Permissions to use when creating remote dirs */
+  long allowed_protocols;
+  long redir_protocols;
 };
 
 struct Names {
Index: lib/easy.c
===================================================================
--- lib/easy.c.orig
+++ lib/easy.c
@@ -733,6 +733,13 @@ void curl_easy_reset(CURL *curl)
                                                       type */
   data->set.new_file_perms = 0644;    /* Default permissions */
   data->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 */
+  data->set.allowed_protocols = PROT_EXTMASK;
+  data->set.redir_protocols =
+    PROT_EXTMASK & ~(CURLPROTO_FILE|CURLPROTO_SCP); /* not FILE or SCP */
 }
 
 #ifdef CURL_DOES_CONVERSIONS

--- NEW FILE: curl-7.19.0-CVE-2009-0037.patch ---
Index: docs/libcurl/curl_easy_setopt.3
===================================================================
--- docs/libcurl/curl_easy_setopt.3.orig
+++ docs/libcurl/curl_easy_setopt.3
@@ -438,6 +438,26 @@ The string given to CURLOPT_URL must be
 
 \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
@@ -684,6 +704,10 @@ This means that the library will re-send
 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
Index: include/curl/curl.h
===================================================================
--- include/curl/curl.h.orig
+++ include/curl/curl.h
@@ -535,6 +535,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
@@ -1135,6 +1150,18 @@ typedef enum {
   /* (IPv6) Address scope */
   CINIT(ADDRESS_SCOPE, LONG, 171),
 
+  /* 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;
 
Index: lib/url.c
===================================================================
--- lib/url.c.orig
+++ lib/url.c
@@ -741,6 +741,13 @@ CURLcode Curl_open(struct SessionHandle
     data->set.new_file_perms = 0644;    /* Default permissions */
     data->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 */
+    data->set.allowed_protocols = PROT_EXTMASK;
+    data->set.redir_protocols =
+      PROT_EXTMASK & ~(CURLPROTO_FILE|CURLPROTO_SCP); /* not FILE or SCP */
+
     /* most recent connection is not yet defined */
     data->state.lastconnect = -1;
 
@@ -2106,6 +2113,22 @@ CURLcode Curl_setopt(struct SessionHandl
     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 CURLPROTO_ALL & ~CURLPROTO_FILE. */
+    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 */
@@ -3239,7 +3262,19 @@ static CURLcode setup_connection_interna
 
   for (pp = protocols; (p = *pp) != NULL; pp++)
     if(strequal(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) {
Index: lib/urldata.h
===================================================================
--- lib/urldata.h.orig
+++ lib/urldata.h
@@ -875,19 +875,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 0xfff
+
+#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 */
@@ -1487,6 +1494,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;
 };
 
 struct Names {
Index: lib/easy.c
===================================================================
--- lib/easy.c.orig
+++ lib/easy.c
@@ -785,6 +785,13 @@ void curl_easy_reset(CURL *curl)
                                                       type */
   data->set.new_file_perms = 0644;    /* Default permissions */
   data->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 */
+  data->set.allowed_protocols = PROT_EXTMASK;
+  data->set.redir_protocols =
+    PROT_EXTMASK & ~(CURLPROTO_FILE|CURLPROTO_SCP); /* not FILE or SCP */
 }
 
 /*

--- NEW FILE: curl-7.18.1-CVE-2009-0037.patch ---
Index: docs/libcurl/curl_easy_setopt.3
===================================================================
--- docs/libcurl/curl_easy_setopt.3.orig
+++ docs/libcurl/curl_easy_setopt.3
@@ -432,6 +432,26 @@ The string given to CURLOPT_URL must be
 
 \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
@@ -671,6 +691,10 @@ This means that the library will re-send
 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 non-zero parameter tells the library it can continue to send authentication
 (user+password) when following locations, even when hostname changed. This
Index: include/curl/curl.h
===================================================================
--- include/curl/curl.h.orig
+++ include/curl/curl.h
@@ -580,6 +580,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
@@ -1188,6 +1203,18 @@ typedef enum {
   CINIT(SEEKFUNCTION, FUNCTIONPOINT, 167),
   CINIT(SEEKDATA, OBJECTPOINT, 168),
 
+  /* 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;
 
Index: lib/url.c
===================================================================
--- lib/url.c.orig
+++ lib/url.c
@@ -734,6 +734,13 @@ CURLcode Curl_open(struct SessionHandle
     data->set.new_file_perms = 0644;    /* Default permissions */
     data->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 */
+    data->set.allowed_protocols = PROT_EXTMASK;
+    data->set.redir_protocols =
+      PROT_EXTMASK & ~(CURLPROTO_FILE|CURLPROTO_SCP); /* not FILE or SCP */
+
     /* most recent connection is not yet defined */
     data->state.lastconnect = -1;
 
@@ -2075,6 +2082,22 @@ CURLcode Curl_setopt(struct SessionHandl
     }
     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: */
     result = CURLE_FAILED_INIT; /* correct this */
@@ -3128,7 +3151,19 @@ static CURLcode setup_connection_interna
 
   for (pp = protocols; (p = *pp) != NULL; pp++)
     if(strequal(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) {
Index: lib/urldata.h
===================================================================
--- lib/urldata.h.orig
+++ lib/urldata.h
@@ -863,19 +863,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 0xfff
+
+#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 */
@@ -1467,6 +1474,8 @@ struct UserDefined {
   bool proxy_transfer_mode; /* set transfer mode (;type=<a|i>) when doing FTP
                                via an HTTP proxy */
   char *str[STRING_LAST]; /* array of strings, pointing to allocated memory */
+  long allowed_protocols;
+  long redir_protocols;
 };
 
 struct Names {
Index: lib/easy.c
===================================================================
--- lib/easy.c.orig
+++ lib/easy.c
@@ -756,6 +756,13 @@ void curl_easy_reset(CURL *curl)
                                                       type */
   data->set.new_file_perms = 0644;    /* Default permissions */
   data->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 */
+  data->set.allowed_protocols = PROT_EXTMASK;
+  data->set.redir_protocols =
+    PROT_EXTMASK & ~(CURLPROTO_FILE|CURLPROTO_SCP); /* not FILE or SCP */
 }
 
 /*

--- NEW FILE: curl-7.18.2-CVE-2009-0037.patch ---
Only in curl-7.18.2-protpatched: debug
diff -X curl/diff-exclude -ru curl-7.18.2/docs/libcurl/curl_easy_setopt.3 curl-7.18.2-protpatched/docs/libcurl/curl_easy_setopt.3
--- curl-7.18.2/docs/libcurl/curl_easy_setopt.3	2008-05-24 13:19:51.000000000 +0200
+++ curl-7.18.2-protpatched/docs/libcurl/curl_easy_setopt.3	2009-02-24 10:26:15.000000000 +0100
@@ -438,6 +438,26 @@
 
 \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
@@ -677,6 +697,10 @@
 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 non-zero parameter tells the library it can continue to send authentication
 (user+password) when following locations, even when hostname changed. This
diff -X curl/diff-exclude -ru curl-7.18.2/lib/url.c curl-7.18.2-protpatched/lib/url.c
--- curl-7.18.2/lib/url.c	2008-04-30 23:20:09.000000000 +0200
+++ curl-7.18.2-protpatched/lib/url.c	2009-02-24 10:30:02.000000000 +0100
@@ -743,6 +743,13 @@
 
     Curl_easy_initHandleData(data);
 
+    /* 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;
+    data->set.redir_protocols =
+      PROT_EXTMASK & ~(CURLPROTO_FILE|CURLPROTO_SCP); /* not FILE or SCP */
+
     /*
      * libcurl 7.10 introduced SSL verification *by default*! This needs to be
      * switched off unless wanted.
@@ -2083,6 +2090,22 @@
     }
     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 */
@@ -2338,7 +2361,6 @@
   }
 }
 
-
 /*
  * Given one filled in connection struct (named needle), this function should
  * detect if there already is one that has all the significant details
@@ -3136,7 +3158,19 @@
 
   for (pp = protocols; (p = *pp) != NULL; pp++)
     if(strequal(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) {
diff -X curl/diff-exclude -ru curl-7.18.2/lib/urldata.h curl-7.18.2-protpatched/lib/urldata.h
--- curl-7.18.2/lib/urldata.h	2008-04-30 23:20:09.000000000 +0200
+++ curl-7.18.2-protpatched/lib/urldata.h	2009-02-24 10:27:00.000000000 +0100
@@ -865,19 +865,26 @@
   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 */
@@ -1467,6 +1474,8 @@
   bool proxy_transfer_mode; /* set transfer mode (;type=<a|i>) when doing FTP
                                via an HTTP proxy */
   char *str[STRING_LAST]; /* array of strings, pointing to allocated memory */
+  long allowed_protocols;
+  long redir_protocols;
 };
 
 struct Names {

--- NEW FILE: curl-7.11.0-CVE-2009-0037.patch ---
Index: docs/libcurl/curl_easy_setopt.3
===================================================================
--- docs/libcurl/curl_easy_setopt.3.orig
+++ docs/libcurl/curl_easy_setopt.3
@@ -234,6 +234,26 @@ it, as it doesn't copy the string.
 
 \fBNOTE:\fP this option is (the only one) required to 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.
+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
@@ -410,6 +430,10 @@ server sends as part of a HTTP header.
 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 non-zero parameter tells the library it can continue to send authentication
 (user+password) when following locations, even when hostname changed. Note
Index: include/curl/curl.h
===================================================================
--- include/curl/curl.h.orig
+++ include/curl/curl.h
@@ -265,6 +265,18 @@ typedef enum {
   CURLFTPSSL_LAST     /* not an option, never use */
 } curl_ftpssl;
 
+/* 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
@@ -745,6 +757,18 @@ typedef enum {
   */
   CINIT(FTP_SSL, LONG, 119),
 
+  /* 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;
 
Index: lib/url.c
===================================================================
--- lib/url.c.orig
+++ lib/url.c
@@ -296,6 +296,13 @@ CURLcode Curl_open(struct SessionHandle
   data->set.httpauth = CURLAUTH_BASIC; /* defaults to basic authentication */
   data->set.proxyauth = CURLAUTH_BASIC; /* defaults to basic authentication */
 
+  /* 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 **)
@@ -1282,6 +1289,22 @@ CURLcode Curl_setopt(struct SessionHandl
     data->set.max_filesize = va_arg(param, off_t);
     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 */
@@ -2579,8 +2602,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!");
@@ -2592,6 +2613,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
Index: lib/urldata.h
===================================================================
--- lib/urldata.h.orig
+++ lib/urldata.h
@@ -399,17 +399,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;
@@ -870,6 +880,8 @@ struct UserDefined {
   bool no_signal;        /* do not use any signal/alarm handler */
 
   bool global_dns_cache;
+  long allowed_protocols;
+  long redir_protocols;
 };
 
 /*

--- NEW FILE: curl-CVSHEAD-CVE-2009-0037.patch ---
Index: docs/libcurl/curl_easy_setopt.3
===================================================================
RCS file: /cvsroot/curl/curl/docs/libcurl/curl_easy_setopt.3,v
retrieving revision 1.254
diff -u -r1.254 curl_easy_setopt.3
--- docs/libcurl/curl_easy_setopt.3	23 Feb 2009 10:40:36 -0000	1.254
+++ docs/libcurl/curl_easy_setopt.3	1 Mar 2009 14:21:08 -0000
@@ -440,6 +440,26 @@
 
 \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 @@
 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
Index: docs/libcurl/symbols-in-versions
===================================================================
RCS file: /cvsroot/curl/curl/docs/libcurl/symbols-in-versions,v
retrieving revision 1.4
diff -u -r1.4 symbols-in-versions
--- docs/libcurl/symbols-in-versions	17 Feb 2009 09:43:27 -0000	1.4
+++ docs/libcurl/symbols-in-versions	1 Mar 2009 14:21:08 -0000
@@ -191,6 +191,7 @@
 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_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_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
Index: include/curl/curl.h
===================================================================
RCS file: /cvsroot/curl/curl/include/curl/curl.h,v
retrieving revision 1.378
diff -u -r1.378 curl.h
--- include/curl/curl.h	17 Feb 2009 09:08:22 -0000	1.378
+++ include/curl/curl.h	1 Mar 2009 14:21:09 -0000
@@ -550,6 +550,21 @@
   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 @@
   /* 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;
 
Index: lib/url.c
===================================================================
RCS file: /cvsroot/curl/curl/lib/url.c,v
retrieving revision 1.789
diff -u -r1.789 url.c
--- lib/url.c	28 Feb 2009 01:11:57 -0000	1.789
+++ lib/url.c	1 Mar 2009 14:21:11 -0000
@@ -683,6 +683,12 @@
   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 @@
     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 @@
 
   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) {
Index: lib/urldata.h
===================================================================
RCS file: /cvsroot/curl/curl/lib/urldata.h,v
retrieving revision 1.408
diff -u -r1.408 urldata.h
--- lib/urldata.h	20 Feb 2009 08:16:04 -0000	1.408
+++ lib/urldata.h	1 Mar 2009 14:21:11 -0000
@@ -891,19 +891,26 @@
   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 @@
                                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

--- NEW FILE: curl-7.15.1-CVE-2009-0037.patch ---
Index: docs/libcurl/curl_easy_setopt.3
===================================================================
--- docs/libcurl/curl_easy_setopt.3.orig
+++ docs/libcurl/curl_easy_setopt.3
@@ -292,6 +292,26 @@ on which protocols that are supported.
 
 \fICURLOPT_URL\fP is the only option that must 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.
+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
@@ -507,6 +527,10 @@ This means that the library will re-send
 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 non-zero parameter tells the library it can continue to send authentication
 (user+password) when following locations, even when hostname changed. This
Index: include/curl/curl.h
===================================================================
--- include/curl/curl.h.orig
+++ include/curl/curl.h
@@ -379,6 +379,19 @@ typedef enum {
   CURLFTPAUTH_LAST /* not an option, never use */
 } curl_ftpauth;
 
+/* 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_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
@@ -912,6 +925,18 @@ typedef enum {
   /* Select "file method" to use when doing FTP */
   CINIT(FTP_FILEMETHOD, LONG, 138),
 
+  /* 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;
 
Index: lib/url.c
===================================================================
--- lib/url.c.orig
+++ lib/url.c
@@ -342,6 +342,13 @@ CURLcode Curl_open(struct SessionHandle
     data->set.httpauth = CURLAUTH_BASIC;  /* defaults to basic */
     data->set.proxyauth = CURLAUTH_BASIC; /* defaults to basic */
 
+    /* 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 **)
@@ -1460,6 +1467,22 @@ CURLcode Curl_setopt(struct SessionHandl
     data->set.ignorecl = va_arg(param, long)?TRUE:FALSE;
     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: */
     result = CURLE_FAILED_INIT; /* correct this */
@@ -2932,8 +2955,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!");
@@ -2983,6 +3004,17 @@ 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;
 
   if(data->change.proxy && *data->change.proxy) {
     /* If this is supposed to use a proxy, we need to figure out the proxy
Index: lib/urldata.h
===================================================================
--- lib/urldata.h.orig
+++ lib/urldata.h
@@ -538,18 +538,28 @@ 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_TFTP    (1<<11)
-#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
+#define PROT_TFTP    CURLPROTO_TFTP
+/* 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)
+
 
   /* 'dns_entry' is the particular host we use. This points to an entry in the
      DNS cache and it will not get pruned while locked. It gets unlocked in
@@ -1085,6 +1095,8 @@ struct UserDefined {
   bool ignorecl;         /* ignore content length */
   bool ftp_skip_ip;      /* skip the IP address the FTP server passes on to
                             us */
+  long allowed_protocols;
+  long redir_protocols;
 };
 
 /*
Index: lib/easy.c
===================================================================
--- lib/easy.c.orig
+++ lib/easy.c
@@ -642,6 +642,13 @@ void curl_easy_reset(CURL *curl)
   data->set.httpauth = CURLAUTH_BASIC;  /* defaults to basic */
   data->set.proxyauth = CURLAUTH_BASIC; /* defaults to basic */
 
+  /* 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 */
+
   /*
    * libcurl 7.10 introduced SSL verification *by default*! This needs to be
    * switched off unless wanted.