NCSA HTTPd 1.2

This commit is contained in:
I am not me 2013-03-13 02:28:49 -04:00
parent 9572b626b7
commit 346064ddbf
37 changed files with 2898 additions and 1224 deletions

109
README
View File

@ -1,15 +1,37 @@
NCSA httpd 1.2 is now available via anonymous FTP from
ftp://ftp.ncsa.uiuc.edu/Web/ncsa_httpd/current. Note that there is no
longer a binary distributed for the DECstation MIPS machines running
Ultrix as our DECstation 5000 died and it hasn't been fixed as of yet.
Documentation for httpd has been moved online. See the URL
<A HREF="http://hoohoo.ncsa.uiuc.edu/">here</A> for online hypertext
documentation including installation instructions, feature list,
demonstration, etc.
NCSA httpd is an HTTP/1.0 compatible server for hypermedia documents.
It runs on a plethora of UNIX systems. NCSA httpd is also compatible
with the Common Gateway Interface which allows interactive document
generation.
Documentation can also be found where you found this .tar file, in a file
called httpd_docs.tar.Z.
All of the documentation for NCSA httpd is online hypertext. See
http://hoohoo.ncsa.uiuc.edu/. If you cannot use a networked WWW browser to
read it, retrieve the file /Web/ncsa_httpd/current/httpd_docs.tar.Z from
ftp.ncsa.uiuc.edu and use your WWW browser in local only mode to get things
started.
--Rob, Marc, and Eric httpd@ncsa.uiuc.edu
Note that the new features introduced with this release required some
internal restructuring of the code. This may cause some bugs. If you
are pleased with your current setup and do not need the new features
you may consider waiting before upgrading in order to make sure that
any problems (we expect none, but who ever does?) are worked out prior
to your upgrade.
By popular demand I have written a number of tutorials about various
aspects of NCSA httpd configuration. See
http://hoohoo.ncsa.uiuc.edu/docs/tutorials/ for an index.
Thanks all
--Rob and Eric
httpd@ncsa.uiuc.edu
----
This code is in the public domain. Specifically, we give to the public
domain all rights for future licensing of the source code, all resale
@ -26,3 +48,76 @@ FOR THE SOFTWARE AND/OR DOCUMENTATION PROVIDED, INCLUDING, WITHOUT
LIMITATION, WARRANTY OF MERCHANTABILITY AND WARRANTY OF FITNESS FOR A
PARTICULAR PURPOSE.
----
All of the following information is available at
http://hoohoo.ncsa.uiuc.edu/docs/Upgrade.html in hypertext form. You
should probably read that instead of this primitive plaintext.
New features
* The CGI interface is now revised to version 1.1.
* A new logfile format was agreed upon which should simplify the
lives of the authors of logfile analyzers if commonly adopted.
* CGI scripts are now allowed anywhere.
* The server side includes interface has been completely
rewritten. It is NOT compatible with your old INC SRV documents
but a filter is provided to transform your old documents into
the new format.
* There is a new access control option to disable symbolic links
only if the owner of the pointer is not the same as the
owner of that which is pointed to. This means your users can
have symbolic links to things they own, but not to dangerous
things like /etc.
* A new access control method called mutual-failure has been
added. This method is a bit unorthodox, but allows
you to allow hosts from one domain while excluding certain hosts
(such as public access machines) from that domain.
* Wildcard expressions are now allowed in various areas of server
configuration, to allow patterns to be specified. This is most
useful in the Directory directive.
* Directory indexing has been revamped. It looks much different,
and I've written a short tutorial on how to set it up.
* Access Control Files now allow the indexing directives as well
as the DefaultType directive.
* require user now allows quotes for PGP usernames with spaces.
* Server now explicitly kills CGI scripts when the client aborts
or upon timeout
* Server now verifies the DNS hostname it gets from the IP number
to prevent PTR spoofs.
* Support for 304 and If-modified-since.
* Support for CGI PUT and DELETE scripts. This will become
important later for group annotation features.
Bug fixes
All of the known bugs in 1.1 have now been fixed. Now it's time to
find the ones I introduce with 1.2.
* Fixed problem running scripts in ServerMode inetd under IRIX.
* Fixed bad port problem under OSF/1.
* Inserted missing return statement for the IdentityCheck directive.
* Fixed problem whereby errors would stop being logged after a restart.
* Fixed 256 character limitation on CGI URLs.
* Access control fix from 1.1 integrated but moved in order to
allow certain CGI scripts to continue functioning.

View File

@ -1,6 +1,6 @@
#!/bin/sh
DATE=`which date`
DATE=/bin/date
echo Content-type: text/plain
echo

View File

@ -1,6 +1,6 @@
#!/bin/sh
FINGER=`which finger`
FINGER=/usr/ucb/finger
echo Content-type: text/html
echo

View File

@ -1,6 +1,6 @@
#!/bin/sh
FORTUNE=`which fortune`
FORTUNE=/usr/games/fortune
echo Content-type: text/plain
echo

Binary file not shown.

View File

@ -9,7 +9,6 @@ echo
echo argc is $#. argv is "$*".
echo
echo PATH = $PATH
echo SERVER_SOFTWARE = $SERVER_SOFTWARE
echo SERVER_NAME = $SERVER_NAME
echo GATEWAY_INTERFACE = $GATEWAY_INTERFACE
@ -17,10 +16,10 @@ echo SERVER_PROTOCOL = $SERVER_PROTOCOL
echo SERVER_PORT = $SERVER_PORT
echo REQUEST_METHOD = $REQUEST_METHOD
echo HTTP_ACCEPT = "$HTTP_ACCEPT"
echo PATH_INFO = $PATH_INFO
echo PATH_TRANSLATED = $PATH_TRANSLATED
echo SCRIPT_NAME = $SCRIPT_NAME
echo QUERY_STRING = $QUERY_STRING
echo PATH_INFO = "$PATH_INFO"
echo PATH_TRANSLATED = "$PATH_TRANSLATED"
echo SCRIPT_NAME = "$SCRIPT_NAME"
echo QUERY_STRING = "$QUERY_STRING"
echo REMOTE_HOST = $REMOTE_HOST
echo REMOTE_ADDR = $REMOTE_ADDR
echo REMOTE_USER = $REMOTE_USER

View File

@ -1,6 +1,6 @@
#!/bin/sh
UPTIME=`which uptime`
UPTIME=/usr/ucb/uptime
echo Content-type: text/plain
echo

View File

@ -2,7 +2,7 @@
#
# wais.pl -- WAIS search interface
#
# wais.pl,v 1.1 1993/12/31 09:30:56 robm Exp
# wais.pl,v 1.2 1994/04/10 05:33:29 robm Exp
#
# Tony Sanders <sanders@bsdi.com>, Nov 1993
#
@ -84,4 +84,5 @@ sub docdone {
$score = $headline = $lines = $bytes = $type = $date = '';
}
open (STDERR,"> /dev/null");
eval '&do_wais';

View File

@ -57,5 +57,5 @@ change-passwd: change-passwd.o util.o
clean:
rm -f *.o ../cgi-bin/post-query ../cgi-bin/query ../cgi-bin/change-passwd ../cgi-bin/phf ../cgi-bin/jj
rm -f *.o ../cgi-bin/post-query ../cgi-bin/query ../cgi-bin/change-passwd ../cgi-bin/phf ../cgi-bin/jj ../cgi-bin/imagemap

View File

@ -31,7 +31,7 @@ int isname(char);
int main(int argc, char **argv)
{
char input[MAXLINE], *mapname, def[MAXLINE], conf[80];
char input[MAXLINE], *mapname, def[MAXLINE], conf[MAXLINE];
double testpoint[2], pointarray[MAXVERTS][2];
int i, j, k;
FILE *fp;
@ -63,11 +63,11 @@ int main(int argc, char **argv)
confname[i] = input[i];
confname[i] = '\0';
if(!strcmp(confname,mapname))
break;
goto found;
}
if(feof(fp))
servererr("Map not found in configuration file.");
found:
fclose(fp);
while(isspace(input[i]) || input[i] == ':') ++i;

View File

@ -178,11 +178,17 @@ main(int argc, char *argv[]) {
strcpy(commandstr, "/usr/local/bin/ph -m ");
if (strlen(serverstr)) {
strcat(commandstr, " -s ");
/* RM 2/22/94 oops */
escape_shell_cmd(serverstr);
strcat(commandstr, serverstr);
strcat(commandstr, " ");
}
escape_shell_cmd(typestr);
strcat(commandstr, typestr);
if (atleastonereturn) strcat(commandstr, returnstr);
if (atleastonereturn) {
escape_shell_cmd(returnstr);
strcat(commandstr, returnstr);
}
printf("%s%c", commandstr, LF);
printf("<PRE>%c", LF);

View File

@ -120,3 +120,28 @@ void send_fd(FILE *f, FILE *fd)
fputc(c,fd);
}
}
int ind(char *s, char c) {
register int x;
for(x=0;s[x];x++)
if(s[x] == c) return x;
return -1;
}
void escape_shell_cmd(char *cmd) {
register int x,y,l;
l=strlen(cmd);
for(x=0;cmd[x];x++) {
if(ind("&;`'\"|*?~<>^()[]{}$\\",cmd[x]) != -1){
for(y=l+1;y>x;y--)
cmd[y] = cmd[y-1];
l++; /* length has been increased */
cmd[x] = '\\';
x++; /* skip the character */
}
}
}

View File

@ -52,8 +52,12 @@ TransferLog logs/access_log
PidFile logs/httpd.pid
# ServerName allows you to set a host name which is sent back to clients for
#your server if it's different than the one the program would get (i.e. use
#"www" instead of the host's real name).
# your server if it's different than the one the program would get (i.e. use
# "www" instead of the host's real name).
#
# Note: You cannot just invent host names and hope they work. The name you
# define here must be a valid DNS name for your host. If you don't understand
# this, ask your network administrator.
#ServerName new.host.name

View File

@ -1,6 +1,9 @@
# With this document, you define the name space that users see of your http
# server.
# See the tutorials at http://hoohoo.ncsa.uiuc.edu/docs/tutorials/ for
# more information.
# Rob (robm@ncsa.uiuc.edu)
@ -27,13 +30,15 @@ FancyIndexing on
# AddIcon tells the server which icon to show for different files or filename
# extensions
AddIcon /icons/text.xbm .html .txt
AddIcon /icons/image.xbm .gif .jpg .xbm .tiff
AddIcon /icons/sound.xbm .au
AddIcon /icons/movie.xbm .mpg
AddIconByType (TXT,/icons/text.xbm) text/*
AddIconByType (IMG,/icons/image.xbm) image/*
AddIconByType (SND,/icons/sound.xbm) audio/*
AddIcon /icons/movie.xbm .mpg .qt
AddIcon /icons/binary.xbm .bin
AddIcon /icons/back.xbm ..
AddIcon /icons/menu.xbm **DIRECTORY**
AddIcon /icons/menu.xbm ^^DIRECTORY^^
AddIcon /icons/blank.xbm ^^BLANKICON^^
# DefaultIcon is which icon to show for files which do not have an icon
# explicitly set.
@ -49,13 +54,17 @@ DefaultIcon /icons/unknown.xbm
#
# The server will first look for name.html, include it if found, and it will
# then look for name and include it as plaintext if found.
#
# HeaderName is the name of a file which should be prepended to
# directory indexes.
ReadmeName README
HeaderName HEADER
# IndexIgnore is a set of filenames which directory indexing should ignore
# Format: IndexIgnore name1 name2...
IndexIgnore /.htaccess ~ #
IndexIgnore */.??* *~ *# */HEADER* */README*
# AccessFileName: The name of the file to look for in each directory
# for access control information.
@ -71,6 +80,12 @@ DefaultType text/plain
# make certain files to be certain types.
# Format: AddType type/subtype ext1
# AddEncoding allows you to have certain browsers (Mosaic/X 2.1+) uncompress
# information on the fly. Note: Not all browsers support this.
#AddEncoding x-compress Z
#AddEncoding x-gzip gz
# Redirect allows you to tell clients about documents which used to exist in
# your server's namespace, but do not anymore. This allows you to tell the
# clients where to look for the relocated document.
@ -86,3 +101,9 @@ Alias /icons/ /usr/local/etc/httpd/icons/
# Format: ScriptAlias fakename realname
ScriptAlias /cgi-bin/ /usr/local/etc/httpd/cgi-bin/
# If you want to use server side includes, or CGI outside
# ScriptAliased directories, uncomment the following lines.
#AddType text/x-server-parsed-html .shtml
#AddType application/x-httpd-cgi .cgi

9
icons/blank.xbm Normal file
View File

@ -0,0 +1,9 @@
#define blank_width 20
#define blank_height 23
static char blank_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

View File

@ -4,13 +4,13 @@
#CC= cc
# For Suns or other non-ANSI platforms. Please make sure your gcc is
# 2.0 or later, as 1.40 seems to create bad code for the Sun 4.
CC= gcc
CC= gcc
# For optimization
#CFLAGS= -O2
CFLAGS= -O2
# For debugging information
#CFLAGS= -g -DPEM_AUTH
CFLAGS= -g
#CFLAGS= -g -DPEM_AUTH
#CFLAGS= -g
# Place here any extra libraries you may need to link to. You
# shouldn't have to.
@ -34,7 +34,7 @@ AUX_CFLAGS= -DSUNOS4
# For HP-UX
#AUX_CFLAGS= -DHPUX
# For AIX
#AUX_CFLAGS= -DAIX
#AUX_CFLAGS= -DAIX -U__STR__
# For Ultrix
#AUX_CFLAGS= -DULTRIX
# For DEC OSF/1
@ -47,6 +47,14 @@ AUX_CFLAGS= -DSUNOS4
#AUX_CFLAGS= -DLINUX
# For A/UX
#AUX_CFLAGS= -DAUX
# For SCO ODT
# libcrypt_i available from sosco.sco.com, files /SLS/lng225b.Z and
# /SLS/lng225b.ltr.Z
#AUX_CFLAGS= -DSCO
#EXTRA_LIBS= -lPW -lsocket -lmalloc -lcrypt_i
# For SVR4
#AUX_CFLAGS= -DSVR4
#EXTRA_LIBS= -lsocket -lnsl -lc
# Place here any flags you may need upon linking, such as a flag to
# prevent dynamic linking (if desired)
@ -56,7 +64,8 @@ LFLAGS=
OBJS=http_config.o httpd.o http_request.o util.o http_dir.o \
http_alias.o http_log.o http_mime.o http_access.o http_auth.o \
http_get.o http_put.o http_script.o rfc931.o
http_get.o http_post.o http_script.o http_include.o rfc931.o \
http_put.o http_delete.o
.c.o:
$(CC) -c $(CFLAGS) $(AUX_CFLAGS) $<

View File

@ -1,100 +0,0 @@
# Makefile for NCSA's httpd.
# For normal machines with ANSI compilers
#CC= cc
# For Suns or other non-ANSI platforms. Please make sure your gcc is
# 2.0 or later, as 1.40 seems to create bad code for the Sun 4.
CC= gcc
# For optimization
#CFLAGS= -O2
# For debugging information
CFLAGS= -g -DPEM_AUTH
#CFLAGS= -g
# Place here any extra libraries you may need to link to. You
# shouldn't have to.
EXTRA_LIBS=
# AUX_CFLAGS are system-specific control flags.
# NOTE: IF YOU DO NOT CHOOSE ONE OF THESE, EDIT httpd.h AND CHOOSE
# SETTINGS FOR THE SYSTEM FLAGS. IF YOU DON'T, BAD THINGS WILL HAPPEN.
# For SunOS 4
AUX_CFLAGS= -DSUNOS4
# For Solaris 2. NOTE: Lots of problems have been identified with compiling
# httpd under Solaris. Use with caution. If you see aberrant behavior with
# httpd under Solaris 2, please mail us.
#AUX_CFLAGS= -DSOLARIS2
#EXTRA_LIBS= -lsocket -lnsl
# For SGI IRIX. Use the EXTRA_LIBS line if you're using NIS and want
# user-supported directories
#AUX_CFLAGS= -DIRIX
#EXTRA_LIBS= -lsun
# For HP-UX
#AUX_CFLAGS= -DHPUX
# For AIX
#AUX_CFLAGS= -DAIX
# For Ultrix
#AUX_CFLAGS= -DULTRIX
# For DEC OSF/1
#AUX_CFLAGS= -DOSF1
# For NeXT
#AUX_CFLAGS= -DNEXT
# For Sequent
#AUX_CFLAGS= -DSEQUENT
# For Linux -m486 ONLY IF YOU HAVE 486 BINARY SUPPORT IN KERNEL
#AUX_CFLAGS= -DLINUX
# For A/UX
#AUX_CFLAGS= -DAUX
# Place here any flags you may need upon linking, such as a flag to
# prevent dynamic linking (if desired)
LFLAGS=
# You shouldn't have to edit anything else.
OBJS=http_config.o httpd.o http_request.o util.o http_dir.o \
http_alias.o http_log.o http_mime.o http_access.o http_auth.o \
http_get.o http_put.o http_script.o rfc931.o
.c.o:
$(CC) -c $(CFLAGS) $(AUX_CFLAGS) $<
all: httpd
ibm:
make tar AUX_CFLAGS=-DAIX CC=gcc CFLAGS=-O2
sun:
make tar AUX_CFLAGS=-DSUNOS4 CC=gcc CFLAGS=-O2
hp:
make tar AUX_CFLAGS=-DHPUX CC=gcc CFLAGS=-O2
sgi:
make tar AUX_CFLAGS=-DIRIX EXTRA_LIBS=-lsun CC=cc CFLAGS=-O2
decmips:
make tar AUX_CFLAGS=-DULTRIX CC=cc CFLAGS=-O2
decaxp:
make tar AUX_CFLAGS=-DOSF1 CC=cc CFLAGS=-O2
httpd: $(OBJS)
$(CC) $(LFLAGS) -o httpd $(OBJS) $(EXTRA_LIBS)
purify: $(OBJS)
purify -logfile=/X11/robm/httpd/logs/pure_log \
-program-name=/X11/robm/httpd/src/httpd \
$(CC) $(LFLAGS) -o httpd $(OBJS) $(EXTRA_LIBS)
tar: $(OBJS)
$(CC) $(LFLAGS) -o ../httpd $(OBJS) $(EXTRA_LIBS)
rm -f $(OBJS)
$(OBJS): Makefile httpd.h
clean:
rm -f ../httpd httpd $(OBJS) *pure*

View File

