summaryrefslogtreecommitdiffstats
path: root/curl-7.15.5-CVE-2009-0037.patch
blob: d23cb86492e15edf553b056d62692153b1dfbbb0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
diff -pruN curl-7.15.5.orig/docs/libcurl/curl_easy_setopt.3 curl-7.15.5/docs/libcurl/curl_easy_setopt.3
--- curl-7.15.5.orig/docs/libcurl/curl_easy_setopt.3	2006-08-02 11:33:32.000000000 +0200
+++ curl-7.15.5/docs/libcurl/curl_easy_setopt.3	2009-03-13 15:04:52.000000000 +0100
@@ -346,6 +346,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
@@ -574,6 +594,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
diff -pruN curl-7.15.5.orig/include/curl/curl.h curl-7.15.5/include/curl/curl.h
--- curl-7.15.5.orig/include/curl/curl.h	2006-08-06 22:45:34.000000000 +0200
+++ curl-7.15.5/include/curl/curl.h	2009-03-13 15:04:52.000000000 +0100
@@ -414,6 +414,19 @@ 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_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
@@ -982,6 +995,18 @@ typedef enum {
   /* Pointer to command string to send if USER/PASS fails. */
   CINIT(FTP_ALTERNATIVE_TO_USER, OBJECTPOINT, 147),
 
+  /* 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 -pruN curl-7.15.5.orig/lib/url.c curl-7.15.5/lib/url.c
--- curl-7.15.5.orig/lib/url.c	2006-08-02 20:08:06.000000000 +0200
+++ curl-7.15.5/lib/url.c	2009-03-13 15:04:52.000000000 +0100
@@ -367,6 +367,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;
+    data->set.redir_protocols =
+      (PROT_EXTMASK & ~CURLPROTO_FILE); /* not FILE */
+
     /* create an array with connection data struct pointers */
     data->state.numconnects = 5; /* hard-coded right now */
     data->state.connects = (struct connectdata **)
@@ -1551,6 +1558,22 @@ CURLcode Curl_setopt(struct SessionHandl
     data->set.ftp_alternative_to_user = va_arg(param, char *);
     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 */
@@ -3198,8 +3221,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!");
@@ -3249,6 +3270,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
diff -pruN curl-7.15.5.orig/lib/urldata.h curl-7.15.5/lib/urldata.h
--- curl-7.15.5.orig/lib/urldata.h	2006-07-26 00:46:38.000000000 +0200
+++ curl-7.15.5/lib/urldata.h	2009-03-13 15:04:52.000000000 +0100
@@ -563,17 +563,23 @@ struct connectdata {
                        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_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)
 
   /* '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
@@ -1147,6 +1153,8 @@ struct UserDefined {
   bool ftp_skip_ip;      /* skip the IP address the FTP server passes on to
                             us */
   bool connect_only;     /* make connection, let application use the socket */
+  long allowed_protocols;
+  long redir_protocols;
 };
 
 struct Names {
diff -pruN curl-7.15.5.orig/lib/easy.c curl-7.15.5/lib/easy.c
--- curl-7.15.5.orig/lib/easy.c	2006-07-25 20:39:22.000000000 +0200
+++ curl-7.15.5/lib/easy.c	2009-03-13 15:04:52.000000000 +0100
@@ -670,6 +670,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;
+  data->set.redir_protocols =
+    (PROT_EXTMASK & ~CURLPROTO_FILE); /* not FILE */
+
   /*
    * libcurl 7.10 introduced SSL verification *by default*! This needs to be
    * switched off unless wanted.