diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2011-12-19 12:30:34 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2011-12-19 12:30:34 +0100 |
commit | 03419aa037ce37d1c3accb0df52fdc456b360541 (patch) | |
tree | 6f96d1d0bdaafd2e197c9651dde789a8451c09b9 | |
parent | 93b4a605263612cf32ad9de746a4fafaf4515115 (diff) | |
download | busybox-w32-03419aa037ce37d1c3accb0df52fdc456b360541.tar.gz busybox-w32-03419aa037ce37d1c3accb0df52fdc456b360541.tar.bz2 busybox-w32-03419aa037ce37d1c3accb0df52fdc456b360541.zip |
httpd: don't drop/abuse QUERY_STRING when /cgi-bin/index.cgi is used
Signed-off-by: Peter Korsgaard <jacmet@sunsite.dk>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | networking/httpd.c | 26 | ||||
-rw-r--r-- | networking/httpd_indexcgi.c | 27 |
2 files changed, 34 insertions, 19 deletions
diff --git a/networking/httpd.c b/networking/httpd.c index e9cd213f1..3f4e6aab7 100644 --- a/networking/httpd.c +++ b/networking/httpd.c | |||
@@ -1265,18 +1265,21 @@ static void setenv1(const char *name, const char *value) | |||
1265 | * | 1265 | * |
1266 | * Parameters: | 1266 | * Parameters: |
1267 | * const char *url The requested URL (with leading /). | 1267 | * const char *url The requested URL (with leading /). |
1268 | * const char *orig_uri The original URI before rewriting (if any) | ||
1268 | * int post_len Length of the POST body. | 1269 | * int post_len Length of the POST body. |
1269 | * const char *cookie For set HTTP_COOKIE. | 1270 | * const char *cookie For set HTTP_COOKIE. |
1270 | * const char *content_type For set CONTENT_TYPE. | 1271 | * const char *content_type For set CONTENT_TYPE. |
1271 | */ | 1272 | */ |
1272 | static void send_cgi_and_exit( | 1273 | static void send_cgi_and_exit( |
1273 | const char *url, | 1274 | const char *url, |
1275 | const char *orig_uri, | ||
1274 | const char *request, | 1276 | const char *request, |
1275 | int post_len, | 1277 | int post_len, |
1276 | const char *cookie, | 1278 | const char *cookie, |
1277 | const char *content_type) NORETURN; | 1279 | const char *content_type) NORETURN; |
1278 | static void send_cgi_and_exit( | 1280 | static void send_cgi_and_exit( |
1279 | const char *url, | 1281 | const char *url, |
1282 | const char *orig_uri, | ||
1280 | const char *request, | 1283 | const char *request, |
1281 | int post_len, | 1284 | int post_len, |
1282 | const char *cookie, | 1285 | const char *cookie, |
@@ -1314,9 +1317,9 @@ static void send_cgi_and_exit( | |||
1314 | setenv1("PATH_INFO", script); /* set to /PATH_INFO or "" */ | 1317 | setenv1("PATH_INFO", script); /* set to /PATH_INFO or "" */ |
1315 | setenv1("REQUEST_METHOD", request); | 1318 | setenv1("REQUEST_METHOD", request); |
1316 | if (g_query) { | 1319 | if (g_query) { |
1317 | putenv(xasprintf("%s=%s?%s", "REQUEST_URI", url, g_query)); | 1320 | putenv(xasprintf("%s=%s?%s", "REQUEST_URI", orig_uri, g_query)); |
1318 | } else { | 1321 | } else { |
1319 | setenv1("REQUEST_URI", url); | 1322 | setenv1("REQUEST_URI", orig_uri); |
1320 | } | 1323 | } |
1321 | if (script != NULL) | 1324 | if (script != NULL) |
1322 | *script = '\0'; /* cut off /PATH_INFO */ | 1325 | *script = '\0'; /* cut off /PATH_INFO */ |
@@ -2248,12 +2251,20 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) | |||
2248 | /* protect listing "cgi-bin/" */ | 2251 | /* protect listing "cgi-bin/" */ |
2249 | send_headers_and_exit(HTTP_FORBIDDEN); | 2252 | send_headers_and_exit(HTTP_FORBIDDEN); |
2250 | } | 2253 | } |
2251 | send_cgi_and_exit(urlcopy, prequest, length, cookie, content_type); | 2254 | send_cgi_and_exit(urlcopy, urlcopy, prequest, length, cookie, content_type); |
2252 | } | 2255 | } |
2253 | #endif | 2256 | #endif |
2254 | 2257 | ||
2255 | if (urlp[-1] == '/') | 2258 | if (urlp[-1] == '/') { |
2259 | /* When index_page string is appended to <dir>/ URL, it overwrites | ||
2260 | * the query string. If we fall back to call /cgi-bin/index.cgi, | ||
2261 | * query string would be lost and not available to the CGI. | ||
2262 | * Work around it by making a deep copy. | ||
2263 | */ | ||
2264 | if (ENABLE_FEATURE_HTTPD_CGI) | ||
2265 | g_query = xstrdup(g_query); /* ok for NULL too */ | ||
2256 | strcpy(urlp, index_page); | 2266 | strcpy(urlp, index_page); |
2267 | } | ||
2257 | if (stat(tptr, &sb) == 0) { | 2268 | if (stat(tptr, &sb) == 0) { |
2258 | #if ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR | 2269 | #if ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR |
2259 | char *suffix = strrchr(tptr, '.'); | 2270 | char *suffix = strrchr(tptr, '.'); |
@@ -2261,7 +2272,7 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) | |||
2261 | Htaccess *cur; | 2272 | Htaccess *cur; |
2262 | for (cur = script_i; cur; cur = cur->next) { | 2273 | for (cur = script_i; cur; cur = cur->next) { |
2263 | if (strcmp(cur->before_colon + 1, suffix) == 0) { | 2274 | if (strcmp(cur->before_colon + 1, suffix) == 0) { |
2264 | send_cgi_and_exit(urlcopy, prequest, length, cookie, content_type); | 2275 | send_cgi_and_exit(urlcopy, urlcopy, prequest, length, cookie, content_type); |
2265 | } | 2276 | } |
2266 | } | 2277 | } |
2267 | } | 2278 | } |
@@ -2274,9 +2285,8 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) | |||
2274 | /* It's a dir URL and there is no index.html | 2285 | /* It's a dir URL and there is no index.html |
2275 | * Try cgi-bin/index.cgi */ | 2286 | * Try cgi-bin/index.cgi */ |
2276 | if (access("/cgi-bin/index.cgi"+1, X_OK) == 0) { | 2287 | if (access("/cgi-bin/index.cgi"+1, X_OK) == 0) { |
2277 | urlp[0] = '\0'; | 2288 | urlp[0] = '\0'; /* remove index_page */ |
2278 | g_query = urlcopy; | 2289 | send_cgi_and_exit("/cgi-bin/index.cgi", urlcopy, prequest, length, cookie, content_type); |
2279 | send_cgi_and_exit("/cgi-bin/index.cgi", prequest, length, cookie, content_type); | ||
2280 | } | 2290 | } |
2281 | } | 2291 | } |
2282 | /* else fall through to send_file, it errors out if open fails: */ | 2292 | /* else fall through to send_file, it errors out if open fails: */ |
diff --git a/networking/httpd_indexcgi.c b/networking/httpd_indexcgi.c index 7e0225e19..d732cd4f8 100644 --- a/networking/httpd_indexcgi.c +++ b/networking/httpd_indexcgi.c | |||
@@ -221,20 +221,25 @@ int main(int argc, char *argv[]) | |||
221 | unsigned long long size_total; | 221 | unsigned long long size_total; |
222 | int odd; | 222 | int odd; |
223 | DIR *dirp; | 223 | DIR *dirp; |
224 | char *QUERY_STRING; | 224 | char *location; |
225 | 225 | ||
226 | QUERY_STRING = getenv("QUERY_STRING"); | 226 | location = getenv("REQUEST_URI"); |
227 | if (!QUERY_STRING | 227 | if (!location) |
228 | || QUERY_STRING[0] != '/' | 228 | return 1; |
229 | || strstr(QUERY_STRING, "//") | 229 | |
230 | || strstr(QUERY_STRING, "/../") | 230 | /* drop URL arguments if any */ |
231 | || strcmp(strrchr(QUERY_STRING, '/'), "/..") == 0 | 231 | strchrnul(location, '?')[0] = '\0'; |
232 | |||
233 | if (location[0] != '/' | ||
234 | || strstr(location, "//") | ||
235 | || strstr(location, "/../") | ||
236 | || strcmp(strrchr(location, '/'), "/..") == 0 | ||
232 | ) { | 237 | ) { |
233 | return 1; | 238 | return 1; |
234 | } | 239 | } |
235 | 240 | ||
236 | if (chdir("..") | 241 | if (chdir("..") |
237 | || (QUERY_STRING[1] && chdir(QUERY_STRING + 1)) | 242 | || (location[1] && chdir(location + 1)) |
238 | ) { | 243 | ) { |
239 | return 1; | 244 | return 1; |
240 | } | 245 | } |
@@ -271,14 +276,14 @@ int main(int argc, char *argv[]) | |||
271 | "\r\n" /* Mandatory empty line after headers */ | 276 | "\r\n" /* Mandatory empty line after headers */ |
272 | "<html><head><title>Index of "); | 277 | "<html><head><title>Index of "); |
273 | /* Guard against directories with &, > etc */ | 278 | /* Guard against directories with &, > etc */ |
274 | fmt_html(QUERY_STRING); | 279 | fmt_html(location); |
275 | fmt_str( | 280 | fmt_str( |
276 | "</title>\n" | 281 | "</title>\n" |
277 | STYLE_STR | 282 | STYLE_STR |
278 | "</head>" "\n" | 283 | "</head>" "\n" |
279 | "<body>" "\n" | 284 | "<body>" "\n" |
280 | "<h1>Index of "); | 285 | "<h1>Index of "); |
281 | fmt_html(QUERY_STRING); | 286 | fmt_html(location); |
282 | fmt_str( | 287 | fmt_str( |
283 | "</h1>" "\n" | 288 | "</h1>" "\n" |
284 | "<table>" "\n" | 289 | "<table>" "\n" |