@ -73,16 +73,17 @@ void check_dir_access(int x, int m, int *w, int *n) {
*w=1;
if(find_deny(x,m))
*w=0;
if(sec[x].num_auth[m])
*n=x;
} else {
} else if(sec[x].order[m] == DENY_THEN_ALLOW) {
if(find_deny(x,m))
*w=0;
if(find_allow(x,m))
*w=1;
if(sec[x].num_auth[m])
*n=x;
}
else
*w = find_allow(x,m) && (!find_deny(x,m));
if(sec[x].num_auth[m])
*n=x;
}
void evaluate_access(char *p, struct stat *finfo, int m, int *allow,
@ -91,11 +92,14 @@ void evaluate_access(char *p, struct stat *finfo, int m, int *allow,
int will_allow, need_auth, num_dirs;
char opts[MAX_STRING_LEN], override[MAX_STRING_LEN];
char path[MAX_STRING_LEN], d[MAX_STRING_LEN];
char errstr[MAX_STRING_LEN];
register int x,y,z,n;
if(S_ISDIR(finfo->st_mode)) strcpy_dir(path,p);
else strcpy(path,p);
no2slash(path);
num_dirs = count_dirs(path);
will_allow=1;need_auth=-1;
auth_type=NULL;auth_name=NULL;auth_pwfile=NULL;auth_grpfile=NULL;
@ -106,55 +110,101 @@ void evaluate_access(char *p, struct stat *finfo, int m, int *allow,
}
for(x=0;x<num_sec;x++) {
if(!strncmp(path,sec[x].d,strlen(sec[x].d))) {
for(y=count_dirs(sec[x].d) - 1;y<num_dirs;y++) {
if(!(sec[x].opts & OPT_UNSET))
opts[y] = sec[x].opts;
override[y] = sec[x].override;
if((is_matchexp(path) ? strcmp_match(path,sec[x].d)
: !strncmp(path,sec[x].d,strlen(sec[x].d))))
{
for(y=count_dirs(sec[x].d) - 1;y<num_dirs;y++) {
if(!(sec[x].opts & OPT_UNSET))
opts[y] = sec[x].opts;
override[y] = sec[x].override;
}
check_dir_access(x,m,&will_allow,&need_auth);
}
check_dir_access(x,m,&will_allow,&need_auth);
}
}
n=num_dirs-1;
if((override[n]) || (!(opts[n] & OPT_SYM_LINKS))) {
for(x=0;x<num_dirs;x++) {
y = num_sec;
make_dirstr(path,x+1,d);
if(!(opts[x] & OPT_SYM_LINKS)) {
struct stat fi;
lstat(d,&fi);
if(!(S_ISDIR(fi.st_mode))) {
char errstr[MAX_STRING_LEN];
sprintf(errstr,"httpd: will not follow link %s",d);
log_error(errstr);
*allow=0;
*allow_options = OPT_NONE;
return;
}
}
if(override[x]) {
parse_htaccess(d,override[x],out);
if(num_sec != y) {
for(z=count_dirs(sec[y].d) - 1;z<num_dirs;z++) {
if(!(sec[y].opts & OPT_UNSET))
opts[z] = sec[y].opts;
override[z] = sec[y].override;
if((override[n]) || (!(opts[n] & OPT_SYM_LINKS)) ||
(opts[n] & OPT_SYM_OWNER))
{
for(x=0;x<num_dirs;x++) {
y = num_sec;
make_dirstr(path,x+1,d);
if((!(opts[x] & OPT_SYM_LINKS)) || (opts[x] & OPT_SYM_OWNER)) {
struct stat lfi,fi;
lstat(d,&lfi);
if(!(S_ISDIR(lfi.st_mode))) {
if(opts[x] & OPT_SYM_OWNER) {
char realpath[512];
int bsz;
if((bsz = readlink(d,realpath,256)) == -1)
goto bong;
realpath[bsz] = '\0';
if(realpath[0] != '/') {
char t[256];
strcpy(t,"../");
strcpy(&t[3],realpath);
make_full_path(d,t,realpath);
getparents(realpath);
}
lstat(realpath,&fi);
if(fi.st_uid != lfi.st_uid)
goto bong;
}
else {
bong:
sprintf(errstr,"httpd: will not follow link %s",d);
log_error(errstr);
*allow=0;
*allow_options = OPT_NONE;
return;
}
}
}
if(override[x]) {
parse_htaccess(d,override[x],out);
if(num_sec != y) {
for(z=count_dirs(sec[y].d) - 1;z<num_dirs;z++) {
if(!(sec[y].opts & OPT_UNSET))
opts[z] = sec[y].opts;
override[z] = sec[y].override;
}
check_dir_access(y,m,&will_allow,&need_auth);
}
check_dir_access(y,m,&will_allow,&need_auth);
}
}
}
}
if((!(S_ISDIR(finfo->st_mode))) && (!(opts[n] & OPT_SYM_LINKS))) {
struct stat fi;
if((!(S_ISDIR(finfo->st_mode))) &&
((!(opts[n] & OPT_SYM_LINKS)) || (opts[x] & OPT_SYM_OWNER))) {
struct stat fi,lfi;
lstat(path,&fi);
if(!(S_ISREG(fi.st_mode))) {
char errstr[MAX_STRING_LEN];
sprintf(errstr,"httpd: will not follow link %s",path);
log_error(errstr);
*allow=0;
*allow_options = OPT_NONE;
return;
if(opts[n] & OPT_SYM_OWNER) {
char realpath[512];
int bsz;
if((bsz = readlink(path,realpath,256)) == -1)
goto gong;
realpath[bsz] = '\0';
if(realpath[0] != '/') {
char t[256];
strcpy(t,"../");
strcpy(&t[3],realpath);
make_full_path(path,t,realpath);
getparents(realpath);
}
lstat(realpath,&lfi);
if(fi.st_uid != lfi.st_uid)
goto gong;
}
else {
gong:
sprintf(errstr,"httpd: will not follow link %s",path);
log_error(errstr);
*allow=0;
*allow_options = OPT_NONE;
return;
}
}
}
*allow = will_allow;
@ -179,6 +229,14 @@ void kill_security() {
for(y=0;y<sec[x].num_auth[m];y++)
free(sec[x].auth[m][y]);
}
if(sec[x].auth_type)
free(sec[x].auth_type);
if(sec[x].auth_name)
free(sec[x].auth_name);
if(sec[x].auth_pwfile)
free(sec[x].auth_pwfile);
if(sec[x].auth_grpfile)
free(sec[x].auth_grpfile);
}
}

View File

@ -55,7 +55,7 @@ void check_auth(security_data *sec, int m, FILE *out) {
char t[MAX_STRING_LEN];
char w[MAX_STRING_LEN];
char errstr[MAX_STRING_LEN];
register int x;
register int x,y;
int grpstatus;
if(!auth_type) {
@ -81,7 +81,7 @@ void check_auth(security_data *sec, int m, FILE *out) {
uudecode(t,(unsigned char *)ad,MAX_STRING_LEN);
getword(user,ad,':');
strcpy(sent_pw,ad);
if(!get_pw(user,real_pw)) {
if(!get_pw(user,real_pw,out)) {
sprintf(errstr,"user %s not found",user);
auth_bong(errstr,out);
}
@ -134,6 +134,11 @@ void check_auth(security_data *sec, int m, FILE *out) {
goto found;
if(!strcmp(w,"user")) {
while(t[0]) {
if(t[0] == '\"') {
getword(w,&t[1],'\"');
for(y=0;t[y];y++)
t[y] = t[y+1];
}
getword(w,t,' ');
if(!strcmp(user,w))
goto found;
@ -176,7 +181,7 @@ void pem_cleanup(int status, FILE *out) {
}
}
int pem_decrypt(int sfd, char *req, FILE **out) {
int decrypt_request(int sfd, char *req, FILE **out) {
int tfd,nr,pid,p[2],decrypt_fd,pem,pgp;
char w[MAX_STRING_LEN],w2[MAX_STRING_LEN];
char c;
@ -186,9 +191,10 @@ int pem_decrypt(int sfd, char *req, FILE **out) {
doing_pem = ENCODING_NONE;
if(strcmp(req,"/"))
return -1;
pem = !(strcmp(content_type,"application/x-www-pem-request"));
pgp = !(strcmp(content_type,"application/x-www-pgp-request"));
if((!pem) && (!pgp))
return -1;
@ -276,6 +282,7 @@ int pem_decrypt(int sfd, char *req, FILE **out) {
dup2(p[1],STDOUT_FILENO);
close(p[1]);
}
error_log2stderr();
if(!(argv0 = strrchr(decrypt,'/')))
argv0 = decrypt;
else

View File

@ -35,7 +35,7 @@ char auth_pgp_encrypt[MAX_STRING_LEN];
char auth_pgp_entity[MAX_STRING_LEN];
#endif
void process_server_config() {
void process_server_config(FILE *errors) {
FILE *cfg;
char l[MAX_STRING_LEN],w[MAX_STRING_LEN];
int n=0;
@ -67,7 +67,7 @@ void process_server_config() {
#endif
if(!(cfg = fopen(server_confname,"r"))) {
fprintf(stderr,"httpd: could not open server config. file %s\n",server_confname);
fprintf(errors,"httpd: could not open server config. file %s\n",server_confname);
perror("fopen");
exit(1);
}
@ -81,8 +81,8 @@ void process_server_config() {
if(!strcasecmp(l,"inetd")) standalone=0;
else if(!strcasecmp(l,"standalone")) standalone=1;
else {
fprintf(stderr,"Syntax error on line %d of %s:\n",n,server_confname);
fprintf(stderr,"ServerType is either inetd or standalone.\n");
fprintf(errors,"Syntax error on line %d of %s:\n",n,server_confname);
fprintf(errors,"ServerType is either inetd or standalone.\n");
exit(1);
}
}
@ -107,13 +107,13 @@ void process_server_config() {
if(server_hostname)
free(server_hostname);
if(!(server_hostname = strdup(w)))
die(NO_MEMORY,"process_resource_config",stderr);
die(NO_MEMORY,"process_resource_config",errors);
}
else if(!strcasecmp(w,"ServerRoot")) {
cfg_getword(w,l);
if(!is_directory(w)) {
fprintf(stderr,"Syntax error on line %d of %s:\n",n,server_confname);
fprintf(stderr,"%s is not a valid directory.\n",w);
fprintf(errors,"Syntax error on line %d of %s:\n",n,server_confname);
fprintf(errors,"%s is not a valid directory.\n",w);
exit(1);
}
strcpy(server_root,w);
@ -170,9 +170,9 @@ void process_server_config() {
else if(!strcmp(w,"off"))
do_rfc931 = 0;
else {
fprintf(stderr,"Syntax error on line %d of %s:\n",n,
fprintf(errors,"Syntax error on line %d of %s:\n",n,
srm_confname);
fprintf(stderr,"IdentityCheck must be on or off.\n");
fprintf(errors,"IdentityCheck must be on or off.\n");
}
}
#ifdef PEM_AUTH
@ -202,8 +202,8 @@ void process_server_config() {
}
#endif
else {
fprintf(stderr,"Syntax error on line %d of %s:\n",n,server_confname);
fprintf(stderr,"Unknown keyword %s.\n",w);
fprintf(errors,"Syntax error on line %d of %s:\n",n,server_confname);
fprintf(errors,"Unknown keyword %s.\n",w);
exit(1);
}
}
@ -218,10 +218,8 @@ char access_name[MAX_STRING_LEN];
char document_root[MAX_STRING_LEN];
char default_type[MAX_STRING_LEN];
char default_icon[MAX_STRING_LEN];
int fancy_indexing;
char readme_fname[MAX_STRING_LEN];
void process_resource_config() {
void process_resource_config(FILE *errors) {
FILE *cfg;
char l[MAX_STRING_LEN],w[MAX_STRING_LEN];
int n=0;
@ -232,11 +230,11 @@ void process_resource_config() {
strcpy(document_root,DOCUMENT_LOCATION);
strcpy(default_type,DEFAULT_TYPE);
default_icon[0] = '\0';
fancy_indexing = DEFAULT_INDEXING;
readme_fname[0] = '\0';
add_opts_int(0,"/",errors);
if(!(cfg = fopen(srm_confname,"r"))) {
fprintf(stderr,"httpd: could not open document config. file %s\n",
fprintf(errors,"httpd: could not open document config. file %s\n",
srm_confname);
perror("fopen");
exit(1);
@ -253,9 +251,9 @@ void process_resource_config() {
cfg_getword(w,l);
cfg_getword(w2,l);
if((w[0] == '\0') || (w2[0] == '\0')) {
fprintf(stderr,"Syntax error on line %d of %s:\n",n,
fprintf(errors,"Syntax error on line %d of %s:\n",n,
srm_confname);
fprintf(stderr,
fprintf(errors,
"ScriptAlias must be followed by a fakename, one space, then a realname.\n");
exit(1);
}
@ -267,9 +265,9 @@ void process_resource_config() {
cfg_getword(w,l);
cfg_getword(w2,l);
if((w[0] == '\0') || (w2[0] == '\0')) {
fprintf(stderr,"Syntax error on line %d of %s:\n",n,
fprintf(errors,"Syntax error on line %d of %s:\n",n,
srm_confname);
fprintf(stderr,
fprintf(errors,
"ScriptAlias must be followed by a fakename, one space, then a realname.\n");
exit(1);
}
@ -297,9 +295,9 @@ void process_resource_config() {
else if(!strcasecmp(w,"DocumentRoot")) {
cfg_getword(w,l);
if(!is_directory(w)) {
fprintf(stderr,"Syntax error on line %d of %s:\n",n,
fprintf(errors,"Syntax error on line %d of %s:\n",n,
srm_confname);
fprintf(stderr,"%s is not a valid directory.\n",w);
fprintf(errors,"%s is not a valid directory.\n",w);
exit(1);
}
strcpy(document_root,w);
@ -310,9 +308,9 @@ void process_resource_config() {
cfg_getword(w,l);
cfg_getword(w2,l);
if((w[0] == '\0') || (w2[0] == '\0')) {
fprintf(stderr,"Syntax error on line %d of %s:\n",n,
fprintf(errors,"Syntax error on line %d of %s:\n",n,
srm_confname);
fprintf(stderr,
fprintf(errors,
"Alias must be followed by a fakename, one space, then a realname.\n");
exit(1);
}
@ -323,35 +321,35 @@ void process_resource_config() {
cfg_getword(w,l);
cfg_getword(w2,l);
if((w[0] == '\0') || (w2[0] == '\0')) {
fprintf(stderr,"Syntax error on line %d of %s:\n",n,
fprintf(errors,"Syntax error on line %d of %s:\n",n,
srm_confname);
fprintf(stderr,
fprintf(errors,
"AddType must be followed by a type, one space, then a file or extension.\n");
exit(1);
}
add_type(w2,w,stderr);
add_type(w2,w,errors);
}
else if(!strcasecmp(w,"AddEncoding")) {
char w2[MAX_STRING_LEN];
cfg_getword(w,l);
cfg_getword(w2,l);
if((w[0] == '\0') || (w2[0] == '\0')) {
fprintf(stderr,"Syntax error on line %d of %s:\n",n,
fprintf(errors,"Syntax error on line %d of %s:\n",n,
srm_confname);
fprintf(stderr,
fprintf(errors,
"AddEncoding must be followed by a type, one space, then a file or extension.\n");
exit(1);
}
add_encoding(w2,w,stderr);
add_encoding(w2,w,errors);
}
else if(!strcasecmp(w,"Redirect")) {
char w2[MAX_STRING_LEN];
cfg_getword(w,l);
cfg_getword(w2,l);
if((w[0] == '\0') || (w2[0] == '\0') || (!is_url(w2))) {
fprintf(stderr,"Syntax error on line %d of %s:\n",n,
fprintf(errors,"Syntax error on line %d of %s:\n",n,
srm_confname);
fprintf(stderr,
fprintf(errors,
"Redirect must be followed by a document, one space, then a URL.\n");
exit(1);
}
@ -360,13 +358,13 @@ void process_resource_config() {
else if(!strcasecmp(w,"FancyIndexing")) {
cfg_getword(w,l);
if(!strcmp(w,"on"))
fancy_indexing = 1;
add_opts_int(FANCY_INDEXING,"/",errors);
else if(!strcmp(w,"off"))
fancy_indexing = 0;
add_opts_int(0,"/",errors);
else {
fprintf(stderr,"Syntax error on line %d of %s:\n",n,
fprintf(errors,"Syntax error on line %d of %s:\n",n,
srm_confname);
fprintf(stderr,"FancyIndexing must be on or off.\n");
fprintf(errors,"FancyIndexing must be on or off.\n");
exit(1);
}
}
@ -374,21 +372,21 @@ void process_resource_config() {
char desc[MAX_STRING_LEN];
int fq;
if((fq = ind(l,'\"')) == -1) {
fprintf(stderr,"Syntax error on line %d of %s:\n",n,
fprintf(errors,"Syntax error on line %d of %s:\n",n,
srm_confname);
fprintf(stderr,"AddDescription must have quotes around the description.\n");
fprintf(errors,"AddDescription must have quotes around the description.\n");
exit(1);
}
else {
getword(desc,&l[++fq],'\"');
cfg_getword(w,&l[fq]);
add_desc(desc,w,stderr);
add_desc(BY_PATH,desc,w,"/",errors);
}
}
else if(!strcasecmp(w,"IndexIgnore")) {
while(l[0]) {
cfg_getword(w,l);
add_ignore(w,stderr);
add_ignore(w,"/",errors);
}
}
else if(!strcasecmp(w,"AddIcon")) {
@ -396,7 +394,47 @@ fprintf(stderr,"AddDescription must have quotes around the description.\n");
cfg_getword(w2,l);
while(l[0]) {
cfg_getword(w,l);
add_icon(w2,w,stderr);
add_icon(BY_PATH,w2,w,"/",errors);
}
}
else if(!strcasecmp(w,"AddIconByType")) {
char w2[MAX_STRING_LEN];
cfg_getword(w2,l);
while(l[0]) {
cfg_getword(w,l);
add_icon(BY_TYPE,w2,w,"/",errors);
}
}
else if(!strcasecmp(w,"AddIconByEncoding")) {
char w2[MAX_STRING_LEN];
cfg_getword(w2,l);
while(l[0]) {
cfg_getword(w,l);
add_icon(BY_ENCODING,w2,w,"/",errors);
}
}
else if(!strcasecmp(w,"AddAlt")) {
char w2[MAX_STRING_LEN];
cfg_getword(w2,l);
while(l[0]) {
cfg_getword(w,l);
add_alt(BY_PATH,w2,w,"/",errors);
}
}
else if(!strcasecmp(w,"AddAltByType")) {
char w2[MAX_STRING_LEN];
cfg_getword(w2,l);
while(l[0]) {
cfg_getword(w,l);
add_alt(BY_TYPE,w2,w,"/",errors);
}
}
else if(!strcasecmp(w,"AddAltByEncoding")) {
char w2[MAX_STRING_LEN];
cfg_getword(w2,l);
while(l[0]) {
cfg_getword(w,l);
add_alt(BY_ENCODING,w2,w,"/",errors);
}
}
else if(!strcasecmp(w,"DefaultIcon")) {
@ -405,11 +443,18 @@ fprintf(stderr,"AddDescription must have quotes around the description.\n");
}
else if(!strcasecmp(w,"ReadmeName")) {
cfg_getword(w,l);
strcpy(readme_fname,w);
add_readme(w,"/",errors);
}
else if(!strcasecmp(w,"HeaderName")) {
cfg_getword(w,l);
add_header(w,"/",errors);
}
else if(!strcasecmp(w,"IndexOptions"))
add_opts(l,"/",errors);
else {
fprintf(stderr,"Syntax error on line %d of %s:\n",n,srm_confname);
fprintf(stderr,"Unknown keyword %s.\n",w);
fprintf(errors,"Syntax error on line %d of %s:\n",n,
srm_confname);
fprintf(errors,"Unknown keyword %s.\n",w);
exit(1);
}
}
@ -430,8 +475,8 @@ security_data sec[MAX_SECURITY];
void access_syntax_error(int n, char *err, char *file, FILE *out) {
if(!file) {
fprintf(stderr,"Syntax error on line %d of access config. file.\n",n);
fprintf(stderr,"%s\n",err);
fprintf(out,"Syntax error on line %d of access config. file.\n",n);
fprintf(out,"%s\n",err);
exit(1);
}
else {
@ -508,8 +553,14 @@ int parse_access_dir(FILE *f, int line, char or, char *dir,
sec[x].opts |= OPT_INDEXES;
else if(!strcasecmp(w,"Includes"))
sec[x].opts |= OPT_INCLUDES;
else if(!strcasecmp(w,"IncludesNOEXEC"))
sec[x].opts |= (OPT_INCLUDES | OPT_INCNOEXEC);
else if(!strcasecmp(w,"FollowSymLinks"))
sec[x].opts |= OPT_SYM_LINKS;
else if(!strcasecmp(w,"SymLinksIfOwnerMatch"))
sec[x].opts |= OPT_SYM_OWNER;
else if(!strcasecmp(w,"execCGI"))
sec[x].opts |= OPT_EXECCGI;
else if(!strcasecmp(w,"None"))
sec[x].opts = OPT_NONE;
else if(!strcasecmp(w,"All"))
@ -567,6 +618,12 @@ int parse_access_dir(FILE *f, int line, char or, char *dir,
}
add_type(w2,w,out);
}
else if(!strcasecmp(w,"DefaultType")) {
if(!(or & OR_FILEINFO))
access_syntax_error(n,"override violation",file,out);
cfg_getword(w,l);
strcpy(default_type,w);
}
else if(!strcasecmp(w,"AddEncoding")) {
if(!(or & OR_FILEINFO))
access_syntax_error(n,"override violation",file,out);
@ -579,49 +636,84 @@ int parse_access_dir(FILE *f, int line, char or, char *dir,
}
add_encoding(w2,w,out);
}
else if(!strcasecmp(w,"AddDescription")) {
int fq;
if(!(or & OR_FILEINFO))
else if(!strcasecmp(w,"DefaultIcon")) {
if(!(or & OR_INDEXES))
access_syntax_error(n,"override violation",file,out);
if((fq = ind(l,'\"')) == -1) {
access_syntax_error(n,
"AddDescription must have quotes around the description.\n",
cfg_getword(w,l);
strcpy(default_icon,w);
}
else if(!strcasecmp(w,"AddDescription")) {
char desc[MAX_STRING_LEN];
int fq;
if(!(or & OR_INDEXES))
access_syntax_error(n,"override violation",file,out);
if((fq = ind(l,'\"')) == -1)
access_syntax_error(n,"AddDescription must have quotes",
file,out);
}
else {
getword(w2,&l[++fq],'\"');
getword(desc,&l[++fq],'\"');
cfg_getword(w,&l[fq]);
add_desc(w2,w,stderr);
add_desc(BY_PATH,desc,w,sec[x].d,out);
}
}
else if(!strcasecmp(w,"IndexIgnore")) {
if(!(or & OR_FILEINFO))
if(!(or & OR_INDEXES))
access_syntax_error(n,"override violation",file,out);
while(l[0]) {
cfg_getword(w,l);
add_ignore(w,out);
add_ignore(w,sec[x].d,out);
}
}
else if(!strcasecmp(w,"AddIcon")) {
if(!(or & OR_FILEINFO))
char w2[MAX_STRING_LEN];
if(!(or & OR_INDEXES))
access_syntax_error(n,"override violation",file,out);
cfg_getword(w2,l);
while(l[0]) {
cfg_getword(w,l);
add_icon(w2,w,out);
add_icon(BY_PATH,w2,w,sec[x].d,out);
}
}
else if(!strcasecmp(w,"AddIconByType")) {
char w2[MAX_STRING_LEN];
if(!(or & OR_INDEXES))
access_syntax_error(n,"override violation",file,out);
cfg_getword(w2,l);
while(l[0]) {
cfg_getword(w,l);
add_icon(BY_TYPE,w2,w,sec[x].d,out);
}
}
else if(!strcasecmp(w,"AddIconByEncoding")) {
char w2[MAX_STRING_LEN];
if(!(or & OR_INDEXES))
access_syntax_error(n,"override violation",file,out);
cfg_getword(w2,l);
while(l[0]) {
cfg_getword(w,l);
add_icon(BY_ENCODING,w2,w,sec[x].d,out);
}
}
else if(!strcasecmp(w,"ReadmeName")) {
if(!(or & OR_FILEINFO))
if(!(or & OR_INDEXES))
access_syntax_error(n,"override violation",file,out);
cfg_getword(w,l);
strcpy(readme_fname,w);
add_readme(w,sec[x].d,out);
}
else if(!strcasecmp(w,"DefaultIcon")) {
if(!(or & OR_FILEINFO))
else if(!strcasecmp(w,"HeaderName")) {
if(!(or & OR_INDEXES))
access_syntax_error(n,"override violation",file,out);
cfg_getword(w,l);
strcpy(default_icon,w);
add_header(w,sec[x].d,out);
}
else if(!strcasecmp(w,"IndexOptions")) {
if(!(or & OR_INDEXES))
access_syntax_error(n,"override violation",file,out);
add_opts(l,sec[x].d,out);
}
else if(!strcasecmp(w,"Redirect")) {
if(!(or & OR_FILEINFO))
@ -650,6 +742,7 @@ int parse_access_dir(FILE *f, int line, char or, char *dir,
if(!strcasecmp(w,"GET")) m[M_GET]=1;
else if(!strcasecmp(w,"PUT")) m[M_PUT]=1;
else if(!strcasecmp(w,"POST")) m[M_POST]=1;
else if(!strcasecmp(w,"DELETE")) m[M_DELETE]=1;
}
while(1) {
if(cfg_getline(l,MAX_STRING_LEN,f))
@ -671,6 +764,11 @@ int parse_access_dir(FILE *f, int line, char or, char *dir,
if(m[i])
sec[x].order[i] = DENY_THEN_ALLOW;
}
else if(!strcasecmp(l,"mutual-failure")) {
for(i=0;i<METHODS;i++)
if(m[i])
sec[x].order[i] = MUTUAL_FAILURE;
}
else
access_syntax_error(n,"Unknown order.",file,out);
}
@ -751,7 +849,7 @@ void parse_htaccess(char *path, char override, FILE *out) {
}
void process_access_config() {
void process_access_config(FILE *errors) {
FILE *f;
char l[MAX_STRING_LEN];
char w[MAX_STRING_LEN];
@ -759,7 +857,7 @@ void process_access_config() {
num_sec = 0;n=0;
if(!(f=fopen(access_confname,"r"))) {
fprintf(stderr,"httpd: could not open access configuration file %s.\n",
fprintf(errors,"httpd: could not open access configuration file %s.\n",
access_confname);
perror("fopen");
exit(1);
@ -769,18 +867,18 @@ void process_access_config() {
if((l[0] == '#') || (!l[0])) continue;
cfg_getword(w,l);
if(strcasecmp(w,"<Directory")) {
fprintf(stderr,
fprintf(errors,
"Syntax error on line %d of access config. file.\n",n);
fprintf(stderr,"Unknown directive %s.\n",w);
fprintf(errors,"Unknown directive %s.\n",w);
exit(1);
}
getword(w,l,'>');
n=parse_access_dir(f,n,OR_ALL,w,NULL,stderr);
n=parse_access_dir(f,n,OR_ALL,w,NULL,errors);
}
fclose(f);
}
int get_pw(char *user, char *pw) {
int get_pw(char *user, char *pw, FILE *errors) {
FILE *f;
char errstr[MAX_STRING_LEN];
char l[MAX_STRING_LEN];
@ -788,7 +886,7 @@ int get_pw(char *user, char *pw) {
if(!(f=fopen(auth_pwfile,"r"))) {
sprintf(errstr,"Could not open user file %s",auth_pwfile);
die(SERVER_ERROR,errstr,stdout); /* AAAAAAAAGH stdout */
die(SERVER_ERROR,errstr,errors);
}
while(!(cfg_getline(l,MAX_STRING_LEN,f))) {
if((l[0] == '#') || (!l[0])) continue;
@ -868,12 +966,12 @@ void kill_group() {
}
}
void read_config()
void read_config(FILE *errors)
{
reset_aliases();
process_server_config();
init_mime();
process_server_config(errors);
init_mime(errors);
init_indexing();
process_resource_config();
process_access_config();
process_resource_config(errors);
process_access_config(errors);
}

57
src/http_delete.c Normal file
View File

@ -0,0 +1,57 @@
/*
* http_delete.c: Handles DELETE
*
* Rob McCool
*
*/
#include "httpd.h"
void handle_delete(char *name, char *args, int in, FILE *out) {
struct stat finfo;
char ct_bak[MAX_STRING_LEN];
if(stat(name,&finfo) == -1) {
if(find_script("DELETE",name,args,in,out))
return;
if(errno==ENOENT) {
log_reason("file does not exist",name);
unmunge_name(name);
die(NOT_FOUND,name,out);
}
else {
log_reason("file permissions deny server access",name);
unmunge_name(name);
die(FORBIDDEN,name,out);
}
}
probe_content_type(name);
if(!strcmp(content_type,CGI_MAGIC_TYPE)) {
strcpy(content_type,ct_bak);
send_cgi("DELETE",name,"",args,&finfo,in,out);
return;
}
/* Not a script, do group ann thang */
die(NOT_IMPLEMENTED,"DELETE to non-script",out);
}
void delete_node(char *name, char *args, int in, FILE *out) {
struct stat finfo;
int s;
s=translate_name(name,out);
switch(s) {
case STD_DOCUMENT:
handle_delete(name,args,in,out);
return;
case REDIRECT_URL:
die(REDIRECT,name,out);
case SCRIPT_CGI:
exec_cgi_script("DELETE",name,args,in,out);
default:
die(NOT_IMPLEMENTED,"NCSA script exeuction of delete",out);
}
}

View File

@ -13,31 +13,46 @@
struct ent {
char *name;
char *icon;
char *alt;
char *desc;
size_t size;
time_t lm;
struct ent *next;
};
struct item {
char *msg;
char *fn;
int type;
char *apply_to;
char *apply_path;
char *data;
struct item *next;
};
static struct item *icon_list, *desc_list, *ign_list;
static struct item *icon_list, *alt_list, *desc_list, *ign_list;
static struct item *hdr_list, *rdme_list, *opts_list;
static int dir_opts;
void init_indexing() {
icon_list = NULL;
alt_list = NULL;
desc_list = NULL;
ign_list = NULL;
hdr_list = NULL;
rdme_list = NULL;
opts_list = NULL;
}
void kill_item_list(struct item *p) {
struct item *q;
while(p) {
if(p->msg) free(p->msg);
if(p->fn) free(p->fn);
if(p->apply_to) free(p->apply_to);
if(p->apply_path) free(p->apply_path);
if(p->data) free(p->data);
q = p;
p = p->next;
free(q);
@ -46,202 +61,444 @@ void kill_item_list(struct item *p) {
void kill_indexing() {
kill_item_list(icon_list);
kill_item_list(alt_list);
kill_item_list(desc_list);
kill_item_list(ign_list);
kill_item_list(hdr_list);
kill_item_list(rdme_list);
kill_item_list(opts_list);
}
void add_icon(char *icon, char *ext, FILE *out) {
struct item *new_item(int type, char *to, char *path, char *data, FILE *out)
{
struct item *p;
if(!(p = (struct item *)malloc(sizeof(struct item))))
die(NO_MEMORY,"add_icon",out);
if(!(p->msg = strdup(icon)))
die(NO_MEMORY,"add_icon",out);
if(!(p->fn = strdup(ext)))
die(NO_MEMORY,"add_icon",out);
die(NO_MEMORY,"new_item",out);
p->type = type;
if(data) {
if(!(p->data = strdup(data)))
die(NO_MEMORY,"new_item",out);
} else
p->data = NULL;
if(to) {
if(!(p->apply_to = (char *)malloc(strlen(to) + 2)))
die(NO_MEMORY,"new_item",out);
if((type == BY_PATH) && (!is_matchexp(to))) {
p->apply_to[0] = '*';
strcpy(&p->apply_to[1],to);
} else
strcpy(p->apply_to,to);
} else
p->apply_to = NULL;
if(!(p->apply_path = (char *)malloc(strlen(path) + 2)))
die(NO_MEMORY,"new_item",out);
sprintf(p->apply_path,"%s*",path);
return p;
}
void add_alt(int type, char *alt, char *to, char *path, FILE *out) {
struct item *p;
if(type == BY_PATH) {
if(!strcmp(to,"**DIRECTORY**"))
strcpy(to,"^^DIRECTORY^^");
}
p = new_item(type,to,path,alt,out);
p->next = alt_list;
alt_list = p;
}
void add_icon(int type, char *icon, char *to, char *path, FILE *out) {
struct item *p;
char iconbak[MAX_STRING_LEN];
strcpy(iconbak,icon);
if(icon[0] == '(') {
char alt[MAX_STRING_LEN];
getword(alt,iconbak,',');
add_alt(type,&alt[1],to,path,out);
iconbak[strlen(iconbak) - 1] = '\0';
}
if(type == BY_PATH) {
if(!strcmp(to,"**DIRECTORY**"))
strcpy(to,"^^DIRECTORY^^");
}
p = new_item(type,to,path,iconbak,out);
p->next = icon_list;
icon_list = p;
}
char *find_icon(char *path) {
struct item *p = icon_list;
int pl, el;
pl = strlen(path);
while(p) {
el = strlen(p->fn);
if(el <= pl)
if(!strcmp(&path[pl - el],p->fn))
return p->msg;
p = p->next;
}
return NULL;
}
void add_desc(char *desc, char *ext, FILE *out) {
void add_desc(int type, char *desc, char *to, char *path, FILE *out) {
struct item *p;
if(!(p = (struct item *)malloc(sizeof(struct item))))
die(NO_MEMORY,"add_desc",out);
if(!(p->msg = strdup(desc)))
die(NO_MEMORY,"add_desc",out);
if(!(p->fn = strdup(ext)))
die(NO_MEMORY,"add_desc",out);
p = new_item(type,to,path,desc,out);
p->next = desc_list;
desc_list = p;
}
char *find_desc(char *path) {
struct item *p = desc_list;
int pl, el;
void add_ignore(char *ext, char *path, FILE *out) {
struct item *p;
p = new_item(0,ext,path,NULL,out);
p->next = ign_list;
ign_list = p;
}
void add_header(char *name, char *path, FILE *out) {
struct item *p;
p = new_item(0,NULL,path,name,out);
p->next = hdr_list;
hdr_list = p;
}
void add_readme(char *name, char *path, FILE *out) {
struct item *p;
p = new_item(0,NULL,path,name,out);
p->next = rdme_list;
rdme_list = p;
}
void add_opts_int(int opts, char *path, FILE *out) {
struct item *p;
p = new_item(0,NULL,path,NULL,out);
p->type = opts;
p->next = opts_list;
opts_list = p;
}
void add_opts(char *optstr, char *path, FILE *out) {
char w[MAX_STRING_LEN];
int opts = 0;
while(optstr[0]) {
cfg_getword(w,optstr);
if(!strcasecmp(w,"FancyIndexing"))
opts |= FANCY_INDEXING;
else if(!strcasecmp(w,"IconsAreLinks"))
opts |= ICONS_ARE_LINKS;
else if(!strcasecmp(w,"ScanHTMLTitles"))
opts |= SCAN_HTML_TITLES;
else if(!strcasecmp(w,"None"))
opts = 0;
}
add_opts_int(opts,path,out);
}
char *find_item(struct item *list, char *path, int path_only) {
struct item *p = list;
char *t;
pl = strlen(path);
while(p) {
el = strlen(p->fn);
if(el <= pl)
if(!strcmp(&path[pl - el],p->fn))
return p->msg;
/* Special cased for ^^DIRECTORY^^ and ^^BLANKICON^^ */
if((path[0] == '^') || (!strcmp_match(path,p->apply_path))) {
if(!(p->apply_to))
return p->data;
else if(p->type == BY_PATH) {
if(!strcmp_match(path,p->apply_to))
return p->data;
} else if(!path_only) {
char pathbak[MAX_STRING_LEN];
strcpy(pathbak,path);
content_encoding[0] = '\0';
set_content_type(pathbak);
if(!content_encoding[0]) {
if(p->type == BY_TYPE) {
if(!strcmp_match(content_type,p->apply_to))
return p->data;
}
} else {
if(p->type == BY_ENCODING) {
if(!strcmp_match(content_encoding,p->apply_to))
return p->data;
}
}
}
}
p = p->next;
}
return NULL;
}
void add_ignore(char *ext,FILE *out) {
struct item *p;
#define find_icon(p,t) find_item(icon_list,p,t)
#define find_alt(p) find_item(alt_list,p,0)
#define find_desc(p) find_item(desc_list,p,0)
#define find_header(p) find_item(hdr_list,p,0)
#define find_readme(p) find_item(rdme_list,p,0)
if(!(p = (struct item *)malloc(sizeof(struct item))))
die(NO_MEMORY,"add_ignore",out);
p->msg = NULL;
if(!(p->fn = strdup(ext)))
die(NO_MEMORY,"add_ignore",out);
p->next = ign_list;
ign_list = p;
}
int ignore_entry(char *path) {
struct item *p;
int pl,el;
struct item *p = ign_list;
pl = strlen(path);
p = ign_list;
while(p) {
el = strlen(p->fn);
if(el <= pl)
if(!strcmp(&path[pl - el],p->fn))
if(!strcmp_match(path,p->apply_path))
if(!strcmp_match(path,p->apply_to))
return 1;
p = p->next;
}
return 0;
}
void insert_readme(char *name, FILE *fd) {
int find_opts(char *path) {
struct item *p = opts_list;
while(p) {
if(!strcmp_match(path,p->apply_path))
return p->type;
p = p->next;
}
return 0;
}
int insert_readme(char *name, char *readme_fname, int rule, FILE *fd) {
char fn[MAX_STRING_LEN];
FILE *r;
struct stat finfo;
int plaintext=0;
if(!readme_fname[0])
return;
make_full_path(name,readme_fname,fn);
strcat(fn,".html");
if(stat(fn,&finfo) == -1) {
fn[strlen(fn)-5] = '\0';
if(stat(fn,&finfo) == -1)
return;
return 0;
plaintext=1;
fprintf(fd,"<HR><PRE>%c",LF);
if(rule) bytes_sent += fprintf(fd,"<HR>%c",LF);
bytes_sent += fprintf(fd,"<PRE>%c",LF);
}
else fprintf(fd,"<HR>");
else if(rule) bytes_sent += fprintf(fd,"<HR>%c",LF);
if(!(r = fopen(fn,"r")))
return;
send_fd(r,fd,"");
return 0;
send_fd(r,fd,NULL);
fclose(r);
if(plaintext)
fprintf(fd,"</PRE>%c",LF);
bytes_sent += fprintf(fd,"</PRE>%c",LF);
return 1;
}
char *find_title(char *filename) {
char titlebuf[MAX_STRING_LEN], *find = "<TITLE>";
char filebak[MAX_STRING_LEN];
FILE *thefile;
int x,n,p;
content_encoding[0] = '\0';
strcpy(filebak,filename);
set_content_type(filebak);
if((!strcmp(content_type,"text/html")) && (!content_encoding[0])) {
if(!(thefile = fopen(filename,"r")))
return NULL;
n = fread(titlebuf,sizeof(char),MAX_STRING_LEN - 1,thefile);
titlebuf[n] = '\0';
for(x=0,p=0;titlebuf[x];x++) {
if(titlebuf[x] == find[p]) {
if(!find[++p]) {
if((p = ind(&titlebuf[++x],'<')) != -1)
titlebuf[x+p] = '\0';
return strdup(&titlebuf[x]);
}
} else p=0;
}
return NULL;
}
content_encoding[0] = '\0';
return NULL;
}
struct ent *make_dir_entry(char *path, char *name, FILE *out) {
struct ent *p;
struct stat finfo;
char t[MAX_STRING_LEN];
char t[MAX_STRING_LEN], t2[MAX_STRING_LEN];
if((name[0] == '.') && (!name[1]))
return(NULL);
make_full_path(path,name,t);
if(ignore_entry(t))
return(NULL);
if(!(p=(struct ent *)malloc(sizeof(struct ent))))
die(NO_MEMORY,"make_dir_entry",out);
if(!(p->name=strdup(name)))
if(!(p->name=(char *)malloc(strlen(name) + 2)))
die(NO_MEMORY,"make_dir_entry",out);
if(fancy_indexing) {
p->icon = find_icon(t);
if((!fancy_indexing) || stat(t,&finfo) == -1) {
if(dir_opts & FANCY_INDEXING) {
p->alt = find_alt(t);
if((!(dir_opts & FANCY_INDEXING)) || stat(t,&finfo) == -1) {
strcpy(p->name,name);
p->size = -1;
p->icon = NULL;
p->desc = NULL;
p->lm = -1;
}
else {
p->lm = finfo.st_mtime;
if(S_ISDIR(finfo.st_mode)) {
if(!p->icon)
p->icon = find_icon("**DIRECTORY**");
if(!(p->icon = find_icon(t,1)))
p->icon = find_icon("^^DIRECTORY^^",1);
p->alt = "DIR";
p->size = -1;
strcpy_dir(p->name,name);
}
else
else {
p->icon = find_icon(t,0);
p->size = finfo.st_size;
strcpy(p->name,name);
}
}
p->desc = find_desc(t);
if(p->desc = find_desc(t))
p->desc = strdup(p->desc);
if((!p->desc) && (dir_opts & SCAN_HTML_TITLES))
p->desc = find_title(t);
}
else {
p->icon = NULL;
p->alt = NULL;
p->desc = NULL;
p->size = -1;
p->lm = -1;
strcpy(p->name,name);
}
return(p);
}
void send_size(size_t size, FILE *fd) {
char schar;
if(size == -1) {
fputs(" -",fd);
bytes_sent += 5;
}
else {
if(!size) {
fputs(" 0K",fd);
bytes_sent += 5;
}
else if(size < 1024) {
fputs(" 1K",fd);
bytes_sent += 5;
}
else if(size < 1048576)
bytes_sent += fprintf(fd,"%4dK",size / 1024);
else
bytes_sent += fprintf(fd,"%4dM",size / 1048576);
}
}
void output_directories(struct ent **ar,int n,char *name,FILE *fd)
{
int x;
char blorf[MAX_STRING_LEN];
int x,pad;
char anchor[HUGE_STRING_LEN],t[MAX_STRING_LEN],t2[MAX_STRING_LEN];
char *tp;
if(name[0] == '\0') {
name[0] = '/'; name[1] = '\0';
}
/* aaaaargh Solaris sucks. */
fflush(fd);
if(dir_opts & FANCY_INDEXING) {
fputs("<PRE>",fd);
bytes_sent += 5;
if(tp = find_icon("^^BLANKICON^^",1))
bytes_sent += fprintf(fd,"<IMG SRC=\"%s\" ALT=\" \"> ",tp);
bytes_sent += fprintf(fd,
"Name Last modified Size Description%c<HR>%c",LF,LF);
}
else {
fputs("<UL>",fd);
bytes_sent += 4;
}
for(x=0;x<n;x++) {
fprintf(fd,"<%s>%c",(fancy_indexing ? "DD" : "LI"),LF);
if(fancy_indexing && ((ar[x]->icon) || default_icon[0])) {
fprintf(fd,"<IMG SRC=\"%s\"> ",
ar[x]->icon ? ar[x]->icon : default_icon);
}
if(strcmp(ar[x]->name,"..")) {
make_full_path(name,ar[x]->name,blorf);
escape_url(blorf);
fprintf(fd,"<A NAME=\"%s\" HREF=\"%s\">%s</A>",ar[x]->name,
blorf,ar[x]->name);
if((!strcmp(ar[x]->name,"../")) || (!strcmp(ar[x]->name,".."))) {
make_full_path(name,"..",t);
getparents(t);
if(t[0] == '\0') {
t[0] = '/'; t[1] = '\0';
}
sprintf(anchor,"<A HREF=\"%s\">",t);
strcpy(t2,"Parent Directory</A>");
}
else {
make_full_path(name,"..",blorf);
getparents(blorf);
if(blorf[0] == '\0') {
blorf[0] = '/'; blorf[1] = '\0';
strcpy(t,ar[x]->name);
strcpy(t2,t);
if(strlen(t2) > 21) {
t2[21] = '>';
t2[22] = '\0';
}
escape_url(blorf);
fprintf(fd,"<A HREF=\"%s\">%s</A>",blorf,"Parent Directory");
strcat(t2,"</A>");
escape_url(t);
sprintf(anchor,"<A NAME=\"%s\" HREF=\"%s\">",t,t);
}
if(fancy_indexing) {
if(ar[x]->desc)
fprintf(fd," : %s",ar[x]->desc,LF);
if(ar[x]->size != -1)
fprintf(fd," (%d bytes)",ar[x]->size);
escape_url(t);
if(dir_opts & FANCY_INDEXING) {
if(dir_opts & ICONS_ARE_LINKS)
bytes_sent += fprintf(fd,"%s",anchor);
if((ar[x]->icon) || default_icon[0]) {
bytes_sent += fprintf(fd,"<IMG SRC=\"%s\" ALT=\"[%s]\">",
ar[x]->icon ? ar[x]->icon : default_icon,
ar[x]->alt ? ar[x]->alt : " ");
}
if(dir_opts & ICONS_ARE_LINKS) {
fputs("</A>",fd);
bytes_sent += 4;
}
bytes_sent += fprintf(fd," %s",anchor);
bytes_sent += fprintf(fd,"%-27.27s",t2);
if(ar[x]->lm != -1) {
struct tm *ts = localtime(&ar[x]->lm);
strftime(t,MAX_STRING_LEN,"%d-%h-%y %H:%M ",ts);
fputs(t,fd);
bytes_sent += strlen(t);
}
else {
fputs(" ",fd);
bytes_sent += 17;
}
send_size(ar[x]->size,fd);
fputs(" ",fd);
bytes_sent += 2;
if(ar[x]->desc) {
if(strlen(ar[x]->desc) > 23) {
ar[x]->desc[23] = '>';
ar[x]->desc[24] = '\0';
}
bytes_sent += fprintf(fd,"%s",ar[x]->desc);
}
}
else
bytes_sent += fprintf(fd,"<LI> %s %s",anchor,t2);
fputc(LF,fd);
++bytes_sent;
}
if(dir_opts & FANCY_INDEXING) {
fputs("</PRE>",fd);
bytes_sent += 6;
}
else {
fputs("</UL>",fd);
bytes_sent += 5;
}
}
int dsortf(struct ent **s1,struct ent **s2)
{
return(strcmp((*s1)->name,(*s2)->name));
@ -256,26 +513,33 @@ void index_directory(char *name, FILE *fd)
struct ent *head,*p,*q;
struct ent **ar;
char unmunged_name[MAX_STRING_LEN];
char *tmp;
strcpy(unmunged_name,name);
strcpy_dir(unmunged_name,name);
unmunge_name(unmunged_name);
if(!(d=opendir(name)))
die(FORBIDDEN,unmunged_name,fd);
strcpy(content_type,"text/html");
status = 200;
if(!assbackwards)
send_http_header(fd);
if(header_only) return;
/* Spew HTML preamble */
fprintf(fd,"<HEAD><TITLE>Index of %s</TITLE></HEAD>",unmunged_name);
fputc(LF,fd);
fprintf(fd,"<BODY><H1>Index of %s</H1>",unmunged_name);
fputc(LF,fd);
bytes_sent = 0;
fprintf(fd,fancy_indexing ? "<DL>%c" : "<UL>%c",LF);
dir_opts = find_opts(name);
/* Spew HTML preamble */
bytes_sent += fprintf(fd,"<HEAD><TITLE>Index of %s</TITLE></HEAD><BODY>",
unmunged_name);
fputc(LF,fd);
++bytes_sent;
if((!(tmp = find_header(name))) || (!(insert_readme(name,tmp,0,fd))))
bytes_sent += fprintf(fd,"<H1>Index of %s</H1>%c",unmunged_name,LF);
/*
* Since we don't know how many dir. entries there are, put them into a
@ -310,12 +574,21 @@ void index_directory(char *name, FILE *fd)
while(q) {
p=q->next;
free(q->name);
if(q->desc)
free(q->desc);
free(q);
q=p;
}
closedir(d);
fprintf(fd,fancy_indexing ? "</DL>" : "</UL>");
if(fancy_indexing)
insert_readme(name,fd);
fprintf(fd,"</BODY>");
if(dir_opts & FANCY_INDEXING)
if(tmp = find_readme(name))
insert_readme(name,tmp,1,fd);
else {
fputs("</UL>",fd);
bytes_sent += 5;
}
fputs("</BODY>",fd);
bytes_sent += 7;
log_transaction();
}

View File

@ -5,8 +5,6 @@
*
*/
#include "httpd.h"
@ -16,34 +14,106 @@ int allow;
char allow_options;
void send_file(char *file, FILE *fd, char *args) {
void send_file(char *file, FILE *fd, char *path_args, char *args) {
FILE *f;
struct stat finfo;
set_content_type(file);
if((allow_options & OPT_INCLUDES) &&
(!strcmp(content_type,INCLUDES_MAGIC_TYPE)) &&
(!content_encoding[0]))
{
status = 200;
bytes_sent = 0;
send_parsed_file(file,fd,path_args,args,
allow_options & OPT_INCNOEXEC);
log_transaction();
return;
}
if(!(f=fopen(file,"r"))) {
log_reason("file permissions deny server access",file);
unmunge_name(file);
die(FORBIDDEN,file,fd); /* we've already established that it exists */
}
set_content_type(file);
status = 200;
bytes_sent = 0;
if(!assbackwards) {
fstat(fileno(f),&finfo);
if(!((allow_options & OPT_INCLUDES) && is_content_type("text/html")))
set_content_length(finfo.st_size);
set_last_modified(finfo.st_mtime);
set_content_length(finfo.st_size);
set_last_modified(finfo.st_mtime,fd);
send_http_header(fd);
}
num_includes=0;
if(!header_only)
send_fd(f,fd,args);
send_fd(f,fd,NULL);
log_transaction();
fclose(f);
}
void send_cgi(char *method, char *file, char *path_args, char *args,
struct stat *finfo, int in, FILE *fd)
{
char **env;
int m;
void send_node(char *file, char *args, FILE *fd)
if((!strcmp(method,"GET")) || (!strcmp(method,"HEAD")))
m = M_GET;
else if(!strcmp(method,"POST"))
m = M_POST;
else if(!strcmp(method,"PUT"))
m = M_PUT;
else if(!strcmp(method,"DELETE"))
m = M_DELETE;
evaluate_access(file,finfo,m,&allow,&allow_options,fd);
if((!allow) || (!(allow_options & OPT_EXECCGI))) {
log_reason("client denied by server configuration",file);
unmunge_name(file);
die(FORBIDDEN,file,fd);
}
if(!(env = add_common_vars(in_headers_env,fd)))
die(NO_MEMORY,"send_cgi",fd);
bytes_sent = 0;
if(cgi_stub(method,file,path_args,args,env,finfo,in,fd) == REDIRECT_URL)
die(REDIRECT,location,fd);
free_env(env);
log_transaction();
}
void send_node(char *file, char *args, int in, FILE *fd)
{
struct stat finfo;
char pa[MAX_STRING_LEN];
pa[0] = '\0';
if(stat(file,&finfo) == -1) {
/* Look for script or include document */
int n=count_dirs(file),i,l;
char t[MAX_STRING_LEN];
for(i=n;i;--i) {
make_dirstr(file,i,t);
probe_content_type(t);
if(!strcmp(content_type,CGI_MAGIC_TYPE)) {
if(stat(t,&finfo) == -1)
continue;
if(!(S_ISREG(finfo.st_mode)))
break;
l=strlen(t);
strcpy(pa,&file[l]);
file[l] = '\0';
send_cgi("GET",file,pa,args,&finfo,in,fd);
return;
} else if(!strcmp(content_type,INCLUDES_MAGIC_TYPE)) {
if(stat(t,&finfo) == -1)
continue;
l=strlen(t);
strcpy(pa,&file[l]);
file[l] = '\0';
goto send_regular;
}
}
if(errno==ENOENT) {
log_reason("file does not exist",file);
unmunge_name(file);
@ -55,6 +125,13 @@ void send_node(char *file, char *args, FILE *fd)
die(FORBIDDEN,file,fd);
}
}
probe_content_type(file);
if(S_ISREG(finfo.st_mode) && (!strcmp(content_type,CGI_MAGIC_TYPE))) {
send_cgi("GET",file,"",args,&finfo,in,fd);
return;
}
send_regular: /* aaaaack */
evaluate_access(file,&finfo,M_GET,&allow,&allow_options, fd);
if(!allow) {
log_reason("client denied by server configuration",file);
@ -65,6 +142,13 @@ void send_node(char *file, char *args, FILE *fd)
if(S_ISDIR(finfo.st_mode)) {
char ifile[MAX_STRING_LEN];
if(file[strlen(file) - 1] != '/') {
char url[MAX_STRING_LEN];
strcpy_dir(ifile,file);
unmunge_name(ifile);
construct_url(url,ifile);
die(REDIRECT,url,fd);
}
make_full_path(file,index_name,ifile);
if(stat(ifile,&finfo) == -1) {
if(allow_options & OPT_INDEXES)
@ -76,19 +160,16 @@ void send_node(char *file, char *args, FILE *fd)
}
}
else {
if(file[strlen(file) - 1] != '/') {
char url[MAX_STRING_LEN];
strcpy_dir(ifile,file);
unmunge_name(ifile);
construct_url(url,ifile);
die(REDIRECT,url,fd);
}
send_file(ifile,fd,args);
probe_content_type(ifile);
if(!strcmp(content_type,CGI_MAGIC_TYPE))
send_cgi("GET",ifile,pa,args,&finfo,in,fd);
else
send_file(ifile,fd,pa,args);
}
return;
}
if(S_ISREG(finfo.st_mode))
send_file(file,fd,args);
send_file(file,fd,pa,args);
else {
log_reason("improper file type",file);
unmunge_name(file);
@ -106,12 +187,12 @@ void process_get(int in, FILE *out, char *m, char *url, char *args) {
s=translate_name(url,out);
switch(s) {
case STD_DOCUMENT:
send_node(url,args,out);
send_node(url,args,in,out);
return;
case REDIRECT_URL:
die(REDIRECT,url,out);
case SCRIPT_NCSA:
exec_get_NCSA(url,args,out);
exec_get_NCSA(url,args,in,out);
return;
case SCRIPT_CGI:
exec_cgi_script(m,url,args,in,out);

619
src/http_include.c Normal file
View File

@ -0,0 +1,619 @@
/*
* http_include.c: Handles the server-parsed HTML documents
*
* Rob McCool
*
*/
#include "httpd.h"
#define STARTING_SEQUENCE "<!--#"
#define ENDING_SEQUENCE "-->"
#define DEFAULT_ERROR_MSG "[an error occurred while processing this directive]"
#define DEFAULT_TIME_FORMAT "%A, %d-%h-%y %T %Z"
#define SIZEFMT_BYTES 0
#define SIZEFMT_KMG 1
/* These are stored statically so that they can be reformatted quickly */
static time_t date,lm;
/* ------------------------ Environment function -------------------------- */
#define NUM_INCLUDE_VARS 5
char **add_include_vars(char **env,char *file, char *path_args, char *args,
char *timefmt,FILE *out)
{
int x;
struct stat finfo;
char ufile[HUGE_STRING_LEN];
char *t;
if(!(env = new_env(env,NUM_INCLUDE_VARS,&x)))
die(NO_MEMORY,"add_include_vars",out);
date = time(NULL);
env[x++] = make_env_str("DATE_LOCAL",ht_time(date,timefmt,0),out);
env[x++] = make_env_str("DATE_GMT",ht_time(date,timefmt,1),out);
if(stat(file,&finfo) != -1) {
lm = finfo.st_mtime;
env[x++] = make_env_str("LAST_MODIFIED",ht_time(lm,timefmt,1),out);
}
strcpy(ufile,file);
unmunge_name(ufile);
env[x++] = make_env_str("DOCUMENT_URI",ufile,out);
if(t = strrchr(ufile,'/'))
++t;
else
t = ufile;
env[x++] = make_env_str("DOCUMENT_NAME",t,out);
env[x] = NULL;
return env;
}
#define GET_CHAR(f,c,r) \
{ \
int i = getc(f); \
if(feof(f) || ferror(f) || (i == -1)) { \
fclose(f); \
return r; \
} \
c = (char)i; \
}
/* --------------------------- Parser functions --------------------------- */
int find_string(FILE *in,char *str, FILE *out) {
int x,l=strlen(str),p;
char c;
p=0;
while(1) {
GET_CHAR(in,c,1);
if(c == str[p]) {
if((++p) == l)
return 0;
}
else {
if(out) {
if(p) {
for(x=0;x<p;x++) {
putc(str[x],out);
++bytes_sent;
}
}
putc(c,out);
++bytes_sent;
}
p=0;
}
}
}
char *get_tag(FILE *in, char *tag) {
char *t = tag, *tag_val, c;
int n;
n = 0;
while(1) {
GET_CHAR(in,c,NULL);
if(!isspace(c)) break;
}
/* problem: this drops tags starting with - or -- (tough s***) */
if(c == '-') {
GET_CHAR(in,c,NULL);
if(c == '-') {
GET_CHAR(in,c,NULL);
if(c == '>') {
strcpy(tag,"done");
return tag;
}
}
}
/* this parser is very rigid, needs quotes around value and no spaces */
while(1) {
if(++n == MAX_STRING_LEN) {
t[MAX_STRING_LEN - 1] = '\0';
return NULL;
}
if((*t = c) == '\\') {
GET_CHAR(in,c,NULL);
*t = c;
} else if(*t == '=') {
*t++ = '\0';
tag_val = t;
GET_CHAR(in,c,NULL);
if(c == '\"') {
while(1) {
GET_CHAR(in,c,NULL);
if(++n == MAX_STRING_LEN) {
t[MAX_STRING_LEN - 1] = '\0';
return NULL;
}
if((*t = c) == '\\') {
GET_CHAR(in,c,NULL);
*t = c;
} else if(*t == '\"') {
*t = '\0';
return tag_val;
}
++t;
}
} else
return NULL;
}
++t;
GET_CHAR(in,c,NULL);
}
}
int get_directive(FILE *in,char *d) {
char c;
/* skip initial whitespace */
while(1) {
GET_CHAR(in,c,1);
if(!isspace(c))
break;
}
/* now get directive */
while(1) {
*d++ = c;
GET_CHAR(in,c,1);
if(isspace(c))
break;
}
*d = '\0';
return 0;
}
/* --------------------------- Action handlers ---------------------------- */
int send_included_file(char *file, FILE *out, char *fn) {
FILE *f;
struct stat finfo;
int allow;char op,i;
if(stat(file,&finfo) == -1)
return -1;
evaluate_access(file,&finfo,M_GET,&allow,&op,out);
if(!allow)
return -1;
set_content_type(file);
if((op & OPT_INCLUDES) && (!strcmp(content_type,INCLUDES_MAGIC_TYPE))) {
send_parsed_file(file,out,"","",op & OPT_INCNOEXEC);
chdir_file(fn); /* grumble */
}
else if(!strcmp(content_type,CGI_MAGIC_TYPE))
return -1;
else {
if(!(f=fopen(file,"r")))
return -1;
send_fd(f,out,NULL);
fclose(f);
}
return 0;
}
int handle_include(FILE *in, FILE *out, char *fn, char *error) {
char tag[MAX_STRING_LEN],errstr[MAX_STRING_LEN];
char *tag_val;
while(1) {
if(!(tag_val = get_tag(in,tag)))
return 1;
if(!strcmp(tag,"file")) {
char dir[MAX_STRING_LEN],to_send[MAX_STRING_LEN];
getparents(tag_val); /* get rid of any nasties */
getwd(dir);
make_full_path(dir,tag_val,to_send);
if(send_included_file(to_send,out,fn)) {
sprintf(errstr,"unable to include %s in parsed file %s",
tag_val, fn);
log_error_noclose(errstr);
bytes_sent += fprintf(out,"%s",error);
}
}
else if(!strcmp(tag,"virtual")) {
if(translate_name(tag_val,out) != STD_DOCUMENT) {
bytes_sent += fprintf(out,"%s",error);
log_error_noclose(errstr);
}
else if(send_included_file(tag_val,out,fn)) {
sprintf(errstr,"unable to include %s in parsed file %s",
tag_val, fn);
log_error_noclose(errstr);
bytes_sent += fprintf(out,"%s",error);
}
}
else if(!strcmp(tag,"done"))
return 0;
else {
sprintf(errstr,"unknown parameter %s to tag echo in %s",tag,fn);
log_error_noclose(errstr);
bytes_sent += fprintf(out,"%s",error);
}
}
}
int handle_echo(FILE *in, FILE *out, char *file, char *error, char **env) {
char tag[MAX_STRING_LEN];
char *tag_val;
while(1) {
if(!(tag_val = get_tag(in,tag)))
return 1;
if(!strcmp(tag,"var")) {
int x,i;
for(x=0;env[x] != NULL; x++) {
i = ind(env[x],'=');
if(!strncmp(env[x],tag_val,i)) {
bytes_sent += fprintf(out,"%s",&env[x][i+1]);
break;
}
}
if(!env[x]) bytes_sent += fprintf(out,"(none)");
} else if(!strcmp(tag,"done"))
return 0;
else {
char errstr[MAX_STRING_LEN];
sprintf(errstr,"unknown parameter %s to tag echo in %s",tag,file);
log_error_noclose(errstr);
bytes_sent += fprintf(out,"%s",error);
}
}
}
int include_cgi(char *s, char *pargs, char *args, char **env, FILE *out)
{
char *argp,op,d[HUGE_STRING_LEN];
int allow,check_cgiopt;
struct stat finfo;
getparents(s);
if(s[0] == '/') {
strcpy(d,s);
if(translate_name(d,out) != SCRIPT_CGI)
return -1;
check_cgiopt=0;
} else {
char dir[MAX_STRING_LEN];
getwd(dir);
make_full_path(dir,s,d);
check_cgiopt=1;
}
/* No hardwired path info or query allowed */
if(stat(d,&finfo) == -1)
return -1;
evaluate_access(d,&finfo,M_GET,&allow,&op,out);
if((!allow) || (check_cgiopt && (!(op & OPT_EXECCGI))))
return -1;
if(cgi_stub("GET",d,pargs,args,env,&finfo,-1,out) == REDIRECT_URL)
bytes_sent += fprintf(out,"<A HREF=\"%s\">%s</A>",location,location);
return 0;
}
static int ipid;
void kill_include_child() {
char errstr[MAX_STRING_LEN];
sprintf(errstr,"killing command process %d",ipid);
log_error_noclose(errstr);
kill(ipid,SIGKILL);
waitpid(ipid,NULL,0);
}
int include_cmd(char *s, char *pargs, char *args, char **env, FILE *out) {
int p[2],x;
FILE *f;
if(pipe(p) == -1)
die(SERVER_ERROR,"httpd: could not create IPC pipe",out);
if((ipid = fork()) == -1)
die(SERVER_ERROR,"httpd: could not fork new process",out);
if(!ipid) {
char *argv0;
if(pargs[0] || args[0]) {
if(!(env = new_env(env,4,&x)))
return -1;
if(pargs[0]) {
char p2[HUGE_STRING_LEN];
escape_shell_cmd(pargs);
env[x++] = make_env_str("PATH_INFO",pargs,out);
strcpy(p2,pargs);
translate_name(p2,out);
env[x++] = make_env_str("PATH_TRANSLATED",p2,out);
}
if(args[0]) {
env[x++] = make_env_str("QUERY_STRING",args,out);
unescape_url(args);
escape_shell_cmd(args);
env[x++] = make_env_str("QUERY_STRING_UNESCAPED",args,out);
}
env[x] = NULL;
}
close(p[0]);
if(p[1] != STDOUT_FILENO) {
dup2(p[1],STDOUT_FILENO);
close(p[1]);
}
error_log2stderr();
if(!(argv0 = strrchr(SHELL_PATH,'/')))
argv0=SHELL_PATH;
if(execle(SHELL_PATH,argv0,"-c",s,(char *)0,env) == -1) {
fprintf(stderr,"httpd: exec of %s failed, errno is %d\n",
SHELL_PATH,errno);
exit(1);
}
}
close(p[1]);
if(!(f=fdopen(p[0],"r"))) {
waitpid(ipid,NULL,0);
return -1;
}
send_fd(f,out,kill_include_child);
fclose(f);
waitpid(ipid,NULL,0);
return 0;
}
int handle_exec(FILE *in, FILE *out, char *file, char *path_args, char *args,
char *error, char **env)
{
char tag[MAX_STRING_LEN],errstr[MAX_STRING_LEN];
char *tag_val;
while(1) {
if(!(tag_val = get_tag(in,tag)))
return 1;
if(!strcmp(tag,"cmd")) {
if(include_cmd(tag_val,path_args,args,env,out) == -1) {
sprintf(errstr,"invalid command exec %s in %s",tag_val,file);
log_error_noclose(errstr);
bytes_sent += fprintf(out,"%s",error);
}
/* just in case some stooge changed directories */
chdir_file(file);
}
else if(!strcmp(tag,"cgi")) {
if(include_cgi(tag_val,path_args,args,env,out) == -1) {
sprintf(errstr,"invalid CGI ref %s in %s",tag_val,file);
log_error_noclose(errstr);
bytes_sent += fprintf(out,"%s",error);
}
/* grumble groan */
chdir_file(file);
}
else if(!strcmp(tag,"done"))
return 0;
else {
char errstr[MAX_STRING_LEN];
sprintf(errstr,"unknown parameter %s to tag echo in %s",tag,file);
log_error_noclose(errstr);
bytes_sent += fprintf(out,"%s",error);
}
}
}
int handle_config(FILE *in, FILE *out, char *file, char *error, char *tf,
int *sizefmt, char **env) {
char tag[MAX_STRING_LEN];
char *tag_val;
while(1) {
if(!(tag_val = get_tag(in,tag)))
return 1;
if(!strcmp(tag,"errmsg"))
strcpy(error,tag_val);
else if(!strcmp(tag,"timefmt")) {
strcpy(tf,tag_val);
/* Replace DATE* and LAST_MODIFIED (they should be first) */
free(env[0]);
env[0] = make_env_str("DATE_LOCAL",ht_time(date,tf,0),out);
free(env[1]);
env[1] = make_env_str("DATE_GMT",ht_time(date,tf,1),out);
if(!strncmp(env[2],"LAST_MODIFIED",13)) {
free(env[2]);
env[2] = make_env_str("LAST_MODIFIED",ht_time(lm,tf,1),out);
}
}
else if(!strcmp(tag,"sizefmt")) {
if(!strcmp(tag_val,"bytes"))
*sizefmt = SIZEFMT_BYTES;
else if(!strcmp(tag_val,"abbrev"))
*sizefmt = SIZEFMT_KMG;
}
else if(!strcmp(tag,"done"))
return 0;
else {
char errstr[MAX_STRING_LEN];
sprintf(errstr,"unknown parameter %s to tag config in %s",
tag,file);
log_error_noclose(errstr);
bytes_sent += fprintf(out,"%s",error);
}
}
}
int find_file(FILE *out, char *file, char *directive, char *tag,
char *tag_val, struct stat *finfo, char *error)
{
char errstr[MAX_STRING_LEN], dir[MAX_STRING_LEN], to_send[MAX_STRING_LEN];
if(!strcmp(tag,"file")) {
getparents(tag_val); /* get rid of any nasties */
getwd(dir);
make_full_path(dir,tag_val,to_send);
if(stat(to_send,finfo) == -1) {
sprintf(errstr,
"unable to get information about %s in parsed file %s",
to_send,file);
log_error_noclose(errstr);
bytes_sent += fprintf(out,"%s",error);
return -1;
}
return 0;
}
else if(!strcmp(tag,"virtual")) {
if(translate_name(tag_val,out) != STD_DOCUMENT) {
bytes_sent += fprintf(out,"%s",error);
log_error_noclose(errstr);
}
else if(stat(tag_val,finfo) == -1) {
sprintf(errstr,
"unable to get information about %s in parsed file %s",
to_send,file);
log_error_noclose(errstr);
bytes_sent += fprintf(out,"%s",error);
return -1;
}
return 0;
}
else {
sprintf(errstr,"unknown parameter %s to tag %s in %s",
tag,directive,file);
log_error_noclose(errstr);
bytes_sent += fprintf(out,"%s",error);
return -1;
}
}
int handle_fsize(FILE *in, FILE *out, char *file, char *error, int sizefmt,
char **env)
{
char tag[MAX_STRING_LEN];
char *tag_val;
struct stat finfo;
while(1) {
if(!(tag_val = get_tag(in,tag)))
return 1;
else if(!strcmp(tag,"done"))
return 0;
else if(!find_file(out,file,"fsize",tag,tag_val,&finfo,error)) {
if(sizefmt == SIZEFMT_KMG) {
send_size(finfo.st_size,out);
bytes_sent += 5;
}
else {
int l,x;
sprintf(tag,"%ld",finfo.st_size);
l = strlen(tag); /* grrr */
for(x=0;x<l;x++) {
if(x && (!((l-x) % 3))) {
fputc(',',out);
++bytes_sent;
}
fputc(tag[x],out);
++bytes_sent;
}
}
}
}
}
int handle_flastmod(FILE *in, FILE *out, char *file, char *error, char *tf,
char **env)
{
char tag[MAX_STRING_LEN];
char *tag_val;
struct stat finfo;
while(1) {
if(!(tag_val = get_tag(in,tag)))
return 1;
else if(!strcmp(tag,"done"))
return 0;
else if(!find_file(out,file,"flastmod",tag,tag_val,&finfo,error))
bytes_sent += fprintf(out,"%s",ht_time(finfo.st_mtime,tf,0));
}
}
/* -------------------------- The main function --------------------------- */
void send_parsed_file(char *file, FILE *fd, char *path_args, char *args,
int noexec)
{
char directive[MAX_STRING_LEN], error[MAX_STRING_LEN], c, **env;
char timefmt[MAX_STRING_LEN], errstr[MAX_STRING_LEN];
int ret, sizefmt;
FILE *f;
if(!(f=fopen(file,"r"))) {
log_reason("file permissions deny server access",file);
unmunge_name(file);
die(FORBIDDEN,file,fd);
}
strcpy(content_type,"text/html");
if(!assbackwards)
send_http_header(fd);
if(header_only)
return;
/* Make sure no children inherit our buffers */
fflush(fd);
assbackwards = 1; /* make sure no headers get inserted anymore */
alarm(timeout);
strcpy(error,DEFAULT_ERROR_MSG);
strcpy(timefmt,DEFAULT_TIME_FORMAT);
sizefmt = SIZEFMT_KMG;
chdir_file(file);
env = add_include_vars(in_headers_env,file,path_args,args,timefmt,fd);
env = add_common_vars(env,fd);
while(1) {
if(!find_string(f,STARTING_SEQUENCE,fd)) {
if(get_directive(f,directive))
goto bye;
if(!strcmp(directive,"exec")) {
if(noexec) {
sprintf(errstr,"httpd: exec used but not allowed in %s",
file);
log_error_noclose(errstr);
bytes_sent += fprintf(fd,"%s",error);
ret = find_string(f,ENDING_SEQUENCE,NULL);
} else
ret=handle_exec(f,fd,file,path_args,args,error,env);
}
else if(!strcmp(directive,"config"))
ret=handle_config(f,fd,file,error,timefmt,&sizefmt,env);
else if(!strcmp(directive,"include"))
ret=handle_include(f,fd,file,error);
else if(!strcmp(directive,"echo"))
ret=handle_echo(f,fd,file,error,env);
else if(!strcmp(directive,"fsize"))
ret=handle_fsize(f,fd,file,error,sizefmt,env);
else if(!strcmp(directive,"flastmod"))
ret=handle_flastmod(f,fd,file,error,timefmt,env);
else {
sprintf(errstr,"httpd: unknown directive %s in parsed doc %s",
directive,file);
log_error_noclose(errstr);
bytes_sent += fprintf(fd,"%s",error);
ret=find_string(f,ENDING_SEQUENCE,NULL);
}
if(ret) {
sprintf(errstr,"httpd: premature EOF in parsed file %s",file);
log_error_noclose(errstr);
goto bye;
}
} else
goto bye;
}
bye:
free_env(env);
}

View File

@ -8,7 +8,7 @@
#include "httpd.h"
static FILE *error_log;
FILE *error_log;
static FILE *xfer_log;
void open_logs() {
@ -18,9 +18,6 @@ void open_logs() {
perror("fopen");
exit(1);
}
/* Make sure nasty scripts or includes send errors here */
if(fileno(error_log) != STDERR_FILENO)
dup2(fileno(error_log),STDERR_FILENO);
if(!(xfer_log = fopen(xfer_fname,"a"))) {
fprintf(stderr,"httpd: could not open transfer log file %s.\n",
xfer_fname);
@ -32,7 +29,11 @@ void open_logs() {
void close_logs() {
fclose(xfer_log);
fclose(error_log);
fclose(stderr);
}
void error_log2stderr() {
if(fileno(error_log) != STDERR_FILENO)
dup2(fileno(error_log),STDERR_FILENO);
}
void log_pid() {
@ -46,13 +47,67 @@ void log_pid() {
fclose(pid_file);
}
void log_transaction(char *cmd_line) {
static char the_request[HUGE_STRING_LEN];
int status;
int bytes_sent;
void record_request(char *cmd_line) {
status = -1;
bytes_sent = -1;
strcpy(the_request,cmd_line);
#if 0
if(!do_rfc931)
fprintf(xfer_log, "%s [%s] %s\n", remote_name, get_time(), cmd_line);
else
fprintf(xfer_log, "%s@%s [%s] %s\n", remote_logname, remote_name,
get_time(), cmd_line);
fclose(xfer_log); /* we should be done with it... */
#endif
}
/* NEXT MUST DIE. */
static char *mon[] = {
"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"
};
void log_transaction() {
char str[HUGE_STRING_LEN];
long timz;
struct tm *t;
char tstr[MAX_STRING_LEN],sign;
t = get_gmtoff(&timz);
sign = (timz < 0 ? '-' : '+');
if(timz < 0)
timz = -timz;
sprintf(tstr,"%2d/%s/%4d:%2d:%2d:%2d",
t->tm_mday,mon[t->tm_mon],1900 + t->tm_year,
t->tm_hour,t->tm_min,t->tm_sec);
strftime(tstr,MAX_STRING_LEN,"%d/%h/%Y:%H:%M:%S",t);
sprintf(str,"%s %s %s [%s %c%02d%02d] \"%s\" ",
remote_name,
(do_rfc931 ? remote_logname : "-"),
(user[0] ? user : "-"),
tstr,
sign,
timz/3600,
timz%3600,
the_request);
if(status != -1)
sprintf(str,"%s%d ",str,status);
else
strcat(str,"- ");
if(bytes_sent != -1)
sprintf(str,"%s%d",str,bytes_sent);
else
strcat(str,"- ");
fprintf(xfer_log,"%s\n",str);
fclose(xfer_log);
}
void log_error(char *err) {
@ -60,6 +115,11 @@ void log_error(char *err) {
fclose(error_log);
}
void log_error_noclose(char *err) {
fprintf(error_log, "[%s] %s\n",get_time(),err);
fflush(error_log);
}
void log_reason(char *reason, char *file) {
char t[MAX_STRING_LEN];
@ -76,8 +136,7 @@ void begin_http_header(FILE *fd, char *msg) {
void error_head(FILE *fd, char *err) {
if(!assbackwards) {
begin_http_header(fd,err);
fprintf(fd,"Content-type: text/html%c",LF);
fprintf(fd,"%c",LF);
fprintf(fd,"Content-type: text/html%c%c",LF,LF);
}
if(!header_only) {
fprintf(fd,"<HEAD><TITLE>%s</TITLE></HEAD>%c",err,LF);
@ -95,6 +154,7 @@ void die(int type, char *err_string, FILE *fd) {
switch(type) {
case REDIRECT:
status = 302;
if(!assbackwards) {
begin_http_header(fd,"302 Found");
fprintf(fd,"Location: %s%c",err_string,LF);
@ -106,9 +166,17 @@ void die(int type, char *err_string, FILE *fd) {
fprintf(fd,"This document has moved <A HREF=\"%s\">here</A>.<P>%c",
err_string,LF);
break;
case USE_LOCAL_COPY:
status = USE_LOCAL_COPY;
begin_http_header(fd,"304 Not modified");
fputc(LF,fd);
header_only = 1;
break;
case AUTH_REQUIRED:
status = 401;
if(!assbackwards) {
begin_http_header(fd,"401 Unauthorized");
fprintf(fd,"Content-type: text/html%c",LF);
fprintf(fd,"WWW-Authenticate: %s%c%c",err_string,LF,LF);
}
if(header_only) break;
@ -117,6 +185,7 @@ void die(int type, char *err_string, FILE *fd) {
fprintf(fd,"authentication failed.%c",LF);
break;
case BAD_REQUEST:
status = 400;
error_head(fd,"400 Bad Request");
if(header_only) break;
fprintf(fd,"Your client sent a query that this server could not%c",LF);
@ -124,6 +193,7 @@ void die(int type, char *err_string, FILE *fd) {
fprintf(fd,"Reason: %s<P>%c",err_string,LF);
break;
case FORBIDDEN:
status = 403;
error_head(fd,"403 Forbidden");
if(header_only) break;
fprintf(fd,"Your client does not have permission to get URL %s ",
@ -131,12 +201,14 @@ void die(int type, char *err_string, FILE *fd) {
fprintf(fd,"from this server.<P>%c",LF);
break;
case NOT_FOUND:
status = 404;
error_head(fd,"404 Not Found");
if(header_only) break;
fprintf(fd,"The requested URL %s was not found on this server.<P>%c",
err_string,LF);
break;
case SERVER_ERROR:
status = 500;
error_head(fd,"500 Server Error");
log_error(err_string);
if(header_only)
@ -150,16 +222,8 @@ void die(int type, char *err_string, FILE *fd) {
fprintf(fd,"anything you might have done that may have caused%c",LF);
fprintf(fd,"the error.<P>%c",LF);
break;
case INCLUDE_ERROR:
/* error_head(fd,"500 Server Error"); */
log_error(err_string);
if(header_only) break;
fprintf(fd,"[we're sorry, the following error has occurred: %s]%c",
err_string,LF);
fflush(fd);
htexit(1,fd);
break;
case NOT_IMPLEMENTED:
status = 501;
error_head(fd,"501 Not Implemented");
if(header_only) break;
fprintf(fd,"We are sorry to be unable to perform the method %s",
@ -171,9 +235,18 @@ void die(int type, char *err_string, FILE *fd) {
SERVER_VERSION,LF);
fprintf(fd,"to <ADDRESS>%s</ADDRESS><P>%c",SERVER_SUPPORT,LF);
break;
case NO_MEMORY:
log_error("httpd: memory exhausted");
status = 500;
error_head(fd,"500 Server Error");
if(header_only) break;
fprintf(fd,"The server has temporarily run out of resources for%c",LF);
fprintf(fd,"your request. Please try again at a later time.<P>%c",LF);
break;
}
if(!header_only)
fprintf(fd,"</BODY>%c",LF);
fflush(fd);
log_transaction();
htexit(1,fd);
}

View File

@ -14,7 +14,11 @@ struct mime_ext {
struct mime_ext *next;
};
#if 0
#define hash(i) (isalpha(i) ? (tolower(i)) - 'a' : 26)
#else
#define hash(i) ((i) % 27)
#endif
/* Hash table */
struct mime_ext *types[27];
@ -23,14 +27,19 @@ struct mime_ext *encoding_types;
int content_length;
char content_type[MAX_STRING_LEN];
char content_encoding[MAX_STRING_LEN];
char location[MAX_STRING_LEN];
static char last_modified[MAX_STRING_LEN];
static char content_encoding[MAX_STRING_LEN];
char http_accept[HUGE_STRING_LEN];
char auth_line[MAX_STRING_LEN];
char *out_headers;
char **in_headers_env;
char *status_line;
char ims[MAX_STRING_LEN]; /* If-modified-since */
void hash_insert(struct mime_ext *me) {
register int i = hash(me->ext[0]);
register struct mime_ext *p, *q;
@ -151,7 +160,7 @@ int is_content_type(char *type) {
return(!strcmp(content_type,type));
}
void set_content_type(char *file) {
void find_ct(char *file, int store_encoding) {
int i,l,l2;
struct mime_ext *p;
char fn[MAX_STRING_LEN];
@ -165,10 +174,13 @@ void set_content_type(char *file) {
while(p) {
if(!strcmp(p->ext,&fn[i])) {
fn[i-1] = '\0';
if(content_encoding[0])
sprintf(content_encoding,"%s, %s",content_encoding,p->ct);
else
strcpy(content_encoding,p->ct);
if(store_encoding) {
if(content_encoding[0])
sprintf(content_encoding,"%s, %s",content_encoding,
p->ct);
else
strcpy(content_encoding,p->ct);
}
if((i=rind(fn,'.')) < 0)
break;
++i;
@ -208,20 +220,57 @@ void set_content_type(char *file) {
strcpy(content_type,default_type);
}
void probe_content_type(char *file) {
find_ct(file,0);
}
void set_content_type(char *file) {
find_ct(file,1);
}
int scan_script_header(FILE *f, FILE *fd) {
char l[MAX_STRING_LEN];
char w[MAX_STRING_LEN];
char *l;
int p;
while(1) {
if(getline(l,MAX_STRING_LEN,fileno(f),timeout))
if(getline(w,MAX_STRING_LEN-1,fileno(f),timeout))
die(SERVER_ERROR,"httpd: malformed header from script",fd);
if(l[0] == '\0') return is_url(location);
getword(w,l,':');
if(w[0] == '\0') return is_url(location);
if(!(l = strchr(w,':')))
l = w;
*l++ = '\0';
if(!strcasecmp(w,"Content-type"))
sscanf(l,"%s",content_type);
else if(!strcasecmp(w,"Location"))
sscanf(l,"%s",location);
else if(!strcasecmp(w,"Status")) {
for(p=0;isspace(l[p]);p++);
sscanf(&l[p],"%d",&status);
if(!(status_line = strdup(&l[p])))
die(NO_MEMORY,"scan_script_header",fd);
}
else {
*(--l) = ':';
for(p=0;w[p];p++);
w[p] = LF;
w[++p] = '\0';
if(!out_headers) {
if(!(out_headers = strdup(w)))
die(NO_MEMORY,"scan_script_header",fd);
}
else {
int loh = strlen(out_headers);
out_headers = (char *) realloc(out_headers,
(loh+strlen(w)+1)*sizeof(char));
if(!out_headers)
die(NO_MEMORY,"scan_script_header",fd);
strcpy(&out_headers[loh],w);
}
}
}
}
@ -257,41 +306,109 @@ void set_content_length(int l) {
content_length = l;
}
void set_last_modified(time_t t) {
void set_last_modified(time_t t, FILE *out) {
strcpy(last_modified,gm_timestr_822(t));
if(!ims[0])
return;
if(later_than(last_modified, ims))
die(USE_LOCAL_COPY,NULL,out);
}
void get_mime_headers(int fd) {
char l[MAX_STRING_LEN];
char w[MAX_STRING_LEN];
void init_header_vars() {
content_type[0] = '\0';
last_modified[0] = '\0';
content_length = -1;
auth_line[0] = '\0';
content_encoding[0] = '\0';
http_accept[0] = '\0';
location[0] = '\0';
ims[0] = '\0';
status_line = NULL;
out_headers = NULL;
in_headers_env = NULL;
}
while(!(getline(l,MAX_STRING_LEN,fd,timeout))) {
getword(w,l,':');
if(!strcasecmp(w,"Content-type"))
sscanf(l,"%s",content_type);
else if(!strcasecmp(w,"Authorization"))
strcpy(auth_line,l);
else if(!strcasecmp(w,"Content-length"))
sscanf(l,"%d",&content_length);
else if(!strcasecmp(w,"Accept")) {
if(http_accept[0])
sprintf(http_accept,"%s, %s%c",http_accept,l,'\0');
else
strcpy(http_accept,l);
int merge_header(char *h, char *v, FILE *out) {
register int x,l,lt;
char **t;
for(l=0;h[l];++l);
h[l] = '=';
h[++l] = '\0';
for(t=in_headers_env;*t;++t) {
if(!strncmp(*t,h,l)) {
lt = strlen(*t);
if(!(*t = (char *) realloc(*t,(lt+strlen(v)+3)*sizeof(char))))
die(NO_MEMORY,"merge_header",out);
(*t)[lt++] = ',';
(*t)[lt++] = ' ';
strcpy(&((*t)[lt]),v);
return 1;
}
else if(!l[0])
}
h[l-1] = '\0';
return 0;
}
void get_mime_headers(int fd, FILE *out) {
char w[MAX_STRING_LEN];
char l[MAX_STRING_LEN];
int num_inh, num_processed;
char *t;
num_inh = 0;
num_processed = 0;
while(!(getline(w,MAX_STRING_LEN-1,fd,timeout))) {
if(!w[0])
return;
if((++num_processed) > MAX_HEADERS)
die(BAD_REQUEST,"too many header lines",out);
if(!(t = strchr(w,':')))
continue;
*t++ = '\0';
while(isspace(*t)) ++t;
strcpy(l,t);
if(!strcasecmp(w,"Content-type")) {
strcpy(content_type,l);
continue;
}
if(!strcasecmp(w,"Authorization")) {
strcpy(auth_line,l);
continue;
}
if(!strcasecmp(w,"Content-length")) {
sscanf(l,"%d",&content_length);
continue;
}
if(!strcasecmp(w,"If-modified-since"))
strcpy(ims,l);
http2cgi(w);
if(in_headers_env) {
if(!merge_header(w,l,out)) {
in_headers_env =
(char **) realloc(in_headers_env,
(num_inh+2)*sizeof(char *));
if(!in_headers_env)
die(NO_MEMORY,"get_mime_headers",out);
in_headers_env[num_inh++] = make_env_str(w,l,out);
in_headers_env[num_inh] = NULL;
}
}
else {
if(!(in_headers_env = (char **) malloc(2*sizeof(char *))))
die(NO_MEMORY,"get_mime_headers",out);
in_headers_env[num_inh++] = make_env_str(w,l,out);
in_headers_env[num_inh] = NULL;
}
}
}
void dump_default_header(FILE *fd) {
fprintf(fd,"Date: %s%c",gm_timestr_822(time(NULL)),LF);
fprintf(fd,"Server: %s%c",SERVER_VERSION,LF);
@ -299,7 +416,17 @@ void dump_default_header(FILE *fd) {
}
void send_http_header(FILE *fd) {
begin_http_header(fd,(location[0] ? "302 Found" : "200 OK"));
if(!status_line) {
if(location[0]) {
status = 302;
status_line = "302 Found";
}
else {
status = 200;
status_line = "200 OK";
}
}
begin_http_header(fd,status_line);
if(content_type[0])
fprintf(fd,"Content-type: %s%c",content_type,LF);
if(last_modified[0])
@ -309,7 +436,8 @@ void send_http_header(FILE *fd) {
if(location[0])
fprintf(fd,"Location: %s%c",location,LF);
if(content_encoding[0])
fprintf(fd,"Content-encoding: %s%c",content_encoding,LF,LF);
fprintf(fd,"Content-encoding: %s%c",content_encoding,LF);
if(out_headers)
fprintf(fd,"%s",out_headers);
fprintf(fd,"%c",LF);
}

59
src/http_post.c Normal file
View File

@ -0,0 +1,59 @@
/*
* http_post.c: Handles POST
*
* Rob McCool
*
*/
#include "httpd.h"
void handle_post(char *name, char *args, int in, FILE *out) {
struct stat finfo;
char ct_bak[MAX_STRING_LEN];
strcpy(ct_bak,content_type); /* oop ack */
if(stat(name,&finfo) == -1) {
if(find_script("POST",name,args,in,out))
return;
if(errno==ENOENT) {
log_reason("file does not exist",name);
unmunge_name(name);
die(NOT_FOUND,name,out);
}
else {
log_reason("file permissions deny server access",name);
unmunge_name(name);
die(FORBIDDEN,name,out);
}
}
probe_content_type(name);
if(!strcmp(content_type,CGI_MAGIC_TYPE)) {
strcpy(content_type,ct_bak);
send_cgi("POST",name,"",args,&finfo,in,out);
return;
}
/* Not a script, do group ann thang */
die(NOT_IMPLEMENTED,"POST to non-script",out);
}
void post_node(char *name, char *args, int in, FILE *out) {
struct stat finfo;
int s;
s=translate_name(name,out);
switch(s) {
case STD_DOCUMENT:
handle_post(name,args,in,out);
return;
case REDIRECT_URL:
die(REDIRECT,name,out);
case SCRIPT_NCSA:
exec_post_NCSA(name,args,in,out);
return;
case SCRIPT_CGI:
exec_cgi_script("POST",name,args,in,out);
}
}

View File

@ -1,5 +1,5 @@
/*
* http_put.c: Handles PUT and POST
* http_put.c: Handles PUT
*
* Rob McCool
*
@ -7,8 +7,38 @@
#include "httpd.h"
void handle_put(char *name, char *args, int in, FILE *out) {
struct stat finfo;
char ct_bak[MAX_STRING_LEN];
void get_node(char *name, char *args, int in, FILE *out) {
strcpy(ct_bak,content_type); /* oop ack */
if(stat(name,&finfo) == -1) {
if(find_script("PUT",name,args,in,out))
return;
if(errno==ENOENT) {
log_reason("file does not exist",name);
unmunge_name(name);
die(NOT_FOUND,name,out);
}
else {
log_reason("file permissions deny server access",name);
unmunge_name(name);
die(FORBIDDEN,name,out);
}
}
probe_content_type(name);
if(!strcmp(content_type,CGI_MAGIC_TYPE)) {
strcpy(content_type,ct_bak);
send_cgi("PUT",name,"",args,&finfo,in,out);
return;
}
/* Not a script, do group ann thang */
die(NOT_IMPLEMENTED,"PUT to non-script",out);
}
void put_node(char *name, char *args, int in, FILE *out) {
struct stat finfo;
int s;
@ -16,14 +46,13 @@ void get_node(char *name, char *args, int in, FILE *out) {
switch(s) {
case STD_DOCUMENT:
die(NOT_IMPLEMENTED,
"POST access to area not configured as script area",out);
handle_put(name,args,in,out);
return;
case REDIRECT_URL:
die(REDIRECT,name,out);
case SCRIPT_NCSA:
exec_post_NCSA(name,args,in,out);
return;
case SCRIPT_CGI:
exec_cgi_script("POST",name,args,in,out);
exec_cgi_script("PUT",name,args,in,out);
default:
die(NOT_IMPLEMENTED,"NCSA script exeuction of delete",out);
}
}

View File

@ -3,14 +3,11 @@
*
* Rob McCool 3/21/93
*
* Include code by Charles Henrich
*/
#include "httpd.h"
#define OUTBUFSIZE 1024
int assbackwards;
char *remote_host;
char *remote_ip;
@ -18,212 +15,87 @@ char *remote_name;
/* If RFC931 identity check is on, the remote user name */
char *remote_logname;
/*
* Thanks to Charles Henrich
*/
void process_include(FILE *f, FILE *fd, char *incstring, char *args)
{
FILE *ifp;
char srcfile[HUGE_STRING_LEN];
char command[HUGE_STRING_LEN];
char errstr[MAX_STRING_LEN];
char cmd[10];
if(sscanf(incstring,"%s \"%[^\"]", cmd, srcfile) != 2) {
sprintf(errstr,"the include string %s was invalid",incstring);
die(INCLUDE_ERROR,errstr,fd);
}
if(strncasecmp(cmd,"srv",3) != 0) {
fprintf(fd, "%s\r\n",cmd);
return;
}
if(srcfile[0] != '|') {
if(num_includes > MAXINCLUDES) {
die(INCLUDE_ERROR,
"the maximum number of includes has been exceeded",fd);
}
num_includes++;
if(translate_name(srcfile,fd) != 0)
die(INCLUDE_ERROR,"non-standard file include",fd);
ifp=fopen(srcfile,"r");
if(ifp != NULL) {
send_fd(ifp, fd, "");
fclose(ifp);
}
else {
sprintf(errstr,"the include file %s was invalid",srcfile);
die(INCLUDE_ERROR,errstr,fd);
}
}
else {
#ifndef PEM_AUTH
escape_shell_cmd(&srcfile[1]);
if(strncasecmp(cmd,"srvurl",6) == 0) {
escape_shell_cmd(args);
sprintf(command,"%s '%s'",&srcfile[1],args);
}
else {
strcpy(command,&srcfile[1]);
}
ifp=popen(command,"r");
if(ifp != NULL) {
send_fd(ifp, fd, args);
pclose(ifp);
}
else {
sprintf(errstr,"the command %s is invalid",&srcfile[1]);
die(INCLUDE_ERROR,errstr,fd);
}
#else
int pid,p[2];
/* This is done because popen() seems to wait for the wrong */
/* child process when encryption is being used. Suggestions */
/* are welcome. */
if(pipe(p) == -1)
die(SERVER_ERROR,"Could not create an IPC pipe",fd);
if((pid = fork()) == -1)
die(SERVER_ERROR,"Could not fork a new process",fd);
if(!pid) {
char *argv0;
char *cmd;
cmd = &srcfile[1];
if(!(argv0 = strrchr(cmd,'/')))
argv0 = cmd;
else
argv0++;
close(p[0]);
if(p[1] != STDOUT_FILENO) {
dup2(p[1],STDOUT_FILENO);
close(p[1]);
}
if(strncasecmp(cmd,"srvurl",6) == 0) {
escape_shell_cmd(args);
if(execlp(cmd,argv0,args,(char *)0) == -1) {
char errstr[MAX_STRING_LEN];
sprintf(errstr,"could not execute included pgm %s",cmd);
die(INCLUDE_ERROR,errstr,fd);
}
}
else {
if(execlp(cmd,argv0,(char *)0) == -1) {
char errstr[MAX_STRING_LEN];
sprintf(errstr,"could not execute included pgm %s",cmd);
die(INCLUDE_ERROR,errstr,fd);
}
}
} else {
close(p[1]);
if(!(ifp = fdopen(p[0],"r")))
die(INCLUDE_ERROR,"could not open stream to include pipe",fd);
send_fd(ifp,fd,args);
fclose(ifp);
waitpid(pid,NULL,0);
}
#endif
}
}
static void (*exit_callback)();
void send_fd_timed_out() {
char errstr[MAX_STRING_LEN];
if(exit_callback) (*exit_callback)();
sprintf(errstr,"httpd: send timed out for %s",remote_host);
log_error(errstr);
log_transaction();
fclose(stdin);
fclose(stdout);
exit(0);
}
void send_fd(FILE *f, FILE *fd, char *args)
void send_fd(FILE *f, FILE *fd, void (*onexit)())
{
int num_chars=0;
char c;
struct stat finfo;
char buf[IOBUFSIZE];
register int n,o,w;
exit_callback = onexit;
signal(SIGALRM,send_fd_timed_out);
signal(SIGPIPE,send_fd_timed_out);
if((allow_options & OPT_INCLUDES) && is_content_type("text/html")) {
char *find="<inc";
char incstring[MAX_STRING_LEN];
int x,p;
p=0;
while(1) {
alarm(timeout);
c = fgetc(f);
if(feof(f))
return;
if(tolower(c) == find[p]) {
if((++p) == 4) {
x=0;
c=fgetc(f); /* get the space instead of the c */
while(c != '>') {
incstring[x++] = c;
c = fgetc(f);
if(feof(f)) {
incstring[x] = '\0';
fputs("<inc",fd);
fputs(incstring,fd);
return;
}
}
incstring[x] = '\0';
process_include(f,fd,incstring,args);
p=0;
}
}
else {
if(p) {
for(x=0;x<p;x++)
fputc(find[x],fd);
p=0;
}
fputc(c,fd);
}
while (1) {
alarm(timeout);
if((n=fread(buf,sizeof(char),IOBUFSIZE,f)) < 1) {
break;
}
} else {
char buf[OUTBUFSIZE];
register int n,o,w;
while (1) {
alarm(timeout);
if((n=fread(buf,sizeof(char),OUTBUFSIZE,f)) < 1) {
break;
}
o=0;
while(n) {
w=fwrite(&buf[o],sizeof(char),n,fd);
n-=w;
o+=w;
}
o=0;
if(bytes_sent != -1)
bytes_sent += n;
while(n) {
w=fwrite(&buf[o],sizeof(char),n,fd);
n-=w;
o+=w;
}
}
fflush(fd);
}
int find_script(char *method, char *name, char *args, int in, FILE *out)
{
int n=count_dirs(name),i;
char t[HUGE_STRING_LEN],ct_bak[MAX_STRING_LEN];
struct stat finfo;
strcpy(ct_bak,content_type);
for(i=n;i;--i) {
make_dirstr(name,i,t);
probe_content_type(t);
if(!strcmp(content_type,CGI_MAGIC_TYPE)) {
char pa[HUGE_STRING_LEN];
int l=strlen(t);
if(stat(t,&finfo) == -1)
continue;
if(!(S_ISREG(finfo.st_mode)))
return 0;
strcpy(pa,&name[l]);
name[l] = '\0';
strcpy(content_type,ct_bak);
send_cgi(method,name,pa,args,&finfo,in,out);
return 1;
}
}
return 0;
}
void process_request(int in, FILE *out) {
char m[HUGE_STRING_LEN];
char w[HUGE_STRING_LEN];
char l[HUGE_STRING_LEN];
char url[HUGE_STRING_LEN];
char args[HUGE_STRING_LEN];
#ifdef HENRICHS_SILLY_HACK
char tmpargs[HUGE_STRING_LEN];
#endif
int s,n;
get_remote_host(in);
exit_callback = NULL;
signal(SIGPIPE,send_fd_timed_out);
#ifdef PEM_AUTH
doing_pem = -1;
handle_request:
@ -234,32 +106,21 @@ void process_request(int in, FILE *out) {
if(!l[0])
return;
#ifdef PEM_AUTH
if(doing_pem == -1)
#endif
log_transaction(l);
record_request(l);
getword(m,l,' ');
getword(args,l,' ');
#ifdef HENRICHS_SILLY_HACK
strcpy(tmpargs,args);
getword(url,tmpargs,';');
if(!tempargs[0])
getword(url,args,'?');
else
strcpy(args,tmpargs);
#else
getword(url,args,'?');
#endif
plustospace(url);
/* plustospace(url); */
unescape_url(url);
getword(w,l,'\0');
init_header_vars();
if(w[0] != '\0') {
assbackwards = 0;
get_mime_headers(in);
get_mime_headers(in,out);
}
else
assbackwards = 1;
if(!strcmp(m,"HEAD")) {
header_only=1;
process_get(in,out,m,url,args);
@ -269,7 +130,7 @@ void process_request(int in, FILE *out) {
if(!assbackwards) {
if(doing_pem == -1) {
int s2;
s2 = pem_decrypt(in,url,&out);
s2 = decrypt_request(in,url,&out);
if(s2 != -1) {
in = s2;
content_type[0] = '\0';
@ -283,7 +144,15 @@ void process_request(int in, FILE *out) {
}
else if(!strcmp(m,"POST")) {
header_only = 0;
get_node(url,args,in,out);
post_node(url,args,in,out);
}
else if(!strcmp(m,"PUT")) {
header_only = 0;
put_node(url,args,in,out);
}
else if(!strcmp(m,"DELETE")) {
header_only = 0;
delete_node(url,args,in,out);
}
else
die(BAD_REQUEST,"Invalid or unsupported method.",out);

View File

@ -9,11 +9,24 @@
#include "httpd.h"
int pid;
void kill_children() {
char errstr[MAX_STRING_LEN];
sprintf(errstr,"killing CGI process %d",pid);
log_error_noclose(errstr);
kill(pid,SIGTERM);
sleep(5); /* give them time to clean up */
kill(pid,SIGKILL);
waitpid(pid,NULL,0);
}
char **create_argv(char *av0, char *args, FILE *out) {
register int x,n;
char **av;
char w[MAX_STRING_LEN];
char l[MAX_STRING_LEN];
char w[HUGE_STRING_LEN];
char l[HUGE_STRING_LEN];
for(x=0,n=2;args[x];x++)
if(args[x] == '+') ++n;
@ -37,7 +50,7 @@ void get_path_info(char *path, char *path_args, FILE *out,
struct stat *finfo)
{
register int x,max;
char t[MAX_STRING_LEN];
char t[HUGE_STRING_LEN];
path_args[0] = '\0';
max=count_dirs(path);
@ -45,8 +58,9 @@ void get_path_info(char *path, char *path_args, FILE *out,
make_dirstr(path,x+1,t);
if(!(stat(t,finfo))) {
if(S_ISREG(finfo->st_mode)) {
strcpy(path_args,&path[strlen(t)]);
strcpy(path,t);
int l=strlen(t);
strcpy(path_args,&path[l]);
path[l] = '\0';
return;
}
}
@ -65,82 +79,96 @@ void get_path_info(char *path, char *path_args, FILE *out,
die(NOT_FOUND,path,out);
}
#define MAX_CGI_VARS 18
#define MAX_COMMON_VARS 9
#define MAX_CGI_VARS (MAX_COMMON_VARS+9)
void exec_cgi_script(char *method, char *path, char *args, int in, FILE *out)
char **add_cgi_vars(char **env,
char *method, char *path, char *path_args, char *args,
int *content,
FILE *out)
{
int pid, p[2];
int content, nph;
char cl[MAX_STRING_LEN],t[MAX_STRING_LEN],t2[MAX_STRING_LEN];
char path_args[MAX_STRING_LEN];
char *argv0,**env;
FILE *psin;
struct stat finfo;
register int n,x;
int x;
char t[HUGE_STRING_LEN],t2[HUGE_STRING_LEN];
get_path_info(path,path_args,out,&finfo);
if(!can_exec(&finfo)) {
unmunge_name(path);
die(FORBIDDEN,path,out);
}
if(!(env = new_env(env,MAX_CGI_VARS,&x)))
die(NO_MEMORY,"add_cgi_vars",out);
/* BAD -- method specific */
evaluate_access(path,&finfo,((!strcmp(method,"POST")) ? M_POST : M_GET),
&allow,&allow_options,out);
if(!allow) {
log_reason("client denied by server configuration",path);
unmunge_name(path);
die(FORBIDDEN,path,out);
}
env[x++] = make_env_str("GATEWAY_INTERFACE","CGI/1.1",out);
if(!(env = (char **)malloc((MAX_CGI_VARS + 2) * sizeof(char *))))
die(NO_MEMORY,"exec_cgi_script",out);
n = 0;
env[n++] = make_env_str("PATH",getenv("PATH"),out);
env[n++] = make_env_str("SERVER_SOFTWARE",SERVER_VERSION,out);
env[n++] = make_env_str("SERVER_NAME",server_hostname,out);
env[n++] = make_env_str("GATEWAY_INTERFACE","CGI/1.0",out);
sprintf(t,"%d",port);
env[n++] = make_env_str("SERVER_PORT",t,out);
env[n++] = make_env_str("SERVER_PROTOCOL",
env[x++] = make_env_str("SERVER_PROTOCOL",
(assbackwards ? "HTTP/0.9" : "HTTP/1.0"),out);
env[n++] = make_env_str("REQUEST_METHOD",method,out);
env[n++] = make_env_str("HTTP_ACCEPT",http_accept,out);
if(path_args[0]) {
env[n++] = make_env_str("PATH_INFO",path_args,out);
strcpy(t2,path_args);
translate_name(t2,out);
env[n++] = make_env_str("PATH_TRANSLATED",t2,out);
}
env[x++] = make_env_str("REQUEST_METHOD",method,out);
strcpy(t,path);
unmunge_name(t);
env[n++] = make_env_str("SCRIPT_NAME",t,out);
env[n++] = make_env_str("QUERY_STRING",args,out);
env[n++] = make_env_str("REMOTE_HOST",remote_name,out);
env[n++] = make_env_str("REMOTE_ADDR",remote_ip,out);
if(user[0])
env[n++] = make_env_str("REMOTE_USER",user,out);
if(auth_type)
env[n++] = make_env_str("AUTH_TYPE",auth_type,out);
if(do_rfc931)
env[n++] = make_env_str("REMOTE_IDENT",remote_logname,out);
content=0;
if((!strcmp(method,"POST")) || (!strcmp(method,"PUT"))) {
content=1;
sprintf(cl,"%d",content_length);
env[n++] = make_env_str("CONTENT_TYPE",content_type,out);
env[n++] = make_env_str("CONTENT_LENGTH",cl,out);
env[x++] = make_env_str("SCRIPT_NAME",t,out);
if(path_args[0]) {
env[x++] = make_env_str("PATH_INFO",path_args,out);
strcpy(t2,path_args);
translate_name(t2,out);
env[x++] = make_env_str("PATH_TRANSLATED",t2,out);
}
env[x++] = make_env_str("QUERY_STRING",args,out);
if(content) {
*content=0;
if((!strcmp(method,"POST")) || (!strcmp(method,"PUT"))) {
*content=1;
sprintf(t,"%d",content_length);
env[x++] = make_env_str("CONTENT_TYPE",content_type,out);
env[x++] = make_env_str("CONTENT_LENGTH",t,out);
}
}
env[x] = NULL;
return env;
}
char **add_common_vars(char **env,FILE *out) {
char t[HUGE_STRING_LEN],*env_path;
int x;
if(!(env = new_env(env,MAX_COMMON_VARS,&x)))
die(NO_MEMORY,"add_common_vars",out);
if(!(env_path = getenv("PATH")))
env_path=DEFAULT_PATH;
env[x++] = make_env_str("PATH",env_path,out);
env[x++] = make_env_str("SERVER_SOFTWARE",SERVER_VERSION,out);
env[x++] = make_env_str("SERVER_NAME",server_hostname,out);
sprintf(t,"%d",port);
env[x++] = make_env_str("SERVER_PORT",t,out);
env[x++] = make_env_str("REMOTE_HOST",remote_name,out);
env[x++] = make_env_str("REMOTE_ADDR",remote_ip,out);
if(user[0])
env[x++] = make_env_str("REMOTE_USER",user,out);
if(auth_type)
env[x++] = make_env_str("AUTH_TYPE",auth_type,out);
if(do_rfc931)
env[x++] = make_env_str("REMOTE_IDENT",remote_logname,out);
env[x] = NULL;
return env;
}
int cgi_stub(char *method, char *path, char *path_args, char *args,
char **env, struct stat *finfo, int in, FILE *out)
{
int p[2];
int content, nph;
char *argv0;
FILE *psin;
register int x;
if(!can_exec(finfo)) {
unmunge_name(path);
die(FORBIDDEN,path,out);
}
env[n] = NULL;
if((argv0 = strrchr(path,'/')) != NULL)
argv0++;
else argv0 = path;
chdir_file(path);
if(pipe(p) < 0)
die(SERVER_ERROR,"httpd: could not create IPC pipe",out);
if((pid = fork()) < 0)
@ -148,6 +176,8 @@ void exec_cgi_script(char *method, char *path, char *args, int in, FILE *out)
nph = (strncmp(argv0,"nph-",4) ? 0 : 1);
if(!pid) {
close(p[0]);
env = add_cgi_vars(env,method,path,path_args,args,&content,out);
if(content)
if(in != STDIN_FILENO) {
dup2(in,STDIN_FILENO);
@ -164,6 +194,7 @@ void exec_cgi_script(char *method, char *path, char *args, int in, FILE *out)
close(p[1]);
}
}
error_log2stderr();
/* Only ISINDEX scripts get decoded arguments. */
if((!args[0]) || (ind(args,'=') >= 0)) {
if(execle(path,argv0,(char *)0,env) == -1) {
@ -181,9 +212,6 @@ void exec_cgi_script(char *method, char *path, char *args, int in, FILE *out)
}
}
else {
for(x=0;x<n;x++)
free(env[n]);
free(env);
close(p[1]);
}
@ -191,33 +219,69 @@ void exec_cgi_script(char *method, char *path, char *args, int in, FILE *out)
if(!(psin = fdopen(p[0],"r")))
die(SERVER_ERROR,"could not read from script",out);
if(scan_script_header(psin,out))
die(REDIRECT,location,out);
if(scan_script_header(psin,out)) {
kill_children(); /* !!! */
return REDIRECT_URL;
}
if(location[0] == '/') {
char t[MAX_STRING_LEN],a[MAX_STRING_LEN],*argp;
char t[HUGE_STRING_LEN],a[HUGE_STRING_LEN],*argp;
a[0] = '\0';
fclose(psin);
waitpid(pid,NULL,0);
strcpy(t,location);
location[0] = '\0';
if(argp = strchr(t,'?')) {
*argp++ = '\0';
strcpy(a,argp);
}
process_get(in,out,method,t,a);
return;
init_header_vars(); /* clear in_header_env and location */
process_get(in,out,"GET",t,a);
return 0;
}
content_length = -1;
if(!assbackwards)
send_http_header(out);
if(!header_only)
send_fd(psin,out,args);
/* This will cause SIGPIPE in child... it should terminate */
send_fd(psin,out,kill_children);
else
kill_children();
fclose(psin);
}
else bytes_sent = -1;
waitpid(pid,NULL,0);
return 0;
}
/* Called for ScriptAliased directories */
void exec_cgi_script(char *method, char *path, char *args, int in, FILE *out)
{
struct stat finfo;
char path_args[HUGE_STRING_LEN];
char **env;
int m;
get_path_info(path,path_args,out,&finfo);
if((!strcmp(method,"GET")) || (!strcmp(method,"HEAD"))) m=M_GET;
else if(!strcmp(method,"POST")) m=M_POST;
else if(!strcmp(method,"PUT")) m=M_PUT;
else if(!strcmp(method,"DELETE")) m=M_DELETE;
evaluate_access(path,&finfo,m,&allow,&allow_options,out);
if(!allow) {
log_reason("client denied by server configuration",path);
unmunge_name(path);
die(FORBIDDEN,path,out);
}
if(!(env = add_common_vars(in_headers_env,out)))
die(NO_MEMORY,"exec_cgi_script",out);
bytes_sent = 0;
if(cgi_stub(method,path,path_args,args,env,&finfo,in,out) == REDIRECT_URL)
die(REDIRECT,location,out);
/* cgi_stub will screw with env, but only after the fork */
free_env(env);
log_transaction();
}
char **set_env_NCSA(FILE *out) {
@ -240,10 +304,10 @@ char **set_env_NCSA(FILE *out) {
return env;
}
void exec_get_NCSA(char *path, char *args, FILE *fd) {
void exec_get_NCSA(char *path, char *args, int in, FILE *fd) {
FILE *tfp;
struct stat finfo;
int pid,pfd[2];
int pfd[2];
char path_args[MAX_STRING_LEN];
char t[MAX_STRING_LEN];
register int n,x;
@ -329,7 +393,7 @@ void exec_get_NCSA(char *path, char *args, FILE *fd) {
if(!(t = strdup(location)))
die(NO_MEMORY,"exec_get_NCSA",fd);
location[0] = '\0';
send_node(t,"",fd);
send_node(t,"",in,fd);
htexit(0,fd);
}
@ -337,7 +401,9 @@ void exec_get_NCSA(char *path, char *args, FILE *fd) {
send_http_header(fd);
if(!header_only)
send_fd(tfp,fd,args);
send_fd(tfp,fd,kill_children);
else
kill_children();
fclose(tfp);
waitpid(pid,NULL,0);
}
@ -345,7 +411,7 @@ void exec_get_NCSA(char *path, char *args, FILE *fd) {
void exec_post_NCSA(char *path, char *args, int in, FILE *out) {
int pid, inpipe[2],outpipe[2], x;
int inpipe[2],outpipe[2], x;
char cl[MAX_STRING_LEN];
FILE *psin,*psout;
struct stat finfo;
@ -404,7 +470,7 @@ void exec_post_NCSA(char *path, char *args, int in, FILE *out) {
if(!(t = strdup(location)))
die(NO_MEMORY,"exec_post_NCSA",out);
location[0] = '\0';
send_node(t,"",out);
send_node(t,"",in,out);
htexit(0,out);
}
@ -412,7 +478,7 @@ void exec_post_NCSA(char *path, char *args, int in, FILE *out) {
if(!assbackwards)
send_http_header(out);
send_fd(psin,out,args);
send_fd(psin,out,kill_children);
fclose(psin);
waitpid(pid,NULL,0);
}

View File

@ -91,7 +91,7 @@ void seg_fault() {
void set_signals();
void restart() {
log_error("httpd: caught SIGHUP, restarting");
log_error_noclose("httpd: caught SIGHUP, restarting");
kill_mime();
kill_security();
kill_indexing();
@ -99,10 +99,10 @@ void restart() {
free(server_hostname);
server_hostname = NULL;
}
read_config();
read_config(error_log);
close_logs();
open_logs();
log_error("httpd: successful restart");
log_error_noclose("httpd: successful restart");
get_local_host();
set_signals();
}
@ -245,7 +245,7 @@ main(int argc, char *argv[])
usage(argv[0]);
}
}
read_config();
read_config(stderr);
open_logs();
get_local_host();
@ -254,6 +254,7 @@ main(int argc, char *argv[])
else {
user_id = getuid();
group_id = getgid();
port = get_portnum(fileno(stdout),stdout);
if(do_rfc931)
remote_logname = get_remote_logname(stdout);

View File

@ -25,7 +25,10 @@ char *crypt(char *pw, char *salt);
#undef BSD
#define NO_KILLPG
#undef NO_SETSID
#ifndef _HPUX_SOURCE
#define _HPUX_SOURCE
#endif
#define getwd(d) getcwd(d,MAX_STRING_LEN)
#elif defined(AIX)
#undef BSD
@ -115,6 +118,11 @@ typedef int pid_t;
#define NEED_STRNCASECMP
#define bzero(a,b) memset(a,0,b)
#elif defined(__NetBSD__)
#define BSD
#undef NO_KILLPG
#undef NO_SETSID
/* Unknown system - Edit these to match */
#else
/* BSD is whether your system uses BSD calls or System V calls. */
@ -134,6 +142,9 @@ typedef int pid_t;
* /usr/include/sys/dir.h, define DIR_TYPE to be direct and include that
* file. If you have neither, I'm confused.
*/
#include <sys/types.h>
#if !defined(NEXT) && !defined(CONVEXOS)
#include <dirent.h>
#define DIR_TYPE dirent
@ -158,9 +169,6 @@ typedef int pid_t;
/* Max. number of security defines */
#define MAX_SECURITY 50
/* Max. number of include files */
#define MAXINCLUDES 20
/* Default administrator's address */
#define DEFAULT_ADMIN "[no address given]"
@ -218,6 +226,11 @@ typedef int pid_t;
/* The default directory in user's home dir */
#define DEFAULT_USER_DIR "public_html"
/* The default path for CGI scripts if none is currently set */
#define DEFAULT_PATH "/bin:/usr/bin:/usr/ucb:/usr/bsd:/usr/local/bin"
/* The path to the Bourne shell, for parsed docs */
#define SHELL_PATH "/bin/sh"
/* The default string lengths */
#define MAX_STRING_LEN 256
@ -226,28 +239,34 @@ typedef int pid_t;
/* The timeout for waiting for messages */
#define DEFAULT_TIMEOUT 1200
/* The size of the server's internal read-write buffers */
#define IOBUFSIZE 8192
/* The number of header lines we will accept from a client */
#define MAX_HEADERS 200
/* ------------------------------ error types ------------------------------ */
#define SERVER_VERSION "NCSA/1.1"
#define SERVER_VERSION "NCSA/1.2"
#define SERVER_PROTOCOL "HTTP/1.0"
#define SERVER_SUPPORT "httpd@ncsa.uiuc.edu"
#define DOCUMENT_FOLLOWS 200
#define REDIRECT 302
#define USE_LOCAL_COPY 304
#define BAD_REQUEST 400
#define AUTH_REQUIRED 401
#define FORBIDDEN 403
#define NOT_FOUND 404
#define SERVER_ERROR 500
#define NOT_IMPLEMENTED 501
#define INCLUDE_ERROR 6991
#define NO_MEMORY 6992
#define METHODS 3
#define METHODS 4
#define M_GET 0
#define M_PUT 1
#define M_POST 2
#define M_DELETE 3
/* Object types */
#define REDIRECT_URL -1
@ -259,21 +278,35 @@ typedef int pid_t;
#define OPT_INDEXES 1
#define OPT_INCLUDES 2
#define OPT_SYM_LINKS 4
#define OPT_UNSET 8
#define OPT_ALL (OPT_INDEXES|OPT_INCLUDES|OPT_SYM_LINKS)
#define OPT_EXECCGI 8
#define OPT_UNSET 16
#define OPT_INCNOEXEC 32
#define OPT_SYM_OWNER 64
#define OPT_ALL (OPT_INDEXES|OPT_INCLUDES|OPT_SYM_LINKS|OPT_EXECCGI)
#define OR_NONE 0
#define OR_LIMIT 1
#define OR_OPTIONS 2
#define OR_FILEINFO 4
#define OR_AUTHCFG 16
#define OR_ALL (OR_LIMIT|OR_OPTIONS|OR_FILEINFO|OR_AUTHCFG)
#define OR_AUTHCFG 8
#define OR_INDEXES 16
#define OR_ALL (OR_LIMIT|OR_OPTIONS|OR_FILEINFO|OR_AUTHCFG|OR_INDEXES)
#define CGI_MAGIC_TYPE "application/x-httpd-cgi"
#define INCLUDES_MAGIC_TYPE "text/x-server-parsed-html"
/* For directory indexing */
#define BY_PATH 0
#define BY_TYPE 1
#define BY_ENCODING 2
#define FANCY_INDEXING 1
#define ICONS_ARE_LINKS 2
#define SCAN_HTML_TITLES 4
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/file.h>
#include <sys/socket.h>
@ -305,6 +338,7 @@ typedef int pid_t;
/* For access control */
#define DENY_THEN_ALLOW 0
#define ALLOW_THEN_DENY 1
#define MUTUAL_FAILURE 2
/* Struct shared by access and auth */
typedef struct {
@ -328,7 +362,7 @@ typedef struct {
char *deny[METHODS][MAX_SECURITY];
} security_data;
/* Globals */
/* Global, global, who's got the globals? */
/* Server config */
extern int standalone;
@ -363,6 +397,7 @@ extern char access_name[MAX_STRING_LEN];
extern char document_root[MAX_STRING_LEN];
extern char default_type[MAX_STRING_LEN];
extern char default_icon[MAX_STRING_LEN];
extern char blank_icon[MAX_STRING_LEN];
extern int fancy_indexing;
extern char readme_fname[MAX_STRING_LEN];
@ -396,14 +431,21 @@ extern int dirs_in_alias;
extern char auth_line[MAX_STRING_LEN];
extern int content_length;
extern char content_type[MAX_STRING_LEN];
extern char content_encoding[MAX_STRING_LEN];
extern char location[MAX_STRING_LEN];
extern char http_accept[HUGE_STRING_LEN];
extern char **in_headers_env;
/* http_log */
extern FILE *error_log;
extern int bytes_sent;
extern int status;
/* Function prototypes. */
/* http_config */
void read_config();
void parse_htaccess(char *dir, char override, FILE *out);
int get_pw(char *user, char *pw);
int get_pw(char *user, char *pw, FILE *errors);
int in_group(char *user, char *group);
int init_group(char *grpfile, FILE *out);
void kill_group();
@ -418,44 +460,69 @@ void unmunge_name(char *name);
/* http_request */
void process_request(int in, FILE *out);
void send_fd(FILE *f, FILE *fd, char *args);
void send_fd(FILE *f, FILE *fd, void (*callback)());
void send_fd_timed_out();
int find_script(char *method, char *name, char *args, int in, FILE *out);
/* http_get */
void send_file(char *file,FILE *fd, char *args);
void send_file(char *file,FILE *fd, char *path_args, char *args);
void process_include(FILE *f, FILE *fd, char *incstring, char *args);
void send_node(char *name, char *args, FILE *fd);
void send_node(char *name, char *args, int in, FILE *fd);
void process_get(int in, FILE *out, char *m, char *url, char *args);
/* http_post */
void post_node(char *name, char *args, int in, FILE *out);
/* http_put */
void get_node(char *name, char *args, int in, FILE *out);
void put_node(char *name, char *args, int in, FILE *out);
/* http_delete */
void delete_node(char *name, char *args, int in, FILE *out);
/* http_script */
void exec_cgi_script(char *method, char *path, char *args, int in, FILE *out);
void exec_get_NCSA(char *path, char *args, FILE *fd);
int cgi_stub(char *method, char *path, char *path_args, char *args,
char **env, struct stat *finfo, int in, FILE *out);
void exec_get_NCSA(char *path, char *args, int in, FILE *fd);
void exec_post_NCSA(char *path, char *args, int in, FILE *out);
char **add_common_vars(char **env, FILE *out);
void get_path_info(char *path, char *path_args, FILE *out,
struct stat *finfo);
/* http_dir */
extern void index_directory(char *name, FILE *fd);
extern void add_icon(char *icon, char *ext, FILE *out);
extern void add_desc(char *desc, char *ext, FILE *out);
extern void add_ignore(char *ext, FILE *out);
extern void init_indexing();
extern void kill_indexing();
void index_directory(char *name, FILE *fd);
void add_icon(int type, char *icon, char *to, char *path, FILE *out);
void add_alt(int type, char *alt, char *to, char *path, FILE *out);
void add_desc(int type, char *desc, char *to, char *path, FILE *out);
void add_ignore(char *ext, char *path, FILE *out);
void add_header(char *name, char *path, FILE *out);
void add_readme(char *name, char *path, FILE *out);
void add_opts(char *optstr, char *path, FILE *out);
void add_opts_int(int opts, char *path, FILE *out);
void send_size(size_t size, FILE *fd);
void init_indexing();
void kill_indexing();
/* http_log */
void log_transaction(char *cmd_line);
void record_request(char *cmd_line);
void log_error(char *err);
void log_error_noclose(char *err);
void log_reason(char *reason, char *file);
void die(int type, char *err_string, FILE *fd);
void open_logs();
void close_logs();
void begin_http_header(FILE *fd, char *msg);
void error_log2stderr();
void log_transaction();
/* http_mime */
void get_mime_headers(int fd);
void get_mime_headers(int fd, FILE *out);
void init_header_vars();
void send_http_header(FILE *fd);
void set_content_type(char *fn);
void set_last_modified(time_t t, FILE *out);
void probe_content_type(char *fn);
int scan_script_header(FILE *f, FILE *fd);
void add_type(char *fn, char *t,FILE *out);
void add_encoding(char *fn, char *t,FILE *out);
@ -474,15 +541,25 @@ void kill_security();
/* http_auth */
void check_auth(security_data *s, int m, FILE *out);
#ifdef PEM_AUTH
int pem_decrypt(int sfd, char *req, FILE **out);
int decrypt_request(int sfd, char *req, FILE **out);
void htexit(int status, FILE *out);
#endif
/* http_include */
void send_parsed_file(char *file, FILE *fd, char *path_args, char *args,
int noexec);
/* util */
void chdir_file(char *file);
void http2cgi(char *w);
int later_than(char *l, char *i);
int strcmp_match(char *str, char *exp);
int is_matchexp(char *str);
void strsubfirst(int start,char *dest, char *src);
void make_full_path(char *src1,char *src2,char *dst);
int is_directory(char *name);
void getparents(char *name);
void no2slash(char *name);
uid_t uname2id(char *name);
gid_t gname2id(char *name);
int getline(char *s, int n, int f, unsigned int timeout);
@ -492,6 +569,8 @@ void cfg_getword(char *word, char *line);
void get_remote_host(int fd);
char *get_time();
char *gm_timestr_822(time_t t);
char *ht_time(time_t t, char *fmt, int gmt);
struct tm *get_gmtoff(long *tz);
void make_dirstr(char *s, int n, char *d);
int count_dirs(char *path);
void strcpy_dir(char *d, char *s);
@ -506,12 +585,14 @@ void uudecode(char *s,unsigned char *d,int dl);
char *strdup (char *str);
#endif
#ifdef NEED_STRCASECMP
char *strcasecmp(const char *s1, const char *s2);
int strcasecmp(const char *s1, const char *s2);
#endif
#ifdef NEED_STRNCASECMP
char *strncasecmp(const char *s1, const char *s2, int n);
int strncasecmp(const char *s1, const char *s2, int n);
#endif
char *make_env_str(char *n, char *v, FILE *out);
char **new_env(char **env, int to_add, int *pos);
void free_env(char **env);
int ind(char *s, char c);
int rind(char *s, char c);
void construct_url(char *d, char *s);

View File

@ -19,15 +19,139 @@ char *get_time() {
}
char *gm_timestr_822(time_t sec) {
struct tm *t;
static char ts[MAX_STRING_LEN];
/* HUH??? Why is the GMT hardcode necessary? */
return ht_time(sec,"%A, %d-%h-%y %T GMT", 1);
}
char *ht_time(time_t t, char *fmt, int gmt) {
static char ts[MAX_STRING_LEN];
struct tm *tms;
tms = (gmt ? gmtime(&t) : localtime(&t));
t = gmtime(&sec);
/* check return code? */
strftime(ts,MAX_STRING_LEN,"%A, %d-%h-%y %T GMT",t);
strftime(ts,MAX_STRING_LEN,fmt,tms);
return ts;
}
/* What a pain in the ass. */
struct tm *get_gmtoff(long *tz) {
time_t tt;
struct tm *t;
tt = time(NULL);
t = localtime(&tt);
#ifdef BSD
*tz = t->tm_gmtoff;
#else
*tz = - timezone;
if(t->tm_isdst)
*tz += 3600;
#endif
return t;
}
/* What another pain in the ass. */
static char *months[] = {
"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"
};
static int ydays[] = {
0,31,59,90,120,151,181,212,243,273,304,334
};
int find_month(char *mon) {
register int x;
for(x=0;x<12;x++)
if(!strcmp(months[x],mon))
return x;
return -1;
}
#define find_yday(mon,day) (ydays[mon] + day)
int later_than(char *last_modified, char *ims) {
char idate[MAX_STRING_LEN], ldate[MAX_STRING_LEN];
char itime[MAX_STRING_LEN], ltime[MAX_STRING_LEN];
char w[MAX_STRING_LEN];
int lday,lmon,lyear, iday,imon,iyear, lhour,lmin, ihour,imin, x;
long lsec, isec;
sscanf(ims,"%*s %s %s",idate,itime);
sscanf(last_modified,"%*s %s %s",ldate,ltime);
getword(w,idate,'-');
sscanf(w,"%d",&iday);
getword(w,ldate,'-');
sscanf(w,"%d",&lday);
getword(w,idate,'-');
imon = find_month(w);
getword(w,ldate,'-');
lmon = find_month(w);
sscanf(idate,"%d",&iyear);
sscanf(ldate,"%d",&lyear);
x = lyear - iyear;
if(x > 0) return 0;
if(x < 0) return 1;
x = find_yday(lmon, lday) - find_yday(imon,iday);
if(x > 0) return 0;
if(x < 0) return 1;
sscanf(itime,"%d:%d:%ld",&ihour,&imin,&isec);
sscanf(ltime,"%d:%d:%ld",&lhour,&lmin,&lsec);
isec += (imin*60) + (ihour*3600);
lsec += (lmin*60) + (lhour*3600);
x = lsec - isec;
if(x > 0) return 0;
return 1;
}
/* Match = 0, NoMatch = 1, Abort = -1 */
/* Based loosely on sections of wildmat.c by Rich Salz */
int strcmp_match(char *str, char *exp) {
int x,y;
for(x=0,y=0;exp[y];++y,++x) {
if((!str[x]) && (exp[y] != '*'))
return -1;
if(exp[y] == '*') {
while(exp[++y] == '*');
if(!exp[y])
return 0;
while(str[x]) {
int ret;
if((ret = strcmp_match(&str[x++],&exp[y])) != 1)
return ret;
}
return -1;
} else
if((exp[y] != '?') && (str[x] != exp[y]))
return 1;
}
return (str[x] != '\0');
}
int is_matchexp(char *str) {
register int x;
for(x=0;str[x];x++)
if((str[x] == '*') || (str[x] == '?'))
return 1;
return 0;
}
void strsubfirst(int start,char *dest, char *src)
{
char tmp[MAX_STRING_LEN];
@ -69,6 +193,15 @@ void getparents(char *name)
}
}
void no2slash(char *name) {
register int x,y;
for(x=0; name[x]; x++)
if(x && (name[x-1] == '/') && (name[x] == '/'))
for(y=x+1;name[y-1];y++)
name[y-1] = name[y];
}
void make_dirstr(char *s, int n, char *d) {
register int x,f;
@ -101,6 +234,23 @@ void strcpy_dir(char *d, char *s) {
d[x] = '\0';
}
void chdir_file(char *file) {
int i;
if((i = rind(file,'/')) == -1)
return;
file[i] = '\0';
chdir(file);
file[i] = '/';
}
void http2cgi(char *w) {
register int x;
for(x=strlen(w);x != -1; --x)
w[x+5]= (w[x] == '-' ? '_' : toupper(w[x]));
strncpy(w,"HTTP_",5);
}
void getline_timed_out() {
char errstr[MAX_STRING_LEN];
@ -113,12 +263,15 @@ void getline_timed_out() {
}
int getline(char *s, int n, int f, unsigned int timeout) {
register int i=0;
register int i=0, ret;
signal(SIGALRM,getline_timed_out);
alarm(timeout);
while(1) {
if(read(f,&s[i],1) <= 0) {
if((ret = read(f,&s[i],1)) <= 0) {
/* Mmmmm, Solaris. */
if((ret == -1) && (errno == EINTR))
continue;
s[i] = '\0';
return 1;
}
@ -311,6 +464,34 @@ char *make_env_str(char *name, char *value, FILE *out) {
return t;
}
char **new_env(char **env, int to_add, int *pos) {
if(!env) {
*pos = 0;
return (char **)malloc((to_add+1)*sizeof(char *));
}
else {
int x;
char **newenv;
for(x=0;env[x];x++);
if(!(newenv = (char **)malloc((to_add+x+1)*(sizeof(char *)))))
return NULL;
for(x=0;env[x];x++)
newenv[x] = env[x];
*pos = x;
free(env);
return newenv;
}
}
void free_env(char **env) {
int x;
for(x=0;env[x];x++)
free(env[x]);
free(env);
}
int can_exec(struct stat *finfo) {
if(user_id == finfo->st_uid)
if(finfo->st_mode & S_IXUSR)
@ -453,8 +634,20 @@ int get_portnum(int sd,FILE *out) {
len = sizeof(struct sockaddr);
if(getsockname(sd,&addr,&len) < 0)
die(SERVER_ERROR,"could not get port number",out);
return ntohs(((struct sockaddr_in *)&addr)->sin_port);
}
return(((struct sockaddr_in *)&addr)->sin_port);
char *find_fqdn(struct hostent *p) {
int x;
if(ind(p->h_name,'.') == -1) {
for(x=0;p->h_aliases[x];++x) {
if((ind(p->h_aliases[x],'.') != -1) &&
(!strncmp(p->h_aliases[x],p->h_name,strlen(p->h_name))))
return strdup(p->h_aliases[x]);
}
return NULL;
} else return strdup(p->h_name);
}
void get_remote_host(int fd) {
@ -462,9 +655,9 @@ void get_remote_host(int fd) {
int len;
struct in_addr *iaddr;
struct hostent *hptr;
len = sizeof(struct sockaddr);
if ((getpeername(fd, &addr, &len)) < 0) {
remote_host=NULL;
remote_ip=NULL;
@ -479,7 +672,21 @@ void get_remote_host(int fd) {
remote_name = remote_host;
}
else remote_host = NULL;
/* Grrr. Check THAT name to make sure it's really the name of the addr. */
/* Code from Harald Hanche-Olsen <hanche@imf.unit.no> */
if(remote_host) {
char **haddr;
hptr = gethostbyname(remote_host);
if (hptr) {
for(haddr=hptr->h_addr_list;*haddr;haddr++) {
if(((struct in_addr *)(*haddr))->s_addr == iaddr->s_addr)
break;
}
}
if((!hptr) || (!(*haddr)))
remote_host = NULL;
}
remote_ip = inet_ntoa(*iaddr);
if(!remote_host)
remote_name = remote_ip;
@ -489,8 +696,7 @@ char *get_remote_logname(FILE *fd) {
int len;
char *result;
#ifdef NEXT
struct sockaddr_in sa_server;
struct sockaddr sa_client;
struct sockaddr sa_server, sa_client;
#else
struct sockaddr_in sa_server,sa_client;
#endif
@ -515,9 +721,7 @@ void get_local_host()
if(!server_hostname) {
struct hostent *p;
gethostname(str, len);
if(p=gethostbyname(str))
server_hostname = strdup(p->h_name);
else {
if((!(p=gethostbyname(str))) || (!(server_hostname = find_fqdn(p)))) {
fprintf(stderr,"httpd: cannot determine local host name.\n");
fprintf(stderr,"Use ServerName to set it manually.\n");
exit(1);

View File

@ -7,6 +7,8 @@ CC= gcc
#CFLAGS= -O2
#For debugging
CFLAGS= -g
# For SCO ODT
#EXTRA_LIBS= -lcrypt_i
RM= /bin/rm -f
#--- You shouldn't have to edit anything else. ---
@ -14,7 +16,7 @@ RM= /bin/rm -f
.c.o:
$(CC) -c $(CFLAGS) $<
all: htpasswd unescape
all: htpasswd unescape inc2shtml
ibm: $(OBJS)
make all CC=gcc
@ -38,11 +40,14 @@ tar: htpasswd unescape
$(RM) htpasswd unescape
htpasswd: htpasswd.c
$(CC) $(CFLAGS) htpasswd.c -o htpasswd
$(CC) $(CFLAGS) htpasswd.c -o htpasswd $(EXTRA_LIBS)
unescape: unescape.c
$(CC) $(CFLAGS) unescape.c -o unescape
inc2shtml: inc2shtml.c
$(CC) $(CFLAGS) inc2shtml.c -o inc2shtml
clean:
rm -f htpasswd
rm -f htpasswd unescape inc2shtml

File diff suppressed because it is too large Load Diff

102
support/inc2shtml.c Normal file
View File

@ -0,0 +1,102 @@
/*
* inc2shtml: Convert httpd <1.1 style includes to 1.2 style
*
* Rob McCool
*
* Usage: inc2shtml [filename]
*
* If filename is given, this program will open filename. If not, it will
* look on stdin. It will output the new shtml file on stdout.
*/
#include <stdio.h>
#define MAX_STRING_LEN 256
void usage(char *argv0) {
fprintf(stderr,"Usage: %s [filename]\n",argv0);
fprintf(stderr,"If filename is given, this program will open filename.\n");
fprintf(stderr,"If not, it will look on stdin for the inc file.\n");
fprintf(stderr,
"In either case, it will write the new shtml file on stdout.\n");
exit(1);
}
void translate_tag(char *tag, FILE *fd) {
char *tp = tag, *tp2;
int url;
url = (*tp == 'U' || *tp == 'u' ? 1 : 0);
while(*tp++ != '\"');
tp2 = tp + 1;
while(*tp2 != '\"') ++tp2;
*tp2 = '\0';
if(*tp == '|') {
fprintf(fd,"<!--#exec cmd=\"%s",++tp);
if(url) fputs(" '$QUERY_STRING_UNESCAPED'",fd);
fputs("\"-->",fd);
} else
fprintf(fd,"<!--#include virtual=\"%s\"-->",tp);
}
main(int argc, char *argv[]) {
FILE *f;
int c,x,p;
char c2;
char *lookfor = "<inc srv";
switch(argc) {
case 1:
f = stdin;
break;
case 2:
if(!(f = fopen(argv[1],"r"))) {
perror("fopen");
exit(1);
}
break;
default:
usage(argv[0]);
}
p=0;
while(1) {
c = fgetc(f);
if(c == -1) {
fflush(stdout);
exit(0);
}
c2 = (char)c;
if(isalpha((char)c))
c = tolower((char)c);
if(c == lookfor[p]) {
if(!lookfor[++p]) {
char tag[MAX_STRING_LEN];
x=0;
c = fgetc(f); /* get space */
while(c != '>') {
tag[x++] = c;
c = fgetc(f);
if(c == -1) {
fputs("<inc srv ",stdout);
fputs(tag,stdout);
fflush(stdout);
exit(1);
}
}
tag[x] = '\0';
translate_tag(tag,stdout);
p = 0;
}
}
else {
for(x=0;x<p;x++)
fputc(lookfor[x],stdout);
fputc(c2,stdout);
p=0;
}
}
}

Binary file not shown.