httpd: move data off bss.

httpd: do not realpath() for SCRIPT_FILENAME - it resolves symlinks
but it should not:

-                /* SCRIPT_FILENAME required by PHP in CGI mode */
-               if (!realpath(purl + 1, realpath_buff))
-                       goto error_execing_cgi;
-               setenv1("SCRIPT_FILENAME", realpath_buff);
+
+               /* SCRIPT_FILENAME required by PHP in CGI mode */
+               fullpath = concat_path_file(home_httpd, purl);
+               setenv1("SCRIPT_FILENAME", fullpath);
This commit is contained in:
Denis Vlasenko 2007-06-09 23:49:05 +00:00
parent 66db264a5f
commit 77e44d60e6

View File

@ -98,10 +98,8 @@
# define PIPE_BUF 4096
#endif
static const char httpdVersion[] = "busybox httpd/1.35 6-Oct-2004";
static const char default_path_httpd_conf[] = "/etc";
static const char httpd_conf[] = "httpd.conf";
static const char home[] = "./";
#define TIMEOUT 60
@ -122,55 +120,85 @@ typedef struct HT_ACCESS {
} Htaccess;
typedef struct HT_ACCESS_IP {
unsigned int ip;
unsigned int mask;
unsigned ip;
unsigned mask;
int allow_deny;
struct HT_ACCESS_IP *next;
} Htaccess_IP;
typedef struct {
char buf[MAX_MEMORY_BUFF];
struct globals {
int server_socket;
int accepted_socket;
volatile smallint alarm_signaled;
smallint flg_deny_all;
const char *g_query;
const char *configFile;
const char *home_httpd;
unsigned rmt_ip;
USE_FEATURE_HTTPD_BASIC_AUTH(const char *realm;)
const char *found_mime_type;
const char *found_moved_temporarily;
off_t ContentLength; /* -1 - unknown */
time_t last_mod;
Htaccess_IP *ip_a_d; /* config allow/deny lines */
USE_FEATURE_HTTPD_BASIC_AUTH(const char *g_realm;)
USE_FEATURE_HTTPD_BASIC_AUTH(char *remoteuser;)
const char *query;
USE_FEATURE_HTTPD_CGI(char *referer;)
const char *configFile;
unsigned int rmt_ip;
#if ENABLE_FEATURE_HTTPD_CGI || DEBUG
char *rmt_ip_str; /* for set env REMOTE_ADDR */
#endif
unsigned port; /* server initial port and for
set env REMOTE_PORT */
const char *found_mime_type;
const char *found_moved_temporarily;
off_t ContentLength; /* -1 - unknown */
time_t last_mod;
Htaccess_IP *ip_a_d; /* config allow/deny lines */
int flg_deny_all;
unsigned tcp_port; /* server initial port and for
set env REMOTE_PORT */
#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
Htaccess *auth; /* config user:password lines */
Htaccess *g_auth; /* config user:password lines */
#endif
#if ENABLE_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES
Htaccess *mime_a; /* config mime types */
#endif
int server_socket;
int accepted_socket;
volatile int alarm_signaled;
#if ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR
Htaccess *script_i; /* config script interpreters */
#endif
} HttpdConfig;
static HttpdConfig *config;
char iobuf[MAX_MEMORY_BUFF];
};
#define G (*ptr_to_globals)
#define server_socket (G.server_socket )
#define accepted_socket (G.accepted_socket)
#define alarm_signaled (G.alarm_signaled )
#define flg_deny_all (G.flg_deny_all )
#define g_query (G.g_query )
#define configFile (G.configFile )
#define home_httpd (G.home_httpd )
#define rmt_ip (G.rmt_ip )
#define found_mime_type (G.found_mime_type)
#define found_moved_temporarily (G.found_moved_temporarily)
#define ContentLength (G.ContentLength )
#define last_mod (G.last_mod )
#define ip_a_d (G.ip_a_d )
#define g_realm (G.g_realm )
#define remoteuser (G.remoteuser )
#define referer (G.referer )
#if ENABLE_FEATURE_HTTPD_CGI || DEBUG
#define rmt_ip_str (G.rmt_ip_str )
#endif
#define tcp_port (G.tcp_port )
#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
#define g_auth (G.g_auth )
#endif
#if ENABLE_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES
#define mime_a (G.mime_a )
#endif
#if ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR
#define script_i (G.script_i )
#endif
#define iobuf (G.iobuf )
#define INIT_G() do { \
PTR_TO_GLOBALS = xzalloc(sizeof(G)); \
USE_FEATURE_HTTPD_BASIC_AUTH(g_realm = "Web Server Authentication";) \
tcp_port = 80; \
ContentLength = -1; \
} while (0)
static const char request_GET[] = "GET"; /* size algorithmic optimize */
@ -264,7 +292,7 @@ static const char RFC1123FMT[] = "%a, %d %b %Y %H:%M:%S GMT";
#define STRNCASECMP(a, str) strncasecmp((a), (str), sizeof(str)-1)
static int scan_ip(const char **ep, unsigned int *ip, unsigned char endc)
static int scan_ip(const char **ep, unsigned *ip, unsigned char endc)
{
const char *p = *ep;
int auto_mask = 8;
@ -272,7 +300,7 @@ static int scan_ip(const char **ep, unsigned int *ip, unsigned char endc)
*ip = 0;
for (j = 0; j < 4; j++) {
unsigned int octet;
unsigned octet;
if ((*p < '0' || *p > '9') && (*p != '/' || j == 0) && *p != 0)
return -auto_mask;
@ -301,10 +329,10 @@ static int scan_ip(const char **ep, unsigned int *ip, unsigned char endc)
return auto_mask;
}
static int scan_ip_mask(const char *ipm, unsigned int *ip, unsigned int *mask)
static int scan_ip_mask(const char *ipm, unsigned *ip, unsigned *mask)
{
int i;
unsigned int msk;
unsigned msk;
i = scan_ip(&ipm, ip, '/');
if (i < 0)
@ -397,13 +425,13 @@ static void parse_conf(const char *path, int flag)
Htaccess *cur;
#endif
const char *cf = config->configFile;
const char *cf = configFile;
char buf[160];
char *p0 = NULL;
char *c, *p;
/* free previous ip setup if present */
Htaccess_IP *pip = config->ip_a_d;
Htaccess_IP *pip = ip_a_d;
while (pip) {
Htaccess_IP *cur_ipl = pip;
@ -411,9 +439,9 @@ static void parse_conf(const char *path, int flag)
pip = cur_ipl->next;
free(cur_ipl);
}
config->ip_a_d = NULL;
ip_a_d = NULL;
config->flg_deny_all = 0;
flg_deny_all = 0;
#if ENABLE_FEATURE_HTTPD_BASIC_AUTH \
|| ENABLE_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES \
@ -421,13 +449,13 @@ static void parse_conf(const char *path, int flag)
/* retain previous auth and mime config only for subdir parse */
if (flag != SUBDIR_PARSE) {
#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
free_config_lines(&config->auth);
free_config_lines(&g_auth);
#endif
#if ENABLE_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES
free_config_lines(&config->mime_a);
free_config_lines(&mime_a);
#endif
#if ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR
free_config_lines(&config->script_i);
free_config_lines(&script_i);
#endif
}
#endif
@ -447,16 +475,16 @@ static void parse_conf(const char *path, int flag)
/* config file not found, no changes to config */
return;
}
if (config->configFile && flag == FIRST_PARSE) /* if -c option given */
if (configFile && flag == FIRST_PARSE) /* if -c option given */
bb_perror_msg_and_die("%s", cf);
flag = FIND_FROM_HTTPD_ROOT;
cf = httpd_conf;
}
#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
prev = config->auth;
prev = g_auth;
#endif
/* This could stand some work */
/* This could stand some work */
while ((p0 = fgets(buf, sizeof(buf), f)) != NULL) {
c = NULL;
for (p = p0; *p0 != 0 && *p0 != '#'; p0++) {
@ -477,7 +505,7 @@ static void parse_conf(const char *path, int flag)
if (*c == '*') {
if (*p0 == 'D') {
/* memorize deny all */
config->flg_deny_all++;
flg_deny_all = 1;
}
/* skip default other "word:*" config lines */
continue;
@ -509,14 +537,14 @@ static void parse_conf(const char *path, int flag)
pip->allow_deny = *p0;
if (*p0 == 'D') {
/* Deny:form_IP move top */
pip->next = config->ip_a_d;
config->ip_a_d = pip;
pip->next = ip_a_d;
ip_a_d = pip;
} else {
/* add to bottom A:form_IP config line */
Htaccess_IP *prev_IP = config->ip_a_d;
Htaccess_IP *prev_IP = ip_a_d;
if (prev_IP == NULL) {
config->ip_a_d = pip;
ip_a_d = pip;
} else {
while (prev_IP->next)
prev_IP = prev_IP->next;
@ -579,16 +607,16 @@ static void parse_conf(const char *path, int flag)
#if ENABLE_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES
if (*cf == '.') {
/* config .mime line move top for overwrite previous */
cur->next = config->mime_a;
config->mime_a = cur;
cur->next = mime_a;
mime_a = cur;
continue;
}
#endif
#if ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR
if (*cf == '*' && cf[1] == '.') {
/* config script interpreter line move top for overwrite previous */
cur->next = config->script_i;
config->script_i = cur;
cur->next = script_i;
script_i = cur;
continue;
}
#endif
@ -596,10 +624,10 @@ static void parse_conf(const char *path, int flag)
free(p0);
if (prev == NULL) {
/* first line */
config->auth = prev = cur;
g_auth = prev = cur;
} else {
/* sort path, if current lenght eq or bigger then move up */
Htaccess *prev_hti = config->auth;
Htaccess *prev_hti = g_auth;
size_t l = strlen(cf);
Htaccess *hti;
@ -611,7 +639,7 @@ static void parse_conf(const char *path, int flag)
prev_hti->next = cur;
} else {
/* insert as top */
config->auth = cur;
g_auth = cur;
}
break;
}
@ -818,7 +846,7 @@ static int openServer(void)
int fd;
/* create the socket right now */
fd = create_and_bind_stream_or_die(NULL, config->port);
fd = create_and_bind_stream_or_die(NULL, tcp_port);
xlisten(fd, 9);
return fd;
}
@ -840,7 +868,7 @@ static int openServer(void)
****************************************************************************/
static int sendHeaders(HttpResponseNum responseNum)
{
char *buf = config->buf;
char *buf = iobuf;
const char *responseString = "";
const char *infoString = 0;
const char *mime_type;
@ -861,7 +889,7 @@ static int sendHeaders(HttpResponseNum responseNum)
}
/* error message is HTML */
mime_type = responseNum == HTTP_OK ?
config->found_mime_type : "text/html";
found_mime_type : "text/html";
/* emit the current date */
strftime(timeStr, sizeof(timeStr), RFC1123FMT, gmtime(&timer));
@ -874,20 +902,20 @@ static int sendHeaders(HttpResponseNum responseNum)
if (responseNum == HTTP_UNAUTHORIZED) {
len += sprintf(buf+len,
"WWW-Authenticate: Basic realm=\"%s\"\r\n",
config->realm);
g_realm);
}
#endif
if (responseNum == HTTP_MOVED_TEMPORARILY) {
len += sprintf(buf+len, "Location: %s/%s%s\r\n",
config->found_moved_temporarily,
(config->query ? "?" : ""),
(config->query ? config->query : ""));
found_moved_temporarily,
(g_query ? "?" : ""),
(g_query ? g_query : ""));
}
if (config->ContentLength != -1) { /* file */
strftime(timeStr, sizeof(timeStr), RFC1123FMT, gmtime(&config->last_mod));
if (ContentLength != -1) { /* file */
strftime(timeStr, sizeof(timeStr), RFC1123FMT, gmtime(&last_mod));
len += sprintf(buf+len, "Last-Modified: %s\r\n%s %"OFF_FMT"d\r\n",
timeStr, "Content-length:", config->ContentLength);
timeStr, "Content-length:", ContentLength);
}
strcat(buf, "\r\n");
len += 2;
@ -900,7 +928,7 @@ static int sendHeaders(HttpResponseNum responseNum)
}
if (DEBUG)
fprintf(stderr, "headers: '%s'\n", buf);
i = config->accepted_socket;
i = accepted_socket;
if (i == 0) i++; /* write to fd# 1 in inetd mode */
return full_write(i, buf, len);
}
@ -919,9 +947,9 @@ static int sendHeaders(HttpResponseNum responseNum)
static int getLine(void)
{
int count = 0;
char *buf = config->buf;
char *buf = iobuf;
while (read(config->accepted_socket, buf + count, 1) == 1) {
while (read(accepted_socket, buf + count, 1) == 1) {
if (buf[count] == '\r') continue;
if (buf[count] == '\n') {
buf[count] = 0;
@ -962,8 +990,8 @@ static int sendCgi(const char *url,
{
int fromCgi[2]; /* pipe for reading data from CGI */
int toCgi[2]; /* pipe for sending data to CGI */
static char * argp[] = { 0, 0 };
char *fullpath;
char *argp[] = { NULL, NULL };
int pid = 0;
int inFd;
int outFd;
@ -985,7 +1013,14 @@ static int sendCgi(const char *url,
* since httpd is run from inetd (and it can't run standalone
* in uClinux).
*/
// FIXME: setenv leaks memory! (old values of env vars are leaked)
// Thus we have a bug on NOMMU.
// Need to use this instead:
// [malloc +] putenv + (in child: exec) + (in parent: unsetenv [+ free])
#if !BB_MMU
fullpath = NULL;
pid = vfork();
#else
pid = fork();
@ -997,25 +1032,19 @@ static int sendCgi(const char *url,
/* child process */
char *script;
char *purl;
char realpath_buff[MAXPATHLEN];
if (config->accepted_socket > 1)
close(config->accepted_socket);
if (config->server_socket > 1)
close(config->server_socket);
if (accepted_socket > 1)
close(accepted_socket);
if (server_socket > 1)
close(server_socket);
dup2(toCgi[0], 0); // replace stdin with the pipe
dup2(fromCgi[1], 1); // replace stdout with the pipe
/* Huh? User seeing stderr can be a security problem...
* and if CGI really wants that, it can always dup2(1,2)...
if (!DEBUG)
dup2(fromCgi[1], 2); // replace stderr with the pipe
*/
/* I think we cannot inadvertently close 0, 1 here... */
close(toCgi[0]);
close(toCgi[1]);
xmove_fd(toCgi[0], 0); /* replace stdin with the pipe */
xmove_fd(fromCgi[1], 1); /* replace stdout with the pipe */
close(fromCgi[0]);
close(fromCgi[1]);
/* Huh? User seeing stderr can be a security problem...
* and if CGI really wants that, it can always dup2(1,2)...
* dup2(fromCgi[1], 2); */
/*
* Find PATH_INFO.
@ -1036,22 +1065,21 @@ static int sendCgi(const char *url,
*script = '/'; /* is directory, find next '/' */
}
setenv1("PATH_INFO", script); /* set /PATH_INFO or "" */
/* setenv1("PATH", getenv("PATH")); redundant */
setenv1("REQUEST_METHOD", request);
if (config->query) {
char *uri = alloca(strlen(purl) + 2 + strlen(config->query));
if (g_query) {
char *uri = alloca(strlen(purl) + 2 + strlen(g_query));
if (uri)
sprintf(uri, "%s?%s", purl, config->query);
sprintf(uri, "%s?%s", purl, g_query);
setenv1("REQUEST_URI", uri);
} else {
setenv1("REQUEST_URI", purl);
}
if (script != NULL)
*script = '\0'; /* cut off /PATH_INFO */
/* SCRIPT_FILENAME required by PHP in CGI mode */
if (!realpath(purl + 1, realpath_buff))
goto error_execing_cgi;
setenv1("SCRIPT_FILENAME", realpath_buff);
/* SCRIPT_FILENAME required by PHP in CGI mode */
fullpath = concat_path_file(home_httpd, purl);
setenv1("SCRIPT_FILENAME", fullpath);
/* set SCRIPT_NAME as full path: /cgi-bin/dirs/script.cgi */
setenv1("SCRIPT_NAME", purl);
/* http://hoohoo.ncsa.uiuc.edu/cgi/env.html:
@ -1061,8 +1089,8 @@ static int sendCgi(const char *url,
* should always be set when there is query information,
* regardless of command line decoding. */
/* (Older versions of bbox seem to do some decoding) */
setenv1("QUERY_STRING", config->query);
setenv1("SERVER_SOFTWARE", httpdVersion);
setenv1("QUERY_STRING", g_query);
putenv((char*)"SERVER_SOFTWARE=busybox httpd/"BB_VER);
putenv((char*)"SERVER_PROTOCOL=HTTP/1.0");
putenv((char*)"GATEWAY_INTERFACE=CGI/1.1");
/* Having _separate_ variables for IP and port defeats
@ -1071,15 +1099,16 @@ static int sendCgi(const char *url,
* IOW - REMOTE_PEER="1.2.3.4:56" makes much more sense.
* Oh well... */
{
char *p = config->rmt_ip_str ? : (char*)"";
char *p = rmt_ip_str ? : (char*)"";
char *cp = strrchr(p, ':');
if (ENABLE_FEATURE_IPV6 && cp && strchr(cp, ']'))
cp = NULL;
if (cp) *cp = '\0'; /* delete :PORT */
setenv1("REMOTE_ADDR", p);
if (cp) *cp = ':';
}
#if ENABLE_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV
setenv_long("REMOTE_PORT", config->port);
setenv_long("REMOTE_PORT", tcp_port);
#endif
if (bodyLen)
setenv_long("CONTENT_LENGTH", bodyLen);
@ -1088,22 +1117,22 @@ static int sendCgi(const char *url,
if (content_type)
setenv1("CONTENT_TYPE", content_type);
#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
if (config->remoteuser) {
setenv1("REMOTE_USER", config->remoteuser);
if (remoteuser) {
setenv1("REMOTE_USER", remoteuser);
putenv((char*)"AUTH_TYPE=Basic");
}
#endif
if (config->referer)
setenv1("HTTP_REFERER", config->referer);
if (referer)
setenv1("HTTP_REFERER", referer);
/* set execve argp[0] without path */
argp[0] = strrchr(purl, '/') + 1;
/* but script argp[0] must have absolute path and chdiring to this */
script = strrchr(realpath_buff, '/');
script = strrchr(fullpath, '/');
if (!script)
goto error_execing_cgi;
*script = '\0';
if (chdir(realpath_buff) == 0) {
if (chdir(fullpath) == 0) {
// Now run the program. If it fails,
// use _exit() so no destructors
// get called and make a mess.
@ -1113,7 +1142,7 @@ static int sendCgi(const char *url,
if (suffix) {
Htaccess *cur;
for (cur = config->script_i; cur; cur = cur->next) {
for (cur = script_i; cur; cur = cur->next) {
if (strcmp(cur->before_colon + 1, suffix) == 0) {
interpr = cur->after_colon;
break;
@ -1127,16 +1156,19 @@ static int sendCgi(const char *url,
execv(interpr, argp);
else
#endif
execv(realpath_buff, argp);
execv(fullpath, argp);
}
error_execing_cgi:
/* send to stdout (even if we are not from inetd) */
config->accepted_socket = 1;
accepted_socket = 1;
sendHeaders(HTTP_NOT_FOUND);
_exit(242);
} /* end child */
/* parent process */
#if !BB_MMU
free(fullpath);
#endif
buf_count = 0;
post_read_size = 0;
@ -1161,9 +1193,9 @@ static int sendCgi(const char *url,
FD_SET(outFd, &writeSet);
nfound = outFd > inFd ? outFd : inFd;
if (post_read_size == 0) {
FD_SET(config->accepted_socket, &readSet);
if (nfound < config->accepted_socket)
nfound = config->accepted_socket;
FD_SET(accepted_socket, &readSet);
if (nfound < accepted_socket)
nfound = accepted_socket;
}
/* Now wait on the set of sockets! */
nfound = select(nfound + 1, &readSet, &writeSet, NULL, NULL);
@ -1201,13 +1233,13 @@ static int sendCgi(const char *url,
post_read_size = bodyLen = 0; /* broken pipe to CGI */
}
} else if (bodyLen > 0 && post_read_size == 0
&& FD_ISSET(config->accepted_socket, &readSet)
&& FD_ISSET(accepted_socket, &readSet)
) {
/* We expect data, prev data portion is eaten by CGI
* and there *is* data to read from the peer
* (POSTDATA?) */
count = bodyLen > (int)sizeof(wbuf) ? (int)sizeof(wbuf) : bodyLen;
count = safe_read(config->accepted_socket, wbuf, count);
count = safe_read(accepted_socket, wbuf, count);
if (count > 0) {
post_read_size = count;
post_read_idx = 0;
@ -1223,8 +1255,8 @@ static int sendCgi(const char *url,
#endif
if (FD_ISSET(inFd, &readSet)) {
/* There is something to read from CGI */
int s = config->accepted_socket;
char *rbuf = config->buf;
int s = accepted_socket;
char *rbuf = iobuf;
/* Are we still buffering CGI output? */
if (buf_count >= 0) {
@ -1306,14 +1338,14 @@ static int sendFile(const char *url)
break;
}
/* also, if not found, set default as "application/octet-stream"; */
config->found_mime_type = table[1];
found_mime_type = table[1];
#if ENABLE_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES
if (suffix) {
Htaccess * cur;
for (cur = config->mime_a; cur; cur = cur->next) {
for (cur = mime_a; cur; cur = cur->next) {
if (strcmp(cur->before_colon, suffix) == 0) {
config->found_mime_type = cur->after_colon;
found_mime_type = cur->after_colon;
break;
}
}
@ -1322,17 +1354,17 @@ static int sendFile(const char *url)
if (DEBUG)
fprintf(stderr, "sending file '%s' content-type: %s\n",
url, config->found_mime_type);
url, found_mime_type);
f = open(url, O_RDONLY);
if (f >= 0) {
int count;
char *buf = config->buf;
char *buf = iobuf;
sendHeaders(HTTP_OK);
/* TODO: sendfile() */
while ((count = full_read(f, buf, MAX_MEMORY_BUFF)) > 0) {
int fd = config->accepted_socket;
int fd = accepted_socket;
if (fd == 0) fd++; /* write to fd# 1 in inetd mode */
if (full_write(fd, buf, count) != count)
break;
@ -1352,9 +1384,9 @@ static int checkPermIP(void)
Htaccess_IP * cur;
/* This could stand some work */
for (cur = config->ip_a_d; cur; cur = cur->next) {
for (cur = ip_a_d; cur; cur = cur->next) {
#if ENABLE_FEATURE_HTTPD_CGI && DEBUG
fprintf(stderr, "checkPermIP: '%s' ? ", config->rmt_ip_str);
fprintf(stderr, "checkPermIP: '%s' ? ", rmt_ip_str);
#endif
#if DEBUG
fprintf(stderr, "'%u.%u.%u.%u/%u.%u.%u.%u'\n",
@ -1368,12 +1400,12 @@ static int checkPermIP(void)
(unsigned char)(cur->mask)
);
#endif
if ((config->rmt_ip & cur->mask) == cur->ip)
if ((rmt_ip & cur->mask) == cur->ip)
return cur->allow_deny == 'A'; /* Allow/Deny */
}
/* if unconfigured, return 1 - access from all */
return !config->flg_deny_all;
return !flg_deny_all;
}
/****************************************************************************
@ -1403,7 +1435,7 @@ static int checkPerm(const char *path, const char *request)
const char *prev = NULL;
/* This could stand some work */
for (cur = config->auth; cur; cur = cur->next) {
for (cur = g_auth; cur; cur = cur->next) {
size_t l;
p0 = cur->before_colon;
@ -1449,9 +1481,9 @@ static int checkPerm(const char *path, const char *request)
if (strcmp(p, request) == 0) {
set_remoteuser_var:
config->remoteuser = strdup(request);
if (config->remoteuser)
config->remoteuser[(u - request)] = 0;
remoteuser = strdup(request);
if (remoteuser)
remoteuser[(u - request)] = 0;
return 1; /* Ok */
}
/* unauthorized */
@ -1474,7 +1506,7 @@ set_remoteuser_var:
static void handle_sigalrm(int sig)
{
sendHeaders(HTTP_REQUEST_TIMEOUT);
config->alarm_signaled = sig;
alarm_signaled = 1;
}
/****************************************************************************
@ -1486,7 +1518,7 @@ static void handle_sigalrm(int sig)
****************************************************************************/
static void handleIncoming(void)
{
char *buf = config->buf;
char *buf = iobuf;
char *url;
char *purl;
int blank = -1;
@ -1556,10 +1588,10 @@ static void handleIncoming(void)
strcpy(url, buf);
/* extract url args if present */
test = strchr(url, '?');
config->query = NULL;
g_query = NULL;
if (test) {
*test++ = '\0';
config->query = test;
g_query = test;
}
test = decodeString(url, 0);
@ -1605,11 +1637,11 @@ static void handleIncoming(void)
/* If URL is directory, adding '/' */
if (test[-1] != '/') {
if (is_directory(url + 1, 1, &sb)) {
config->found_moved_temporarily = url;
found_moved_temporarily = url;
}
}
if (DEBUG)
fprintf(stderr, "url='%s', args=%s\n", url, config->query);
fprintf(stderr, "url='%s', args=%s\n", url, g_query);
test = url;
ip_allowed = checkPermIP();
@ -1656,7 +1688,7 @@ static void handleIncoming(void)
} else if ((STRNCASECMP(buf, "Content-Type:") == 0)) {
content_type = strdup(skip_whitespace(buf + sizeof("Content-Type:")-1));
} else if ((STRNCASECMP(buf, "Referer:") == 0)) {
config->referer = strdup(skip_whitespace(buf + sizeof("Referer:")-1));
referer = strdup(skip_whitespace(buf + sizeof("Referer:")-1));
}
#endif
@ -1679,7 +1711,7 @@ static void handleIncoming(void)
} /* while extra header reading */
}
alarm(0);
if (config->alarm_signaled)
if (alarm_signaled)
break;
if (strcmp(strrchr(url, '/') + 1, httpd_conf) == 0 || ip_allowed == 0) {
@ -1698,10 +1730,10 @@ static void handleIncoming(void)
}
#endif
if (config->found_moved_temporarily) {
if (found_moved_temporarily) {
sendHeaders(HTTP_MOVED_TEMPORARILY);
/* clear unforked memory flag */
config->found_moved_temporarily = NULL;
found_moved_temporarily = NULL;
break;
}
@ -1719,7 +1751,7 @@ static void handleIncoming(void)
char *suffix = strrchr(test, '.');
if (suffix) {
Htaccess *cur;
for (cur = config->script_i; cur; cur = cur->next) {
for (cur = script_i; cur; cur = cur->next) {
if (strcmp(cur->before_colon + 1, suffix) == 0) {
sendCgi(url, prequest, length, cookie, content_type);
goto bail_out;
@ -1737,8 +1769,8 @@ static void handleIncoming(void)
strcpy(purl, "index.html");
if (stat(test, &sb) == 0) {
/* It's a dir URL and there is index.html */
config->ContentLength = sb.st_size;
config->last_mod = sb.st_mtime;
ContentLength = sb.st_size;
last_mod = sb.st_mtime;
}
#if ENABLE_FEATURE_HTTPD_CGI
else if (purl[-1] == '/') {
@ -1746,14 +1778,14 @@ static void handleIncoming(void)
* Try cgi-bin/index.cgi */
if (access("/cgi-bin/index.cgi"+1, X_OK) == 0) {
purl[0] = '\0';
config->query = url;
g_query = url;
sendCgi("/cgi-bin/index.cgi", prequest, length, cookie, content_type);
break;
}
}
#endif /* FEATURE_HTTPD_CGI */
sendFile(test);
config->ContentLength = -1;
ContentLength = -1;
} while (0);
#if ENABLE_FEATURE_HTTPD_CGI
@ -1765,28 +1797,28 @@ static void handleIncoming(void)
#if ENABLE_FEATURE_HTTPD_CGI
free(cookie);
free(content_type);
free(config->referer);
config->referer = NULL;
free(referer);
referer = NULL;
# if ENABLE_FEATURE_HTTPD_BASIC_AUTH
free(config->remoteuser);
config->remoteuser = NULL;
free(remoteuser);
remoteuser = NULL;
# endif
#endif
shutdown(config->accepted_socket, SHUT_WR);
shutdown(accepted_socket, SHUT_WR);
/* Properly wait for remote to closed */
FD_ZERO(&s_fd);
FD_SET(config->accepted_socket, &s_fd);
FD_SET(accepted_socket, &s_fd);
do {
tv.tv_sec = 2;
tv.tv_usec = 0;
retval = select(config->accepted_socket + 1, &s_fd, NULL, NULL, &tv);
} while (retval > 0 && read(config->accepted_socket, buf, sizeof(config->buf) > 0));
retval = select(accepted_socket + 1, &s_fd, NULL, NULL, &tv);
} while (retval > 0 && read(accepted_socket, buf, sizeof(iobuf) > 0));
shutdown(config->accepted_socket, SHUT_RD);
shutdown(accepted_socket, SHUT_RD);
/* In inetd case, we close fd 1 (stdout) here. We will exit soon anyway */
close(config->accepted_socket);
close(accepted_socket);
}
/****************************************************************************
@ -1830,24 +1862,24 @@ static int miniHttpd(int server)
s = accept(server, &fromAddr.sa, &fromAddrLen);
if (s < 0)
continue;
config->accepted_socket = s;
config->rmt_ip = 0;
config->port = 0;
accepted_socket = s;
rmt_ip = 0;
tcp_port = 0;
#if ENABLE_FEATURE_HTTPD_CGI || DEBUG
free(config->rmt_ip_str);
config->rmt_ip_str = xmalloc_sockaddr2dotted(&fromAddr.sa, fromAddrLen);
free(rmt_ip_str);
rmt_ip_str = xmalloc_sockaddr2dotted(&fromAddr.sa, fromAddrLen);
#if DEBUG
bb_error_msg("connection from '%s'", config->rmt_ip_str);
bb_error_msg("connection from '%s'", rmt_ip_str);
#endif
#endif /* FEATURE_HTTPD_CGI */
if (fromAddr.sa.sa_family == AF_INET) {
config->rmt_ip = ntohl(fromAddr.sin.sin_addr.s_addr);
config->port = ntohs(fromAddr.sin.sin_port);
rmt_ip = ntohl(fromAddr.sin.sin_addr.s_addr);
tcp_port = ntohs(fromAddr.sin.sin_port);
}
#if ENABLE_FEATURE_IPV6
if (fromAddr.sa.sa_family == AF_INET6) {
//config->rmt_ip = ntohl(fromAddr.sin.sin_addr.s_addr);
config->port = ntohs(fromAddr.sin6.sin6_port);
//rmt_ip = ntohl(fromAddr.sin.sin_addr.s_addr);
tcp_port = ntohs(fromAddr.sin6.sin6_port);
}
#endif
@ -1880,20 +1912,20 @@ static int miniHttpd_inetd(void)
socklen_t fromAddrLen = sizeof(fromAddr);
getpeername(0, &fromAddr.sa, &fromAddrLen);
config->rmt_ip = 0;
config->port = 0;
rmt_ip = 0;
tcp_port = 0;
#if ENABLE_FEATURE_HTTPD_CGI || DEBUG
free(config->rmt_ip_str);
config->rmt_ip_str = xmalloc_sockaddr2dotted(&fromAddr.sa, fromAddrLen);
free(rmt_ip_str);
rmt_ip_str = xmalloc_sockaddr2dotted(&fromAddr.sa, fromAddrLen);
#endif
if (fromAddr.sa.sa_family == AF_INET) {
config->rmt_ip = ntohl(fromAddr.sin.sin_addr.s_addr);
config->port = ntohs(fromAddr.sin.sin_port);
rmt_ip = ntohl(fromAddr.sin.sin_addr.s_addr);
tcp_port = ntohs(fromAddr.sin.sin_port);
}
#if ENABLE_FEATURE_IPV6
if (fromAddr.sa.sa_family == AF_INET6) {
//config->rmt_ip = ntohl(fromAddr.sin.sin_addr.s_addr);
config->port = ntohs(fromAddr.sin6.sin6_port);
//rmt_ip = ntohl(fromAddr.sin.sin_addr.s_addr);
tcp_port = ntohs(fromAddr.sin6.sin6_port);
}
#endif
handleIncoming();
@ -1942,7 +1974,6 @@ int httpd_main(int argc, char **argv);
int httpd_main(int argc, char **argv)
{
unsigned opt;
const char *home_httpd = home;
char *url_for_decode;
USE_FEATURE_HTTPD_ENCODE_URL_STR(const char *url_for_encode;)
const char *s_port;
@ -1955,22 +1986,20 @@ int httpd_main(int argc, char **argv)
setlocale(LC_TIME, "C");
#endif
config = xzalloc(sizeof(*config));
#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
config->realm = "Web Server Authentication";
#endif
config->port = 80;
config->ContentLength = -1;
INIT_G();
home_httpd = xrealloc_getcwd_or_warn(NULL);
/* We do not "absolutize" path given by -h (home) opt.
* If user gives relative path in -h, $SCRIPT_FILENAME can end up
* relative too. */
opt = getopt32(argc, argv, "c:d:h:"
USE_FEATURE_HTTPD_ENCODE_URL_STR("e:")
USE_FEATURE_HTTPD_BASIC_AUTH("r:")
USE_FEATURE_HTTPD_AUTH_MD5("m:")
USE_FEATURE_HTTPD_SETUID("u:")
"p:if",
&(config->configFile), &url_for_decode, &home_httpd
&(configFile), &url_for_decode, &home_httpd
USE_FEATURE_HTTPD_ENCODE_URL_STR(, &url_for_encode)
USE_FEATURE_HTTPD_BASIC_AUTH(, &(config->realm))
USE_FEATURE_HTTPD_BASIC_AUTH(, &g_realm)
USE_FEATURE_HTTPD_AUTH_MD5(, &pass)
USE_FEATURE_HTTPD_SETUID(, &s_ugid)
, &s_port
@ -1992,7 +2021,7 @@ int httpd_main(int argc, char **argv)
}
#endif
if (opt & OPT_PORT)
config->port = xatou16(s_port);
tcp_port = xatou16(s_port);
#if ENABLE_FEATURE_HTTPD_SETUID
if (opt & OPT_SETUID) {
@ -2005,7 +2034,7 @@ int httpd_main(int argc, char **argv)
xchdir(home_httpd);
if (!(opt & OPT_INETD)) {
signal(SIGCHLD, SIG_IGN);
config->server_socket = openServer();
server_socket = openServer();
#if ENABLE_FEATURE_HTTPD_SETUID
/* drop privileges */
if (opt & OPT_SETUID) {
@ -2022,12 +2051,12 @@ int httpd_main(int argc, char **argv)
#if ENABLE_FEATURE_HTTPD_CGI
{
char *p = getenv("PATH");
p = xstrdup(p); /* if gets NULL, returns NULL */
/* env strings themself are not freed, no need to strdup(p): */
clearenv();
if (p)
setenv1("PATH", p);
putenv(p - 5);
if (!(opt & OPT_INETD))
setenv_long("SERVER_PORT", config->port);
setenv_long("SERVER_PORT", tcp_port);
}
#endif
@ -2042,5 +2071,5 @@ int httpd_main(int argc, char **argv)
if (!(opt & OPT_FOREGROUND))
bb_daemonize(0); /* don't change current directory */
return miniHttpd(config->server_socket);
return miniHttpd(server_socket);
}