aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--networking/httpd.c26
-rw-r--r--networking/httpd_indexcgi.c27
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 */
1272static void send_cgi_and_exit( 1273static 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;
1278static void send_cgi_and_exit( 1280static 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"