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.
This commit is contained in:
parent
0861e828d0
commit
4fe3ff8cff
@ -41,33 +41,70 @@
|
|||||||
*
|
*
|
||||||
* The server can also be invoked as a url arg decoder and html text encoder
|
* The server can also be invoked as a url arg decoder and html text encoder
|
||||||
* as follows:
|
* as follows:
|
||||||
* foo=`httpd -d $foo` # decode "Hello%20World" as "Hello World"
|
* foo=`httpd -d $foo` # decode "Hello%20World" as "Hello World"
|
||||||
* bar=`httpd -e "<Hello World>"` # encode as "<Hello World>"
|
* bar=`httpd -e "<Hello World>"` # encode as "<Hello World>"
|
||||||
|
* Note that url encoding for arguments is not the same as html encoding for
|
||||||
|
* presenation. -d decodes a url-encoded argument while -e encodes in html
|
||||||
|
* for page display.
|
||||||
*
|
*
|
||||||
* httpd.conf has the following format:
|
* httpd.conf has the following format:
|
||||||
|
*
|
||||||
|
* A:172.20. # Allow any address that begins with 172.20
|
||||||
|
* A:10.10. # Allow any address that begins with 10.10.
|
||||||
|
* A:10.20 # Allow any address that previous set and 10.200-209.X.X
|
||||||
|
* A:127.0.0.1 # Allow local loopback connections
|
||||||
|
* D:* # Deny from other IP connections
|
||||||
|
* /cgi-bin:foo:bar # Require user foo, pwd bar on urls starting with /cgi-bin/
|
||||||
|
* /adm:admin:setup # Require user admin, pwd setup on urls starting with /adm/
|
||||||
|
* /adm:toor:PaSsWd # or user toor, pwd PaSsWd on urls starting with /adm/
|
||||||
|
* .au:audio/basic # additional mime type for audio.au files
|
||||||
|
*
|
||||||
|
* A/D may be as a/d or allow/deny - first char case unsensitive
|
||||||
|
* Deny IP rules take precedence over allow rules. Any IP rules after D:* are
|
||||||
|
* ignored.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* The Deny/Allow IP logic:
|
||||||
|
*
|
||||||
|
* - Default is to allow all. No addresses are denied unless
|
||||||
|
* denied with a D: rule.
|
||||||
|
* - Order of Deny/Allow rules is significant
|
||||||
|
* - Deny rules take precedence over allow rules.
|
||||||
|
* - If a deny all rule (D:*) is used it acts as a catch-all for unmatched
|
||||||
|
* addresses.
|
||||||
|
* - Specification of Allow all (A:*) is a no-op
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* 1. Allow only specified addresses
|
||||||
|
* A:172.20. # Allow any address that begins with 172.20
|
||||||
|
* A:10.10. # Allow any address that begins with 10.10.
|
||||||
|
* A:10.10 # Allow any address that previous set and 10.100-109.X.X
|
||||||
|
* A:127.0.0.1 # Allow local loopback connections
|
||||||
|
* D:* # Deny from other IP connections
|
||||||
|
*
|
||||||
|
* 2. Only deny specified addresses
|
||||||
|
* D:1.2.3. # deny from 1.2.3.0 - 1.2.3.255
|
||||||
|
* D:2.3.4. # deny from 2.3.4.0 - 2.3.4.255
|
||||||
|
* A:* # (optional line added for clarity)
|
||||||
|
*
|
||||||
|
* If a sub directory contains a config file it is parsed and merged with
|
||||||
|
* any existing settings as if it was appended to the original configuration
|
||||||
|
* except that all previous IP config rules are discarded.
|
||||||
|
*
|
||||||
|
* subdir paths are relative to the containing subdir and thus cannot
|
||||||
|
* affect the parent rules.
|
||||||
|
*
|
||||||
|
* Note that since the sub dir is parsed in the forked thread servicing the
|
||||||
|
* subdir http request, any merge is discarded when the process exits. As a
|
||||||
|
* result, the subdir settings only have a lifetime of a single request.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* If -c is not set, an attempt will be made to open the default
|
||||||
|
* root configuration file. If -c is set and the file is not found, the
|
||||||
|
* server exits with an error.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
A:172.20. # Allow any address that begins with 172.20
|
|
||||||
A:10.10. # Allow any address that begins with 10.10.
|
|
||||||
A:10.10 # Allow any address that previous set and 10.100-109.X.X
|
|
||||||
A:127.0.0.1 # Allow local loopback connections
|
|
||||||
D:* # Deny from other IP connections
|
|
||||||
/cgi-bin:foo:bar # Require user foo, pwd bar on urls starting with /cgi-bin/
|
|
||||||
/adm:admin:setup # Require user admin, pwd setup on urls starting with /adm/
|
|
||||||
/adm:toor:PaSsWd # or user toor, pwd PaSsWd on urls starting with /adm/
|
|
||||||
.au:audio/basic # additional mime type for audio.au files
|
|
||||||
|
|
||||||
A/D may be as a/d or allow/deny - first char case unsensitive parsed only.
|
|
||||||
|
|
||||||
Each subdir can have config file.
|
|
||||||
You can set less IP allow from subdir config.
|
|
||||||
Password protection from subdir config can rewriten previous sets for
|
|
||||||
current or/and next subpathes.
|
|
||||||
For protect as user:pass current subdir and subpathes set from subdir config:
|
|
||||||
/:user:pass
|
|
||||||
/subpath:user2:pass2
|
|
||||||
|
|
||||||
If -c don`t setted, used httpd root config, else httpd root config skiped.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <ctype.h> /* for isspace */
|
#include <ctype.h> /* for isspace */
|
||||||
@ -86,10 +123,10 @@ For protect as user:pass current subdir and subpathes set from subdir config:
|
|||||||
#include "busybox.h"
|
#include "busybox.h"
|
||||||
|
|
||||||
|
|
||||||
static const char httpdVersion[] = "busybox httpd/1.25 10-May-2003";
|
static const char httpdVersion[] = "busybox httpd/1.26 18-May-2003";
|
||||||
static const char default_path_httpd_conf[] = "/etc";
|
static const char default_path_httpd_conf[] = "/etc";
|
||||||
static const char httpd_conf[] = "httpd.conf";
|
static const char httpd_conf[] = "httpd.conf";
|
||||||
static const char home[] = "/www";
|
static const char home[] = "./";
|
||||||
|
|
||||||
// Note: bussybox xfuncs are not used because we want the server to keep running
|
// Note: bussybox xfuncs are not used because we want the server to keep running
|
||||||
// if something bad happens due to a malformed user request.
|
// if something bad happens due to a malformed user request.
|
||||||
@ -160,7 +197,7 @@ void bb_show_usage(void)
|
|||||||
|
|
||||||
/* CGI environ size */
|
/* CGI environ size */
|
||||||
#ifdef CONFIG_FEATURE_HTTPD_SET_CGI_VARS_TO_ENV
|
#ifdef CONFIG_FEATURE_HTTPD_SET_CGI_VARS_TO_ENV
|
||||||
#define ENVSIZE 50 /* set max 35 CGI_variable */
|
#define ENVSIZE 70 /* set max CGI variable */
|
||||||
#else
|
#else
|
||||||
#define ENVSIZE 15 /* minimal requires */
|
#define ENVSIZE 15 /* minimal requires */
|
||||||
#endif
|
#endif
|
||||||
@ -325,7 +362,31 @@ static void free_config_lines(Htaccess **pprev)
|
|||||||
#define SUBDIR_PARSE 1
|
#define SUBDIR_PARSE 1
|
||||||
#define SIGNALED_PARSE 2
|
#define SIGNALED_PARSE 2
|
||||||
#define FIND_FROM_HTTPD_ROOT 3
|
#define FIND_FROM_HTTPD_ROOT 3
|
||||||
|
/****************************************************************************
|
||||||
|
*
|
||||||
|
> $Function: parse_conf()
|
||||||
|
*
|
||||||
|
* $Description: parse configuration file into in-memory linked list.
|
||||||
|
*
|
||||||
|
* The first non-white character is examined to determine if the config line
|
||||||
|
* is one of the following:
|
||||||
|
* .ext:mime/type # new mime type not compiled into httpd
|
||||||
|
* [adAD]:from # ip address allow/deny, * for wildcard
|
||||||
|
* /path:user:pass # username/password
|
||||||
|
*
|
||||||
|
* Any previous IP rules are discarded.
|
||||||
|
* If the flag argument is not SUBDIR_PARSE then all /path and mime rules
|
||||||
|
* are also discarded. That is, previous settings are retained if flag is
|
||||||
|
* SUBDIR_PARSE.
|
||||||
|
*
|
||||||
|
* $Parameters:
|
||||||
|
* (const char *) path . . null for ip address checks, path for password
|
||||||
|
* checks.
|
||||||
|
* (int) flag . . . . . . the source of the parse request.
|
||||||
|
*
|
||||||
|
* $Return: (None)
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
static void parse_conf(const char *path, int flag)
|
static void parse_conf(const char *path, int flag)
|
||||||
{
|
{
|
||||||
FILE *f;
|
FILE *f;
|
||||||
@ -335,17 +396,18 @@ static void parse_conf(const char *path, int flag)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
const char *cf = config->configFile;
|
const char *cf = config->configFile;
|
||||||
char buf[80];
|
char buf[160];
|
||||||
char *p0 = NULL;
|
char *p0 = NULL;
|
||||||
char *c, *p;
|
char *c, *p;
|
||||||
|
|
||||||
/* free previous setuped */
|
/* free previous ip setup if present */
|
||||||
free_config_lines(&config->ip_a_d);
|
free_config_lines(&config->ip_a_d);
|
||||||
|
/* retain previous auth and mime config only for subdir parse */
|
||||||
if(flag != SUBDIR_PARSE) {
|
if(flag != SUBDIR_PARSE) {
|
||||||
#ifdef CONFIG_FEATURE_HTTPD_BASIC_AUTH
|
#ifdef CONFIG_FEATURE_HTTPD_BASIC_AUTH
|
||||||
free_config_lines(&config->auth)
|
free_config_lines(&config->auth)
|
||||||
#endif
|
#endif
|
||||||
; /* syntax confuse */
|
; /* appease compiler warnings if option is not set */
|
||||||
#ifdef CONFIG_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES
|
#ifdef CONFIG_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES
|
||||||
free_config_lines(&config->mime_a);
|
free_config_lines(&config->mime_a);
|
||||||
#endif
|
#endif
|
||||||
@ -363,7 +425,7 @@ static void parse_conf(const char *path, int flag)
|
|||||||
|
|
||||||
while((f = fopen(cf, "r")) == NULL) {
|
while((f = fopen(cf, "r")) == NULL) {
|
||||||
if(flag != FIRST_PARSE) {
|
if(flag != FIRST_PARSE) {
|
||||||
/* config file not found */
|
/* config file not found, no changes to config */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(config->configFile) /* if -c option given */
|
if(config->configFile) /* if -c option given */
|
||||||
@ -376,7 +438,7 @@ static void parse_conf(const char *path, int flag)
|
|||||||
prev = config->auth;
|
prev = config->auth;
|
||||||
#endif
|
#endif
|
||||||
/* This could stand some work */
|
/* This could stand some work */
|
||||||
while ( (p0 = fgets(buf, 80, f)) != NULL) {
|
while ( (p0 = fgets(buf, sizeof(buf), f)) != NULL) {
|
||||||
c = NULL;
|
c = NULL;
|
||||||
for(p = p0; *p0 != 0 && *p0 != '#'; p0++) {
|
for(p = p0; *p0 != 0 && *p0 != '#'; p0++) {
|
||||||
if(!isspace(*p0)) {
|
if(!isspace(*p0)) {
|
||||||
@ -393,18 +455,20 @@ static void parse_conf(const char *path, int flag)
|
|||||||
if(*c == '*')
|
if(*c == '*')
|
||||||
*c = 0; /* Allow all */
|
*c = 0; /* Allow all */
|
||||||
p0 = buf;
|
p0 = buf;
|
||||||
|
if((*p0 == 'i') || (*p0 == 'I'))
|
||||||
|
*p0 = 'A'; // version 1.1/1.2 compatibility for ip:
|
||||||
if(*p0 == 'a')
|
if(*p0 == 'a')
|
||||||
*p0 = 'A';
|
*p0 = 'A';
|
||||||
if(*p0 == 'd')
|
if(*p0 == 'd')
|
||||||
*p0 = 'D';
|
*p0 = 'D';
|
||||||
if(*p0 != 'A' && *p0 != 'D'
|
if(*p0 != 'A' && *p0 != 'D'
|
||||||
#ifdef CONFIG_FEATURE_HTTPD_BASIC_AUTH
|
#ifdef CONFIG_FEATURE_HTTPD_BASIC_AUTH
|
||||||
&& *p0 != '/'
|
&& *p0 != '/'
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES
|
#ifdef CONFIG_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES
|
||||||
&& *p0 != '.'
|
&& *p0 != '.'
|
||||||
#endif
|
#endif
|
||||||
)
|
)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if(*p0 == 'A' && *c == 0) {
|
if(*p0 == 'A' && *c == 0) {
|
||||||
@ -681,9 +745,12 @@ static void addEnvCgi(const char *pargs)
|
|||||||
{
|
{
|
||||||
char *args;
|
char *args;
|
||||||
char *memargs;
|
char *memargs;
|
||||||
|
char *namelist; /* space separated list of arg names */
|
||||||
if (pargs==0) return;
|
if (pargs==0) return;
|
||||||
|
|
||||||
/* args are a list of name=value&name2=value2 sequences */
|
/* args are a list of name=value&name2=value2 sequences */
|
||||||
|
namelist = (char *) malloc(strlen(pargs));
|
||||||
|
if (namelist) namelist[0]=0;
|
||||||
memargs = args = strdup(pargs);
|
memargs = args = strdup(pargs);
|
||||||
while (args && *args) {
|
while (args && *args) {
|
||||||
const char *name = args;
|
const char *name = args;
|
||||||
@ -696,8 +763,14 @@ static void addEnvCgi(const char *pargs)
|
|||||||
if (args)
|
if (args)
|
||||||
*args++ = 0;
|
*args++ = 0;
|
||||||
addEnv("CGI", name, decodeString(value, 1));
|
addEnv("CGI", name, decodeString(value, 1));
|
||||||
|
if (*namelist) strcat(namelist, " ");
|
||||||
|
strcat(namelist,name);
|
||||||
}
|
}
|
||||||
free(memargs);
|
free(memargs);
|
||||||
|
if (namelist) {
|
||||||
|
addEnv("CGI","ARGLIST_",namelist);
|
||||||
|
free(namelist);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_FEATURE_HTTPD_SET_CGI_VARS_TO_ENV */
|
#endif /* CONFIG_FEATURE_HTTPD_SET_CGI_VARS_TO_ENV */
|
||||||
|
|
||||||
@ -1050,10 +1123,11 @@ static int sendCgi(const char *url,
|
|||||||
if(script) {
|
if(script) {
|
||||||
*script = '\0';
|
*script = '\0';
|
||||||
if(chdir(realpath_buff) == 0) {
|
if(chdir(realpath_buff) == 0) {
|
||||||
*script = '/';
|
*script = '/';
|
||||||
// now run the program. If it fails, use _exit() so no destructors
|
// now run the program. If it fails,
|
||||||
// get called and make a mess.
|
// use _exit() so no destructors
|
||||||
execve(realpath_buff, argp, config->envp);
|
// get called and make a mess.
|
||||||
|
execve(realpath_buff, argp, config->envp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1605,6 +1679,9 @@ static int miniHttpd(int server)
|
|||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
close(s);
|
close(s);
|
||||||
|
#ifdef TEST
|
||||||
|
return 0; // exit after processing one request
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // while (1)
|
} // while (1)
|
||||||
@ -1655,6 +1732,10 @@ int httpd_main(int argc, char *argv[])
|
|||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
const char *home_httpd = home;
|
const char *home_httpd = home;
|
||||||
|
#ifdef TEST
|
||||||
|
const char *testArgs[5];
|
||||||
|
int numTestArgs=0;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef CONFIG_FEATURE_HTTPD_USAGE_FROM_INETD_ONLY
|
#ifndef CONFIG_FEATURE_HTTPD_USAGE_FROM_INETD_ONLY
|
||||||
int server;
|
int server;
|
||||||
@ -1689,6 +1770,9 @@ int httpd_main(int argc, char *argv[])
|
|||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_FEATURE_HTTPD_SETUID
|
#ifdef CONFIG_FEATURE_HTTPD_SETUID
|
||||||
"u:"
|
"u:"
|
||||||
|
#endif
|
||||||
|
#ifdef TEST
|
||||||
|
"t:"
|
||||||
#endif
|
#endif
|
||||||
);
|
);
|
||||||
if (c == EOF) break;
|
if (c == EOF) break;
|
||||||
@ -1734,6 +1818,11 @@ int httpd_main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
|
#ifdef TEST
|
||||||
|
case 't':
|
||||||
|
testArgs[numTestArgs++]=optarg;
|
||||||
|
break;
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
bb_error_msg("%s", httpdVersion);
|
bb_error_msg("%s", httpdVersion);
|
||||||
@ -1762,6 +1851,17 @@ int httpd_main(int argc, char *argv[])
|
|||||||
parse_conf(default_path_httpd_conf, FIRST_PARSE);
|
parse_conf(default_path_httpd_conf, FIRST_PARSE);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef TEST
|
||||||
|
if (numTestArgs)
|
||||||
|
{
|
||||||
|
if (strcmp(testArgs[0],"ip") == 0) testArgs[0] = 0;
|
||||||
|
if (numTestArgs > 2)
|
||||||
|
parse_conf(testArgs[2], SUBDIR_PARSE);
|
||||||
|
int result = printf("%d\n",checkPerm(testArgs[0],testArgs[1]));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef CONFIG_FEATURE_HTTPD_USAGE_FROM_INETD_ONLY
|
#ifndef CONFIG_FEATURE_HTTPD_USAGE_FROM_INETD_ONLY
|
||||||
if (!config->debugHttpd) {
|
if (!config->debugHttpd) {
|
||||||
if (daemon(1, 0) < 0) /* don`t change curent directory */
|
if (daemon(1, 0) < 0) /* don`t change curent directory */
|
||||||
|
Loading…
Reference in New Issue
Block a user