aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGlenn L McGrath <bug1@ihug.co.nz>2003-05-19 05:56:16 +0000
committerGlenn L McGrath <bug1@ihug.co.nz>2003-05-19 05:56:16 +0000
commit4fe3ff8cffce83b3132223daf80e3e77ca89c259 (patch)
treef9f7383cc233313f026058f6f0395114e4fb65ec
parent0861e828d028cdb6ad0798143a88c9eb6fabb631 (diff)
downloadbusybox-w32-4fe3ff8cffce83b3132223daf80e3e77ca89c259.tar.gz
busybox-w32-4fe3ff8cffce83b3132223daf80e3e77ca89c259.tar.bz2
busybox-w32-4fe3ff8cffce83b3132223daf80e3e77ca89c259.zip
Patch from Glenn Engel
- more comments - larger allowed number of CGI script variables - ifdefs for regression test hooks - default to ./ rather than /www (if unspecified) for compatibility with earlier versions. - Allow ip: as a synomym for A: rules for compatibility with earlier versions. - Setting of CGI_ARGLIST_ when automatic setting of env vars for form scripting is utilized. This helps with minimal systems like openap.
-rw-r--r--networking/httpd.c178
1 files changed, 139 insertions, 39 deletions
diff --git a/networking/httpd.c b/networking/httpd.c
index df99f1c8b..e9f4c15bc 100644
--- a/networking/httpd.c
+++ b/networking/httpd.c
@@ -41,33 +41,70 @@
41 * 41 *
42 * The server can also be invoked as a url arg decoder and html text encoder 42 * The server can also be invoked as a url arg decoder and html text encoder
43 * as follows: 43 * as follows:
44 * foo=`httpd -d $foo` # decode "Hello%20World" as "Hello World" 44 * foo=`httpd -d $foo` # decode "Hello%20World" as "Hello World"
45 * bar=`httpd -e "<Hello World>"` # encode as "&#60Hello&#32World&#62" 45 * bar=`httpd -e "<Hello World>"` # encode as "&#60Hello&#32World&#62"
46 * Note that url encoding for arguments is not the same as html encoding for
47 * presenation. -d decodes a url-encoded argument while -e encodes in html
48 * for page display.
46 * 49 *
47 * httpd.conf has the following format: 50 * httpd.conf has the following format:
51 *
52 * A:172.20. # Allow any address that begins with 172.20
53 * A:10.10. # Allow any address that begins with 10.10.
54 * A:10.20 # Allow any address that previous set and 10.200-209.X.X
55 * A:127.0.0.1 # Allow local loopback connections
56 * D:* # Deny from other IP connections
57 * /cgi-bin:foo:bar # Require user foo, pwd bar on urls starting with /cgi-bin/
58 * /adm:admin:setup # Require user admin, pwd setup on urls starting with /adm/
59 * /adm:toor:PaSsWd # or user toor, pwd PaSsWd on urls starting with /adm/
60 * .au:audio/basic # additional mime type for audio.au files
61 *
62 * A/D may be as a/d or allow/deny - first char case unsensitive
63 * Deny IP rules take precedence over allow rules. Any IP rules after D:* are
64 * ignored.
65 *
66 *
67 * The Deny/Allow IP logic:
68 *
69 * - Default is to allow all. No addresses are denied unless
70 * denied with a D: rule.
71 * - Order of Deny/Allow rules is significant
72 * - Deny rules take precedence over allow rules.
73 * - If a deny all rule (D:*) is used it acts as a catch-all for unmatched
74 * addresses.
75 * - Specification of Allow all (A:*) is a no-op
76 *
77 * Example:
78 * 1. Allow only specified addresses
79 * A:172.20. # Allow any address that begins with 172.20
80 * A:10.10. # Allow any address that begins with 10.10.
81 * A:10.10 # Allow any address that previous set and 10.100-109.X.X
82 * A:127.0.0.1 # Allow local loopback connections
83 * D:* # Deny from other IP connections
84 *
85 * 2. Only deny specified addresses
86 * D:1.2.3. # deny from 1.2.3.0 - 1.2.3.255
87 * D:2.3.4. # deny from 2.3.4.0 - 2.3.4.255
88 * A:* # (optional line added for clarity)
89 *
90 * If a sub directory contains a config file it is parsed and merged with
91 * any existing settings as if it was appended to the original configuration
92 * except that all previous IP config rules are discarded.
93 *
94 * subdir paths are relative to the containing subdir and thus cannot
95 * affect the parent rules.
96 *
97 * Note that since the sub dir is parsed in the forked thread servicing the
98 * subdir http request, any merge is discarded when the process exits. As a
99 * result, the subdir settings only have a lifetime of a single request.
100 *
101 *
102 * If -c is not set, an attempt will be made to open the default
103 * root configuration file. If -c is set and the file is not found, the
104 * server exits with an error.
105 *
106*/
48 107
49A:172.20. # Allow any address that begins with 172.20
50A:10.10. # Allow any address that begins with 10.10.
51A:10.10 # Allow any address that previous set and 10.100-109.X.X
52A:127.0.0.1 # Allow local loopback connections
53D:* # Deny from other IP connections
54/cgi-bin:foo:bar # Require user foo, pwd bar on urls starting with /cgi-bin/
55/adm:admin:setup # Require user admin, pwd setup on urls starting with /adm/
56/adm:toor:PaSsWd # or user toor, pwd PaSsWd on urls starting with /adm/
57.au:audio/basic # additional mime type for audio.au files
58
59A/D may be as a/d or allow/deny - first char case unsensitive parsed only.
60
61Each subdir can have config file.
62You can set less IP allow from subdir config.
63Password protection from subdir config can rewriten previous sets for
64current or/and next subpathes.
65For protect as user:pass current subdir and subpathes set from subdir config:
66/:user:pass
67/subpath:user2:pass2
68
69 If -c don`t setted, used httpd root config, else httpd root config skiped.
70 */
71 108
72#include <stdio.h> 109#include <stdio.h>
73#include <ctype.h> /* for isspace */ 110#include <ctype.h> /* for isspace */
@@ -86,10 +123,10 @@ For protect as user:pass current subdir and subpathes set from subdir config:
86#include "busybox.h" 123#include "busybox.h"
87 124
88 125
89static const char httpdVersion[] = "busybox httpd/1.25 10-May-2003"; 126static const char httpdVersion[] = "busybox httpd/1.26 18-May-2003";
90static const char default_path_httpd_conf[] = "/etc"; 127static const char default_path_httpd_conf[] = "/etc";
91static const char httpd_conf[] = "httpd.conf"; 128static const char httpd_conf[] = "httpd.conf";
92static const char home[] = "/www"; 129static const char home[] = "./";
93 130
94// Note: bussybox xfuncs are not used because we want the server to keep running 131// Note: bussybox xfuncs are not used because we want the server to keep running
95// if something bad happens due to a malformed user request. 132// if something bad happens due to a malformed user request.
@@ -160,7 +197,7 @@ void bb_show_usage(void)
160 197
161/* CGI environ size */ 198/* CGI environ size */
162#ifdef CONFIG_FEATURE_HTTPD_SET_CGI_VARS_TO_ENV 199#ifdef CONFIG_FEATURE_HTTPD_SET_CGI_VARS_TO_ENV
163#define ENVSIZE 50 /* set max 35 CGI_variable */ 200#define ENVSIZE 70 /* set max CGI variable */
164#else 201#else
165#define ENVSIZE 15 /* minimal requires */ 202#define ENVSIZE 15 /* minimal requires */
166#endif 203#endif
@@ -325,7 +362,31 @@ static void free_config_lines(Htaccess **pprev)
325#define SUBDIR_PARSE 1 362#define SUBDIR_PARSE 1
326#define SIGNALED_PARSE 2 363#define SIGNALED_PARSE 2
327#define FIND_FROM_HTTPD_ROOT 3 364#define FIND_FROM_HTTPD_ROOT 3
328 365/****************************************************************************
366 *
367 > $Function: parse_conf()
368 *
369 * $Description: parse configuration file into in-memory linked list.
370 *
371 * The first non-white character is examined to determine if the config line
372 * is one of the following:
373 * .ext:mime/type # new mime type not compiled into httpd
374 * [adAD]:from # ip address allow/deny, * for wildcard
375 * /path:user:pass # username/password
376 *
377 * Any previous IP rules are discarded.
378 * If the flag argument is not SUBDIR_PARSE then all /path and mime rules
379 * are also discarded. That is, previous settings are retained if flag is
380 * SUBDIR_PARSE.
381 *
382 * $Parameters:
383 * (const char *) path . . null for ip address checks, path for password
384 * checks.
385 * (int) flag . . . . . . the source of the parse request.
386 *
387 * $Return: (None)
388 *
389 ****************************************************************************/
329static void parse_conf(const char *path, int flag) 390static void parse_conf(const char *path, int flag)
330{ 391{
331 FILE *f; 392 FILE *f;
@@ -335,17 +396,18 @@ static void parse_conf(const char *path, int flag)
335#endif 396#endif
336 397
337 const char *cf = config->configFile; 398 const char *cf = config->configFile;
338 char buf[80]; 399 char buf[160];
339 char *p0 = NULL; 400 char *p0 = NULL;
340 char *c, *p; 401 char *c, *p;
341 402
342 /* free previous setuped */ 403 /* free previous ip setup if present */
343 free_config_lines(&config->ip_a_d); 404 free_config_lines(&config->ip_a_d);
405 /* retain previous auth and mime config only for subdir parse */
344 if(flag != SUBDIR_PARSE) { 406 if(flag != SUBDIR_PARSE) {
345#ifdef CONFIG_FEATURE_HTTPD_BASIC_AUTH 407#ifdef CONFIG_FEATURE_HTTPD_BASIC_AUTH
346 free_config_lines(&config->auth) 408 free_config_lines(&config->auth)
347#endif 409#endif
348 ; /* syntax confuse */ 410 ; /* appease compiler warnings if option is not set */
349#ifdef CONFIG_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES 411#ifdef CONFIG_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES
350 free_config_lines(&config->mime_a); 412 free_config_lines(&config->mime_a);
351#endif 413#endif
@@ -363,7 +425,7 @@ static void parse_conf(const char *path, int flag)
363 425
364 while((f = fopen(cf, "r")) == NULL) { 426 while((f = fopen(cf, "r")) == NULL) {
365 if(flag != FIRST_PARSE) { 427 if(flag != FIRST_PARSE) {
366 /* config file not found */ 428 /* config file not found, no changes to config */
367 return; 429 return;
368 } 430 }
369 if(config->configFile) /* if -c option given */ 431 if(config->configFile) /* if -c option given */
@@ -376,7 +438,7 @@ static void parse_conf(const char *path, int flag)
376 prev = config->auth; 438 prev = config->auth;
377#endif 439#endif
378 /* This could stand some work */ 440 /* This could stand some work */
379 while ( (p0 = fgets(buf, 80, f)) != NULL) { 441 while ( (p0 = fgets(buf, sizeof(buf), f)) != NULL) {
380 c = NULL; 442 c = NULL;
381 for(p = p0; *p0 != 0 && *p0 != '#'; p0++) { 443 for(p = p0; *p0 != 0 && *p0 != '#'; p0++) {
382 if(!isspace(*p0)) { 444 if(!isspace(*p0)) {
@@ -393,18 +455,20 @@ static void parse_conf(const char *path, int flag)
393 if(*c == '*') 455 if(*c == '*')
394 *c = 0; /* Allow all */ 456 *c = 0; /* Allow all */
395 p0 = buf; 457 p0 = buf;
458 if((*p0 == 'i') || (*p0 == 'I'))
459 *p0 = 'A'; // version 1.1/1.2 compatibility for ip:
396 if(*p0 == 'a') 460 if(*p0 == 'a')
397 *p0 = 'A'; 461 *p0 = 'A';
398 if(*p0 == 'd') 462 if(*p0 == 'd')
399 *p0 = 'D'; 463 *p0 = 'D';
400 if(*p0 != 'A' && *p0 != 'D' 464 if(*p0 != 'A' && *p0 != 'D'
401#ifdef CONFIG_FEATURE_HTTPD_BASIC_AUTH 465#ifdef CONFIG_FEATURE_HTTPD_BASIC_AUTH
402 && *p0 != '/' 466 && *p0 != '/'
403#endif 467#endif
404#ifdef CONFIG_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES 468#ifdef CONFIG_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES
405 && *p0 != '.' 469 && *p0 != '.'
406#endif 470#endif
407 ) 471 )
408 continue; 472 continue;
409 473
410 if(*p0 == 'A' && *c == 0) { 474 if(*p0 == 'A' && *c == 0) {
@@ -681,9 +745,12 @@ static void addEnvCgi(const char *pargs)
681{ 745{
682 char *args; 746 char *args;
683 char *memargs; 747 char *memargs;
748 char *namelist; /* space separated list of arg names */
684 if (pargs==0) return; 749 if (pargs==0) return;
685 750
686 /* args are a list of name=value&name2=value2 sequences */ 751 /* args are a list of name=value&name2=value2 sequences */
752 namelist = (char *) malloc(strlen(pargs));
753 if (namelist) namelist[0]=0;
687 memargs = args = strdup(pargs); 754 memargs = args = strdup(pargs);
688 while (args && *args) { 755 while (args && *args) {
689 const char *name = args; 756 const char *name = args;
@@ -696,8 +763,14 @@ static void addEnvCgi(const char *pargs)
696 if (args) 763 if (args)
697 *args++ = 0; 764 *args++ = 0;
698 addEnv("CGI", name, decodeString(value, 1)); 765 addEnv("CGI", name, decodeString(value, 1));
766 if (*namelist) strcat(namelist, " ");
767 strcat(namelist,name);
699 } 768 }
700 free(memargs); 769 free(memargs);
770 if (namelist) {
771 addEnv("CGI","ARGLIST_",namelist);
772 free(namelist);
773 }
701} 774}
702#endif /* CONFIG_FEATURE_HTTPD_SET_CGI_VARS_TO_ENV */ 775#endif /* CONFIG_FEATURE_HTTPD_SET_CGI_VARS_TO_ENV */
703 776
@@ -1050,10 +1123,11 @@ static int sendCgi(const char *url,
1050 if(script) { 1123 if(script) {
1051 *script = '\0'; 1124 *script = '\0';
1052 if(chdir(realpath_buff) == 0) { 1125 if(chdir(realpath_buff) == 0) {
1053 *script = '/'; 1126 *script = '/';
1054 // now run the program. If it fails, use _exit() so no destructors 1127 // now run the program. If it fails,
1055 // get called and make a mess. 1128 // use _exit() so no destructors
1056 execve(realpath_buff, argp, config->envp); 1129 // get called and make a mess.
1130 execve(realpath_buff, argp, config->envp);
1057 } 1131 }
1058 } 1132 }
1059 } 1133 }
@@ -1605,6 +1679,9 @@ static int miniHttpd(int server)
1605 exit(0); 1679 exit(0);
1606 } 1680 }
1607 close(s); 1681 close(s);
1682#ifdef TEST
1683 return 0; // exit after processing one request
1684#endif
1608 } 1685 }
1609 } 1686 }
1610 } // while (1) 1687 } // while (1)
@@ -1655,6 +1732,10 @@ int httpd_main(int argc, char *argv[])
1655#endif 1732#endif
1656{ 1733{
1657 const char *home_httpd = home; 1734 const char *home_httpd = home;
1735#ifdef TEST
1736 const char *testArgs[5];
1737 int numTestArgs=0;
1738#endif
1658 1739
1659#ifndef CONFIG_FEATURE_HTTPD_USAGE_FROM_INETD_ONLY 1740#ifndef CONFIG_FEATURE_HTTPD_USAGE_FROM_INETD_ONLY
1660 int server; 1741 int server;
@@ -1690,6 +1771,9 @@ int httpd_main(int argc, char *argv[])
1690#ifdef CONFIG_FEATURE_HTTPD_SETUID 1771#ifdef CONFIG_FEATURE_HTTPD_SETUID
1691 "u:" 1772 "u:"
1692#endif 1773#endif
1774#ifdef TEST
1775 "t:"
1776#endif
1693 ); 1777 );
1694 if (c == EOF) break; 1778 if (c == EOF) break;
1695 switch (c) { 1779 switch (c) {
@@ -1735,6 +1819,11 @@ int httpd_main(int argc, char *argv[])
1735 } 1819 }
1736 break; 1820 break;
1737#endif 1821#endif
1822#ifdef TEST
1823 case 't':
1824 testArgs[numTestArgs++]=optarg;
1825 break;
1826#endif
1738 default: 1827 default:
1739 bb_error_msg("%s", httpdVersion); 1828 bb_error_msg("%s", httpdVersion);
1740 bb_show_usage(); 1829 bb_show_usage();
@@ -1762,6 +1851,17 @@ int httpd_main(int argc, char *argv[])
1762 parse_conf(default_path_httpd_conf, FIRST_PARSE); 1851 parse_conf(default_path_httpd_conf, FIRST_PARSE);
1763#endif 1852#endif
1764 1853
1854#ifdef TEST
1855 if (numTestArgs)
1856 {
1857 if (strcmp(testArgs[0],"ip") == 0) testArgs[0] = 0;
1858 if (numTestArgs > 2)
1859 parse_conf(testArgs[2], SUBDIR_PARSE);
1860 int result = printf("%d\n",checkPerm(testArgs[0],testArgs[1]));
1861 return result;
1862 }
1863#endif
1864
1765#ifndef CONFIG_FEATURE_HTTPD_USAGE_FROM_INETD_ONLY 1865#ifndef CONFIG_FEATURE_HTTPD_USAGE_FROM_INETD_ONLY
1766 if (!config->debugHttpd) { 1866 if (!config->debugHttpd) {
1767 if (daemon(1, 0) < 0) /* don`t change curent directory */ 1867 if (daemon(1, 0) < 0) /* don`t change curent directory */