NCSA HTTPd 1.5c - I'm not sure where this fits into the history. It's probably even older than 1.5.1a, but the SUNET archives date it to the same day as 1.5.2

This commit is contained in:
I am not me 2013-03-13 03:07:59 -04:00
parent e843970069
commit bb0575c774
57 changed files with 1898 additions and 4334 deletions

42
BUGS
View File

@ -1,47 +1,5 @@
NOTE: Bugs are mentioned in the version they are found in. This doesn't
mean that they didn't exist prior to that version.
Known Bugs in 1.5.1b3
---------------------
*) 299: File descriptors aren't set correctly on child_alone()
*) 301: Sending headers on HTTP/0.9 response
Known Bugs in 1.5.1b2
---------------------
*) 900: ErrorDocument 401s as html files doesn't work on Mosaic/X, does on
netscape
*) 293: Socket isn't closed before CGI execution, causing client to hang
waiting for close
Known Bugs in 1.5.1b1
---------------------
*) 264: imagemap fails because of invalid fgets() argument
*) 265: in_ip() broken causing all access control by ip to fail
*) 266: 301 and 204 status codes broken in set_stat_line()
*) 267: no bounds checking in access_control array
Known Bugs in 1.5a
---------------------
*) server doesn't clean up directory indexing information added by .htaccess
*) fgets in src/imagemap.c only uses MAX_STRING_LEN, which may be too short
for complex polygons
*) If you don't have an allow or require line in .htaccess LIMIT, it won't
work (ie, just a deny)
*) Doesn't log HEAD request to automatically indexed directory
*) Can't use group and user name which are the same in flat group file
*) Off by one errors in DBM support
*) typo in LOCALHACK
*) Server core dumped if user aborted before reqInfo->remote_name set
*) Server core dumped if setuid/setgid failed
*) Bug in http_access.c which makes matchexp directories in access control
not work correctly
*) NIS group files only work if using NIS password files as well
*) Order mutual-failure is broken, does exact opposite
*) Don't strip Content-Length header from CGI scripts
*) require group will match user as postfix of another, and fails if a
prefix occurs first
Known Bugs in 1.5

43
CHANGES
View File

@ -1,37 +1,3 @@
Changes for 1.5.1
------------------
*) Imagemaps (both internal and external) now add the path of the map file
for non full path urls in the map file
*) A couple logging functions didn't check reqInfo->remote_name for a NULL
*) change getuid to geteuid in httpd.c so that effectively root people can
start the server and have it change uids
*) Slight code rearrangement to make Redirects from .htaccess more
useful because the file doesn't have to exist.
*) Added support for restricted access by Referer field
*) Added OnDeny command for Limit directive which allows a redirect on
failure (esp. useful for denying by referer)
*) Added string allocating mechanism for speed
*) Added CONTENT_MD5 header support from patches by Martin Hamilton
(martin@net.lut.ac.uk)
*) Server doesn't keep creating more structures in the event of KeepAlive
*) Added bounds checking for security structures
*) Fixed Order mutual-failure
*) Support both CERN and NCSA style imagemaps (on a line by line basis)
*) Attempting to make the server thread safe
*) First attempt at allowing ErrorDocument 401s as html files (still broken)
*) Fixed string searching for user in group
*) Close csd (socket) on exec of CGI scripts so that client doesn't hang
waiting for the scripts (and their children) to finish
*) made a single interface for most output functions to make it easier
to go to different output functions (SSL is a good example)
*) remove path_args/path_alias crap, and put it in reqInfo structure
*) Why do we require full URLs in Redirect? A local (root) url should work fine
*) Redirect from .htaccess should work now (completely)
*) Added hack to allow SSI of CGI, at a great expense of speed (CGI_SSI_HACK)
*) Made getline() code re-entrant (now has its own sock_buf struct)
Fixes for 1.5c
------------------
*) add newline character to list of characters to strip from shell cmds
@ -46,6 +12,15 @@ Fixes for 1.5c
start the server and have it change uids
*) Fix group checking
Fixes for 1.5b (internal)
------------------
*) Couple of off by one errors in the DBM support (server and support files)
*) HP/Apollo Domain/OS support updated
*) SCO ODT and SCO SVR3 support updated
*) Typo in LOCALHACK
*) No error message for NO_CONTENT default imagemap
*) clean up after directory indexing (memory leak)
Fixes for 1.5a
-------------------
*) Typo/Thinko for http_access.c which makes order deny/allow not work as

View File

@ -28,8 +28,6 @@ Vince Tkac (tkac@oclc.org)
Elf Sternberg (elf@aaden.spry.com)
Nathan Neulinger (nneul@umr.edu)
Stuart Lynne (sl@wimsey.com)
Martin Hamilton (martin@net.lut.ac.uk)
Tim Hudson (tjh@mincom.oz.au) SSL
And for Porting information/help:
Alex Podlecki (a.podlecki@att.com) SVR4

5
README
View File

@ -1,5 +1,5 @@
NCSA HTTPd Server 1.5.1 Beta
NCSA HTTPd Server 1.5c
Copyright (c) 1995 Board of Trustees, University of Illinois
@ -70,8 +70,6 @@ support/dbmpasswd Program to make password files that use dbm
support/htdigest Program to make MD5 password files (std/text)
support/htpasswd Program to make password files (std/text)
support/std2dbm Program to convert std files to dbm
support/webgrab Brian J. Swetland's Command Line Browser
(its almost as good as telnet)
Version Number Defined
---------------------------
@ -84,4 +82,3 @@ Version Number Defined
| ---- Major revisions. Probably not going to be another until 2.0
------ Really major revisions, code overhauls, goal changes, language
changes

0
cgi-src/Makefile Normal file → Executable file
View File

View File

@ -47,9 +47,6 @@
**
** 1.9 : Fixed bug: If you requested a new style conf file in DOCUMENT_ROOT,
** and didn't have an old style conf file, it would fail
** 1.9a: Most other imagemap programs seem to allow a non-full path as the url,
** so we'll switch to that. Any url not starting with / goes to the
** same path as the map file.
*/
#include <stdio.h>
@ -243,39 +240,19 @@ int main(int argc, char **argv)
static void sendmesg(char *url)
{
char *port;
char *path_info;
char path[MAXLINE];
if (strchr(url, ':')) /*** It is a full URL ***/
printf("Location: %s%c%c",url,LF,LF);
printf("Location: ");
else { /*** It is a virtual URL ***/
char *port;
printf("Location: http://%s", getenv("SERVER_NAME"));
/* only add port if it's not the default */
if ((port = getenv("SERVER_PORT")) && strcmp(port,"80"))
printf(":%s",port);
/* if its a full path, just use it, else add path from PATH_INFO */
if (url[0] == '/') {
printf("%s%c%c",url,LF,LF);
} else {
if ((path_info = getenv("PATH_INFO"))) {
char *last = strrchr(path_info,'/');
int x = 0;
while (((path_info+x) <= last) && (x < MAXLINE)) {
path[x] = *(path_info+x);
x++;
}
path[x] = '\0';
} else {
strcpy(path,"/");
}
printf("%s%s%c%c",path,url,LF,LF);
}
}
printf("This document has moved <A HREF=\"%s\">here</A>%c",url,LF);
exit(1);
printf("%s%c%c",url,10,10);
printf("This document has moved <A HREF=\"%s\">here</A>%c",url,10);
exit(1);
}
static int pointinrect(double point[2], double coords[MAXVERTS][2])
@ -364,7 +341,7 @@ static int pointinpoly(double point[2], double pgon[MAXVERTS][2])
static void servererr(char *msg)
{
printf("Content-type: text/html%c%c",LF,LF);
printf("Content-type: text/html%c%c",10,10);
printf("<title>Mapping Server Error</title>");
printf("<h1>Mapping Server Error</h1>");
printf("This server encountered an error:<p>");

View File

@ -139,7 +139,7 @@ void escape_shell_cmd(char *cmd) {
l=strlen(cmd);
for(x=0;cmd[x];x++) {
if(ind("&;`'\"|*?~<>^()[]{}$\\\x0A",cmd[x]) != -1){
if(ind("&;`'\"|*?~<>^()[]{}$\\",cmd[x]) != -1){
for(y=l+1;y>x;y--)
cmd[y] = cmd[y-1];
l++; /* length has been increased */

View File

@ -160,13 +160,13 @@ AccessConfig conf/access.conf
LogOptions Separate
# LogDirGroupWriteOk, LogDirOtherWriteOk: Define either of these if you
# LogDirGroupWriteOk, LogDirPublicWriteOk: Define either of these if you
# want the server to start even if you have write permissions on the log
# directory. Having write permissions set is a potential security hole.
# Only makes a difference if the server process is started by root.
#LogDirGroupWriteOk
#LogDirOtherWriteOk
#LogDirPublicWriteOk
# RefererIgnore: If you don't want to keep track of links from certain
# servers (like your own), place it here. If you want to log them all,

View File

@ -122,8 +122,8 @@ DefaultType text/plain
# AddEncoding allows you to have certain browsers (Mosaic/X 2.1+) uncompress
# information on the fly. Note: Not all browsers support this.
#AddEncoding compress Z
#AddEncoding gzip gz
#AddEncoding x-compress Z
#AddEncoding x-gzip gz
# The following are known to the server as "Magic Mime Types" They allow
# you to change how the server perceives a document by the extension

View File

@ -1,37 +0,0 @@
Port configurable per VirtualHost
kadow@msg.net (Kevin Kadow)
Server Parse CGI output
not feasible because SSI parser using buffered I/O, CGI uses getline()
(server buffered I/O)
But, we did it anyways. See CGI_SSI_HACK in config.h
Allow extra CGI environment variables to be specified via configuration
Kevin Kadow (kadow@msg.net) and Brian Millett (bpm@techapp.com)
Shouldn't be too hard, probably in 1.5.1b4
Ok, maybe in 1.5.2
AuthUserScript - Heiner Schorn (Heiner.Schorn@informatik.umu.se)
Pass a user name to a script, it returns the password to check against
the one the client sent to the server. This is safe from someone
writing a script to gather passwords, because the given password is
never sent to the script. This is unsafe on the server system because
it will return the password of a user. That could be made safer by
making the mechanism employ crypt on the password before hand..
Shouldn't be too hard, but needs some design work. Perhaps 1.5.1b4
Ok, maybe 1.5.2
Have separate UID/GID per CGI script - Marc Evans (marc@destek.net)
With Patch (NF-1.5b7-marc_cgi_uid_hack)
Basically, changes calls from setuid to seteuid, so it changes the
effective user id of the server. This makes any security hole
potentially dangerous, such as the one in 1.3, since the program
that you can force to run can set the euid back to root.
Look at it for 1.5.1b4, probably always have to be a #define for the
more security conscious users of NCSA HTTPd
Push off to 1.5.2
SHTTP
Alpha is done, but we need to test it more
SSL
Again, alpha code is in place, but it needs to be tested more
RADIUS
Ok, I was expecting something slightly different. Doesn't quite fit
the current way of doing things, but shouldn't be too hard to figure
out either. Probably 1.5.2

View File

@ -1,81 +0,0 @@
The following is NCSA HTTPd treatment of HTTP headers. By Supported,
we mean that the server explicitly manipulates the headers. This
doesn't include forwarding of headers to CGI scripts or including
headers from CGI scripts.
In
HTTP HEADER HTTP Section Sup to/why length Used for?
Date 1.0 General N Do I care what the clients date is?
MIME-Version 1.0 General N The server isn't MIME Compliant
Pragma 1.0 General N Only no-cache is defined, and this isn't a proxy server
Authorization 1.0 Request Y reqInfo->inh_auth_line HUGE_STRING_LEN Authentication (Basic/MD5/Keberos)
From 1.0 Request N no one uses it
If-Modified-Since 1.0 Request Y reqInfo->inh_if_mod MAX_STRING_LEN 304 Use Local Copy response
Referer 1.0 Request Y reqInfo->inh_referer HUGE_STRING_LEN Logs
User-agent 1.0 Request Y reqInfo->inh_agent HUGE_STRING_LEN Logs
Allow 1.0 Entity N not clear how useful in request
Content-Encoding 1.0 Entity N
Content-Length 1.0 Entity Y reqInfo->inh_content_length int POST content length
Content-Type 1.0 Entity Y reqInfo->inh_content_type MAX_STRING_LEN POST content should be application/x-www-form-urlencoded
Expires 1.0 Entity N time request expires?
Last-Modified 1.0 Entity N last time request was modified?
Cache-Control 1.1 General N
Connection 1.1 General Y Keep-Alive
Forwarded 1.1 General N
Keep-Alive 1.1 General N max= timeout= same
Upgrade 1.1 General N
Accept 1.1 Request N
Accept-Charset 1.1 Request N
Accept-Encoding 1.1 Request N
Accept-Language 1.1 Request N
Host 1.1 Request Y reqInfo->inh_called_hostname MAX_STRING_LEN to provide virtual host support with CNAMES
Proxy-Authorization 1.1 Request N
Range 1.1 Request N
Unless 1.1 Request N
Content-Language 1.1 Entity N
Content-MD5 1.1 Entity N
Content-Range 1.1 Entity N
Content-Version 1.1 Entity N
Derived-From 1.1 Entity N
Link 1.1 Entity N
Title 1.1 Entity N
Transfer-Encoding 1.1 Entity N
URI-header 1.1 Entity N
Extension
Out
HTTP HEADER HTTP Section Sup from/why
Date 1.0 General Y GMT Date in rfc 822 format
MIME-Version 1.0 General N The server isn't MIME Compliant
Pragma 1.0 General N Only no-cache is defined, and this isn't a proxy server
Location 1.0 Response Y reqInfo->outh_location HUGE_STRING_LEN redirects
Server 1.0 Response Y #define SERVER_VERSION
WWW-Authenticate 1.0 Response Y reqInfo->outh_www_auth HUGE_STRING_LEN
Allow 1.0 Entity N We could make a list in evaluate_access(), but wouldn't that be a security hole?
Content-Encoding 1.0 Entity Y reqInfo->outh_content_encoding MAX_STRING_LEN AddEncoding
Content-Length 1.0 Entity Y reqInfo->outh_content_length int
Content-Type 1.0 Entity Y reqInfo->outh_content_type MAX_STRING_LEN
Expires 1.0 Entity N could add an AddExpires config option
Last-Modified 1.0 Entity Y reqInfo->outh_last_mod MAX_STRING_LEN client caching
Cache-Control 1.1 General N
Connection 1.1 General Y keep_alive. stuff Keep-Alive
Forwarded 1.1 General N
Keep-Alive 1.1 General Y max= timeout= same
Upgrade 1.1 General N
Proxy-Authenticate 1.1 Response N
Public 1.1 Response N
Retry-After 1.1 Response N
Content-Language 1.1 Entity N
Content-MD5 1.1 Entity Y reqInfo->outh_content_md5 allocated do you get what you asked for
Content-Range 1.1 Entity N
Content-Version 1.1 Entity N
Derived-From 1.1 Entity N
Link 1.1 Entity N
Title 1.1 Entity N
Transfer-Encoding 1.1 Entity N
URI-header 1.1 Entity N
Annotations-cgi reqInfo->hostInfo->annotation_server
Extension: Domain-Restricted reqInfo->bNotifyDomainRestricted &&
reqInfo->bSatisfiedDomain

View File

@ -1,212 +0,0 @@
child_main httpd.c
GetDescriptor httpd.c
setproctitle
recv_fd
GetRemoteLogName httpd.c
getpeername
rfc931
initialize_request http_request.c
malloc
reset_security http_access.c
free
init_header_vars http_mime.c
free
RequestMain http_request.c
signal
getline
setproctitle
decode_request http_request.c
strtok
MapMethod http_request.c
get_mime_headers
getline
strchr
isspace
strcasecmp
http2cgi util.c
merge_header env.c
realloc
make_env_str env.c
malloc
realloc
unescape_url util.c
which_host_conf
get_local_addr
getsockname
get_remote_host util.c
getpeername
strdup
gethostbyaddr
gethostbyname
inet_ntoa
process_request http_request.c
translate_name http_alias.c
getparents util.c
make_full_path util.c
log_reason
malloc
log_error util.c
free
send_node http_send.c
stat
extract_path_info http_send.c
count_dirs util.c
make_dirstr util.c
stat
evaluate_access http_access.c
no2slash util.c
reset_mime_vars http_mime.c
is_matchexp util.c
strcmp_match util.c
check_dir_access http_access.c
find_allow http_access.c
in_ip http_access.c
get_remote_host_min util.c
getpeername
gethostbyaddr
in_domain http_access.c
find_deny http_access.c
in_ip http_access.c
get_remote_host_min util.c
in_domain http_access.c
parse_htaccess http_config.c
stat
FOpen fdwrap.c
parse_access_dir http_config.c
cfg_getline util.c
access_syntax_error http_config.c
cfg_getword util.c
add_type http_mime.c
malloc
strdup
add_encoding http_mime.c
malloc
strdup
add_desc http_dir.c
new_item http_dir.c
malloc
strdup
add_ignore http_dir.c
new_item http_dir.c
add_icon http_dir.c
add_alt http_dir.c
new_item http_dir.c
new_item http_dir.c
add_readme http_dir.c
new_item http_dir.c
add_header http_dir.c
new_item http_dir.c
add_opts http_dir.c
cfg_getword util.c
add_opts_int http_dir.c
new_item http_dir.c
strdup
FClose fdwrap.c
readlink
check_auth http_auth.c
auth_bong
uudecode
getword
get_pw
crypt
Digest_Check
k4_server_auth
k5_server_auth
check_krb_restrict
init_group http_auth.c
FOpen fdwrap.c
malloc
fread
FClose fdwrap.c
DBM_Open fdwrap.c
in_group http_auth.c
DBM_Close fdwrap.c
send_dir http_send.c
construct_url
escape_url
index_directory http_dir.c
Opendir
send_http_header
CloseDir
find_opts
find_header
insert_readme
make_dir_entry
malloc
qsort
output_directories
free
find_readme
insert_readme
log_transaction
probe_content_type http_mime.c
find_ct http_mime.c
send_cgi cgi.c
add_common_vars cgi.c
make_env_str env.c
cgi_stub cgi.c
can_exec util.c
Pipe fdwrap.c
fork
add_cgi_vars
error_log2stderr
execle/execve
getline util.c
write
read
scan_script_header cgi.c
getline util.c
strdup
realloc
waitpid
send_http_header http_mime.c
set_stat_line http_mime.c
free
strdup
begin_http_header http_log.c
dump_default_header http_mime.c
send_script cgi.c
alarm
getline
write
read
kill_children cgi.c
sleep
kill
waitpid
log_transaction
send_file http_send.c
set_content_type http_mime.c
find_ct http_mime.c
send_parsed_file http_include.c
FOpen fdwrap.c
set_content_length http_mime.c
set_last_modified http_mime.c
gmtime
strftime
later_than util.c
send_http_header http_mime.c
send_fd http_send.c
signal
fread
write
log_transaction http_log.c
FClose fdwrap.c
probe_content_type http_mime.c
send_cgi cgi.c
send_imagemap imagemap.c
FOpen fdwrap.c
pointinpoly imagemap.c
sendmsg imagemap.c
pointincircle imagemap.c
pointinrect imagemap.c
FClose fdwrap.c
send_file http_send.c
exec_cgi_script cgi.c
get_path_info
evaluate_access
add_common_vars
cgi_stub
CompleteRequest httpd.c
CloseAll fd_wrap.c
free_request http_request.c

View File

@ -1,13 +1,12 @@
# NCSA HTTPd 1.5
#
# For normal machines with ANSI compilers
#CC= cc
# CC= cc
# For Suns or other non-ANSI platforms.
CC= gcc
#CC = xlc
QUANTIFY=/hdf2/pure/quantify-2.0.1-sunos4/quantify
PURIFY=/hdf2/pure/purify-3.2-sunos4/purify
#PURIFY=/X11/sgi5/purify3.1/purify
QUANTIFY=/hdf2/pure/quantify-2.0-sunos4/quantify
PURIFY=purify
# CFLAGS, compile flags.
#
@ -15,10 +14,12 @@ PURIFY=/hdf2/pure/purify-3.2-sunos4/purify
# All other defines are in config.h
# If you want to ensure that CGI scripts can't mess with the log files,
# use -DSECURE_LOGS
#
CFLAGS= -g
#CFLAGS= -pg -DPROFILE
#CFLAGS= -g -ansi -pedantic -Wall -DAIX_BROKEN_HEADERS
#CFLAGS= -g -Wall -ansi -pedantic
# DIGEST AUTHENTICATION
#
@ -45,8 +46,9 @@ KRB5_CFLAGS = -DKRB5 -I$(KRB5_DIR)/include -I$(KRB5_DIR)/include/krb5
# Comment out the following two lines to exclude Kerberos support
#KRB_CFLAGS = $(KRB4_CFLAGS) $(KRB5_CFLAGS) # -DKRB-ENCRYPT
#KRB_LIBS = $(KRB4_LIBS) $(KRB5_LIBS)
# KRB_CFLAGS = $(KRB4_CFLAGS) $(KRB5_CFLAGS) # -DKRB-ENCRYPT
# KRB_LIBS = $(KRB4_LIBS) $(KRB5_LIBS)
# DBM
#
@ -87,7 +89,7 @@ LFLAGS= # -pg -DPROFILE
# For HP-UX
# AUX_CFLAGS= -DHPUX
# For AIX3
# AUX_CFLAGS= -DAIX3 -D_ALL_SOURCE # For xlc compiler
AUX_CFLAGS= -DAIX3
# For AIX4
# AUX_CFLAGS= -DAIX4
# For Ultrix
@ -100,7 +102,6 @@ LFLAGS= # -pg -DPROFILE
# AUX_CFLAGS= -DSEQUENT
# For Linux -m486 ONLY IF YOU HAVE 486 BINARY SUPPORT IN KERNEL
# AUX_CFLAGS= -DLINUX
# DBM_LIBS = -lgdbm
# For NetBSD 1.0
# May not need -lcrypt if its included in your libc
# AUX_CFLAGS= -DNetBSD
@ -141,21 +142,18 @@ LFLAGS= # -pg -DPROFILE
# -------------- You shouldn't have to edit anything else -----------------
# -------------------------------------------------------------------------
SEC_CFLAGS = $(MD5_CFLAGS) $(KRB_CFLAGS)
SEC_CFLAGS = $(MD5_CFLAGS) $(PGP_CFLAGS) $(KRB_CFLAGS)
SEC_LIBS = $(KRB_LIBS)
ALL_CFLAGS = $(CFLAGS) $(AUX_CFLAGS) $(SEC_CFLAGS) $(DBM_CFLAGS)
ALL_LIBS = $(EXTRA_LIBS) $(SEC_LIBS) $(DBM_LIBS)
OBJS=httpd.o http_config.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_send.o cgi.o http_include.o rfc931.o imagemap.o \
http_ipc.o digest.o md5.o md5c.o env.o host_config.o fdwrap.o \
open_logfile.o allocate.o debug.o blackout.o
open_logfile.o
.c.o: Makefile config.h portability.h constants.h
$(CC) -c $(ALL_CFLAGS) $<
$(CC) -c $(CFLAGS) $(AUX_CFLAGS) $(SEC_CFLAGS) $(DBM_CFLAGS) $<
all: httpd
@ -205,22 +203,21 @@ ultrix:
make tar AUX_CFLAGS=-DULTRIX CC=gcc CFLAGS=-O2
httpd: $(OBJS)
$(CC) $(LFLAGS) -o httpd $(OBJS) $(ALL_LIBS)
$(CC) $(LFLAGS) -o httpd $(OBJS) $(EXTRA_LIBS) $(SEC_LIBS) $(DBM_LIBS)
# -logfile=/X11/blong/httpd/logs/pure_log
purify: $(OBJS)
$(PURIFY) -program-name=/X11/blong/httpd/src/httpd \
$(PURIFY) -logfile=/X11/blong/httpd/logs/pure_log \
-program-name=/X11/blong/httpd/src/httpd \
-follow-child-processes=yes \
$(CC) $(LFLAGS) -o httpd $(OBJS) $(ALL_LIBS)
$(CC) $(LFLAGS) -o httpd $(OBJS) $(EXTRA_LIBS) $(SEC_LIBS) $(DBM_LIBS)
quantify: $(OBJS)
$(QUANTIFY) -record-child-process-data=yes \
-record-data=no \
-avoid-recording-system-calls=1,6,93,113,114 \
$(CC) $(LFLAGS) -o httpd $(OBJS) $(ALL_LIBS)
-avoid-recording-system-calls=93,113,114 \
$(CC) $(LFLAGS) -o httpd $(OBJS) $(EXTRA_LIBS) $(SEC_LIBS) $(DBM_LIBS)
tar: $(OBJS)
$(CC) $(LFLAGS) -o ../httpd $(OBJS) $(ALL_LIBS)
$(CC) $(LFLAGS) -o ../httpd $(OBJS) $(EXTRA_LIBS) $(SEC_LIBS) $(DBM_LIBS)
http_access.o: Makefile config.h portability.h constants.h http_access.h \
@ -251,9 +248,10 @@ http_log.o: config.h portability.h constants.h http_log.h \
http_mime.o: Makefile config.h portability.h constants.h http_mime.h \
http_log.h util.h http_config.h http_access.h env.h
http_request.o: Makefile config.h portability.h constants.h http_request.h \
allocate.h cgi.h env.h http_access.h http_alias.h \
host_config.h http_config.h http_log.h http_send.h util.h
imagemap.o: Makefile constants.h imagemap.h allocate.h
util.h http_mime.h http_config.h http_log.h http_auth.h \
httpd.h http_send.h cgi.h http_access.h host_config.h \
http_alias.h env.h
imagemap.o: Makefile constants.h imagemap.h
cgi.o: Makefile config.h portability.h constants.h cgi.h \
http_log.h http_request.h util.h http_mime.h http_access.h \
http_auth.h http_alias.h http_config.h
@ -267,8 +265,6 @@ env.o: config.h portability.h constants.h http_log.h env.h
rfc931.o: config.h portability.h
open_logfile.o: config.h portability.h constants.h open_logfile.h \
http_config.h util.h
allocate.o: config.h portability.h constants.h host_config.h http_log.h \
allocate.h
# file descriptor scoreboarding
fdwrap.o: config.h portability.h constants.h fdwrap.h
@ -286,5 +282,5 @@ SRC = $(OBJS:%.o=%.c)
codecenter:
#setopt ansi
#setopt print_string 128
#setopt load_flags $(ALL_FLAGS)
#load $(LFLAGS) $(SRC) $(ALL_LIBS)
#setopt load_flags $(CFLAGS) $(AUX_CFLAGS) $(SEC_CFLAGS) $(DBM_CFLAGS)
#load $(LFLAGS) $(SRC) $(EXTRA_LIBS) $(SEC_LIBS) $(DBM_LIBS)

View File

@ -1,267 +0,0 @@
/************************************************************************
* NCSA HTTPd Server
* Software Development Group
* National Center for Supercomputing Applications
* University of Illinois at Urbana-Champaign
* 605 E. Springfield, Champaign, IL 61820
* httpd@ncsa.uiuc.edu
*
* Copyright (C) 1995, Board of Trustees of the University of Illinois
*
************************************************************************
*
* allocate.c,v 1.5 1996/04/05 18:54:28 blong Exp
*
************************************************************************
*
* allocate.c: Functions to allocate data types as needed
*
*/
#include "config.h"
#include "portability.h"
#include <stdio.h>
#ifndef NO_STDLIB_H
# include <stdlib.h>
#endif /* NO_STDLIB_H */
#ifndef NO_MALLOC_H
# ifdef NEED_SYS_MALLOC_H
# include <sys/malloc.h>
# else
# include <malloc.h>
# endif /* NEED_SYS_MALLOC_H */
#endif /* NO_MALLOC_H */
#include <string.h>
#include "constants.h"
#include "host_config.h"
#include "http_log.h"
#include "allocate.h"
#include "http_request.h"
string_list free_list;
string_list used_list;
int initialize_allocate()
{
initialize_string_allocate();
return 0;
}
int initialize_string_allocate()
{
free_list.num = 0;
free_list.first = NULL;
used_list.num = 0;
used_list.first = NULL;
allocate_strings(&free_list,HUGE_STRING_LEN,5);
allocate_strings(&free_list,MAX_STRING_LEN,5);
return 0;
}
int allocate_strings(string_list *slist, int length, int num)
{
string_item *stmp;
char *S;
while (num) {
if (!(S = (char *) malloc(length * sizeof(char))))
return 1;
S[0] = '\0';
if (!(stmp = (string_item *) malloc(sizeof(string_item))))
return 1;
stmp->string = S;
stmp->length = length;
if (slist->num == 0) {
slist->first = stmp;
stmp->next = NULL;
slist->num = 1;
} else {
stmp->next = slist->first;
slist->first = stmp;
slist->num++;
}
num--;
}
return 0;
}
int remove_string_item(string_list *slist, string_item *sitem)
{
string_item *stmp,*last;
int x;
stmp = slist->first;
last = NULL;
for(x = 0; x < slist->num ; x++) {
if (stmp == sitem) {
if (stmp == slist->first) {
slist->first = slist->first->next;
} else {
last->next = stmp->next;
}
slist->num--;
stmp->next = NULL;
return TRUE;
}
last = stmp;
stmp = stmp->next;
}
return FALSE;
}
int add_string_item(string_list *slist, string_item *sitem)
{
if (slist->num == 0) {
slist->first = sitem;
slist->num = 1;
} else {
sitem->next = slist->first;
slist->first = sitem;
slist->num++;
}
return TRUE;
}
char* newString(int length, int type)
{
int num, x;
string_item *sitem;
if (free_list.num == 0) {
if ((length == HUGE_STRING_LEN) || (length == MAX_STRING_LEN))
num = 5;
else
num = 1;
allocate_strings(&free_list, length, num);
}
sitem = free_list.first;
for(x = 0; x < free_list.num ; x++) {
if (sitem->length == length) {
remove_string_item(&free_list,sitem);
add_string_item(&used_list,sitem);
sitem->type = type;
return sitem->string;
}
sitem = sitem->next;
}
/* Don't have a string of the correct size, make one.
* Since allocate_strings adds strings to beginning of list, just return
* first string in used_list.
* In the future, might want to just return one which is larger.
*/
allocate_strings(&used_list, length, 1);
used_list.first->type = type;
return used_list.first->string;
}
int freeString(char *string)
{
int x;
string_item *sitem;
if (string == NULL) return FALSE;
sitem = used_list.first;
for(x = 0; x < used_list.num ; x++) {
if (sitem->string == string) {
string[0] = '\0';
remove_string_item(&used_list,sitem);
add_string_item(&free_list,sitem);
return TRUE;
}
sitem = sitem->next;
}
log_error("Attempt to Free String not in Use",gConfiguration->error_log);
return FALSE;
}
/* Look up allocated size of string
* Success returns lenth of string
* Failure returns -1
*/
int sizeofString(char *string)
{
int x;
string_item *sitem;
if (string == NULL) return -1;
sitem = used_list.first;
for(x = 0; x < used_list.num ; x++) {
if (sitem->string == string) {
return sitem->length;
}
sitem = sitem->next;
}
/* log_error("String not allocated.",gConfiguration->error_log); */
return -1;
}
int freeAllStrings(int type)
{
string_item *sitem,*slast;
slast = NULL;
sitem = used_list.first;
while (used_list.num && (sitem != NULL)) {
if (sitem->type <= type) {
sitem->string[0] = '\0';
if (sitem == used_list.first) {
used_list.first = sitem->next;
used_list.num--;
sitem->next = NULL;
add_string_item(&free_list,sitem);
sitem = used_list.first;
} else {
used_list.num--;
slast->next = sitem->next;
add_string_item(&free_list,sitem);
sitem = slast->next;
}
} else {
slast = sitem;
sitem = sitem->next;
}
}
return TRUE;
}
/* dupStringP() : Promotes and copies strings to MAX/HUGE in order to
* attempt to use already existing strings (no malloc). This will
* truncate strings to HUGE length.
*/
char *dupStringP(char *str_in, int type)
{
int req_len;
char *str_out;
req_len = strlen(str_in);
if (req_len <= MAX_STRING_LEN)
req_len = MAX_STRING_LEN;
else
req_len = HUGE_STRING_LEN;
str_out = newString(req_len,type);
strncpy(str_out,str_in,req_len);
str_out[req_len-1] = '\0';
return str_out;
}

View File

@ -1,61 +0,0 @@
/************************************************************************
* NCSA HTTPd Server
* Software Development Group
* National Center for Supercomputing Applications
* University of Illinois at Urbana-Champaign
* 605 E. Springfield, Champaign, IL 61820
* httpd@ncsa.uiuc.edu
*
* Copyright (C) 1995, Board of Trustees of the University of Illinois
*
************************************************************************
*
* allocate.h,v 1.2 1996/04/05 18:54:29 blong Exp
*
************************************************************************
*
* allocate.h: Functions to allocate data types as needed
*
*/
#ifndef _ALLOCATE_H
#define _ALLOCATE_H 1
/* There are different levels of strings, depending on when they can
* be "free'd".
* STR_TMP can be free'd outside the function.
* STR_REQ can be free'd at the end of the request.
* STR_HUP can be free'd at Restart.
*/
#define STR_TMP 0
#define STR_REQ 2
#define STR_HUP 5
typedef struct _string_item {
char *string;
int length;
int type;
struct _string_item* next;
} string_item;
typedef struct _string_list {
string_item* first;
int num;
} string_list;
/* Public Interface */
int initialize_allocate(void);
char* newString(int length, int type);
char *dupStringP(char *str_in, int type);
int freeString(char *string);
int freeAllStrings(int type);
int sizeofString(char *string);
/* Private Interface */
int initialize_string_allocate();
int allocate_strings(string_list *slist, int length, int num);
int remove_string_item(string_list *slist, string_item *sitem);
int add_string_item(string_list *slist, string_item *sitem);
#endif /* _ALLOCATE_H */

View File

@ -1,187 +0,0 @@
/************************************************************************
* NCSA HTTPd Server
* Software Development Group
* National Center for Supercomputing Applications
* University of Illinois at Urbana-Champaign
* 605 E. Springfield, Champaign, IL 61820
* httpd@ncsa.uiuc.edu
*
* Copyright (C) 1995, Board of Trustees of the University of Illinois
*
************************************************************************
*
* blackout.c,v 1.3 1996/03/07 21:27:21 blong Exp
*
************************************************************************
*
*/
#include "config.h"
#include "portability.h"
#include <stdio.h>
#ifndef NO_STDLIB_H
# include <stdlib.h>
#endif /* NO_STDLIB_H */
#include <string.h>
#include <sys/stat.h>
#include <errno.h>
#include <signal.h>
#include <setjmp.h>
#include <ctype.h>
#include "constants.h"
#include "fdwrap.h"
#include "allocate.h"
#include "http_send.h"
#include "cgi.h"
#include "imagemap.h"
#include "http_mime.h"
#include "http_log.h"
#include "http_request.h"
#include "http_config.h"
#include "http_include.h"
#include "http_alias.h"
#include "http_access.h"
#include "http_dir.h"
#include "httpd.h"
#include "util.h"
#ifdef BLACKOUT_CODE
char *bodyTag = "<BODY BGCOLOR=\"#000000\" TEXT=\"#FFFFFF\" LINK=\"#0099FF\" VLINK=\"#00FF99\"\n>";
static void (*exit_callback)(void);
int realWrite(int fd, char *buf, int length)
{
int left = length;
int sent = 0;
int off = 0;
int wrote = 0;
while(left) {
if ((wrote = write(fd,&buf[off],left)) < 0) {
if (errno != EINTR) break;
}
left -= wrote;
off += wrote;
sent += wrote;
}
return sent;
}
int sendBody(per_request *reqInfo, char *buf, int length)
{
int x = 0;
int found = 0;
int state = 0;
int begin = 0;
while(x < length) {
switch (state) {
case 0 :
if (buf[x] == '<') {
begin = x;
state++;
}
break;
case 1 :
if ((buf[x] == 'B') || (buf[x] == 'b')) state++;
else state = 0;
break;
case 2 :
if ((buf[x] == 'O') || (buf[x] == 'o')) state++;
else state = 0;
break;
case 3 :
if ((buf[x] == 'D') || (buf[x] == 'd')) state++;
else state = 0;
break;
case 4 :
if ((buf[x] == 'Y') || (buf[x] == 'y')) state++;
else state = 0;
break;
/* case 5 :
if (buf[x] == ' ') state++;
else state = 0;
break; */
case 5 :
if (buf[x] == '>') state++;
break;
case 6 :
realWrite(fileno(reqInfo->out), buf,begin);
realWrite(fileno(reqInfo->out), bodyTag, strlen(bodyTag));
realWrite(fileno(reqInfo->out), buf+x,length-x);
x = length;
}
x++;
}
if (state != 6) realWrite(fileno(reqInfo->out),buf,length);
return FALSE;
}
/*
We'll make it return the number of bytes sent
so that we know if we need to send a body by default
*/
long send_fp_black(per_request *reqInfo, FILE *f, void (*onexit)(void))
{
char *buf;
long total_bytes_sent;
register int n,o,w;
int isHTML = FALSE;
buf = newString(IOBUFSIZE,STR_TMP);
exit_callback = onexit;
signal(SIGALRM,send_fd_timed_out);
signal(SIGPIPE,send_fd_timed_out);
total_bytes_sent = 0;
if (!strcmp(reqInfo->outh_content_type,"text/html")) {
isHTML = TRUE;
total_bytes_sent = rprintf(reqInfo,bodyTag);
}
rflush(reqInfo);
while (1) {
alarm(timeout);
if((n=fread(buf,sizeof(char),IOBUFSIZE,f)) < 1) {
if (errno != EINTR) break;
}
o=0;
if(reqInfo->bytes_sent != -1)
reqInfo->bytes_sent += n;
if (isHTML) {
sendBody(reqInfo,buf,n);
total_bytes_sent += n;
n = 0;
}
while(n) {
/* Seems some systems have broken fwrite's (like AIX 3.2.5 on PowerPC)
* this should be a drop in replacement, maybe even be faster.
* For now, we'll just replace, but may have to #define one or the other
* depending on the system.
*/
if ((w=write(fileno(reqInfo->out),&buf[o],n)) < 0) {
if (errno != EINTR) break;
}
n-=w;
o+=w;
total_bytes_sent += w;
}
}
if (isHTML)
rprintf(reqInfo,"<HR><a href=\"http://www.vtw.org/speech/\">My World Wide Web Pages are black for 48 hours to protest second-class treatment from the US Government for free speech. Read about it at this WWW page.</a>");
alarm(0);
signal(SIGALRM,SIG_IGN);
signal(SIGPIPE,SIG_IGN);
freeString(buf);
return total_bytes_sent;
}
#endif /* BLACKOUT_CODE */

View File

@ -1,26 +0,0 @@
/************************************************************************
* NCSA HTTPd Server
* Software Development Group
* National Center for Supercomputing Applications
* University of Illinois at Urbana-Champaign
* 605 E. Springfield, Champaign, IL 61820
* httpd@ncsa.uiuc.edu
*
* Copyright (C) 1995, Board of Trustees of the University of Illinois
*
************************************************************************
*
* blackout.h,v 1.1 1996/02/08 18:01:02 blong Exp
*
************************************************************************
*
*/
#ifndef _BLACKOUT_H
#define _BLACKOUT_H
/* function prototypes */
long send_fp_black(per_request *reqInfo, FILE *f, void (*onexit)(void));
#endif /* _BLACKOUT_H */

651
src/cgi.c
View File

@ -10,7 +10,7 @@
*
************************************************************************
*
* cgi.c,v 1.44 1996/04/05 18:54:31 blong Exp
* cgi.c,v 1.34 1995/11/28 09:01:37 blong Exp
*
************************************************************************
*
@ -56,34 +56,21 @@
#include <errno.h>
#include <sys/stat.h>
#include <signal.h>
#include <sys/wait.h>
#include "constants.h"
#include "fdwrap.h"
#include "allocate.h"
#include "cgi.h"
#include "env.h"
#include "http_access.h"
#include "http_alias.h"
#include "http_auth.h"
#include "http_config.h"
#include "http_include.h"
#include "http_log.h"
#include "http_mime.h"
#include "http_request.h"
#include "http_send.h"
#include "http_include.h"
#include "httpd.h"
#include "http_log.h"
#include "http_access.h"
#include "http_mime.h"
#include "http_config.h"
#include "http_auth.h"
#include "http_alias.h"
#include "util.h"
int pid;
#ifdef KRB4
# include <krb.h>
extern AUTH_DAT kerb_kdata;
# include <string.h>
#endif /* KRB4 */
void kill_children(per_request *reqInfo) {
char errstr[MAX_STRING_LEN];
sprintf(errstr,"killing CGI process %d",pid);
@ -95,83 +82,75 @@ void kill_children(per_request *reqInfo) {
waitpid(pid,NULL,0);
}
#ifdef KRB4
# include <krb.h>
extern AUTH_DAT kerb_kdata;
# include <string.h>
#endif /* KRB4 */
char **create_argv(per_request *reqInfo,char *av0) {
register int x,n;
char **av;
char *str1,*str2;
str1 = newString(HUGE_STRING_LEN,STR_TMP);
str2 = newString(HUGE_STRING_LEN,STR_TMP);
char w[HUGE_STRING_LEN];
char l[HUGE_STRING_LEN];
for(x=0,n=2;reqInfo->args[x];x++)
if(reqInfo->args[x] == '+') ++n;
if(!(av = (char **)malloc((n+1)*sizeof(char *)))) {
freeString(str1);
freeString(str2);
if(!(av = (char **)malloc((n+1)*sizeof(char *))))
die(reqInfo,SC_NO_MEMORY,"create_argv");
}
av[0] = av0;
strcpy(str2,reqInfo->args);
strcpy(l,reqInfo->args);
for(x=1;x<n;x++) {
getword(str1,str2,'+');
unescape_url(str1);
escape_shell_cmd(str1);
if(!(av[x] = strdup(str1))) {
freeString(str1);
freeString(str2);
getword(w,l,'+');
unescape_url(w);
escape_shell_cmd(w);
if(!(av[x] = strdup(w)))
die(reqInfo,SC_NO_MEMORY,"create_argv");
}
}
av[n] = NULL;
freeString(str1);
freeString(str2);
return av;
}
void get_path_info(per_request *reqInfo, struct stat *finfo)
void get_path_info(per_request *reqInfo, char *path_args,
struct stat *finfo)
{
register int x,max;
char *str;
str = newString(HUGE_STRING_LEN,STR_TMP);
char t[HUGE_STRING_LEN];
path_args[0] = '\0';
max=count_dirs(reqInfo->filename);
for(x=dirs_in_alias;x<=max;x++) {
make_dirstr(reqInfo->filename,x+1,str);
if(!(stat(str,finfo))) {
make_dirstr(reqInfo->filename,x+1,t);
if(!(stat(t,finfo))) {
if(S_ISREG(finfo->st_mode)) {
int l=strlen(str);
strcpy(reqInfo->path_info,&(reqInfo->filename[l]));
int l=strlen(t);
strcpy(path_args,&(reqInfo->filename[l]));
reqInfo->filename[l] = '\0';
reqInfo->url[strlen(reqInfo->url) - strlen(reqInfo->path_info)] = '\0';
freeString(str);
reqInfo->url[strlen(reqInfo->url) - strlen(path_args)] = '\0';
return;
}
}
}
for(x=dirs_in_alias - 1; (x > 0) ;--x) {
make_dirstr(reqInfo->filename,x+1,str);
if(!(stat(str,finfo))) {
make_dirstr(reqInfo->filename,x+1,t);
if(!(stat(t,finfo))) {
if(S_ISREG(finfo->st_mode)) {
strcpy(reqInfo->path_info,&(reqInfo->filename[strlen(str)]));
strcpy(reqInfo->filename,str);
reqInfo->url[strlen(reqInfo->url) - strlen(reqInfo->path_info)] = '\0';
freeString(str);
strcpy(path_args,&(reqInfo->filename[strlen(t)]));
strcpy(reqInfo->filename,t);
reqInfo->url[strlen(reqInfo->url) - strlen(path_args)] = '\0';
return;
}
}
}
/* unmunge_name(reqInfo,reqInfo->filename); */
log_reason(reqInfo,"script does not exist",reqInfo->filename);
freeString(str);
die(reqInfo,SC_NOT_FOUND,reqInfo->url);
}
int add_cgi_vars(per_request *reqInfo, int *content)
int add_cgi_vars(per_request *reqInfo, char *path_args, int *content)
{
char *str;
str = newString(HUGE_STRING_LEN,STR_TMP);
char t[HUGE_STRING_LEN];
make_env_str(reqInfo,"GATEWAY_INTERFACE","CGI/1.1");
@ -181,10 +160,10 @@ int add_cgi_vars(per_request *reqInfo, int *content)
methods[reqInfo->method]);
make_env_str(reqInfo,"SCRIPT_NAME",reqInfo->url);
if(reqInfo->path_info[0]) {
make_env_str(reqInfo,"PATH_INFO",reqInfo->path_info);
translate_name(reqInfo,reqInfo->path_info,str);
make_env_str(reqInfo,"PATH_TRANSLATED",str);
if(path_args[0]) {
make_env_str(reqInfo,"PATH_INFO",path_args);
translate_name(reqInfo,path_args,t);
make_env_str(reqInfo,"PATH_TRANSLATED",t);
}
make_env_str(reqInfo,"QUERY_STRING",reqInfo->args);
@ -192,21 +171,18 @@ int add_cgi_vars(per_request *reqInfo, int *content)
*content=0;
if ((reqInfo->method == M_POST) || (reqInfo->method == M_PUT)) {
*content=1;
sprintf(str,"%d",reqInfo->inh_content_length);
make_env_str(reqInfo,"CONTENT_TYPE",reqInfo->inh_content_type);
make_env_str(reqInfo,"CONTENT_LENGTH",str);
sprintf(t,"%d",content_length);
make_env_str(reqInfo,"CONTENT_TYPE",content_type_in);
make_env_str(reqInfo,"CONTENT_LENGTH",t);
}
}
freeString(str);
return TRUE;
}
int add_common_vars(per_request *reqInfo) {
char *env_path,*env_tz;
char *str;
char t[MAX_STRING_LEN],*env_path,*env_tz;
str = newString(HUGE_STRING_LEN,STR_TMP);
if(!(env_path = getenv("PATH")))
env_path=DEFAULT_PATH;
@ -217,32 +193,32 @@ int add_common_vars(per_request *reqInfo) {
make_env_str(reqInfo,"SERVER_NAME",reqInfo->hostInfo->server_hostname);
make_env_str(reqInfo,"SERVER_ADMIN",reqInfo->hostInfo->server_admin);
sprintf(str,"%d",port);
make_env_str(reqInfo,"SERVER_PORT",str);
sprintf(t,"%d",port);
make_env_str(reqInfo,"SERVER_PORT",t);
make_env_str(reqInfo,"REMOTE_HOST",reqInfo->remote_name);
make_env_str(reqInfo,"REMOTE_ADDR",reqInfo->remote_ip);
make_env_str(reqInfo,"DOCUMENT_ROOT",reqInfo->hostInfo->document_root);
if(reqInfo->auth_user[0])
make_env_str(reqInfo,"REMOTE_USER",reqInfo->auth_user);
if(reqInfo->auth_group[0])
make_env_str(reqInfo,"REMOTE_GROUP",reqInfo->auth_group);
if(user[0])
make_env_str(reqInfo,"REMOTE_USER",user);
if(reqInfo->hostInfo->annotation_server[0])
make_env_str(reqInfo,"ANNOTATION_SERVER",
reqInfo->hostInfo->annotation_server);
if(groupname[0])
make_env_str(reqInfo,"REMOTE_GROUP",groupname);
if (reqInfo->auth_type[0]) {
#ifdef KRB4
if(strncmp(reqInfo->auth_type, "kerberos", 8) == 0) {
char buffer[1024];
make_env_str(reqInfo,"AUTH_TYPE","KERB4_MUTUAL");
make_env_str(reqInfo,"KERB4_USER",kerb_kdata.pname);
make_env_str(reqInfo,"KERB4_INSTANCE",kerb_kdata.pinst);
make_env_str(reqInfo,"KERB4_REALM",kerb_kdata.prealm);
sprintf (str, "%s.%s@%s", kerb_kdata.pname,
sprintf (buffer, "%s.%s@%s", kerb_kdata.pname,
kerb_kdata.pinst, kerb_kdata.prealm);
make_env_str(reqInfo,"KERB4_PRINCIPAL",str);
make_env_str(reqInfo,"KERB4_PRINCIPAL",buffer);
} else
#endif /* KRB4 */
make_env_str(reqInfo,"AUTH_TYPE",reqInfo->auth_type);
@ -258,353 +234,268 @@ int add_common_vars(per_request *reqInfo) {
make_env_str(reqInfo,"REDIRECT_STATUS",set_stat_line(reqInfo));
}
freeString(str);
return TRUE;
}
int scan_cgi_header(per_request *reqInfo, int pd)
int scan_script_header(per_request *reqInfo, int pd)
{
char w[HUGE_STRING_LEN];
char *l;
int p;
int nFirst = 1;
int ret;
int options = 0;
char *str;
str = newString(HUGE_STRING_LEN,STR_TMP);
/* Don't do keepalive unless the script returns a content-length
header */
keep_alive.bKeepAlive = 0;
reqInfo->cgi_buf = new_sock_buf(reqInfo,pd);
cgibuf_count++;
/* ADC put in the G_SINGLE_CHAR option, so that CGI SSI's would work.
* it was:
* if((ret = getline(reqInfo->cgi_buf,str,HUGE_STRING_LEN-1,0,timeout)) <= 0)
*
* This should be cleaned up perhaps so that it only does this if SSI's are
* allowed for this script directory. ZZZZ
*/
#ifdef CGI_SSI_HACK
if (reqInfo->RequestFlags & DOING_SHTTP)
options = G_SINGLE_CHAR;
#endif /* CGI_SSI_HACK */
while(1) {
if((ret = getline(reqInfo->cgi_buf,str,HUGE_STRING_LEN-1,options,timeout)) <= 0)
{
char error_msg[MAX_STRING_LEN];
Close(pd);
freeString(str);
sprintf(error_msg,"HTTPd: malformed header from script %s",
reqInfo->filename);
die(reqInfo,SC_SERVER_ERROR,error_msg);
}
if((ret = getline(pd,w,HUGE_STRING_LEN-1,nFirst,timeout)) <= 0) {
char error_msg[MAX_STRING_LEN];
Close(pd);
sprintf(error_msg,"HTTPd: malformed header from script %s",
reqInfo->filename);
die(reqInfo,SC_SERVER_ERROR,error_msg);
}
/* turn off forced read off socket */
if (nFirst) nFirst = 0;
/* Always return zero, so as not to cause redirect+sleep3+kill */
if(str[0] == '\0') {
if (reqInfo->outh_content_type[0] == '\0') {
if (reqInfo->outh_location[0] != '\0') {
strcpy(reqInfo->outh_content_type,"text/html");
if(w[0] == '\0') {
if (content_type[0] == '\0') {
if (location[0] != '\0') {
strcpy(content_type,"text/html");
} else {
if (local_default_type[0] != '\0')
strcpy(reqInfo->outh_content_type,local_default_type);
else strcpy(reqInfo->outh_content_type,
reqInfo->hostInfo->default_type);
strcpy(content_type,local_default_type);
else strcpy(content_type,reqInfo->hostInfo->default_type);
}
}
freeString(str);
return 0;
}
if(!(l = strchr(str,':')))
l = str;
if(!(l = strchr(w,':')))
l = w;
*l++ = '\0';
if(!strcasecmp(str,"Content-type")) {
if(!strcasecmp(w,"Content-type")) {
/* Thanks Netscape for showing this bug to everyone */
/* delete trailing whitespace, esp. for "server push" */
char *endp = l + strlen(l) - 1;
while ((endp > l) && isspace(*endp)) *endp-- = '\0';
sscanf(l,"%s",reqInfo->outh_content_type);
sscanf(l,"%s",content_type);
}
else if(!strcasecmp(str,"Location")) {
else if(!strcasecmp(w,"Location")) {
/* If we don't already have a status line, make one */
if (!reqInfo->status_line) {
reqInfo->status = SC_REDIRECT_TEMP;
if (!&status_line[0]) {
reqInfo->status = 302;
set_stat_line(reqInfo);
}
sscanf(l,"%s",reqInfo->outh_location);
sscanf(l,"%s",location);
}
else if(!strcasecmp(str,"Status")) {
else if(!strcasecmp(w,"Status")) {
for(p=0;isspace(l[p]);p++);
sscanf(&l[p],"%d",&(reqInfo->status));
if(!(reqInfo->status_line = dupStringP(&l[p],STR_REQ))) {
sscanf(&l[p],"%d",&reqInfo->status);
if(!(status_line = strdup(&l[p]))) {
Close(pd);
freeString(str);
die(reqInfo,SC_NO_MEMORY,"CGI: scan_cgi_header");
die(reqInfo,SC_NO_MEMORY,"CGI: scan_script_header");
}
}
else if(!strcasecmp(str,"Content-length")) {
else if(!strcasecmp(w,"Content-length")) {
keep_alive.bKeepAlive = 1;
sscanf(l,"%d",&(reqInfo->outh_content_length));
}
else if(!strcasecmp(str,"WWW-Authenticate")) {
if (!reqInfo->status_line) {
reqInfo->status = SC_AUTH_REQUIRED;
set_stat_line(reqInfo);
}
strncpy(reqInfo->outh_www_auth,l,HUGE_STRING_LEN);
reqInfo->outh_www_auth[HUGE_STRING_LEN-1] = '\0';
}
else {
*(--l) = ':';
for(p=0;str[p];p++);
str[p] = LF;
str[++p] = '\0';
if(!(reqInfo->outh_cgi)) {
if(!(reqInfo->outh_cgi = strdup(str))) {
for(p=0;w[p];p++);
w[p] = LF;
w[++p] = '\0';
if(!out_headers) {
if(!(out_headers = strdup(w))) {
Close(pd);
freeString(str);
die(reqInfo,SC_NO_MEMORY,"CGI: scan_cgi_header");
die(reqInfo,SC_NO_MEMORY,"CGI: scan_script_header");
}
}
else {
int loh = strlen(reqInfo->outh_cgi);
reqInfo->outh_cgi = (char *) realloc(reqInfo->outh_cgi,
(loh+strlen(str)+1)*sizeof(char));
if(!(reqInfo->outh_cgi)) {
int loh = strlen(out_headers);
out_headers = (char *) realloc(out_headers,
(loh+strlen(w)+1)*sizeof(char));
if(!out_headers) {
Close(pd);
freeString(str);
die(reqInfo,SC_NO_MEMORY,"CGI: scan_cgi_header");
die(reqInfo,SC_NO_MEMORY,"CGI: scan_script_header");
}
strcpy(&(reqInfo->outh_cgi[loh]),str);
strcpy(&out_headers[loh],w);
}
}
}
}
void internal_redirect(per_request *reqInfo)
int cgi_stub(per_request *reqInfo, char *path_args, struct stat *finfo)
{
char url[HUGE_STRING_LEN],args[HUGE_STRING_LEN],*argp;
per_request *newInfo;
int p[2], p2[2]; /* p = script-> server, p2 = server -> script */
int content, nph;
char *argv0;
char errlog[100];
url[0] = '\0';
args[0] = '\0';
/* Split the location header into URL and args */
strncpy(url,reqInfo->outh_location,HUGE_STRING_LEN);
if((argp = strchr(url,'?'))) {
*argp++ = '\0';
strcpy(args,argp);
}
log_transaction(reqInfo);
/* The global string the_request currently holds the request as
* read off the socket, and is used to log the information. We force
* it to this internal request here. Only redirects to GET requests
*/
sprintf(the_request,"GET ");
strncat(the_request,url,HUGE_STRING_LEN - strlen(the_request));
if (args[0] != '\0') {
strncat(the_request,"?",HUGE_STRING_LEN - strlen(the_request));
strncat(the_request,args, HUGE_STRING_LEN - strlen(the_request));
}
strncat(the_request," ",HUGE_STRING_LEN - strlen(the_request));
/* Replace the protocal with Internal to let people know it was an
* internal redirect.
*/
/* strncat(the_request, protocals[reqInfo->http_version],
HUGE_STRING_LEN - strlen(the_request)); */
strncat(the_request, "Internal",HUGE_STRING_LEN - strlen(the_request));
newInfo = continue_request(reqInfo, KEEP_AUTH | FORCE_GET);
newInfo->status = SC_DOCUMENT_FOLLOWS;
set_stat_line(newInfo);
strcpy(newInfo->url, url);
strcpy(newInfo->args, args);
construct_url(newInfo->outh_location,reqInfo->hostInfo,
reqInfo->outh_location);
process_request(newInfo);
}
int cgi_stub(per_request *reqInfo, struct stat *finfo, int allow_options)
{
int p[2], p2[2]; /* p = script-> server, p2 = server -> script */
int content, nph;
char *argv0;
char errlog[100];
FILE *fp = NULL;
if(!can_exec(finfo)) {
log_reason(reqInfo,
"client denied by server configuration (CGI non-executable)",
reqInfo->filename);
die(reqInfo,SC_FORBIDDEN,reqInfo->url);
}
if((argv0 = strrchr(reqInfo->filename,'/')) != NULL)
argv0++;
else argv0 = reqInfo->filename;
chdir_file(reqInfo->filename);
if(Pipe(p) < 0)
die(reqInfo,SC_SERVER_ERROR,"HTTPd/CGI: could not create IPC pipe");
if(Pipe(p2) < 0) {
Close(p[0]);
Close(p[1]);
die(reqInfo,SC_SERVER_ERROR,"HTTPd/CGI: could not create IPC pipe");
}
if((pid = fork()) < 0) {
Close(p[0]);
Close(p[1]);
Close(p2[0]);
Close(p2[1]);
sprintf(errlog,"HTTPd/CGI: could not fork new process, errno is %d",
errno);
die(reqInfo,SC_SERVER_ERROR,errlog);
}
nph = (strncmp(argv0,"nph-",4) ? 0 : 1);
if(!pid) {
Close(p[0]);
Close(p2[1]);
standalone = 0;
add_cgi_vars(reqInfo,&content);
/* TAKE OUT "if (nph)" THROUGH "else {" IF SHIT HAPPENS */
if (nph) {
if (fileno(reqInfo->out) != STDOUT_FILENO) {
dup2(fileno(reqInfo->out), STDOUT_FILENO);
close(fileno(reqInfo->out));
}
if(!can_exec(finfo)) {
log_reason(reqInfo,
"client denied by server configuration (CGI non-executable)",
reqInfo->filename);
die(reqInfo,SC_FORBIDDEN,reqInfo->url);
}
else
dup2(p[1],STDOUT_FILENO);
Close(p[1]);
dup2(p2[0],STDIN_FILENO);
Close(p2[0]);
/* Close the socket so the CGI program doesn't hold it open */
close(csd);
if((argv0 = strrchr(reqInfo->filename,'/')) != NULL)
argv0++;
else argv0 = reqInfo->filename;
error_log2stderr(reqInfo->hostInfo->error_log);
/* To make the signal handling work on HPUX, according to
* David-Michael Lincke (dlincke@bandon.unisg.ch)
*/
chdir_file(reqInfo->filename);
if(Pipe(p) < 0)
die(reqInfo,SC_SERVER_ERROR,"HTTPd/CGI: could not create IPC pipe");
if(Pipe(p2) < 0) {
Close(p[0]);
Close(p[1]);
die(reqInfo,SC_SERVER_ERROR,"HTTPd/CGI: could not create IPC pipe");
}
if((pid = fork()) < 0) {
Close(p[0]);
Close(p[1]);
Close(p2[0]);
Close(p2[1]);
sprintf(errlog,"HTTPd/CGI: could not fork new process, errno is %d",
errno);
die(reqInfo,SC_SERVER_ERROR,errlog);
}
nph = (strncmp(argv0,"nph-",4) ? 0 : 1);
if(!pid) {
Close(p[0]);
Close(p2[1]);
standalone = 0;
add_cgi_vars(reqInfo,path_args,&content);
/* TAKE OUT "if (nph)" THROUGH "else {" IF SHIT HAPPENS */
if (nph) {
if (reqInfo->connection_socket != STDOUT_FILENO) {
dup2(reqInfo->connection_socket, STDOUT_FILENO);
close(reqInfo->connection_socket);
}
}
else
dup2(p[1],STDOUT_FILENO);
Close(p[1]);
dup2(p2[0],STDIN_FILENO);
Close(p2[0]);
/* Need to close the connection for processes which spawn processes.
* is there a CLOSE_ON_EXEC_ON_EXEC ? */
/* close(reqInfo->connection_socket); */
/* fclose(reqInfo->out); */
error_log2stderr(reqInfo->hostInfo->error_log);
/* To make the signal handling work on HPUX, according to
David-Michael Lincke (dlincke@bandon.unisg.ch) */
#ifdef HPUX
signal(SIGCHLD, SIG_DFL);
signal(SIGCHLD, SIG_DFL);
#endif /* HPUX */
/* Only ISINDEX scripts get decoded arguments. */
if((!reqInfo->args[0]) || (ind(reqInfo->args,'=') >= 0)) {
execle(reqInfo->filename,argv0,NULL,reqInfo->env);
/* Only ISINDEX scripts get decoded arguments. */
if((!reqInfo->args[0]) || (ind(reqInfo->args,'=') >= 0)) {
execle(reqInfo->filename,argv0,NULL,reqInfo->env);
}
else {
execve(reqInfo->filename,create_argv(reqInfo,argv0),
reqInfo->env);
}
fprintf(stderr,"HTTPd/CGI: exec of %s failed, errno is %d\n",
reqInfo->filename,errno);
exit(1);
}
else {
execve(reqInfo->filename,create_argv(reqInfo,argv0),
reqInfo->env);
Close(p[1]);
Close(p2[0]);
if (content_length > 0) {
/* read content off socket and write to script */
char szBuf[IOBUFSIZE];
int nBytes, nTotalBytes = 0;
int nDone = 0;
}
fprintf(stderr,"HTTPd/CGI: exec of %s failed, errno is %d\n",
reqInfo->filename,errno);
exit(1);
}
else {
Close(p[1]);
Close(p2[0]);
if (reqInfo->inh_content_length > 0) {
/* read content off socket and write to script */
char szBuf[HUGE_STRING_LEN];
int nBytes, nTotalBytes = 0;
int nDone = 0;
signal(SIGPIPE,SIG_IGN);
nBytes=getline(reqInfo->sb, szBuf,HUGE_STRING_LEN,G_FLUSH, timeout);
nTotalBytes = nBytes;
if (nBytes >= 0) {
if (nBytes > 0) write(p2[1], szBuf, nBytes);
while (!nDone && (nTotalBytes < reqInfo->inh_content_length)) {
nBytes=read(reqInfo->in, szBuf,HUGE_STRING_LEN);
if(nBytes < 1) {
break;
}
write(p2[1], szBuf, nBytes);
nTotalBytes += nBytes;
}
}
}
Close(p2[1]);
}
if(!nph) {
reqInfo->outh_content_type[0] = '\0';
scan_cgi_header(reqInfo,p[0]);
if(reqInfo->outh_location[0] == '/') {
Close(p[0]);
waitpid(pid,NULL,0);
internal_redirect(reqInfo);
return SC_REDIRECT_LOCAL;
}
reqInfo->outh_content_length = -1;
/* Previously, this was broken because we read the results of the CGI using
* getline, but the SSI parser used buffered stdio.
*
* ADC changed scan_cgi_header so that it uses G_SINGLE_CHAR when it
* calls getline. Yes, this means pitiful performance for CGI scripts.
*/
/* Fine, parse the output of CGI scripts. Talk about useless
* overhead. . .
*/
#ifdef CGI_SSI_HACK
if (!strcasecmp(reqInfo->outh_content_type, INCLUDES_MAGIC_TYPE) &&
(allow_options & OPT_INCLUDES)) {
strcpy(reqInfo->outh_content_type, "text/html");
if(reqInfo->http_version != P_HTTP_0_9)
send_http_header(reqInfo);
if(reqInfo->method != M_HEAD) {
rflush(reqInfo);
alarm(timeout);
add_include_vars(reqInfo,DEFAULT_TIME_FORMAT);
if (!(fp = FdOpen(p[0],"r"))) {
char errstr[MAX_STRING_LEN];
sprintf(errstr,"HTTPd/CGI/SSI: Could not fdopen() fildes, errno is %d.",errno);
die(reqInfo,SC_SERVER_ERROR,errstr);
signal(SIGPIPE,SIG_IGN);
nBytes=getline(reqInfo->connection_socket, szBuf,IOBUFSIZE,2,
timeout);
nTotalBytes = nBytes;
write (p2[1], szBuf, nBytes);
while (!nDone && (nTotalBytes < content_length)) {
if((nBytes=read(reqInfo->connection_socket,
szBuf,IOBUFSIZE)) < 1) {
break;
}
write (p2[1], szBuf, nBytes);
nTotalBytes += nBytes;
}
}
send_parsed_content(reqInfo,fp,allow_options & OPT_EXECCGI);
}
}
else
#endif /* CGI_SSI_HACK */
{ /* Not Parsed, send normally */
if(reqInfo->http_version != P_HTTP_0_9)
send_http_header(reqInfo);
if(reqInfo->method != M_HEAD) {
/* Send a default body of text if the script
* failed to produce any, but ONLY for redirects
*/
if (!send_fd(reqInfo,p[0],NULL) && reqInfo->outh_location[0]) {
title_html(reqInfo,"Document moved");
rprintf(reqInfo,
"This document has temporarily moved <A HREF=\"%s\">here</A>.</P>%c",
reqInfo->outh_location,LF);
}
} else
kill_children(reqInfo);
}
}
else { /* Is nph- script */
reqInfo->bytes_sent = -1;
/* If there is KeepAlive going on, its handled internally to the
script. This means that we want to close the connection after
the nph- script has finished. */
keep_alive.bKeepAlive = 0;
}
Close(p2[1]);
}
waitpid(pid,NULL,0);
if (fp != NULL) FClose(fp); else Close(p[0]);
return SC_DOCUMENT_FOLLOWS;
if(!nph) {
content_type[0] = '\0';
scan_script_header(reqInfo,p[0]);
if(location[0] == '/') {
char t[HUGE_STRING_LEN],a[HUGE_STRING_LEN],*argp;
a[0] = '\0';
Close(p[0]);
waitpid(pid,NULL,0);
strcpy(t,location);
if((argp = strchr(t,'?'))) {
*argp++ = '\0';
strcpy(a,argp);
}
reqInfo->status = SC_REDIRECT_TEMP;
log_transaction(reqInfo);
reqInfo->status = SC_DOCUMENT_FOLLOWS;
init_header_vars(reqInfo); /* clear location */
sprintf(the_request,"GET ");
strncat(the_request,t,HUGE_STRING_LEN - strlen(the_request));
if (a[0] != '\0') {
strncat(the_request,"?",HUGE_STRING_LEN - strlen(the_request));
strncat(the_request,a, HUGE_STRING_LEN - strlen(the_request));
}
strncat(the_request," ",HUGE_STRING_LEN - strlen(the_request));
strncat(the_request, protocals[reqInfo->http_version],
HUGE_STRING_LEN - strlen(the_request));
reqInfo = continue_request(reqInfo, KEEP_AUTH | FORCE_GET);
strcpy(reqInfo->url, t);
strcpy(reqInfo->args, a);
process_request(reqInfo);
return SC_REDIRECT_LOCAL;
}
content_length = -1;
if(!no_headers)
send_http_header(reqInfo);
if(!header_only) {
/* Send a default body of text if the script
failed to produce any, but ONLY for redirects */
if (!send_fd(reqInfo,p[0],NULL) && location[0]) {
title_html(reqInfo,"Document moved");
fprintf(reqInfo->out,
"This document has temporarily moved <A HREF=\"%s\">here</A>.</P>%c",
location,LF);
}
} else
kill_children(reqInfo);
}
else {
reqInfo->bytes_sent = -1;
/* If there is KeepAlive going on, its handled internally to the
script. This means that we want to close the connection after
the nph- script has finished. */
keep_alive.bKeepAlive = 0;
}
waitpid(pid,NULL,0);
Close(p[0]);
return SC_DOCUMENT_FOLLOWS;
}
/*
@ -613,30 +504,23 @@ int cgi_stub(per_request *reqInfo, struct stat *finfo, int allow_options)
*/
long send_fd(per_request *reqInfo, int pd, void (*onexit)(void))
{
char *buf;
char buf[IOBUFSIZE];
register int n,w,o;
int fd;
buf = newString(IOBUFSIZE,STR_TMP);
signal(SIGALRM,send_fd_timed_out);
signal(SIGPIPE,send_fd_timed_out);
/* Flush stdio pipe, since scripts now use non buffered i/o */
rflush(reqInfo);
fflush(reqInfo->out);
fd = fileno(reqInfo->out);
alarm(timeout);
if (reqInfo->cgi_buf != NULL)
n=getline(reqInfo->cgi_buf, buf,IOBUFSIZE,G_FLUSH,timeout);
else
n = 0;
n=getline(pd, buf,IOBUFSIZE,2,timeout);
while (1) {
o=0;
while(n) {
w = write(fd, buf + o,n);
if (w < 1) {
if ((w=write(fd, buf + o,n)) < 1) {
if (errno != EINTR) break;
}
n-=w;
@ -654,18 +538,18 @@ long send_fd(per_request *reqInfo, int pd, void (*onexit)(void))
alarm(0);
signal(SIGALRM,SIG_IGN);
signal(SIGPIPE,SIG_IGN);
freeString(buf);
return reqInfo->bytes_sent;
}
/* Called for ScriptAliased directories */
void exec_cgi_script(per_request *reqInfo) {
struct stat finfo;
char path_args[HUGE_STRING_LEN];
int stub_returns;
int allow;
char allow_options;
get_path_info(reqInfo,&finfo);
get_path_info(reqInfo,path_args,&finfo);
evaluate_access(reqInfo,&finfo,&allow,&allow_options);
if(!allow) {
@ -677,11 +561,11 @@ void exec_cgi_script(per_request *reqInfo) {
add_common_vars(reqInfo);
reqInfo->bytes_sent = 0;
stub_returns = cgi_stub(reqInfo,&finfo,allow_options);
stub_returns = cgi_stub(reqInfo,path_args,&finfo);
switch (stub_returns) {
case SC_REDIRECT_TEMP:
die(reqInfo,SC_REDIRECT_TEMP,reqInfo->outh_location);
die(reqInfo,SC_REDIRECT_TEMP,location);
break;
case SC_REDIRECT_LOCAL:
break;
@ -697,7 +581,8 @@ void exec_cgi_script(per_request *reqInfo) {
evaluate_access
*/
void send_cgi(per_request *reqInfo,struct stat *finfo, char allow_options)
void send_cgi(per_request *reqInfo,struct stat *finfo, char *path_args,
char allow_options)
{
int stub_returns;
@ -709,11 +594,11 @@ void send_cgi(per_request *reqInfo,struct stat *finfo, char allow_options)
add_common_vars(reqInfo);
reqInfo->bytes_sent = 0;
stub_returns = cgi_stub(reqInfo,finfo,allow_options);
stub_returns = cgi_stub(reqInfo,path_args,finfo);
switch (stub_returns) {
case SC_REDIRECT_TEMP:
die(reqInfo,SC_REDIRECT_TEMP,reqInfo->outh_location);
die(reqInfo,SC_REDIRECT_TEMP,location);
break;
case SC_REDIRECT_LOCAL:
break;

View File

@ -10,7 +10,7 @@
*
************************************************************************
*
* cgi.h,v 1.9 1996/04/05 18:54:40 blong Exp
* cgi.h,v 1.6 1995/11/28 09:01:39 blong Exp
*
************************************************************************
*
@ -21,17 +21,25 @@
#ifndef _HTTP_SCRIPT_H_
#define _HTTP_SCRIPT_H_
#include <sys/stat.h>
/* function prototypes */
void exec_cgi_script(per_request *reqInfo);
int cgi_stub(per_request *reqInfo, struct stat *finfo, int allow_options);
int cgi_stub(per_request *reqInfo, char *path_args, struct stat *finfo);
int add_common_vars(per_request *reqInfo);
void get_path_info(per_request *reqInfo, struct stat *finfo);
int scan_cgi_header(per_request *reqInfo, int pd);
void get_path_info(per_request *reqInfo, char *path_args, struct stat *finfo);
int scan_script_header(per_request *reqInfo, int pd);
long send_fd(per_request *reqInfo, int pd, void (*onexit)(void));
long send_nph_script(per_request *reqInfo, int pd, void (*onexit)(void));
void send_cgi(per_request *reqInfo,struct stat *finfo, char allow_options);
void internal_redirect(per_request *reqInfo);
void send_cgi(per_request *reqInfo,struct stat *finfo, char *path_args,
char allow_options);
void send_fd_timed_out(int);
#endif /* _HTTP_SCRIPT_H_ */

View File

@ -10,7 +10,7 @@
*
************************************************************************
*
* config.h,v 1.21 1996/03/27 20:43:51 blong Exp
* config.h,v 1.16 1995/11/10 02:01:46 blong Exp
*
************************************************************************
*
@ -32,14 +32,14 @@
on all systems, either. It is known to work under AIX3, SunOS, OSF1,
FreeBSD, and NetBSD. */
/* #define SETPROCTITLE */
/* #define SETPROCTITLE /* */
/* If you have SETPROCTITLE enabled, and you are a stats fanatic, and your
server has a few extra clock cycles to spare, defining the following
will enable an RPM (requests per minute) indicator in the proc title. */
#ifdef SETPROCTITLE
#define TACHOMETER */
#define TACHOMETER /* */
# ifdef TACHOMETER
# define MAX_TACHOMETER 30
# endif
@ -51,45 +51,23 @@
#define IMAGEMAP_SUPPORT /* */
/* To add an additional field -- request duration -- to the access_log.
This adds the duration, in seconds that the processing of this
request took. */
/* #define LOG_DURATION */
/* If you want the server to check the execute bit of an HTML file to
determine if the file should be parsed, uncomment the following.
Using this feature will give better performance for files which
are not parsed without the necessity of using the magic mime type */
/* #define XBITHACK */
/* If you want the server to be able to parse the output of CGI scripts,
then define the following. This will automatically be defined for
SHTTP. This does cause a performance degradation for CGI scripts,
as it requires reading the returned CGI headers off the socket one
byte at a time. */
/* #define CGI_SSI_HACK */
/* #define XBITHACK /* */
/* If you would like to ensure that CGI scripts don't mess with the
log files (except the error_log file), uncomment the following. */
/* #define SECURE_LOGS */
/* If you would like each "static" file to be sent with a Content-MD5
header to give clients a way of telling whether the object they
requested is the one they got - and hasn't been mangled along the way.
Of course, no clients support this yet (to my knowledge) and this will
_really_ hinder performance on really big files, but that's life. */
/* #define CONTENT_MD5 */
/* #define SECURE_LOGS /* */
/* If you would like to specify the keyword LOCAL in your access
configuration file to match local address (ie, those without embedded
dots), uncomment the following. */
/* #define LOCALHACK */
/* #define LOCALHACK /* */
/* If you would like to use NIS services for passwords and group information,
uncomment the following. NOTE: DO NOT USE THIS ON OPEN NETWORKS. The
@ -97,20 +75,20 @@
password in clear text across the network on every request which requires
it. */
/* #define NIS_SUPPORT */
/* #define NIS_SUPPORT /* */
/* If you have a REALLY heavily loaded system, and you can't afford to
have a server per request(low memory?), you can compile with this i
option to make max_servers a hard limit. */
/* #define RESOURCE_LIMIT */
/* #define RESOURCE_LIMIT /* */
/* If your system doesn't support file descriptor passing, or if you
don't want to use it, defining the following will enable HTTPd to
mimic the 1.3 Forking server. This should be defined in the system
specific information in portability.h, and not here. */
/* #define NO_PASS */
/* #define NO_PASS /* */
/* defines for new muli-child approach
@ -125,13 +103,12 @@
PROFILE to set the server up to profile the code
QUANTIFY is a profiler from Pure software
PURIFY is a memory checker from Pure software
DEBUG compiles in extra debugging code (debug.c, mostly)
*/
/* #define DEBUG */
/* #define PROFILE */
/* #define QUANTIFY */
/* #define PURIFY */
/* #define PROFILE /* */
/* #define QUANTIFY /* */
/* #define PURIFY /* */
/* SHELL_PATH defines where the shell path is */

View File

@ -10,7 +10,7 @@
*
************************************************************************
*
* constants.h,v 1.54 1996/04/05 18:54:42 blong Exp
* constants.h,v 1.42 1995/11/28 09:01:40 blong Exp
*
************************************************************************
*
@ -46,34 +46,26 @@
#define IOBUFSIZE 8192
#ifdef NEXT
# define HTTP_TIME_FORMAT "%a, %d %b %Y %X"
#else
# define HTTP_TIME_FORMAT "%a, %d %b %Y %T GMT"
#endif /* NEXT */
#define HTTP_TIME_FORMAT "%a, %d %b %Y %T GMT"
#define SERVER_VERSION "NCSA/1.5.1"
#define SERVER_SOURCE "NCSA/1.5.1"
#define SERVER_VERSION "NCSA/1.5"
#define SERVER_SOURCE "NCSA/1.5.0c"
#define SERVER_PROTOCOL "HTTP/1.0"
/* Response Codes from HTTP/1.0 Spec
all 4 digit codes are internal only */
#define SC_CONTINUE 100
#define SC_SWITCHING_PROTOCOLS 101
#define SC_DOCUMENT_FOLLOWS 200
#define SC_CREATED 201
#define SC_ACCEPTED 202
#define SC_NON_AUTH_INFO 203
#define SC_PROV_INFO 203
#define SC_NO_CONTENT 204
#define SC_RESET_CONTENT 205
#define SC_PARTIAL_CONTENT 206
#define SC_MULTIPLE_CHOICES 300
#define SC_REDIRECT_PERM 301
#define SC_REDIRECT_TEMP 302
#define SC_REDIRECT_LOCAL 3020
#define SC_SEE_OTHER 303
#define SC_METHOD 303
#define SC_USE_LOCAL_COPY 304
#define SC_USE_PROXY 305
#define SC_BAD_REQUEST 400
#define SC_AUTH_REQUIRED 401
#define SC_PAY_REQUIRED 402
@ -85,8 +77,6 @@
#define SC_REQUEST_TIMEOUT 408
#define SC_CONFLICT 409
#define SC_GONE 410
#define SC_LENGTH_REQUIRED 411
#define SC_UNLESS_TRUE 412
#define SC_SERVER_ERROR 500
#define SC_NOT_IMPLEMENTED 501
#define SC_BAD_GATEWAY 502
@ -95,42 +85,23 @@
#define SC_NO_MEMORY 6992
#define SC_CONF_ERROR 6993
#define SC_BAD_IMAGEMAP 6994
#define SC_AUTH_NO_WWW_AUTH 7001
/* Supported Methods - sorta */
#define METHODS 8
/* Supported Methods - sorta*/
#define METHODS 7
#define M_GET 0
#define M_HEAD 1
#define M_POST 2
#define M_PUT 3
#define M_DELETE 4
#define M_SECURE 5
#define M_INVALID -1
/* Unsupported Methods */
#define M_LINK 6
#define M_UNLINK 7
#define M_OPTIONS 8
#define M_PATCH 9
#define M_COPY 10
#define M_MOVE 11
#define M_TRACE 12
#define M_WRAPPED 13
#define M_LINK 5
#define M_UNLINK 6
/* Array containing Method names */
extern char *methods[];
/* Supported Protocals - sorta */
#define PROTOCALS 6
#define P_OTHER 0
#define P_HTTP_0_9 1
#define P_HTTP_1_0 2
#define P_HTTP_1_1 3
#define P_SHTTP_1_1 4
#define P_SHTTP_1_2 5
extern char *protocals[];
/* Object types */
#define A_STD_DOCUMENT 0
#define A_REDIRECT_TEMP 1
@ -155,8 +126,7 @@ extern char *protocals[];
#define OR_AUTHCFG 8
#define OR_INDEXES 16
#define OR_REDIRECT 32
#define OR_PRIVACY_ENHANCE 64
#define OR_ALL (OR_LIMIT | OR_OPTIONS | OR_FILEINFO | OR_AUTHCFG | OR_INDEXES | OR_REDIRECT | OR_PRIVACY_ENHANCE)
#define OR_ALL (OR_LIMIT | OR_OPTIONS | OR_FILEINFO | OR_AUTHCFG | OR_INDEXES | OR_REDIRECT)
/* PEM/PGP Encodings */
@ -164,7 +134,6 @@ extern char *protocals[];
#define CGI_MAGIC_TYPE "application/x-httpd-cgi"
#define INCLUDES_MAGIC_TYPE "text/x-server-parsed-html"
#define IMAGEMAP_MAGIC_TYPE "text/x-imagemap"
#define BLACKOUT_MAGIC_TYPE "text/x-httpd-black"
/* For directory indexing */
#define BY_PATH 0
@ -202,7 +171,6 @@ typedef struct {
#define AUTHFILETYPE_STANDARD 0
#define AUTHFILETYPE_DBM 1
#define AUTHFILETYPE_NIS 2
#define AUTHFILETYPE_RADIUS 3
typedef struct {
char d[MAX_STRING_LEN];
@ -210,25 +178,13 @@ typedef struct {
char override;
int order[METHODS];
int bSatisfy; /* 0 = All, 1 = Any */
int num_allow[METHODS];
char *allow[METHODS][MAX_SECURITY];
int bSatisfy; /* 0 = All, 1 = Any */
int num_auth[METHODS];
char *auth[METHODS][MAX_SECURITY];
int num_referer_allow[METHODS];
char *referer_allow[METHODS][MAX_SECURITY];
int num_referer_deny[METHODS];
char *referer_deny[METHODS][MAX_SECURITY];
int num_deny[METHODS];
char *deny[METHODS][MAX_SECURITY];
char *on_deny[METHODS];
char auth_type[MAX_STRING_LEN];
char auth_name[MAX_STRING_LEN];
char auth_pwfile[MAX_STRING_LEN];
@ -240,8 +196,17 @@ typedef struct {
int auth_digestfile_type;
#endif /* DIGEST_AUTH */
int num_deny[METHODS];
char *deny[METHODS][MAX_SECURITY];
} security_data;
#define PROTOCALS 4
#define P_OTHER 0
#define P_HTTP_0_9 1
#define P_HTTP_1_0 2
#define P_HTTP_1_1 3
extern char *protocals[];
typedef struct _ErrorDoc {
/* int Type; */
@ -256,20 +221,6 @@ typedef struct _ErrorDoc {
#define DNS_STD 2
#define DNS_MAX 3
/* ----------- Our socket buffering routine defines ----------------- */
#define SB_NEW 1
#define SB_READ 2
#define SB_FLUSHED 3
#define SB_ERROR 4
typedef struct _sock_buf {
char buffer[HUGE_STRING_LEN];
int buf_posn;
int buf_good;
int status;
int sd;
} sock_buf;
/* ------------------- per hostname configuration -------------------- */
/* These #defines are for keeping track of which options are links to
@ -329,60 +280,30 @@ typedef struct _per_host {
/* --------- Per request Data Structure ------------- */
/* Request Flags */
#define DOING_PGP 1
#define DOING_SHTTP 2
#define DOING_SSL 3
typedef struct _per_request {
/* Information about Contents; */
int ownENV;
int ownURL;
int ownDNS;
int ownSB;
int RequestFlags;
int ownENV;
/* Request Information */
int status;
char *status_line;
/* char *status_line; */
long bytes_sent;
/* request stuff to be logged */
char agent[HUGE_STRING_LEN];
char referer[HUGE_STRING_LEN];
int http_version;
int method;
char url[HUGE_STRING_LEN];
char args[HUGE_STRING_LEN];
char path_info[HUGE_STRING_LEN];
int http_version;
char inh_agent[HUGE_STRING_LEN];
char inh_referer[HUGE_STRING_LEN];
char inh_called_hostname[MAX_STRING_LEN];
char inh_if_mod_since[MAX_STRING_LEN];
char inh_auth_line[HUGE_STRING_LEN];
char inh_content_type[MAX_STRING_LEN];
int inh_content_length;
/* Internal Info */
char filename[HUGE_STRING_LEN];
/* Outgoing information */
char outh_location[HUGE_STRING_LEN];
char outh_last_mod[MAX_STRING_LEN];
char outh_www_auth[HUGE_STRING_LEN];
char outh_content_type[MAX_STRING_LEN];
char outh_content_encoding[MAX_STRING_LEN];
int outh_content_length;
char *outh_cgi;
#ifdef CONTENT_MD5
char *outh_content_md5;
#endif /* CONTENT_MD5 */
char args[HUGE_STRING_LEN];
/* char *content_type; */
char auth_type[MAX_STRING_LEN];
int dirs_in_alias;
/* Authentication Information */
char auth_user[MAX_STRING_LEN];
char auth_group[MAX_STRING_LEN];
/* authentication files */
char* auth_name;
char* auth_pwfile;
@ -397,7 +318,6 @@ typedef struct _per_request {
/* Domain Restriction Info */
int bNotifyDomainRestricted;
int bSatisfiedDomain;
int bSatisfiedReferer;
int dns_host_lookup;
int num_env;
@ -413,10 +333,7 @@ typedef struct _per_request {
/* Server Information */
int connection_socket;
int in;
FILE *out;
sock_buf *sb;
sock_buf *cgi_buf;
per_host *hostInfo;
struct in_addr address_info;

View File

@ -1,83 +0,0 @@
/* Various debugging routines */
#ifdef DEBUG
#include "config.h"
#include "portability.h"
#include "constants.h"
#include "host_config.h"
#include "http_request.h"
#ifdef SOLARIS2
#include <fcntl.h>
#include <sys/procfs.h>
#include <errno.h>
prpsinfo_t p;
long current_process_size()
{
int retval;
char filename[MAX_STRING_LEN];
int fd;
int pid;
pid = getpid();
fprintf(stderr,"%d\n",pid);
if (pid < 10) {
sprintf(filename,"/proc/0000%d",pid);
} else if (pid < 100) {
sprintf(filename,"/proc/000%d",pid);
} else if (pid < 1000) {
sprintf(filename,"/proc/00%d",pid);
} else if (pid < 10000) {
sprintf(filename,"/proc/0%d",pid);
} else {
sprintf(filename,"/proc/%d",pid);
}
/* fprintf(stderr,filename); */
if (!(fd = open(filename,O_RDONLY))) {
fprintf(stderr,"Error openning file %s, errno=%d\n",filename,errno);
}
retval = ioctl(fd,PIOCPSINFO,&p);
if (retval == -1) {
fprintf(stderr,"Error in ioctl, errno = %d\n", errno);
}
close(fd);
fprintf(stderr,"%X %X\n",&p,filename);
sprintf(filename,"%d bytes memory", p.pr_bysize);
log_error(filename,gConfiguration->error_log);
}
#endif /* SOLARIS2 */
#ifdef AIX3
#include <malloc.h>
long current_process_size(char *msg) {
char S[MAX_STRING_LEN];
struct mallinfo mi;
int memory;
mi = mallinfo();
memory = mi.usmblks+mi.uordblks;
sprintf(S,"%25s: Space in Use: %d", msg,memory);
log_error(S,gConfiguration->error_log);
return memory;
}
#endif /* AIX3 */
#endif /* DEBUG */

View File

@ -53,11 +53,6 @@ int get_digest(per_request *reqInfo, char *user, char *realm, char *digest,
char r[MAX_STRING_LEN];
if (reqInfo->auth_digestfile_type == AUTHFILETYPE_STANDARD) {
if (reqInfo->auth_digestfile == NULL) {
sprintf (errstr, "No digest file specified for URL: %s\n",
reqInfo->url);
die(reqInfo,SC_SERVER_ERROR,errstr);
}
if(!(f=FOpen(reqInfo->auth_digestfile,"r"))) {
sprintf(errstr,"Could not open digest file %s",
reqInfo->auth_digestfile);
@ -207,7 +202,7 @@ void Digest_Check(per_request *reqInfo, char *user, security_data* sec)
opaque[0] = 0;
p = q = NULL;
p = reqInfo->inh_auth_line;
p = auth_line;
while (isspace(*p)) {
p++;
}

View File

@ -10,7 +10,7 @@
*
************************************************************************
*
*env.c,v 1.20 1996/04/05 18:54:44 blong Exp
*env.c,v 1.17 1995/11/28 09:01:42 blong Exp
*
************************************************************************
*
@ -28,15 +28,10 @@
#include <string.h>
#include "constants.h"
#include "env.h"
#include "http_request.h"
#include "http_log.h"
#include "allocate.h"
/* Older version, required external help. Newer version should be self
* contained for easier extensibility
* updated to use string allocation structures for speed and so it doesn't
* leak
*/
contained for easier extensibility */
/* This will change the value of an environment variable to *value
if found. Returns TRUE if the replace took place, FALSE otherwise */
@ -70,7 +65,7 @@ void free_env(per_request *reqInfo) {
int x;
for(x=0;reqInfo->env[x];x++)
freeString(reqInfo->env[x]);
free(reqInfo->env[x]);
free(reqInfo->env);
free(reqInfo->env_len);
reqInfo->env = NULL;
@ -87,7 +82,7 @@ int merge_header(per_request *reqInfo, char *header, char *value)
{
register int l,lt;
int len, ndx;
char **t,*tmp;
char **t;
len = strlen(value);
@ -99,20 +94,14 @@ int merge_header(per_request *reqInfo, char *header, char *value)
if(!strncmp(*t,header,l)) {
lt = strlen(*t);
if ((lt + len + 2) > reqInfo->env_len[ndx]) {
tmp = reqInfo->env[ndx];
if ((lt+len+2) > HUGE_STRING_LEN) {
reqInfo->env[ndx] = newString(lt+len+2,STR_REQ);
} else {
reqInfo->env[ndx] = newString(HUGE_STRING_LEN,STR_REQ);
}
sprintf(reqInfo->env[ndx],"%s, %s",tmp,value);
freeString(tmp);
} else {
(*t)[lt++] = ',';
(*t)[lt++] = ' ';
strcpy(&((*t)[lt]),value);
}
header[l-1] = '\0';
int n = reqInfo->env_len[ndx] / BIG_ENV_VAR_LEN + 1;
if(!(*t = (char *) realloc(*t,n * BIG_ENV_VAR_LEN*sizeof(char))))
die(reqInfo, SC_NO_MEMORY,"merge_header");
reqInfo->env_len[ndx] = n * BIG_ENV_VAR_LEN;
}
(*t)[lt++] = ',';
(*t)[lt++] = ' ';
strcpy(&((*t)[lt]),value);
return 1;
}
}
@ -127,14 +116,7 @@ int merge_header(per_request *reqInfo, char *header, char *value)
int make_env_str(per_request *reqInfo, char *name, char *value)
{
int n;
char tmp[HUGE_STRING_LEN];
if (value == NULL) {
/*
* I've generally protected against this, but sanity isn't a bad thing
*/
return 0;
}
if (reqInfo->env == NULL) {
if (!(reqInfo->env = (char **) malloc(ENV_BEG_SIZE * sizeof(char *)))
|| !(reqInfo->env_len = (int*) malloc(ENV_BEG_SIZE * sizeof(int))))
@ -149,12 +131,13 @@ int make_env_str(per_request *reqInfo, char *name, char *value)
die(reqInfo,SC_NO_MEMORY,"make_env_str:realloc");
reqInfo->max_env += ENV_INC_SIZE;
}
strncpy(tmp, name, HUGE_STRING_LEN);
strncat(tmp,"=",HUGE_STRING_LEN - strlen(tmp));
strncat(tmp,value,HUGE_STRING_LEN - strlen(tmp));
reqInfo->env[reqInfo->num_env] = dupStringP(tmp,STR_REQ);
reqInfo->env_len[reqInfo->num_env] =
sizeofString(reqInfo->env[reqInfo->num_env]);
if (!(reqInfo->env[reqInfo->num_env] =
(char *) malloc(n = (strlen(name) + strlen(value) + 2))))
die(reqInfo,SC_NO_MEMORY,"make_env_str:add");
strcpy(reqInfo->env[reqInfo->num_env], name);
strcat(reqInfo->env[reqInfo->num_env],"=");
strcat(reqInfo->env[reqInfo->num_env],value);
reqInfo->env_len[reqInfo->num_env] = n;
reqInfo->num_env++;
reqInfo->env[reqInfo->num_env] = NULL;

View File

@ -10,7 +10,7 @@
*
************************************************************************
*
* fdwrap.c,v 1.15 1996/04/05 18:54:46 blong Exp
* fdwrap.c,v 1.11 1995/11/28 09:01:44 blong Exp
*
************************************************************************
*
@ -18,6 +18,14 @@
* of open ones and close them when errors happen. Should
* make leaks next to impossible.
*
* 08-15-95 guillory
* initial code
*
* 08-16-95 blong
* added headers, etc.
*
* 09-07-97 mshapiro
* added includes for <malloc.h> / <sys/malloc.h>
*/
#include "config.h"
@ -52,7 +60,7 @@ static int nSize;
void fd_error(char *err_msg)
{
char S[MAX_STRING_LEN];
sprintf(S,"fdwrap error: %s",err_msg);
sprintf(S,"fdwrap error: %s\n",err_msg);
log_error(S,gConfiguration->error_log);
exit(1);
}
@ -60,7 +68,7 @@ void fd_error(char *err_msg)
void fd_warn(char *err_msg)
{
char S[MAX_STRING_LEN];
sprintf(S,"fdwrap warn: %s",err_msg);
sprintf(S,"fdwrap warn: %s\n",err_msg);
log_error(S,gConfiguration->error_log);
}
@ -102,7 +110,6 @@ int GrowTable (int fd)
FdTab[ndx].fp = NULL;
}
nSize = fd + 10;
return 1;
}

View File

@ -10,7 +10,7 @@
*
************************************************************************
*
*host_config.c,v 1.20 1996/04/05 18:54:47 blong Exp
*host_config.c,v 1.15 1995/11/06 20:57:59 blong Exp
*
************************************************************************
*
@ -28,7 +28,6 @@
#include "http_log.h"
#include "http_alias.h"
#include "http_mime.h"
#include "http_request.h"
#include "util.h"
per_host* gConfiguration;
@ -279,10 +278,7 @@ void which_host_conf(per_request *reqInfo) {
while (host && !Found) {
if (host->address_info.s_addr == reqInfo->address_info.s_addr) {
if (!host->virtualhost && host->called_hostname) {
if (!strncasecmp(host->called_hostname,reqInfo->inh_called_hostname,
strlen(host->called_hostname))) {
Found = TRUE;
}
if (!strcasecmp(called_hostname,host->called_hostname)) Found = TRUE;
} else Found = TRUE;
}
if (!Found) host = host->next;

View File

@ -10,12 +10,21 @@
*
************************************************************************
*
* http_access.c,v 1.78 1996/04/05 18:54:49 blong Exp
* http_access.c,v 1.69 1995/11/28 09:01:48 blong Exp
*
************************************************************************
*
* http_access: Security options etc.
*
* Based on NCSA HTTPd 1.3 by Rob McCool
*
* 03-12-95 blong
* Added patch to fix ALLOW_THEN_DENY
*
* 10-02-95 blong
* Added patch by Maurizio Codogno (mau@beatles.cselt.stet.it) to
* allow or deny hosts using a LOCAL keyword which matches all hosts
* without a dot in their name
*/
@ -38,7 +47,12 @@
#include "http_mime.h"
#include "http_log.h"
#include "util.h"
#include "allocate.h"
#ifdef DIGEST_AUTH
int client_accepts_digest;
int assume_digest_support;
#endif /* DIGEST_AUTH */
/*
* Modified this bad boy so he wouldn't
@ -67,28 +81,25 @@ int in_domain(char *domain, char *what)
* Address matching should really be done with subnet masks, though.
* mullen@itd.nrl.navy.mil 11/16/95
*
* Returned to normal, as the patch didn't work. For now, I think
* that updating the documenation to say that you have to end in
* a . in order to prohibit other networks is better, as some people
* might like the ability to allow anything that matches 128.174.1
* blong - 1/26/96
* Forget it, the code didn't work, and we'll just change the docs to
* let everyone know how it really works.
*/
int in_ip(char *domain, char *what)
{
/* int dl=strlen(domain);
return (!strncmp(domain,what,dl)) &&
(domain[dl-1]=='.' && strlen(what)<=dl && what[dl]=='.'); */
(domain[dl-1]=='.' && strlen(what)<=dl && what[dl]=='.');
*/
return(!strncmp(domain,what,strlen(domain)));
}
/* find_host_allow()
/* find_allow()
* Hunts down list of allowed hosts and returns 1 if allowed, 0 if not
* As soon as it finds an allow that matches, it returns 1
*/
int find_host_allow(per_request *reqInfo, int x)
int find_allow(per_request *reqInfo, int x)
{
register int y;
@ -131,11 +142,11 @@ int find_host_allow(per_request *reqInfo, int x)
return FA_DENY;
}
/* find_host_deny()
/* find_deny()
* Hunts down list of denied hosts and returns 0 if denied, 1 if not
* As soon as it finds a deny that matches, it returns 0
*/
int find_host_deny(per_request *reqInfo, int x)
int find_deny(per_request *reqInfo, int x)
{
register int y;
@ -180,85 +191,8 @@ int find_host_deny(per_request *reqInfo, int x)
return FA_ALLOW;
}
/* match_referer()
* currently matches restriction with sent for only as long as restricted
*/
int match_referer(char *restrict, char *sent) {
return !(strcmp_match(sent,restrict));
}
/* find_referer_allow()
* Hunts down list of allowed hosts and returns 1 if allowed, 0 if not
* As soon as it finds an allow that matches, it returns 1
*/
int find_referer_allow(per_request *reqInfo, int x)
{
register int y;
/* If no allows are specified, then allow */
if(sec[x].num_referer_allow[reqInfo->method] == 0)
return FA_ALLOW;
for(y=0;y<sec[x].num_referer_allow[reqInfo->method];y++) {
if(!strcmp("all",sec[x].referer_allow[reqInfo->method][y]))
return FA_ALLOW;
#ifdef LOCALHACK
/* I haven't quite come up with either a reason or a method for
* using the LOCALHACK with referer, so nothing for now.
*/
#endif /* LOCALHACK */
if(match_referer(sec[x].referer_allow[reqInfo->method][y],
reqInfo->inh_referer))
{
reqInfo->bSatisfiedReferer = TRUE;
return FA_ALLOW;
}
}
/* Default is to deny */
return FA_DENY;
}
/* find_referer_deny()
* Hunts down list of denied hosts and returns 0 if denied, 1 if not
* As soon as it finds a deny that matches, it returns 0
*/
int find_referer_deny(per_request *reqInfo, int x)
{
register int y;
/* If there aren't any denies, then it is allowed
*/
if(sec[x].num_referer_deny[reqInfo->method] == 0)
return FA_ALLOW;
for(y=0;y<sec[x].num_referer_deny[reqInfo->method];y++) {
if(!strcmp("all",sec[x].referer_deny[reqInfo->method][y]))
{
reqInfo->bSatisfiedReferer = FALSE;
return FA_DENY;
}
#ifdef LOCALHACK
/* I haven't quite come up with either a reason or a method for
* using the LOCALHACK with referer, so nothing for now.
*/
#endif /* LOCALHACK */
if(match_referer(sec[x].referer_deny[reqInfo->method][y],
reqInfo->inh_referer))
{
reqInfo->bSatisfiedReferer = FALSE;
return FA_DENY;
}
}
/* Default is to allow */
reqInfo->bSatisfiedReferer = TRUE;
return FA_ALLOW;
}
void check_dir_access(per_request *reqInfo,int x,
int *allow, int *allow_options, int *other)
int *allow, int *allow_options)
{
if(sec[x].auth_name[0])
reqInfo->auth_name = sec[x].auth_name;
@ -281,27 +215,21 @@ void check_dir_access(per_request *reqInfo,int x,
if(sec[x].order[reqInfo->method] == ALLOW_THEN_DENY) {
*allow=FA_DENY;
if ((find_host_allow(reqInfo,x) == FA_ALLOW) &&
(find_referer_allow(reqInfo,x) == FA_ALLOW))
if (find_allow(reqInfo,x) == FA_ALLOW)
*allow = FA_ALLOW;
if ((find_host_deny(reqInfo,x) == FA_DENY) ||
(find_referer_deny(reqInfo,x) == FA_DENY))
if (find_deny(reqInfo,x) == FA_DENY)
*allow = FA_DENY;
}
else if(sec[x].order[reqInfo->method] == DENY_THEN_ALLOW) {
if ((find_host_deny(reqInfo,x) == FA_DENY) ||
(find_referer_deny(reqInfo,x) == FA_DENY))
if (find_deny(reqInfo,x) == FA_DENY)
*allow = FA_DENY;
if ((find_host_allow(reqInfo,x) == FA_ALLOW) &&
(find_referer_allow(reqInfo,x) == FA_ALLOW))
if (find_allow(reqInfo,x) == FA_ALLOW)
*allow = FA_ALLOW;
}
else { /* order == MUTUAL_FAILURE: allowed and not denied */
*allow = FA_DENY;
if ((find_host_allow(reqInfo,x) == FA_ALLOW) &&
(find_referer_allow(reqInfo,x) == FA_ALLOW) &&
!(find_host_deny(reqInfo,x) == FA_DENY) &&
!(find_referer_deny(reqInfo,x) == FA_DENY))
if ((find_allow(reqInfo,x) == FA_ALLOW) &&
!(find_deny(reqInfo,x) == FA_DENY))
*allow = FA_ALLOW;
}
@ -313,7 +241,6 @@ void evaluate_access(per_request *reqInfo,struct stat *finfo,int *allow,
char *allow_options)
{
int will_allow, need_auth, num_dirs;
int need_enhance;
char opts[MAX_STRING_LEN], override[MAX_STRING_LEN];
char path[MAX_STRING_LEN], d[MAX_STRING_LEN];
char errstr[MAX_STRING_LEN];
@ -328,10 +255,9 @@ void evaluate_access(per_request *reqInfo,struct stat *finfo,int *allow,
num_dirs = count_dirs(path);
will_allow = FA_ALLOW;
need_auth = -1;
need_enhance = -1;
reqInfo->auth_user[0] = '\0';
reqInfo->auth_group[0] = '\0';
user[0] = '\0';
groupname[0] = '\0';
reset_mime_vars();
for(x=0;x<num_dirs;x++) {
@ -351,7 +277,7 @@ void evaluate_access(per_request *reqInfo,struct stat *finfo,int *allow,
opts[y] = sec[x].opts;
override[y] = sec[x].override;
}
check_dir_access(reqInfo,x,&will_allow,&need_auth,&need_enhance);
check_dir_access(reqInfo,x,&will_allow,&need_auth);
}
}
else if(!strncmp(path,sec[x].d,strlen(sec[x].d))) {
@ -360,10 +286,7 @@ void evaluate_access(per_request *reqInfo,struct stat *finfo,int *allow,
opts[y] = sec[x].opts;
override[y] = sec[x].override;
}
check_dir_access(reqInfo,x,&will_allow,&need_auth,&need_enhance);
}
if (!will_allow && sec[x].on_deny[reqInfo->method]) {
strcpy(reqInfo->outh_location,sec[x].on_deny[reqInfo->method]);
check_dir_access(reqInfo,x,&will_allow,&need_auth);
}
}
if((override[n]) || (!(opts[n] & OPT_SYM_LINKS)) ||
@ -376,7 +299,7 @@ void evaluate_access(per_request *reqInfo,struct stat *finfo,int *allow,
if(lstat(d,&lfi) != 0)
{
sprintf(errstr,"HTTPd: can't lstat %s, errno = %d",d, errno);
sprintf(errstr,"httpd: can't lstat %s, errno = %d",d, errno);
log_error(errstr,reqInfo->hostInfo->error_log);
*allow=FA_DENY;
*allow_options = OPT_NONE;
@ -386,7 +309,7 @@ void evaluate_access(per_request *reqInfo,struct stat *finfo,int *allow,
if(opts[x] & OPT_SYM_OWNER) {
if(stat(d,&fi) != 0)
{
sprintf(errstr,"HTTPd: can't stat %s, errno = %d",d, errno);
sprintf(errstr,"httpd: can't stat %s, errno = %d",d, errno);
log_error(errstr,reqInfo->hostInfo->error_log);
*allow=FA_DENY;
*allow_options = OPT_NONE;
@ -397,7 +320,7 @@ void evaluate_access(per_request *reqInfo,struct stat *finfo,int *allow,
}
else {
bong:
sprintf(errstr,"HTTPd: will not follow link %s",d);
sprintf(errstr,"httpd: will not follow link %s",d);
log_error(errstr,reqInfo->hostInfo->error_log);
*allow=FA_DENY;
*allow_options = OPT_NONE;
@ -415,14 +338,8 @@ void evaluate_access(per_request *reqInfo,struct stat *finfo,int *allow,
}
if ((sec[y].num_auth[reqInfo->method] > 0) ||
(sec[y].num_allow[reqInfo->method] > 0) ||
(sec[y].num_deny[reqInfo->method] > 0) ||
(sec[y].num_referer_allow[reqInfo->method] > 0) ||
(sec[y].num_referer_deny[reqInfo->method] > 0))
check_dir_access(reqInfo,y,&will_allow,&need_auth,&need_enhance);
if (!will_allow && sec[y].on_deny[reqInfo->method]) {
strcpy(reqInfo->outh_location,
sec[y].on_deny[reqInfo->method]);
}
(sec[y].num_deny[reqInfo->method] > 0))
check_dir_access(reqInfo,y,&will_allow,&need_auth);
}
}
}
@ -432,7 +349,7 @@ void evaluate_access(per_request *reqInfo,struct stat *finfo,int *allow,
struct stat fi,lfi;
if(lstat(path,&fi)!=0)
{
sprintf(errstr,"HTTPd: can't lstat %s, errno = %d",path, errno);
sprintf(errstr,"httpd: can't lstat %s, errno = %d",path, errno);
log_error(errstr,reqInfo->hostInfo->error_log);
*allow=FA_DENY;
*allow_options = OPT_NONE;
@ -442,7 +359,7 @@ void evaluate_access(per_request *reqInfo,struct stat *finfo,int *allow,
if(opts[n] & OPT_SYM_OWNER) {
if(stat(path,&lfi)!=0)
{
sprintf(errstr,"HTTPd: can't stat %s, errno = %d",path, errno);
sprintf(errstr,"httpd: can't stat %s, errno = %d",path, errno);
log_error(errstr,reqInfo->hostInfo->error_log);
*allow=FA_DENY;
*allow_options = OPT_NONE;
@ -453,7 +370,7 @@ void evaluate_access(per_request *reqInfo,struct stat *finfo,int *allow,
}
else {
gong:
sprintf(errstr,"HTTPd: will not follow link %s",path);
sprintf(errstr,"httpd: will not follow link %s",path);
log_error(errstr,reqInfo->hostInfo->error_log);
*allow=FA_DENY;
*allow_options = OPT_NONE;
@ -464,12 +381,12 @@ void evaluate_access(per_request *reqInfo,struct stat *finfo,int *allow,
*allow = will_allow;
if(will_allow) {
*allow_options = opts[num_dirs-1];
if ((need_auth >= 0) && (sec[need_auth].bSatisfy == SATISFY_ALL)) {
if ((need_auth >= 0) && !sec[need_auth].bSatisfy) {
reqInfo->bSatisfiedDomain = 0;
check_auth(reqInfo,&sec[need_auth], reqInfo->inh_auth_line);
check_auth(reqInfo,&sec[need_auth], auth_line);
}
} else if ((need_auth >= 0) && (sec[need_auth].bSatisfy == SATISFY_ANY)) {
check_auth(reqInfo,&sec[need_auth], reqInfo->inh_auth_line);
} else if (need_auth >= 0 && sec[need_auth].bSatisfy) {
check_auth(reqInfo,&sec[need_auth], auth_line);
*allow_options = opts[num_dirs-1];
*allow = FA_ALLOW;
}
@ -489,11 +406,6 @@ void kill_security(void)
free(sec[x].deny[m][y]);
for(y=0;y<sec[x].num_auth[m];y++)
free(sec[x].auth[m][y]);
for(y=0;y<sec[x].num_referer_allow[m];y++)
free(sec[x].referer_allow[m][y]);
for(y=0;y<sec[x].num_referer_deny[m];y++)
free(sec[x].referer_deny[m][y]);
free(sec[x].on_deny[m]);
}
/* if(sec[x].auth_type)
free(sec[x].auth_type);
@ -528,11 +440,6 @@ void reset_security(void)
free(sec[x].deny[m][y]);
for(y=0;y<sec[x].num_auth[m];y++)
free(sec[x].auth[m][y]);
for(y=0;y<sec[x].num_referer_allow[m];y++)
free(sec[x].referer_allow[m][y]);
for(y=0;y<sec[x].num_referer_deny[m];y++)
free(sec[x].referer_deny[m][y]);
if (sec[x].on_deny[m]) free(sec[x].on_deny[m]);
}
/* if(sec[x].auth_type)
free(sec[x].auth_type);

View File

@ -10,7 +10,7 @@
*
************************************************************************
*
* http_access.h,v 1.12 1996/02/22 23:46:41 blong Exp
* http_access.h,v 1.11 1995/11/28 09:01:50 blong Exp
*
************************************************************************
*
@ -25,6 +25,11 @@
#define FA_DENY 0
#define FA_ALLOW 1
#ifdef DIGEST_AUTH
extern int client_accepts_digest;
extern int assume_digest_support;
#endif /* DIGEST_AUTH */
/* http_access function prototypes */
void evaluate_access(per_request *reqInfo, struct stat *finfo,int *allow,
char *op);

View File

@ -12,6 +12,21 @@
*
* http_alias.c: Stuff for dealing with directory aliases
*
* Based on NCSA HTTPd 1.3 by Rob McCool
*
* 04-06-95 blong
* Added Saved_ variables to allow reset of aliases to configured
* only. save_aliases is called from http_config, and
* reset_to_saved_alias is called in the initialization of
* transactions.
*
* 06-30-95 blong
* removed saved stuff, since we now don't have to add user directories
* to the aliases, and so they never change after startup
*
* 07-27-95 blong
* log access to unknown users directory as suggested by
* Gioacchino La Vecchia (gio@di.unipi.it)
*/
@ -28,9 +43,17 @@
#include "http_alias.h"
#include "http_config.h"
#include "http_log.h"
#include "http_request.h"
#include "util.h"
/*
static int Saved_num_alias = 0;
static int num_aliases = 0;
static alias aliases[MAX_ALIASES];
static int Saved_num_redirect = 0;
static int num_redirect = 0;
static alias redirect[MAX_ALIASES];
*/
/* To send stat() information to cgi.c */
int dirs_in_alias;

View File

@ -12,6 +12,8 @@
*
* http_auth: authentication
*
* Based on NCSA HTTPd 1.3 by Rob McCool
*
*/
@ -33,17 +35,17 @@
#include <signal.h>
#include <fcntl.h>
#include <ctype.h>
#include <sys/types.h>
#include <termios.h>
#ifdef DBM_SUPPORT
# ifndef _DBMSUPPORT_H /* moronic OSs which don't protect their own include */
# define _DBMSUPPORT_H /* files from being multiply included */
# include <ndbm.h>
# endif /* _DBMSUPPORT_H */
#endif /* DBM_SUPPORT */
#ifdef NIS_SUPPORT
# include <rpcsvc/ypclnt.h>
#include <rpcsvc/ypclnt.h>
#endif /* NIS_SUPPORT */
#if defined(KRB4) || defined(KRB5)
# define HAVE_KERBEROS
#endif /* defined(KRB4) || defined(KRB5) */
@ -53,26 +55,29 @@
#ifdef KRB5
# include <krb5.h>
#endif /* KRB5 */
#include "constants.h"
#include "fdwrap.h"
#include "allocate.h"
#include "http_auth.h"
#include "http_access.h"
#include "http_mime.h"
#include "http_config.h"
#include "http_log.h"
#include "http_request.h"
#include "util.h"
#include "digest.h"
char user[MAX_STRING_LEN];
char groupname[MAX_STRING_LEN];
#ifdef HAVE_KERBEROS
#define T 1
#define NIL 0
char* index();
char krb_authreply[2048];
extern char *remote_logname;
/* extern char out_auth_header[]; */
extern char out_auth_header[];
/* Table for converting binary values to and from hexadecimal */
static char hex[] = "0123456789abcdef";
@ -103,12 +108,6 @@ AUTH_DAT kerb_kdata;
char k5_srvtab[MAX_STRING_LEN] = "";
#endif /* KRB5 */
#ifdef RADIUS_AUTH
/* Experimental RADIUS authentication
*/
int testpass (char * user, char * clear_pw, char * servername);
#endif /* RADIUS_AUTH */
#ifdef NIS_SUPPORT
int
init_nis(char **dom)
@ -221,69 +220,53 @@ int get_pw(per_request *reqInfo, char *user, char *pw, security_data* sec)
return 0;
}
/* in_list()
* Search a comma or space delimited list for a user
* return 0 if not found, 1 if found
int in_group(per_request *reqInfo, char *user,
char *group, char* pchGrps
#ifdef DBM_SUPPORT
, DBM* db
#endif /* DBM_SUPPORT */
) {
char *mems = NULL, *endp = NULL;
char *pch;
char chSaved = '\0';
int nlen, bFound = 0;
char l[MAX_STRING_LEN];
int x,start;
if (reqInfo->auth_grpfile_type == AUTHFILETYPE_STANDARD) {
nlen = strlen (group);
if ((mems = strstr (pchGrps, group)) && *(mems + nlen) == ':') {
if ((endp = strchr (mems + nlen + 1, ':'))) {
while (!isspace(*endp)) endp--;
chSaved = *endp;
*endp = '\0';
}
/* BUG FIX: Couldn't have the same name as the group as a user because
* failed to move the string beyond the group:
*/
int in_list(char *user, char *list)
{
int x = 0;
int start = 0;
int Found = 0;
while(isspace(list[x]) || (list[x] == ','))
x++;
start = x;
while (!Found && (list[x] != '\0')) {
if ((isspace(list[x]) || (list[x] == ','))) {
Found = !strncmp(user,(list+start),x-start);
start = x+1;
}
x++;
mems = mems + nlen;
}
else
return 0;
}
if (!Found && list[x] == '\0' && (x-start > 0)) {
Found = !strncmp(user,(list+start),x-start);
#ifdef DBM_SUPPORT
else if (reqInfo->auth_grpfile_type == AUTHFILETYPE_DBM) {
datum dtKey, dtRec;
dtKey.dptr = group;
dtKey.dsize = strlen(group);
dtRec = dbm_fetch(db, dtKey);
if (dtRec.dptr) {
strncpy(l, dtRec.dptr, dtRec.dsize);
l[dtRec.dsize] = '\0';
mems = l;
}
else
return 0;
}
return Found;
}
/* in_listn()
* Search a comma or space delimited list for a user
* Group list doesn't need to be NULL terminated (for DBM format)
* return 0 if not found, 1 if found
*/
int in_listn(char *user, char *list, int len)
{
int x = 0;
int start = 0;
int Found = 0;
while(isspace(list[x]) || (list[x] == ','))
x++;
start = x;
while (!Found && (list[x] != '\0') && (x < len)) {
if ((isspace(list[x]) || (list[x] == ','))) {
Found = !strncmp(user,(list+start),x-start);
start = x+1;
}
x++;
}
if (!Found && ((list[x] == '\0') || (x == len)) && (x-start > 0)) {
Found = !strncmp(user,(list+start),x-start);
}
return Found;
}
/* nis_group_lookup()
* Validate a user in an NIS group. Retrieves the group from an NIS database.
* (Default group file is webgroup)
* return 0 on failure, 1 on success
*/
#endif /* DBM_SUPPORT */
#ifdef NIS_SUPPORT
int nis_group_lookup(per_request *reqInfo, char *user, char *group)
{
else if (reqInfo->auth_pwfile_type == AUTHFILETYPE_NIS) {
char *domain,
*grfile,
*resptr,
@ -291,10 +274,8 @@ int nis_group_lookup(per_request *reqInfo, char *user, char *group)
int yperr,
resize;
if (init_nis(&domain) != 0) {
log_error("HTTPd/NIS: init_nis() failed",reqInfo->hostInfo->error_log);
return 0;
}
if (init_nis(&domain) != 0)
return 0;
if (strcmp(reqInfo->auth_grpfile, "+"))
grfile = reqInfo->auth_grpfile;
@ -302,94 +283,54 @@ int nis_group_lookup(per_request *reqInfo, char *user, char *group)
grfile = "webgroup";
yperr = yp_match(domain, grfile, group, strlen(group), &resptr, &resize);
if (yperr != 0) {
sprintf(w,"HTTPd/NIS: yp_match() failed, yperr = %d\n",yperr);
log_error(w,reqInfo->hostInfo->error_log);
return 0;
}
if (yperr != 0)
return 0;
getword(w, resptr, ':');
if (strcmp(w, group) != 0)
return 0;
return in_list(user,resptr);
}
#endif /* NIS_SUPPORT */
/* dbm_group_lookup()
* Implicitly requires group line not to exceed HUGE_STRING_LEN because
* groups aren't stored with trailing 0.
* Searches open DBM database (db) for keypair with the group name as key
* and returns 0 if user or group not found, 1 if user is in group
*/
#ifdef DBM_SUPPORT
int dbm_group_lookup(per_request *reqInfo, char *user, char *group, DBM *db)
{
datum dtKey, dtRec;
int Found = 0;
dtKey.dptr = group;
dtKey.dsize = strlen(group);
dtRec = dbm_fetch(db, dtKey);
if (dtRec.dptr) {
Found = in_listn(user,dtRec.dptr,dtRec.dsize);
}
return Found;
}
#endif /* DBM_SUPPORT */
int in_group(per_request *reqInfo, char *user,
char *group, char* gfile_mem
#ifdef DBM_SUPPORT
, DBM* db
#endif /* DBM_SUPPORT */
)
{
char *cur_group = NULL;
char *cur_list = NULL;
int bFound = FALSE;
int Done = FALSE;
if (reqInfo->auth_grpfile_type == AUTHFILETYPE_STANDARD) {
cur_group = strtok(gfile_mem,":");
while (!Done && !bFound) {
cur_list = strtok(NULL,"\n");
if (!strcmp(group,cur_group)) {
bFound = in_list(user,cur_list);
}
cur_group = strtok(NULL,":");
if (cur_group == NULL) Done = TRUE;
while (*resptr && isspace(*resptr))
resptr++;
(void) strcpy(l, resptr);
mems = l;
}
}
#ifdef DBM_SUPPORT
else if (reqInfo->auth_grpfile_type == AUTHFILETYPE_DBM) {
bFound = dbm_group_lookup(reqInfo,user,group,db);
}
#endif /* DBM_SUPPORT */
#ifdef NIS_SUPPORT
else if (reqInfo->auth_grpfile_type == AUTHFILETYPE_NIS) {
bFound = nis_group_lookup(reqInfo,user,group);
}
#endif /* NIS_SUPPORT */
else {
die(reqInfo,SC_SERVER_ERROR,"Invalid group file type");
return 0;
}
else {
die(reqInfo,SC_SERVER_ERROR,"Invalid group file type");
return 0;
}
return bFound;
}
#ifdef DEBUG
int fputsn(FILE *fp,char *S,int num) {
int x;
for(x = 0 ; x < num ; x++)
fprintf(fp,"%c",S[x]);
}
#endif /* DEBUG */
/* init_group(): loads an entire group file into memory for parsing.
* and returns a pointer to it.
/* Actually search the group line for the user. Can be comma or space
* delimited
*/
x = 0;
start = 0;
pch = mems;
while (!bFound && (pch[x] != '\0')) {
if ((isspace(pch[x])) || (pch[x] == ',')) {
bFound = !strncmp(user,(pch+start),x-start);
start = x+1;
}
x++;
}
if (!bFound && pch[x] == '\0' && (x-start > 0)) {
bFound = !strncmp(user,(pch+start),x-start);
}
/* Buggy, and obfuscated. */
/* nlen = strlen (user);
nlen = strlen (user);
pch = mems;
while (!bFound && (pch = strstr(pch, user)) &&
(!*(pch + nlen) || isspace (*(pch + nlen)) || *(pch + nlen) == ','))
bFound = 1;
*/
if (endp && *endp == '\0') *endp = chSaved;
return bFound;
}
char* init_group(per_request *reqInfo,char* grpfile)
{
FILE *fp;
@ -481,63 +422,54 @@ void check_auth(per_request *reqInfo, security_data *sec, char* auth_line)
KerberosInfo kdat;
#endif /* HAVE_KERBEROS */
/* Default to Auth Type Basic */
if(!sec->auth_type[0])
strcpy(sec->auth_type, "Basic");
/* No authorization info, so return the 401 to retrieve it */
if(!auth_line[0])
auth_bong(reqInfo,NULL, reqInfo->auth_name, sec->auth_type);
auth_bong(reqInfo,NULL, reqInfo->auth_name, sec->auth_type);
for (x=0 ; auth_line[x] && (auth_line[x] != ' ') && x < MAX_STRING_LEN; x++)
auth_type[x] = auth_line[x];
auth_type[x++] = '\0';
/* The authorization in the auth line is not the same which protects this
* directory.
*/
if (strcmp(auth_type, sec->auth_type))
auth_bong(reqInfo,"type mismatch",reqInfo->auth_name,sec->auth_type);
/* Basic Authentication */
if(!strcasecmp(sec->auth_type,"Basic")) {
if(!reqInfo->auth_name) {
sprintf(errstr,"HTTPd: need AuthName for %s",sec->d);
sprintf(errstr,"httpd: need AuthName for %s",sec->d);
die(reqInfo,SC_SERVER_ERROR,errstr);
}
if(!reqInfo->auth_pwfile) {
sprintf(errstr,"HTTPd: need AuthUserFile for %s",sec->d);
sprintf(errstr,"httpd: need AuthUserFile for %s",sec->d);
die(reqInfo,SC_SERVER_ERROR,errstr);
}
uudecode(auth_line + strlen(auth_type),(unsigned char *)ad,MAX_STRING_LEN);
getword(reqInfo->auth_user,ad,':');
getword(user,ad,':');
strcpy(sent_pw,ad);
if(!get_pw(reqInfo,reqInfo->auth_user,real_pw,sec)) {
sprintf(errstr,"user %s not found",reqInfo->auth_user);
if(!get_pw(reqInfo,user,real_pw,sec)) {
sprintf(errstr,"user %s not found",user);
auth_bong(reqInfo,errstr,reqInfo->auth_name,sec->auth_type);
}
/* anyone know where the prototype for crypt is? */
/* Yeah, in unistd.h on most systems, it seems */
if(strcmp(real_pw,(char *)crypt(sent_pw,real_pw))) {
sprintf(errstr,"user %s: password mismatch",reqInfo->auth_user);
sprintf(errstr,"user %s: password mismatch",user);
auth_bong(reqInfo,errstr,reqInfo->auth_name,sec->auth_type);
}
}
/* End Basic Authentication */
#ifdef DIGEST_AUTH
else if(!strcasecmp(sec->auth_type,"Digest")) {
if(!reqInfo->auth_name) {
sprintf(errstr,"HTTPd: need AuthName for %s",sec->d);
sprintf(errstr,"httpd: need AuthName for %s",sec->d);
die(reqInfo,SC_SERVER_ERROR,errstr);
}
if(!sec->auth_digestfile) {
sprintf(errstr,"HTTPd: need AuthDigestFile for %s",sec->d);
sprintf(errstr,"httpd: need AuthDigestFile for %s",sec->d);
die(reqInfo,SC_SERVER_ERROR,errstr);
}
Digest_Check(reqInfo,reqInfo->auth_user, sec);
Digest_Check(reqInfo,user, sec);
}
#endif /* DIGEST_AUTH */
#ifdef HAVE_KERBEROS
@ -570,7 +502,8 @@ void check_auth(per_request *reqInfo, security_data *sec, char* auth_line)
if (krbresult) {
if (check_krb_restrict(reqInfo, sec, &kdat)) {
remote_logname = user;
sprintf(reqInfo->outh_www_auth,"%s %s",
out_auth_header[0] = '\0';
sprintf(out_auth_header, "WWW-Authenticate: %s %s\r\n",
sec->auth_type, krb_authreply);
return;
}
@ -624,7 +557,7 @@ void check_auth(per_request *reqInfo, security_data *sec, char* auth_line)
t[y] = t[y+1];
}
getword(w,t,' ');
if(!strcmp(reqInfo->auth_user,w)) {
if(!strcmp(user,w)) {
bValid = 1;
break;
}
@ -639,11 +572,11 @@ void check_auth(per_request *reqInfo, security_data *sec, char* auth_line)
while (t[0]) {
getword(w,t,' ');
#ifdef DBM_SUPPORT
if (in_group(reqInfo,reqInfo->auth_user,w, pchGrpData, db)) {
if (in_group(reqInfo,user,w, pchGrpData, db)) {
#else
if (in_group(reqInfo,reqInfo->auth_user,w, pchGrpData)) {
if (in_group(reqInfo,user,w, pchGrpData)) {
#endif /* DBM_SUPPORT */
strcpy(reqInfo->auth_group,w);
strcpy(groupname,w);
bValid = 1;
break;
}
@ -664,7 +597,7 @@ void check_auth(per_request *reqInfo, security_data *sec, char* auth_line)
}
/* if we didn't validate the user */
if (!bValid) {
sprintf(errstr,"user %s denied",reqInfo->auth_user);
sprintf(errstr,"user %s denied",user);
auth_bong(reqInfo,errstr,reqInfo->auth_name,sec->auth_type);
}
}
@ -1050,3 +983,6 @@ int krb_in_group(KerberosInfo* kdat, char *group, char* pchGrps)
}
#endif /* HAVE_KERBEROS */

View File

@ -10,7 +10,7 @@
*
************************************************************************
*
* http_auth.h,v 1.22 1996/03/27 20:43:57 blong Exp
* http_auth.h,v 1.20 1995/07/25 14:48:05 blong Exp
*
************************************************************************
*
@ -25,10 +25,11 @@
# include <ndbm.h>
# endif /* _DBMSUPPORT_H */
#endif /* DBM_SUPPORT */
#include "global.h"
/* globals defined in this module */
extern char user[];
extern char groupname[];
/* http_auth */
@ -71,4 +72,5 @@ extern char k5_srvtab[];
int k5_server_auth(char* authline, char* reply, KerberosInfo *kdat);
#endif /* KRB5 */
#endif /* _HTTP_AUTH_H_ */

View File

@ -13,6 +13,39 @@
* http_config.c: auxillary functions for reading httpd's config file
* and converting filenames into a namespace
*
* Based on NCSA HTTPd 1.3 by Rob McCool
*
* 10/28/94 cvarela
* Added config options AgentLog and RefererLog for extra log info
*
* 02/19/95 blong
* Added config options MaxServers and StartServers for configuration
* defined children
*
* 03/21/95 cvarela
* Added RefererIgnore to ignore certain URIs when logging referers
*
* 06/01/95 blong
* Added patch by Conrad Damon (damon@netserver.stanford.edu) that
* avoids a cfg_getline loop if a user sets a directory as a password
* file.
*
* 09/02/95 blong
* Added patch by Kevin Ruddy (kevin.ruddy@powerdog.com) that should
* allow systems which don't recognize a numeric address to gethostbyname
* to use a numeric IP in the BindAddress and VirtualHost fields
*
* 09/10/95 mshapiro
* Added includes for <netinet/in.h> and <arpa/inet.h>
* 09/18/95 mshapiro
* Added LogDirGroupWriteOk, LogDirPublicWriteOk
* directives
* 10/06/95 blong
* Added patch by Elf Sternberg (elf@aaden.spry.com) to configure
* the process name which SETPROCTITLE uses
* 10/06/95 blong
* Added patch by Nathan Neulinger (nneul@umr.edu) to have separate
* security permissions for Redirect in .htaccess files
*/
@ -453,9 +486,11 @@ void process_server_config(per_host *host, FILE *cfg, FILE *errors,
}
#ifdef DIGEST_AUTH
else if(!strcasecmp(w,"AssumeDigestSupport")) {
/* Doesn't do anything anymore, but if we take it out, anyone with
* it in their configuration files would complain. *sigh*
*/
cfg_getword(w,l);
if(!strcmp(w,"on"))
assume_digest_support = TRUE;
else
assume_digest_support = FALSE;
}
#endif /* DIGEST_AUTH */
else if(((!strcasecmp(w,"<VirtualHost")) || (!strcasecmp(w,"<Host")))
@ -620,18 +655,11 @@ host->srm_confname,n,errors);
else if(!strcasecmp(w,"Redirect") || !strcasecmp(w,"RedirectTemp")) {
cfg_getword(w,l);
cfg_getword(w2,l);
if((w[0] == '\0') || (w2[0] == '\0') ||
!(is_url(w2) || (w2[0] == '/')))
{
if((w[0] == '\0') || (w2[0] == '\0') || (!is_url(w2))) {
config_error(
"Redirect must be followed by a document, one space, then a URL",
host->srm_confname,n,errors);
}
if (w2[0] == '/') {
char w3[MAX_STRING_LEN];
construct_url(w3,host,w2);
strcpy(w2,w3);
}
if (!set_host_conf_value(host,PH_SRM_CONF,SRM_TRANSLATIONS)) {
host->translations = NULL;
}
@ -640,9 +668,7 @@ host->srm_confname,n,errors);
else if(!strcasecmp(w,"RedirectPermanent")) {
cfg_getword(w,l);
cfg_getword(w2,l);
if((w[0] == '\0') || (w2[0] == '\0') ||
!(is_url(w2) || (w2[0] == '/')))
{
if((w[0] == '\0') || (w2[0] == '\0') || (!is_url(w2))) {
config_error(
"RedirectPermanent must be followed by a document, one space, then a URL",
host->srm_confname,n,errors);
@ -650,11 +676,6 @@ host->srm_confname,n,errors);
if (!set_host_conf_value(host,PH_SRM_CONF,SRM_TRANSLATIONS)) {
host->translations = NULL;
}
if (w2[0] == '/') {
char w3[MAX_STRING_LEN];
construct_url(w3,host,w2);
strcpy(w2,w3);
}
add_redirect(host,w,w2,A_REDIRECT_PERM);
}
else if(!strcasecmp(w,"FancyIndexing")) {
@ -785,7 +806,7 @@ void access_syntax_error(per_request *reqInfo, int n, char *err, FILE *fp,
else {
char e[MAX_STRING_LEN];
FClose(fp);
sprintf(e,"HTTPd: syntax error or override violation in access control file %s, reason: %s",file,err);
sprintf(e,"httpd: syntax error or override violation in access control file %s, reason: %s",file,err);
die(reqInfo,SC_SERVER_ERROR,e);
}
}
@ -800,10 +821,6 @@ int parse_access_dir(per_request *reqInfo, FILE *f, int line, char or,
register int x,i;
x = num_sec;
if (num_sec > MAX_SECURITY)
access_syntax_error(reqInfo,n,
"Too many security entries, increase MAX_SECURITY and recompile",
f,file);
sec[x].opts=OPT_UNSET;
sec[x].override = or;
@ -825,10 +842,7 @@ int parse_access_dir(per_request *reqInfo, FILE *f, int line, char or,
sec[x].order[i] = DENY_THEN_ALLOW;
sec[x].num_allow[i]=0;
sec[x].num_deny[i]=0;
sec[x].num_referer_allow[i]=0;
sec[x].num_referer_deny[i]=0;
sec[x].num_auth[i] = 0;
sec[x].on_deny[i] = NULL;
}
while(!(cfg_getline(l,MAX_STRING_LEN,f))) {
@ -1073,38 +1087,18 @@ int parse_access_dir(per_request *reqInfo, FILE *f, int line, char or,
access_syntax_error(reqInfo,n,"override violation",f,file);
cfg_getword(w,l);
cfg_getword(w2,l);
if((w[0] == '\0') || (w2[0] == '\0') ||
!(is_url(w2) || (w2[0] == '/')))
{
if((w[0] == '\0') || (w2[0] == '\0') || (!is_url(w2))) {
access_syntax_error(reqInfo,n,
"Redirect must be followed by a document, one space, then a URL.",f,file);
}
if(!file) {
if (w2[0] == '/') {
char w3[MAX_STRING_LEN];
construct_url(w3,gConfiguration,w2);
strcpy(w2,w3);
}
if (!set_host_conf_value(gConfiguration,PH_SRM_CONF,SRM_TRANSLATIONS)) {
gConfiguration->translations = NULL;
}
add_redirect(gConfiguration,w,w2,A_REDIRECT_TEMP);
}
else {
char tmp[HUGE_STRING_LEN];
int len;
if (w2[0] == '/') {
construct_url(tmp,reqInfo->hostInfo,w2);
strcpy(w2,tmp);
}
strcpy(tmp,reqInfo->url);
if (reqInfo->path_info[0]) {
len = strlen(reqInfo->url);
if (reqInfo->url[len-1] == '/')
reqInfo->url[len-1] = '\0';
strcat(tmp,reqInfo->path_info);
}
if (!strcmp(tmp,w) || !strcmp_match(tmp,w)) {
if (!strcmp(reqInfo->url,w)) {
FClose(f);
die(reqInfo,SC_REDIRECT_TEMP,w2);
}
@ -1115,40 +1109,20 @@ int parse_access_dir(per_request *reqInfo, FILE *f, int line, char or,
access_syntax_error(reqInfo,n,"override violation",f,file);
cfg_getword(w,l);
cfg_getword(w2,l);
if((w[0] == '\0') || (w2[0] == '\0') ||
!(is_url(w2) || (w2[0] == '/')))
{
if((w[0] == '\0') || (w2[0] == '\0') || (!is_url(w2))) {
access_syntax_error(reqInfo,n,
"Redirect must be followed by a document, one space, then a URL.",f,file);
}
if(!file) {
if (w2[0] == '/') {
char w3[MAX_STRING_LEN];
construct_url(w3,gConfiguration,w2);
strcpy(w2,w3);
}
if (!set_host_conf_value(gConfiguration,PH_SRM_CONF,SRM_TRANSLATIONS)) {
gConfiguration->translations = NULL;
}
add_redirect(gConfiguration,w,w2,A_REDIRECT_PERM);
}
else {
char tmp[HUGE_STRING_LEN];
int len;
if (w2[0] == '/') {
construct_url(tmp,reqInfo->hostInfo,w2);
strcpy(w2,tmp);
}
strcpy(tmp,reqInfo->url);
if (reqInfo->path_info[0]) {
len = strlen(reqInfo->url);
if (reqInfo->url[len-1] == '/')
reqInfo->url[len-1] = '\0';
strcat(tmp,reqInfo->path_info);
}
if (!strcmp(tmp,w) || !strcmp_match(tmp,w)) {
if (!strcmp(reqInfo->url,w)) {
FClose(f);
die(reqInfo,SC_REDIRECT_TEMP,w2);
die(reqInfo,SC_REDIRECT_PERM,w2);
}
}
}
@ -1206,65 +1180,15 @@ int parse_access_dir(per_request *reqInfo, FILE *f, int line, char or,
for(i=0;i<METHODS;i++)
if(m[i]) {
int q=sec[x].num_allow[i]++;
if (q >= MAX_SECURITY)
access_syntax_error(reqInfo,n,
"Too many allow entries, increase MAX_SECURITY and recompile",
f,file);
if(!(sec[x].allow[i][q] = strdup(w)))
die(reqInfo,SC_NO_MEMORY,"parse_access_dir");
}
}
}
else if(!strcasecmp(w,"referer")) {
int ref_type;
cfg_getword(w,l);
if(!strcmp(w,"allow")) {
ref_type = FA_ALLOW;
} else if (!strcmp(w,"deny")) {
ref_type = FA_DENY;
} else access_syntax_error(reqInfo,n,
"unknown referer type.",
f,file);
cfg_getword(w,l);
if(strcmp(w,"from"))
access_syntax_error(reqInfo,n,
"allow/deny must be followed by from.",
f,file);
while(1) {
cfg_getword(w,l);
if (!w[0]) break;
for(i=0;i<METHODS;i++)
if(m[i]) {
int q;
if (ref_type == FA_ALLOW) {
q=sec[x].num_referer_allow[i]++;
if (q >= MAX_SECURITY)
access_syntax_error(reqInfo,n,
"Too many referer allow entries, increase MAX_SECURITY and recompile",
f,file);
if(!(sec[x].referer_allow[i][q] = strdup(w)))
die(reqInfo,SC_NO_MEMORY,"parse_access_dir");
} else if (ref_type == FA_DENY) {
q=sec[x].num_referer_deny[i]++;
if (q >= MAX_SECURITY)
access_syntax_error(reqInfo,n,
"Too many referer deny entries, increase MAX_SECURITY and recompile",
f,file);
if(!(sec[x].referer_deny[i][q] = strdup(w)))
die(reqInfo,SC_NO_MEMORY,"parse_access_dir");
}
}
}
}
else if(!strcasecmp(w,"require")) {
for(i=0;i<METHODS;i++)
if(m[i]) {
int q=sec[x].num_auth[i]++;
if (q >= MAX_SECURITY)
access_syntax_error(reqInfo,n,
"Too many require entries, increase MAX_SECURITY and recompile",
f,file);
if(!(sec[x].auth[i][q] = strdup(l)))
die(reqInfo,SC_NO_MEMORY,"parse_access_dir");
}
@ -1281,10 +1205,6 @@ int parse_access_dir(per_request *reqInfo, FILE *f, int line, char or,
for(i=0;i<METHODS;i++)
if(m[i]) {
int q=sec[x].num_deny[i]++;
if (q >= MAX_SECURITY)
access_syntax_error(reqInfo,n,
"Too many deny entries, increase MAX_SECURITY and recompile",
f,file);
if(!(sec[x].deny[i][q] = strdup(w)))
die(reqInfo,SC_NO_MEMORY,"parse_access_dir");
}
@ -1301,13 +1221,6 @@ int parse_access_dir(per_request *reqInfo, FILE *f, int line, char or,
"Satisfy either any or all.",
f,file);
}
else if(!strcasecmp(w,"OnDeny")) {
for(i=0;i<METHODS;i++)
if(m[i]) {
if(!(sec[x].on_deny[i] = strdup(l)))
die(reqInfo,SC_NO_MEMORY,"parse_access_dir");
}
}
else
access_syntax_error(reqInfo,n,
"Unknown keyword in Limit region.",
@ -1357,7 +1270,7 @@ void process_access_config(FILE *errors)
num_sec = 0;
n=0;
if(!(f=fopen(access_confname,"r"))) {
fprintf(errors,"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);
@ -1389,7 +1302,7 @@ void read_config(FILE *errors)
if(!(cfg = fopen(server_confname,"r"))) {
fprintf(errors,
"HTTPd: could not open server config. file %s\n",
"httpd: could not open server config. file %s\n",
server_confname);
perror("fopen");
exit(1);

View File

@ -10,7 +10,7 @@
*
************************************************************************
*
* http_config.h,v 1.15 1996/03/27 20:44:01 blong Exp
* http_config.h,v 1.13 1995/11/28 09:01:58 blong Exp
*
************************************************************************
*

View File

@ -12,6 +12,12 @@
*
* http_dir.c: Handles the on-the-fly html index generation
*
* 03-23-93 Rob McCool
* Wrote base code up to release 1.3
*
* 03-12-95 blong
* Added patch by Roy T. Fielding <fielding@avron.ICS.UCI.EDU>
* to fix missing trailing slash for parent directory
*/
@ -35,16 +41,15 @@
#include <sys/types.h>
#include <ctype.h>
#include "constants.h"
#include "http_request.h"
#include "http_dir.h"
#include "http_mime.h"
#include "http_log.h"
#include "http_config.h"
#include "http_request.h"
#include "http_send.h"
#include "http_alias.h"
#include "util.h"
#include "fdwrap.h"
#include "allocate.h"
/* Split each item list into two lists, the 0-th entry holds items which
* are valid over this request while the 1-st entry for those valids for
@ -57,21 +62,21 @@ static struct item *hdr_list[2], *rdme_list[2], *opts_list[2];
static int dir_opts;
void init_indexing(int local) {
icon_list[FI_LOCAL] = NULL;
alt_list[FI_LOCAL] = NULL;
desc_list[FI_LOCAL] = NULL;
ign_list[FI_LOCAL] = NULL;
hdr_list[FI_LOCAL] = NULL;
rdme_list[FI_LOCAL] = NULL;
opts_list[FI_LOCAL] = NULL;
icon_list[0] = NULL;
alt_list[0] = NULL;
desc_list[0] = NULL;
ign_list[0] = NULL;
hdr_list[0] = NULL;
rdme_list[0] = NULL;
opts_list[0] = NULL;
if (local == FI_GLOBAL) {
icon_list[FI_GLOBAL] = NULL;
alt_list[FI_GLOBAL] = NULL;
desc_list[FI_GLOBAL] = NULL;
ign_list[FI_GLOBAL] = NULL;
hdr_list[FI_GLOBAL] = NULL;
rdme_list[FI_GLOBAL] = NULL;
opts_list[FI_GLOBAL] = NULL;
icon_list[1] = NULL;
alt_list[1] = NULL;
desc_list[1] = NULL;
ign_list[1] = NULL;
hdr_list[1] = NULL;
rdme_list[1] = NULL;
opts_list[1] = NULL;
}
}
@ -257,48 +262,38 @@ char *find_item(per_request *reqInfo, struct item *list[2], char *path,
{
struct item *p = NULL;
int i;
char *file_type,*file_encoding;
file_type = newString(MAX_STRING_LEN,STR_TMP);
file_encoding = newString(MAX_STRING_LEN,STR_TMP);
for (i=0; i < 2; i++) {
for (p = list[i]; p; p = p->next) {
/* Special cased for ^^DIRECTORY^^ and ^^BLANKICON^^ */
if((path[0] == '^') || (!strcmp_match(path,p->apply_path))) {
if(!(p->apply_to))
goto found_item;
return p->data;
else if(p->type == BY_PATH) {
if(!strcmp_match(path,p->apply_to))
goto found_item;
return p->data;
} else if(!path_only) {
char pathbak[MAX_STRING_LEN];
strcpy(pathbak,path);
get_content_type(reqInfo,pathbak,file_type,file_encoding);
if(!file_encoding[0]) {
content_encoding[0] = '\0';
set_content_type(reqInfo,pathbak);
if(!content_encoding[0]) {
if(p->type == BY_TYPE) {
if(!strcmp_match(file_type,p->apply_to))
goto found_item;
if(!strcmp_match(content_type,p->apply_to))
return p->data;
}
} else {
if(p->type == BY_ENCODING) {
if(!strcmp_match(file_encoding,p->apply_to))
goto found_item;
if(!strcmp_match(content_encoding,p->apply_to))
return p->data;
}
}
}
}
}
}
freeString(file_type);
freeString(file_encoding);
return NULL;
found_item:
freeString(file_type);
freeString(file_encoding);
return p->data;
}
#define find_icon(r,p,t) find_item(r,icon_list,p,t)
@ -347,15 +342,16 @@ int insert_readme(per_request *reqInfo, char *name,
if(stat(fn,&finfo) == -1)
return 0;
plaintext=1;
if(rule) rprintf(reqInfo,"<HR>%c",LF);
rprintf(reqInfo,"<PRE>%c",LF);
if(rule) reqInfo->bytes_sent += fprintf(reqInfo->out,"<HR>%c",LF);
reqInfo->bytes_sent += fprintf(reqInfo->out,"<PRE>%c",LF);
}
else if(rule) rprintf(reqInfo,"<HR>%c",LF);
else if(rule) reqInfo->bytes_sent += fprintf(reqInfo->out,"<HR>%c",LF);
if(!(r = FOpen(fn,"r")))
return 0;
send_fp(reqInfo,r,NULL);
FClose(r);
if(plaintext) rprintf(reqInfo,"</PRE>%c",LF);
if(plaintext)
reqInfo->bytes_sent += fprintf(reqInfo->out,"</PRE>%c",LF);
return 1;
}
@ -365,18 +361,15 @@ char *find_title(per_request *reqInfo, char *filename) {
char filebak[MAX_STRING_LEN];
FILE *thefile;
int x,y,n,p;
char *file_type, *file_encoding;
file_type = newString(MAX_STRING_LEN,STR_TMP);
file_encoding = newString(MAX_STRING_LEN,STR_TMP);
content_encoding[0] = '\0';
strcpy(filebak,filename);
get_content_type(reqInfo,filebak,file_type,file_encoding);
if(((!strcmp(file_type,"text/html")) ||
(strcmp(file_type, INCLUDES_MAGIC_TYPE) == 0))
&& (!file_encoding[0])) {
set_content_type(reqInfo,filebak);
if(((!strcmp(content_type,"text/html")) ||
(strcmp(content_type, INCLUDES_MAGIC_TYPE) == 0))
&& (!content_encoding[0])) {
if(!(thefile = FOpen(filename,"r")))
goto not_found;
return NULL;
n = fread(titlebuf,sizeof(char),MAX_STRING_LEN - 1,thefile);
titlebuf[n] = '\0';
for(x=0,p=0;titlebuf[x];x++) {
@ -389,17 +382,14 @@ char *find_title(per_request *reqInfo, char *filename) {
if((titlebuf[y] == CR) || (titlebuf[y] == LF))
titlebuf[y] = ' ';
FClose(thefile);
freeString(file_type);
freeString(file_encoding);
return strdup(&titlebuf[x]);
}
} else p=0;
}
FClose(thefile);
return NULL;
}
not_found:
freeString(file_type);
freeString(file_encoding);
content_encoding[0] = '\0';
return NULL;
}
@ -505,19 +495,22 @@ struct ent *make_dir_entry(per_request *reqInfo, char *path,
void send_size(per_request *reqInfo, size_t size) {
if(size == -1) {
rputs(" -",reqInfo);
fputs(" -",reqInfo->out);
reqInfo->bytes_sent += 5;
}
else {
if(!size) {
rputs(" 0K",reqInfo);
fputs(" 0K",reqInfo->out);
reqInfo->bytes_sent += 5;
}
else if(size < 1024) {
rputs(" 1K",reqInfo);
fputs(" 1K",reqInfo->out);
reqInfo->bytes_sent += 5;
}
else if(size < 1048576)
rprintf(reqInfo,"%4dK",size / 1024);
reqInfo->bytes_sent += fprintf(reqInfo->out,"%4dK",size / 1024);
else
rprintf(reqInfo,"%4dM",size / 1048576);
reqInfo->bytes_sent += fprintf(reqInfo->out,"%4dM",size / 1048576);
}
}
@ -557,28 +550,30 @@ void output_directories(per_request *reqInfo, struct ent **ar,int n,char *name)
name[0] = '/'; name[1] = '\0';
}
/* aaaaargh Solaris sucks. */
rflush(reqInfo);
fflush(reqInfo->out);
if(dir_opts & FANCY_INDEXING) {
rputs("<PRE>",reqInfo);
fputs("<PRE>",reqInfo->out);
(reqInfo->bytes_sent) += 5;
if((tp = find_icon(reqInfo,"^^BLANKICON^^",1)))
rprintf(reqInfo,"<IMG SRC=\"%s\" ALT=\" \"> ",tp);
rprintf(reqInfo,"Name ");
reqInfo->bytes_sent += (fprintf(reqInfo->out,
"<IMG SRC=\"%s\" ALT=\" \"> ",tp));
reqInfo->bytes_sent += fprintf(reqInfo->out,"Name ");
if(!(dir_opts & SUPPRESS_LAST_MOD))
rprintf(reqInfo,"Last modified ");
reqInfo->bytes_sent += fprintf(reqInfo->out,"Last modified ");
if(!(dir_opts & SUPPRESS_SIZE))
rprintf(reqInfo,"Size ");
reqInfo->bytes_sent += fprintf(reqInfo->out,"Size ");
if(!(dir_opts & SUPPRESS_DESC))
rprintf(reqInfo,"Description");
rprintf(reqInfo,"%c<HR>%c",LF,LF);
reqInfo->bytes_sent += fprintf(reqInfo->out,"Description");
reqInfo->bytes_sent += fprintf(reqInfo->out,"%c<HR>%c",LF,LF);
}
else {
rputs("<UL>",reqInfo);
fputs("<UL>",reqInfo->out);
reqInfo->bytes_sent += 4;
}
for(x=0;x<n;x++) {
if((!strcmp(ar[x]->name,"../")) || (!strcmp(ar[x]->name,".."))) {
int i;
/* Fixes trailing slash for fancy indexing. Thanks Roy ? */
make_full_path(name,"../",t);
@ -586,10 +581,6 @@ void output_directories(per_request *reqInfo, struct ent **ar,int n,char *name)
if(t[0] == '\0') {
t[0] = '/'; t[1] = '\0';
}
i = strlen(t);
if(t[i-1] != '/') {
t[i-1] = '/'; t[i] = '\0';
}
escape_uri(t);
sprintf(anchor,"<A HREF=\"%s\">",t);
strcpy(t2,"Parent Directory</A>");
@ -611,51 +602,59 @@ void output_directories(per_request *reqInfo, struct ent **ar,int n,char *name)
if(dir_opts & FANCY_INDEXING) {
if(dir_opts & ICONS_ARE_LINKS)
rprintf(reqInfo,"%s",anchor);
reqInfo->bytes_sent += fprintf(reqInfo->out,"%s",anchor);
if((ar[x]->icon) || reqInfo->hostInfo->default_icon[0]
|| local_default_icon[0]) {
rprintf(reqInfo,"<IMG SRC=\"%s\" ALT=\"[%s]\">",
ar[x]->icon ? ar[x]->icon :
local_default_icon[0] ?
local_default_icon :
reqInfo->hostInfo->default_icon,
ar[x]->alt ? ar[x]->alt : " ");
reqInfo->bytes_sent += fprintf(reqInfo->out,
"<IMG SRC=\"%s\" ALT=\"[%s]\">",
ar[x]->icon ? ar[x]->icon :
local_default_icon[0] ?
local_default_icon :
reqInfo->hostInfo->default_icon,
ar[x]->alt ? ar[x]->alt : " ");
}
if(dir_opts & ICONS_ARE_LINKS) {
rputs("</A>",reqInfo);
fputs("</A>",reqInfo->out);
reqInfo->bytes_sent += 4;
}
rprintf(reqInfo," %s",anchor);
rprintf(reqInfo,"%-27.27s",t2);
reqInfo->bytes_sent += fprintf(reqInfo->out," %s",anchor);
reqInfo->bytes_sent += fprintf(reqInfo->out,"%-27.27s",t2);
if(!(dir_opts & SUPPRESS_LAST_MOD)) {
if(ar[x]->lm != -1) {
struct tm *ts = localtime(&ar[x]->lm);
strftime(t,MAX_STRING_LEN,"%d-%b-%y %H:%M ",ts);
rputs(t,reqInfo);
fputs(t,reqInfo->out);
reqInfo->bytes_sent += strlen(t);
}
else {
rputs(" ",reqInfo);
fputs(" ",reqInfo->out);
reqInfo->bytes_sent += 17;
}
}
if(!(dir_opts & SUPPRESS_SIZE)) {
send_size(reqInfo,ar[x]->size);
rputs(" ",reqInfo);
fputs(" ",reqInfo->out);
reqInfo->bytes_sent += 2;
}
if(!(dir_opts & SUPPRESS_DESC)) {
if(ar[x]->desc) {
terminate_description(ar[x]->desc);
rprintf(reqInfo,"%s",ar[x]->desc);
reqInfo->bytes_sent += fprintf(reqInfo->out,"%s",ar[x]->desc);
}
}
}
else
rprintf(reqInfo,"<LI> %s %s",anchor,t2);
rputc(LF,reqInfo);
reqInfo->bytes_sent += fprintf(reqInfo->out,"<LI> %s %s",anchor,t2);
fputc(LF,reqInfo->out);
++(reqInfo->bytes_sent);
}
if(dir_opts & FANCY_INDEXING) {
rputs("</PRE>",reqInfo);
fputs("</PRE>",reqInfo->out);
reqInfo->bytes_sent += 6;
}
else {
rputs("</UL>",reqInfo);
fputs("</UL>",reqInfo->out);
reqInfo->bytes_sent += 5;
}
}
@ -679,13 +678,12 @@ void index_directory(per_request *reqInfo)
if(!(d=Opendir(reqInfo->filename)))
die(reqInfo,SC_FORBIDDEN,reqInfo->url);
strcpy(reqInfo->outh_content_type,"text/html");
if(reqInfo->http_version != P_HTTP_0_9)
strcpy(content_type,"text/html");
if(!no_headers)
send_http_header(reqInfo);
if(reqInfo->method == M_HEAD) {
if(header_only) {
Closedir(d);
log_transaction(reqInfo);
return;
}
@ -694,13 +692,16 @@ void index_directory(per_request *reqInfo)
dir_opts = find_opts(reqInfo->filename);
/* Spew HTML preamble */
rprintf(reqInfo,"<HEAD><TITLE>Index of %s</TITLE></HEAD><BODY>",
reqInfo->bytes_sent += fprintf(reqInfo->out,
"<HEAD><TITLE>Index of %s</TITLE></HEAD><BODY>",
reqInfo->url);
rputc(LF,reqInfo);
fputc(LF,reqInfo->out);
++(reqInfo->bytes_sent);
if((!(tmp = find_header(reqInfo, reqInfo->filename))) ||
(!(insert_readme(reqInfo,reqInfo->filename,tmp,0))))
rprintf(reqInfo, "<H1>Index of %s</H1>%c",reqInfo->url,LF);
reqInfo->bytes_sent += fprintf(reqInfo->out,
"<H1>Index of %s</H1>%c",reqInfo->url,LF);
/*
* Since we don't know how many dir. entries there are, put them into a
@ -749,10 +750,13 @@ void index_directory(per_request *reqInfo)
if((tmp = find_readme(reqInfo,reqInfo->filename)))
insert_readme(reqInfo,reqInfo->filename,tmp,1);
else {
rputs("</UL>",reqInfo);
fputs("</UL>",reqInfo->out);
reqInfo->bytes_sent += 5;
}
rputs("</BODY>", reqInfo);
rflush(reqInfo);
fputs("</BODY>", reqInfo->out);
fflush(reqInfo->out);
reqInfo->bytes_sent += 7;
fflush(reqInfo->out);
log_transaction(reqInfo);
}

View File

@ -10,7 +10,7 @@
*
************************************************************************
*
* http_include.c,v 1.50 1996/03/27 20:44:02 blong Exp
* http_include.c,v 1.41 1995/11/28 09:02:02 blong Exp
*
************************************************************************
*
@ -18,6 +18,9 @@
*
* Based on NCSA HTTPd 1.3 by Rob McCool
*
* 04-07-95 blong
* Fixes bug where substrings of the environment variable might be
* included first as suggested by David Robinson (drtr@ast.cam.ac.uk)
*/
@ -38,7 +41,6 @@
#include <ctype.h>
#include "constants.h"
#include "fdwrap.h"
#include "allocate.h"
#include "http_include.h"
#include "http_mime.h"
#include "http_log.h"
@ -60,10 +62,8 @@ static time_t date,lm;
int add_include_vars(per_request *reqInfo, char *timefmt)
{
struct stat finfo;
char *uri;
char *str;
uri = newString(HUGE_STRING_LEN,STR_TMP);
char uri[HUGE_STRING_LEN];
char *t;
date = time(NULL);
make_env_str(reqInfo,"DATE_LOCAL",ht_time(date,timefmt,0));
@ -73,24 +73,23 @@ int add_include_vars(per_request *reqInfo, char *timefmt)
lm = finfo.st_mtime;
make_env_str(reqInfo,"LAST_MODIFIED",ht_time(lm,timefmt,0));
}
if((str = strrchr(reqInfo->filename,'/')))
++str;
if((t = strrchr(reqInfo->filename,'/')))
++t;
else
str = reqInfo->url;
make_env_str(reqInfo,"DOCUMENT_NAME",str);
t = reqInfo->url;
make_env_str(reqInfo,"DOCUMENT_NAME",t);
/* Jump through hoops because <=1.4 set DOCUMENT_URI to
include index file name */
if (reqInfo->url[strlen(reqInfo->url)-1] == '/' ){
strncpy(uri,reqInfo->url,HUGE_STRING_LEN);
strncat(uri,str,HUGE_STRING_LEN-strlen(uri));
strncat(uri,t,HUGE_STRING_LEN-strlen(uri));
make_env_str(reqInfo,"DOCUMENT_URI",uri);
} else {
make_env_str(reqInfo,"DOCUMENT_URI",reqInfo->url);
}
freeString(uri);
return TRUE;
}
@ -120,10 +119,12 @@ int find_string(per_request *reqInfo, FILE *fp, char *str) {
if(reqInfo->out) {
if(p) {
for(x=0;x<p;x++) {
rputc(str[x],reqInfo);
putc(str[x],reqInfo->out);
++(reqInfo->bytes_sent);
}
}
rputc(c,reqInfo);
putc(c,reqInfo->out);
++(reqInfo->bytes_sent);
}
p=0;
}
@ -210,6 +211,9 @@ int get_directive(FILE *fp, char *d) {
/* --------------------------- Action handlers ---------------------------- */
void send_parsed_content(per_request *reqInfo, FILE *f, char *path_args,
int noexec);
int send_included_file(per_request *reqInfo, char *fn)
{
FILE *fp;
@ -223,14 +227,13 @@ int send_included_file(per_request *reqInfo, char *fn)
if(!allow)
return -1;
set_content_type(reqInfo,reqInfo->filename);
if((op & OPT_INCLUDES) &&
(!strcmp(reqInfo->outh_content_type,INCLUDES_MAGIC_TYPE))) {
if((op & OPT_INCLUDES) && (!strcmp(content_type,INCLUDES_MAGIC_TYPE))) {
if(!(fp = FOpen(reqInfo->filename,"r")))
return -1;
send_parsed_content(reqInfo,fp,op & OPT_INCNOEXEC);
send_parsed_content(reqInfo,fp,"",op & OPT_INCNOEXEC);
chdir_file(fn); /* grumble */
}
else if(!strcmp(reqInfo->outh_content_type,CGI_MAGIC_TYPE))
else if(!strcmp(content_type,CGI_MAGIC_TYPE))
return -1;
else {
if(!(fp=FOpen(reqInfo->filename,"r")))
@ -242,30 +245,20 @@ int send_included_file(per_request *reqInfo, char *fn)
}
int handle_include(per_request *reqInfo, FILE *fp, char *error) {
char *tag,*errstr;
char tag[MAX_STRING_LEN],errstr[MAX_STRING_LEN];
char *tag_val;
tag = newString(MAX_STRING_LEN,STR_TMP);
errstr = newString(MAX_STRING_LEN,STR_TMP);
while(1) {
if(!(tag_val = get_tag(fp,tag))) {
freeString(tag);
freeString(errstr);
if(!(tag_val = get_tag(fp,tag)))
return 1;
}
if(!strcmp(tag,"file")) {
char *dir,*to_send;
char dir[MAX_STRING_LEN],to_send[MAX_STRING_LEN];
per_request *newInfo;
dir = newString(MAX_STRING_LEN,STR_TMP);
to_send = newString(MAX_STRING_LEN,STR_TMP);
getparents(tag_val); /* get rid of any nasties */
getcwd(dir,MAX_STRING_LEN);
getwd(dir);
make_full_path(dir,tag_val,to_send);
newInfo = continue_request(reqInfo, KEEP_ENV | KEEP_AUTH);
newInfo->http_version = P_HTTP_0_9;
newInfo = continue_request(reqInfo,NEW_URL | KEEP_ENV);
strcpy(newInfo->url,tag_val);
strcpy(newInfo->args,reqInfo->args);
strcpy(newInfo->filename,to_send);
@ -273,21 +266,18 @@ int handle_include(per_request *reqInfo, FILE *fp, char *error) {
sprintf(errstr,"unable to include %s in parsed file %s",
newInfo->filename,reqInfo->filename );
log_error(errstr,reqInfo->hostInfo->error_log);
rprintf(reqInfo,"%s",error);
reqInfo->bytes_sent += fprintf(reqInfo->out,"%s",error);
}
reqInfo->bytes_sent += newInfo->bytes_sent;
free_request(newInfo,ONLY_LAST);
freeString(dir);
freeString(to_send);
}
else if(!strcmp(tag,"virtual")) {
per_request *newInfo;
newInfo = continue_request(reqInfo, KEEP_ENV | KEEP_AUTH);
newInfo->http_version = P_HTTP_0_9;
newInfo = continue_request(reqInfo, NEW_URL | KEEP_ENV);
strcpy(newInfo->url,tag_val);
if(translate_name(newInfo,newInfo->url,newInfo->filename)
!= A_STD_DOCUMENT) {
rprintf(reqInfo,"%s",error);
reqInfo->bytes_sent += fprintf(reqInfo->out,"%s",error);
sprintf(errstr,"unable to include %s in parsed file %s, non standard document",newInfo->filename, reqInfo->filename);
log_error(errstr,reqInfo->hostInfo->error_log);
} else {
@ -295,22 +285,19 @@ int handle_include(per_request *reqInfo, FILE *fp, char *error) {
sprintf(errstr,"unable to include %s in parsed file %s",
newInfo->filename, reqInfo->filename);
log_error(errstr,reqInfo->hostInfo->error_log);
rprintf(reqInfo,"%s",error);
reqInfo->bytes_sent += fprintf(reqInfo->out,"%s",error);
}
reqInfo->bytes_sent += newInfo->bytes_sent;
}
free_request(newInfo,ONLY_LAST);
}
else if(!strcmp(tag,"done")) {
freeString(tag);
freeString(errstr);
else if(!strcmp(tag,"done"))
return 0;
}
else {
sprintf(errstr,"unknown parameter %s to tag echo in %s",tag,
reqInfo->filename);
log_error(errstr,reqInfo->hostInfo->error_log);
rprintf(reqInfo,"%s",error);
reqInfo->bytes_sent += fprintf(reqInfo->out,"%s",error);
}
}
}
@ -318,22 +305,23 @@ int handle_include(per_request *reqInfo, FILE *fp, char *error) {
#ifndef NO_YOW
#include "httpy.h"
void print_yow(per_request *reqInfo, int yow_num) {
int print_yow(per_request *reqInfo, int yow_num) {
int i = 0;
int href_on = FALSE;
int tmp;
if (yow_num >= MAX_YOW) yow_num = MAX_YOW-1;
while (yow_lines[yow_num][i]) {
rputc(yow_lines[yow_num][i],reqInfo);
putc(yow_lines[yow_num][i],reqInfo->out);
if (yow_lines[yow_num][i] == ' ') {
tmp = href_on;
href_on = (rand() % 100 < 50) ? 1 : 0;
if (tmp != href_on) {
if (!tmp)
rprintf(reqInfo,"<A HREF=\"%s\">", reqInfo->url);
reqInfo->bytes_sent += fprintf(reqInfo->out,"<A HREF=\"%s\">",
reqInfo->url);
else
rprintf(reqInfo,"</A>");
reqInfo->bytes_sent += fprintf(reqInfo->out,"</A>");
}
i++;
while ((yow_lines[yow_num][i] == ' ') && yow_lines[yow_num][i++]);
@ -344,23 +332,19 @@ void print_yow(per_request *reqInfo, int yow_num) {
i++;
}
if (href_on) {
rprintf(reqInfo,"</A>");
reqInfo->bytes_sent += fprintf(reqInfo->out,"</A>");
}
}
#endif /* NO_YOW */
int handle_echo(per_request *reqInfo, FILE *fp, char *error) {
char *tag;
char tag[MAX_STRING_LEN];
char *tag_val;
tag = newString(MAX_STRING_LEN,STR_TMP);
while(1) {
if(!(tag_val = get_tag(fp,tag))) {
freeString(tag);
if(!(tag_val = get_tag(fp,tag)))
return 1;
}
if(!strcmp(tag,"var")) {
int x,i,len;
@ -368,12 +352,13 @@ int handle_echo(per_request *reqInfo, FILE *fp, char *error) {
for(x=0;reqInfo->env[x] != NULL; x++) {
i = ind(reqInfo->env[x],'=');
if((i == len) && !(strncmp(reqInfo->env[x],tag_val,i))) {
rprintf(reqInfo,"%s",&(reqInfo->env[x][i+1]));
reqInfo->bytes_sent += fprintf(reqInfo->out,"%s",
&(reqInfo->env[x][i+1]));
break;
}
}
if(!(reqInfo->env[x]))
rprintf(reqInfo,"(none)");
reqInfo->bytes_sent += fprintf(reqInfo->out,"(none)");
}
#ifndef NO_YOW
else if(!strcmp(tag,"yow")) {
@ -381,26 +366,19 @@ int handle_echo(per_request *reqInfo, FILE *fp, char *error) {
print_yow(reqInfo,num);
}
#endif /* NO_YOW */
else if(!strcmp(tag,"done")) {
freeString(tag);
else if(!strcmp(tag,"done"))
return 0;
}
else {
char *errstr;
errstr = newString(MAX_STRING_LEN,STR_TMP);
char errstr[MAX_STRING_LEN];
sprintf(errstr,"unknown parameter %s to tag echo in %s",tag,
reqInfo->filename);
log_error(errstr,reqInfo->hostInfo->error_log);
rprintf(reqInfo,"%s",error);
freeString(errstr);
reqInfo->bytes_sent += fprintf(reqInfo->out,"%s",error);
}
}
}
int include_cgi(per_request *reqInfo) {
int include_cgi(per_request *reqInfo, char *pargs) {
char op;
int allow,check_cgiopt;
struct stat finfo;
@ -412,12 +390,10 @@ int include_cgi(per_request *reqInfo) {
return -1;
check_cgiopt=0;
} else {
char *dir;
dir = newString(MAX_STRING_LEN, STR_TMP);
getcwd(dir,MAX_STRING_LEN);
char dir[MAX_STRING_LEN];
getwd(dir);
make_full_path(dir,reqInfo->url,reqInfo->filename);
check_cgiopt=1;
freeString(dir);
}
/* No hardwired path info or query allowed */
if(stat(reqInfo->filename,&finfo) == -1)
@ -428,51 +404,43 @@ int include_cgi(per_request *reqInfo) {
if((!allow) || (check_cgiopt && (!(op & OPT_EXECCGI))))
return -1;
if(cgi_stub(reqInfo,&finfo,op) == SC_REDIRECT_TEMP)
rprintf(reqInfo, "<A HREF=\"%s\">%s</A>",reqInfo->outh_location,
reqInfo->outh_location);
if(cgi_stub(reqInfo,pargs,&finfo) == SC_REDIRECT_TEMP)
reqInfo->bytes_sent += fprintf(reqInfo->out,
"<A HREF=\"%s\">%s</A>",location,location);
return 0;
}
static int ipid;
void kill_include_child(void) {
char *errstr;
errstr = newString(MAX_STRING_LEN,STR_TMP);
char errstr[MAX_STRING_LEN];
sprintf(errstr,"killing command process %d",ipid);
log_error(errstr,gCurrentRequest->hostInfo->error_log);
kill(ipid,SIGKILL);
waitpid(ipid,NULL,0);
freeString(errstr);
}
int include_cmd(per_request *reqInfo, char *s) {
int include_cmd(per_request *reqInfo, char *s, char *pargs) {
int p[2];
FILE *fp;
if(Pipe(p) == -1)
die(reqInfo,SC_SERVER_ERROR,"HTTPd: could not create IPC pipe");
die(reqInfo,SC_SERVER_ERROR,"httpd: could not create IPC pipe");
if((ipid = fork()) == -1) {
Close(p[0]);
Close(p[1]);
die(reqInfo,SC_SERVER_ERROR,"HTTPd: could not fork new process");
die(reqInfo,SC_SERVER_ERROR,"httpd: could not fork new process");
}
if(!ipid) {
char *argv0;
if(reqInfo->path_info[0] || reqInfo->args[0]) {
if(reqInfo->path_info[0]) {
char *p2;
if(pargs[0] || reqInfo->args[0]) {
if(pargs[0]) {
char p2[HUGE_STRING_LEN];
p2 = newString(HUGE_STRING_LEN,STR_TMP);
escape_shell_cmd(reqInfo->path_info);
make_env_str(reqInfo,"PATH_INFO",reqInfo->path_info);
translate_name(reqInfo,reqInfo->path_info,p2);
escape_shell_cmd(pargs);
make_env_str(reqInfo,"PATH_INFO",pargs);
translate_name(reqInfo,pargs,p2);
make_env_str(reqInfo,"PATH_TRANSLATED",p2);
freeString(p2);
}
if(reqInfo->args[0]) {
make_env_str(reqInfo,"QUERY_STRING",reqInfo->args);
@ -487,76 +455,72 @@ int include_cmd(per_request *reqInfo, char *s) {
dup2(p[1],STDOUT_FILENO);
Close(p[1]);
}
close(reqInfo->in);
close(reqInfo->connection_socket);
error_log2stderr(reqInfo->hostInfo->error_log);
if(!(argv0 = strrchr(SHELL_PATH,'/')))
argv0=SHELL_PATH;
if(execle(SHELL_PATH,argv0,"-c",s,(char *)0,reqInfo->env) == -1) {
fprintf(stderr,"HTTPd: exec of %s failed, errno is %d\n",
fprintf(stderr,"httpd: exec of %s failed, errno is %d\n",
SHELL_PATH,errno);
exit(1);
}
}
Close(p[1]);
/* if(!(fp=FdOpen(p[0],"r"))) {
waitpid(ipid,NULL,0);
return -1;
} */
send_fd(reqInfo,p[0],kill_include_child);
/* FClose(fp); */
Close(p[0]);
waitpid(ipid,NULL,0);
return 0;
}
int handle_exec(per_request *reqInfo, FILE *fp, char *error)
int handle_exec(per_request *reqInfo, FILE *fp, char *path_args,
char *error)
{
char *tag,*errstr;
char tag[MAX_STRING_LEN],errstr[MAX_STRING_LEN];
char *tag_val;
tag = newString(MAX_STRING_LEN,STR_TMP);
errstr = newString(MAX_STRING_LEN,STR_TMP);
while(1) {
if(!(tag_val = get_tag(fp,tag))) {
freeString(tag);
freeString(errstr);
if(!(tag_val = get_tag(fp,tag)))
return 1;
}
if(!strcmp(tag,"cmd")) {
if(include_cmd(reqInfo,tag_val) == -1) {
if(include_cmd(reqInfo,tag_val,path_args) == -1) {
sprintf(errstr,"invalid command exec %s in %s",tag_val,
reqInfo->filename);
log_error(errstr,reqInfo->hostInfo->error_log);
rprintf(reqInfo,"%s",error);
reqInfo->bytes_sent += fprintf(reqInfo->out,"%s",error);
}
/* just in case some stooge changed directories */
chdir_file(reqInfo->filename);
}
else if(!strcmp(tag,"cgi")) {
per_request *newInfo;
newInfo = continue_request(reqInfo, KEEP_ENV | KEEP_AUTH);
newInfo->http_version = P_HTTP_0_9;
newInfo = continue_request(reqInfo,NEW_URL | KEEP_ENV);
strcpy(newInfo->url,tag_val);
if(include_cgi(newInfo) == -1) {
if(include_cgi(newInfo,path_args) == -1) {
sprintf(errstr,"invalid CGI ref %s in %s",newInfo->filename,
reqInfo->filename);
log_error(errstr,reqInfo->hostInfo->error_log);
rprintf(reqInfo,"%s",error);
reqInfo->bytes_sent += fprintf(reqInfo->out,"%s",error);
}
reqInfo->bytes_sent += newInfo->bytes_sent;
free_request(newInfo,ONLY_LAST);
/* grumble groan */
chdir_file(reqInfo->filename);
}
else if(!strcmp(tag,"done")) {
freeString(errstr);
freeString(tag);
else if(!strcmp(tag,"done"))
return 0;
}
else {
char errstr[MAX_STRING_LEN];
sprintf(errstr,"unknown parameter %s to tag echo in %s",tag,
reqInfo->filename);
log_error(errstr,reqInfo->hostInfo->error_log);
rprintf(reqInfo,"%s",error);
reqInfo->bytes_sent += fprintf(reqInfo->out,"%s",error);
}
}
@ -564,16 +528,12 @@ int handle_exec(per_request *reqInfo, FILE *fp, char *error)
int handle_config(per_request *reqInfo, FILE *fp, char *error,
char *tf, int *sizefmt) {
char *tag;
char tag[MAX_STRING_LEN];
char *tag_val;
tag = newString(MAX_STRING_LEN,STR_TMP);
while(1) {
if(!(tag_val = get_tag(fp,tag))) {
freeString(tag);
if(!(tag_val = get_tag(fp,tag)))
return 1;
}
if(!strcmp(tag,"errmsg"))
strcpy(error,tag_val);
else if(!strcmp(tag,"timefmt")) {
@ -589,32 +549,23 @@ int handle_config(per_request *reqInfo, FILE *fp, char *error,
else if(!strcmp(tag_val,"abbrev"))
*sizefmt = SIZEFMT_KMG;
}
else if(!strcmp(tag,"done")) {
freeString(tag);
else if(!strcmp(tag,"done"))
return 0;
}
else {
char *errstr;
errstr = newString(MAX_STRING_LEN,STR_TMP);
char errstr[MAX_STRING_LEN];
sprintf(errstr,"unknown parameter %s to tag config in %s",
tag, reqInfo->filename);
log_error(errstr,reqInfo->hostInfo->error_log);
rprintf(reqInfo,"%s",error);
freeString(errstr);
reqInfo->bytes_sent += fprintf(reqInfo->out,"%s",error);
}
}
}
#ifndef NO_YOW
int handle_yow(per_request *reqInfo, FILE *fp, char *error) {
char *tag;
char tag[MAX_STRING_LEN];
char c;
tag = newString(MAX_STRING_LEN,STR_TMP);
srand((int) (getpid() + time((long *) 0)));
GET_CHAR(fp,c,1);
if (c == ENDING_SEQUENCE[0]) {
@ -623,20 +574,10 @@ int handle_yow(per_request *reqInfo, FILE *fp, char *error) {
GET_CHAR(fp,c,1);
if (c == ENDING_SEQUENCE[2]) {
print_yow(reqInfo,rand() % MAX_YOW);
freeString(tag);
return 0;
} else {
freeString(tag);
return 1;
}
} else {
freeString(tag);
return 1;
}
} else {
freeString(tag);
return 1;
}
} else return 1;
} else return 1;
} else return 1;
}
#endif /* NO_YOW */
@ -645,41 +586,30 @@ int handle_yow(per_request *reqInfo, FILE *fp, char *error) {
int find_file(per_request *reqInfo, char *directive, char *tag,
char *tag_val, struct stat *finfo, char *error)
{
char *errstr, *dir, *to_send;
errstr = newString(MAX_STRING_LEN,STR_TMP);
dir = newString(MAX_STRING_LEN,STR_TMP);
to_send = newString(MAX_STRING_LEN,STR_TMP);
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 */
getcwd(dir,MAX_STRING_LEN);
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,reqInfo->filename);
log_error(errstr,reqInfo->hostInfo->error_log);
rprintf(reqInfo,"%s",error);
freeString(errstr);
freeString(dir);
freeString(to_send);
reqInfo->bytes_sent += fprintf(reqInfo->out,"%s",error);
return -1;
}
freeString(errstr);
freeString(dir);
freeString(to_send);
return 0;
}
else if(!strcmp(tag,"virtual")) {
per_request *newInfo;
newInfo = continue_request(reqInfo, KEEP_ENV | KEEP_AUTH);
newInfo->http_version = P_HTTP_0_9;
newInfo = continue_request(reqInfo,NEW_URL | KEEP_ENV);
strcpy(newInfo->url,tag_val);
if(translate_name(newInfo,newInfo->url,newInfo->filename)
!= A_STD_DOCUMENT) {
sprintf(errstr,"unable to get information about non standard file %s in parsed file %s",newInfo->filename,reqInfo->filename);
rprintf(reqInfo,"%s",error);
reqInfo->bytes_sent += fprintf(reqInfo->out,"%s",error);
log_error(errstr,reqInfo->hostInfo->error_log);
}
else if(stat(newInfo->filename,finfo) == -1) {
@ -687,27 +617,18 @@ int find_file(per_request *reqInfo, char *directive, char *tag,
"unable to get information about %s in parsed file %s",
newInfo->filename,reqInfo->filename);
log_error(errstr,reqInfo->hostInfo->error_log);
rprintf(reqInfo,"%s",error);
reqInfo->bytes_sent += fprintf(reqInfo->out,"%s",error);
free_request(newInfo,ONLY_LAST);
freeString(errstr);
freeString(dir);
freeString(to_send);
return -1;
}
free_request(newInfo,ONLY_LAST);
freeString(errstr);
freeString(dir);
freeString(to_send);
return 0;
}
else {
sprintf(errstr,"unknown parameter %s to tag %s in %s",
tag,directive,reqInfo->filename);
log_error(errstr,reqInfo->hostInfo->error_log);
rprintf(reqInfo,"%s",error);
freeString(errstr);
freeString(dir);
freeString(to_send);
reqInfo->bytes_sent += fprintf(reqInfo->out,"%s",error);
return -1;
}
}
@ -715,21 +636,15 @@ int find_file(per_request *reqInfo, char *directive, char *tag,
int handle_fsize(per_request *reqInfo, FILE *fp, char *error, int sizefmt)
{
char *tag;
char tag[MAX_STRING_LEN];
char *tag_val;
struct stat finfo;
tag = newString(MAX_STRING_LEN,STR_TMP);
while(1) {
if(!(tag_val = get_tag(fp,tag))) {
freeString(tag);
if(!(tag_val = get_tag(fp,tag)))
return 1;
}
else if(!strcmp(tag,"done")) {
freeString(tag);
else if(!strcmp(tag,"done"))
return 0;
}
else if(!find_file(reqInfo,"fsize",tag,tag_val,&finfo,error)) {
if(sizefmt == SIZEFMT_KMG) {
send_size(reqInfo,finfo.st_size);
@ -741,9 +656,11 @@ int handle_fsize(per_request *reqInfo, FILE *fp, char *error, int sizefmt)
l = strlen(tag); /* grrr */
for(x=0;x<l;x++) {
if(x && (!((l-x) % 3))) {
rputc(',',reqInfo);
fputc(',',reqInfo->out);
++reqInfo->bytes_sent;
}
rputc(tag[x],reqInfo);
fputc(tag[x],reqInfo->out);
++reqInfo->bytes_sent;
}
}
}
@ -752,41 +669,34 @@ int handle_fsize(per_request *reqInfo, FILE *fp, char *error, int sizefmt)
int handle_flastmod(per_request *reqInfo, FILE *fp, char *error, char *tf)
{
char *tag;
char tag[MAX_STRING_LEN];
char *tag_val;
struct stat finfo;
tag = newString(MAX_STRING_LEN,STR_TMP);
while(1) {
if(!(tag_val = get_tag(fp,tag))) {
freeString(tag);
if(!(tag_val = get_tag(fp,tag)))
return 1;
}
else if(!strcmp(tag,"done")) {
freeString(tag);
else if(!strcmp(tag,"done"))
return 0;
}
else if(!find_file(reqInfo,"flastmod",tag,tag_val,&finfo,error))
rprintf(reqInfo,"%s", ht_time(finfo.st_mtime,tf,0));
reqInfo->bytes_sent += fprintf(reqInfo->out,"%s",
ht_time(finfo.st_mtime,tf,0));
}
}
/* -------------------------- The main function --------------------------- */
/* This is a stub which parses a file descriptor. */
void send_parsed_content(per_request *reqInfo, FILE *fp, int noexec)
void send_parsed_content(per_request *reqInfo, FILE *fp, char *path_args,
int noexec)
{
char *directive, *error, *timefmt, *errstr;
char directive[MAX_STRING_LEN], error[MAX_STRING_LEN];
char timefmt[MAX_STRING_LEN], errstr[MAX_STRING_LEN];
int ret, sizefmt;
directive = newString(MAX_STRING_LEN,STR_TMP);
error = newString(MAX_STRING_LEN,STR_TMP);
timefmt = newString(MAX_STRING_LEN,STR_TMP);
errstr = newString(MAX_STRING_LEN,STR_TMP);
strcpy(error,DEFAULT_ERROR_MSG);
strcpy(timefmt,DEFAULT_TIME_FORMAT);
sizefmt = SIZEFMT_KMG;
@ -795,22 +705,17 @@ void send_parsed_content(per_request *reqInfo, FILE *fp, int noexec)
while(1) {
if(!find_string(reqInfo,fp,STARTING_SEQUENCE)) {
if(get_directive(fp,directive)) {
freeString(directive);
freeString(error);
freeString(timefmt);
freeString(errstr);
if(get_directive(fp,directive))
return;
}
if(!strcmp(directive,"exec")) {
if(noexec) {
sprintf(errstr,"HTTPd: exec used but not allowed in %s",
sprintf(errstr,"httpd: exec used but not allowed in %s",
reqInfo->filename);
log_error(errstr,reqInfo->hostInfo->error_log);
rprintf(reqInfo,"%s",error);
reqInfo->bytes_sent += fprintf(reqInfo->out,"%s",error);
ret = find_string(reqInfo,fp,ENDING_SEQUENCE);
} else
ret=handle_exec(reqInfo,fp,error);
ret=handle_exec(reqInfo,fp,path_args,error);
}
else if(!strcmp(directive,"config"))
ret=handle_config(reqInfo,fp,error,timefmt,&sizefmt);
@ -827,35 +732,26 @@ void send_parsed_content(per_request *reqInfo, FILE *fp, int noexec)
ret=handle_yow(reqInfo,fp,error);
#endif /* NO_YOW */
else {
sprintf(errstr,"HTTPd: unknown directive %s in parsed doc %s",
sprintf(errstr,"httpd: unknown directive %s in parsed doc %s",
directive,reqInfo->filename);
log_error(errstr,reqInfo->hostInfo->error_log);
rprintf(reqInfo,"%s",error);
reqInfo->bytes_sent += fprintf(reqInfo->out,"%s",error);
ret=find_string(reqInfo,fp,ENDING_SEQUENCE);
}
if(ret) {
sprintf(errstr,"HTTPd: premature EOF in parsed file %s",
sprintf(errstr,"httpd: premature EOF in parsed file %s",
reqInfo->filename);
log_error(errstr,reqInfo->hostInfo->error_log);
freeString(directive);
freeString(error);
freeString(timefmt);
freeString(errstr);
return;
}
} else {
freeString(directive);
freeString(error);
freeString(timefmt);
freeString(errstr);
} else
return;
}
}
}
/* Called by send_file */
void send_parsed_file(per_request *reqInfo, int noexec)
void send_parsed_file(per_request *reqInfo, char *path_args, int noexec)
{
FILE *fp;
@ -865,8 +761,8 @@ void send_parsed_file(per_request *reqInfo, int noexec)
/* unmunge_name(reqInfo,reqInfo->filename); */
die(reqInfo,SC_FORBIDDEN,reqInfo->url);
}
strcpy(reqInfo->outh_content_type,"text/html");
if(reqInfo->http_version != P_HTTP_0_9)
strcpy(content_type,"text/html");
if(!no_headers)
send_http_header(reqInfo);
if(reqInfo->method == M_HEAD) {
FClose(fp);
@ -874,13 +770,14 @@ void send_parsed_file(per_request *reqInfo, int noexec)
}
/* Make sure no children inherit our buffers */
rflush(reqInfo);
fflush(reqInfo->out);
no_headers = TRUE; /* make sure no headers get inserted anymore */
alarm(timeout);
add_include_vars(reqInfo,DEFAULT_TIME_FORMAT);
add_common_vars(reqInfo);
send_parsed_content(reqInfo,fp,noexec);
send_parsed_content(reqInfo,fp,path_args,noexec);
FClose(fp);
}

View File

@ -10,7 +10,7 @@
*
************************************************************************
*
* http_include.h,v 1.7 1996/03/27 20:44:04 blong Exp
* http_include.h,v 1.5 1995/07/25 06:43:33 blong Exp
*
************************************************************************
*
@ -32,9 +32,7 @@
#define NUM_INCLUDE_VARS 5
/* http_include */
void send_parsed_file(per_request *reqInfo, int noexec);
void send_parsed_file(per_request *reqInfo, char *path_args, int noexec);
char *ht_time(time_t t, char *fmt, int gmt);
int add_include_vars(per_request *reqInfo, char *timefmt);
void send_parsed_content(per_request *reqInfo, FILE *f, int noexec);
#endif /* _HTTP_INCLUDE_H_ */

View File

@ -10,7 +10,7 @@
*
************************************************************************
*
* http_ipc.c,v 1.22 1996/02/22 23:46:59 blong Exp
* http_ipc.c,v 1.20 1995/09/21 22:50:55 blong Exp
*
************************************************************************
*
@ -21,6 +21,13 @@
* Based (with modifications) on code by W. Richard Stevens,
* in _Advanced Programming in the UNIX Environment_
*
* 03-06-95 blong
* Added #ifdefs to handle not using this at all for machines like
* Linux.
*
* 04-17-95 blong
* Added NEED_SPIPE with s_pipe from Stevens _Unix Network Programming_
* for SVR3.2 systems without socketpair.
*/
@ -96,20 +103,20 @@ int recv_fd(int servfd)
dat.maxlen = IOBUFSIZE;
flag = 0;
if (getmsg(servfd, NULL, &dat, &flag) < 0) {
fprintf(stderr,"HTTPd: getmsg error recv_fd\n");
fprintf(stderr,"httpd:getmsg error recv_fd\n");
perror("getmsg");
exit(1);
}
nread = dat.len;
if (nread == 0) {
fprintf(stderr,"HTTPd: connection closed by server\n");
fprintf(stderr,"httpd: connection closed by server\n");
exit(1);
}
for (ptr = buf; ptr < &buf[nread]; ) {
if (*ptr++ == 0) {
if (ptr != &buf[nread-1]) {
fprintf(stderr,"HTTPd: message format error recv_fd\n");
fprintf(stderr,"httpd: message format error recv_fd\n");
perror("recv_fd");
exit(1);
}
@ -259,18 +266,18 @@ int recv_fd(int servfd) {
#endif /* FD_BSDRENO */
if ((nread = recvmsg(servfd, &msg, 0)) < 0) {
fprintf(stderr,"HTTPd: recvmsg error");
fprintf(stderr,"httpd: recvmsg error");
perror("recvmsg");
exit(1);
} else if (nread == 0) {
fprintf(stderr, "HTTPd: connection closed by server");
fprintf(stderr, "httpd: connection closed by server");
exit(1);
}
for (ptr = buf; ptr < &buf[nread]; ) {
if (*ptr++ == 0) {
if (ptr != &buf[nread-1]) {
fprintf(stderr, "HTTPd: message format error");
fprintf(stderr, "httpd:message format error");
exit(1);
}
status = *ptr & 255;
@ -281,7 +288,7 @@ int recv_fd(int servfd) {
if (msg.msg_accrightslen != sizeof(int))
#endif /* FD_BSDRENO */
{
fprintf(stderr, "HTTPd: status = 0 but no fd");
fprintf(stderr, "httpd: status = 0 but no fd");
exit(1);
}
#ifdef FD_BSDRENO

View File

@ -10,12 +10,45 @@
*
************************************************************************
*
* http_log.c,v 1.84 1996/04/05 18:54:59 blong Exp
* http_log.c,v 1.76 1995/11/28 09:02:04 blong Exp
*
************************************************************************
*
* http_log.c: Dealing with the logs and errors
*
* Based on NCSA HTTPd 1.3 by Rob McCool
*
* 10/28/94 cvarela
* Added agent_log and referer_log files.
*
* 02/15/95 blong
* Added support for configuration defined error messages
*
* 03/19/95 blong
* Some modification to status lines for uniformity, and for user
* defined error messages to give the correct status.
*
* 04/11/95 blong
* Changed custom error responses to only send the error string as
* arguments to the script
*
* 05/08/95 blong
* Bowing to pressure, added patch by Paul Phillips (paulp@cerf.net)
* to set CLOSE_ON_EXEC flag for log files under #define SECURE_LOGS
*
* 06/01/95 blong
* Changed die() so that it only logs the transaction on non-ErrorDocument
* errors (errors that are handled internally to the server)
*
* 09/13/95 mshapiro
* Added log directory checking - group/public write permissions
*
* 09-28-95 blong
* Added fix by Vince Tkac (tkac@oclc.org) to check if there are any
* errordocuments defined for the virtual host in the new schema.
*
* 09-29-95 blong
* Changed error_document fix to one suggested by Tim Adam (tma@osa.com.au)
*/
@ -37,10 +70,8 @@
#include <sys/stat.h>
#include <string.h>
#include "constants.h"
#include "allocate.h"
#include "http_log.h"
#include "http_request.h"
#include "http_send.h"
#include "http_config.h"
#include "host_config.h"
#include "http_auth.h"
@ -52,7 +83,6 @@
const char StatLine200[] = "200 Document follows";
const char StatLine204[] = "204 No Content";
const char StatLine206[] = "206 Partial Content";
const char StatLine301[] = "301 Moved Permanently";
const char StatLine302[] = "302 Moved Temporarily";
const char StatLine304[] = "304 Not modified";
@ -63,7 +93,6 @@ const char StatLine404[] = "404 Not Found";
const char StatLine408[] = "408 Request Timeout";
const char StatLine500[] = "500 Server Error";
const char StatLine501[] = "501 Not Implemented";
const char StatLine503[] = "503 Service Unavailable";
char error_msg[MAX_STRING_LEN];
/* Moved to http_request.c */
@ -79,7 +108,7 @@ void open_logs(per_host *host) {
if (host->httpd_conf & HC_ERROR_FNAME) {
if(!(host->error_log = fopen_logfile(host->error_fname,"a"))) {
fprintf(stderr,"HTTPd: could not open error log file %s.\n",
fprintf(stderr,"httpd: could not open error log file %s.\n",
host->error_fname);
perror("fopen");
exit(1);
@ -87,7 +116,7 @@ void open_logs(per_host *host) {
}
if (host->httpd_conf & HC_XFER_FNAME) {
if((host->xfer_log = open_logfile(host->xfer_fname,xfer_flags, xfer_mode)) < 0) {
fprintf(stderr,"HTTPd: could not open transfer log file %s.\n",
fprintf(stderr,"httpd: could not open transfer log file %s.\n",
host->xfer_fname);
perror("open");
exit(1);
@ -101,7 +130,7 @@ void open_logs(per_host *host) {
if (!(host->log_opts & LOG_COMBINED)) {
if (host->httpd_conf & HC_AGENT_FNAME) {
if(!(host->agent_log = fopen_logfile(host->agent_fname,"a"))) {
fprintf(stderr,"HTTPd: could not open agent log file %s.\n",
fprintf(stderr,"httpd: could not open agent log file %s.\n",
host->agent_fname);
perror("fopen");
exit(1);
@ -114,7 +143,7 @@ void open_logs(per_host *host) {
}
if (host->httpd_conf & HC_REFERER_FNAME) {
if(!(host->referer_log = fopen_logfile(host->referer_fname,"a"))) {
fprintf(stderr,"HTTPd: could not open referer log file %s.\n",
fprintf(stderr,"httpd: could not open referer log file %s.\n",
host->referer_fname);
perror("fopen");
exit(1);
@ -158,29 +187,19 @@ void log_pid(void)
FILE *pid_file;
if(!(pid_file = fopen(pid_fname,"w"))) {
fprintf(stderr,"HTTPd: could not log pid to file %s\n",pid_fname);
fprintf(stderr,"httpd: could not log pid to file %s\n",pid_fname);
exit(1);
}
fprintf(pid_file,"%d\n",getpid());
fclose(pid_file);
}
extern int num_children;
void log_transaction(per_request *reqInfo)
{
char *str;
char str[HUGE_STRING_LEN];
long timz;
struct tm *t;
char *tstr,sign;
#ifdef LOG_DURATION
extern time_t request_time;
time_t duration = request_time ? (time(NULL) - request_time) : 0;
#endif /* LOG_DURATION */
str = newString(HUGE_STRING_LEN,STR_TMP);
tstr = newString(MAX_STRING_LEN,STR_TMP);
char tstr[MAX_STRING_LEN],sign;
t = get_gmtoff(&timz);
sign = (timz < 0 ? '-' : '+');
@ -189,9 +208,9 @@ void log_transaction(per_request *reqInfo)
strftime(tstr,MAX_STRING_LEN,"%d/%b/%Y:%H:%M:%S",t);
sprintf(str,"%s %s %s [%s %c%02ld%02d] \"%s\" ",
(reqInfo->remote_name ? reqInfo->remote_name : "-"),
reqInfo->remote_name,
(do_rfc931 ? remote_logname : "-"),
(reqInfo->auth_user[0] ? reqInfo->auth_user : "-"),
(user[0] ? user : "-"),
tstr,
sign,
timz/3600,
@ -212,17 +231,16 @@ void log_transaction(per_request *reqInfo)
else
strcat(str," -");
}
if (reqInfo->hostInfo->referer_ignore && reqInfo->inh_referer[0]) {
char *str1;
if (reqInfo->hostInfo->referer_ignore && reqInfo->referer[0]) {
char str[MAX_STRING_LEN];
int bIgnore = 0;
str1 = newString(MAX_STRING_LEN,STR_TMP);
lim_strcpy(str1, reqInfo->hostInfo->referer_ignore, 255);
lim_strcpy(str, reqInfo->hostInfo->referer_ignore, 255);
if (reqInfo->hostInfo->referer_ignore[0]) {
char* tok = strtok (str1, " ");
char* tok = strtok (str, " ");
while (tok) {
if (strstr(reqInfo->inh_referer, tok)) {
if (strstr(reqInfo->referer, tok)) {
bIgnore = 1;
break;
}
@ -230,50 +248,43 @@ void log_transaction(per_request *reqInfo)
}
}
if (bIgnore) {
reqInfo->inh_referer[0] = '\0';
reqInfo->referer[0] = '\0';
}
freeString(str1);
}
#ifdef LOG_DURATION
sprintf(str+strlen(str), " %ld", duration);
#endif /* LOG_DURATION */
if (!(reqInfo->hostInfo->log_opts & LOG_COMBINED)) {
strcat(str,"\n");
write(reqInfo->hostInfo->xfer_log,str,strlen(str));
/* log the user agent */
if (reqInfo->inh_agent[0]) {
if (reqInfo->agent[0]) {
if (reqInfo->hostInfo->log_opts & LOG_DATE)
fprintf(reqInfo->hostInfo->agent_log, "[%s] %s\n",tstr,
reqInfo->inh_agent);
reqInfo->agent);
else
fprintf(reqInfo->hostInfo->agent_log, "%s\n", reqInfo->inh_agent);
fprintf(reqInfo->hostInfo->agent_log, "%s\n", reqInfo->agent);
fflush(reqInfo->hostInfo->agent_log);
}
/* log the referer */
if (reqInfo->inh_referer[0]) {
if (reqInfo->referer[0]) {
if (reqInfo->hostInfo->log_opts & LOG_DATE)
fprintf(reqInfo->hostInfo->referer_log, "[%s] %s -> %s\n",tstr,
reqInfo->inh_referer, reqInfo->url);
reqInfo->referer, reqInfo->url);
else
fprintf(reqInfo->hostInfo->referer_log, "%s -> %s\n",
reqInfo->inh_referer, reqInfo->url);
reqInfo->referer, reqInfo->url);
fflush(reqInfo->hostInfo->referer_log);
}
} else {
if (reqInfo->inh_referer[0])
sprintf(str,"%s \"%s\"",str,reqInfo->inh_referer);
if (reqInfo->referer[0])
sprintf(str,"%s \"%s\"",str,reqInfo->referer);
else
strcat(str," \"\"");
if (reqInfo->inh_agent[0])
sprintf(str,"%s \"%s\"\n",str,reqInfo->inh_agent);
if (reqInfo->agent[0])
sprintf(str,"%s \"%s\"\n",str,reqInfo->agent);
else
strcat(str," \"\"\n");
write(reqInfo->hostInfo->xfer_log,str,strlen(str));
}
freeString(str);
freeString(tstr);
}
void log_error(char *err, FILE *fp) {
@ -285,46 +296,46 @@ void log_reason(per_request *reqInfo, char *reason, char *file)
{
char *buffer;
/* This might not be big enough, but since its in the heap, the
* worst that will happen is a core dump, and its faster than a
* malloc, and won't fragment the memory as badly.
*/
buffer = newString(HUGE_STRING_LEN,STR_TMP);
sprintf(buffer,"HTTPd: access to %s failed for %s, reason: %s from %s",
buffer = (char *)malloc(strlen(reason)+strlen(reqInfo->referer)+
strlen(reqInfo->remote_name)+strlen(file)+50);
sprintf(buffer,"httpd: access to %s failed for %s, reason: %s from %s",
file,reqInfo->remote_name,reason,
( (reqInfo->inh_referer[0] != '\0') ? reqInfo->inh_referer : "-"));
( (reqInfo->referer[0] != '\0') ? reqInfo->referer : "-"));
log_error(buffer,reqInfo->hostInfo->error_log);
freeString(buffer);
free(buffer);
}
void begin_http_header(per_request *reqInfo, const char *msg)
{
fprintf(reqInfo->out,"%s %s%c",SERVER_PROTOCOL,msg,LF);
dump_default_header(reqInfo);
}
void error_head(per_request *reqInfo, const char *err)
{
if(reqInfo->http_version != P_HTTP_0_9) {
strcpy(reqInfo->outh_content_type,"text/html");
send_http_header(reqInfo);
if(!no_headers) {
begin_http_header(reqInfo,err);
fprintf(reqInfo->out,"Content-type: text/html%c%c",LF,LF);
}
if(reqInfo->method != M_HEAD) {
rprintf(reqInfo,"<HEAD><TITLE>%s</TITLE></HEAD>%c",err,LF);
rprintf(reqInfo,"<BODY><H1>%s</H1>%c",err,LF);
fprintf(reqInfo->out,"<HEAD><TITLE>%s</TITLE></HEAD>%c",err,LF);
fprintf(reqInfo->out,"<BODY><H1>%s</H1>%c",err,LF);
}
}
void title_html(per_request *reqInfo, char *msg)
{
rprintf(reqInfo,"<HEAD><TITLE>%s</TITLE></HEAD>%c",msg,LF);
rprintf(reqInfo,"<BODY><H1>%s</H1>%c",msg,LF);
fprintf(reqInfo->out,"<HEAD><TITLE>%s</TITLE></HEAD>%c",msg,LF);
fprintf(reqInfo->out,"<BODY><H1>%s</H1>%c",msg,LF);
}
int die(per_request *reqInfo, int type, char *err_string)
{
char *arguments;
char arguments[MAX_STRING_LEN];
int RetVal=0;
int x;
int die_type;
arguments = newString(MAX_STRING_LEN,STR_TMP);
/* kill keepalive on errors until we figure out what to do
such as compute content_length of error messages */
die_type = DIE_NORMAL;
@ -335,57 +346,62 @@ int die(per_request *reqInfo, int type, char *err_string)
strcpy(failed_request,the_request);
strcpy(failed_url,reqInfo->url);
/* For 1.4b4, changed to have a common message for ErrorDocument calls
We now send only error=err_string (as passed) and the CGI environment
variable ERROR_STATUS,ERROR_REQUEST,ERROR_URL contain the rest of the
relevent information */
/* For 1.4 release, changed ERROR_ to REDIRECT_ */
switch(type) {
case SC_NO_CONTENT:
reqInfo->status = SC_NO_CONTENT;
set_stat_line(reqInfo);
if (reqInfo->http_version != P_HTTP_0_9) {
send_http_header(reqInfo);
}
begin_http_header(reqInfo,StatLine204);
fputc(LF,reqInfo->out);
keep_alive.bKeepAlive = 0;
header_only = 1;
RetVal = SC_NO_CONTENT;
log_transaction(reqInfo);
break;
case SC_REDIRECT_TEMP:
reqInfo->status = SC_REDIRECT_TEMP;
set_stat_line(reqInfo);
if (((x=have_doc_error(reqInfo,type)) >= 0) && (!ErrorStat)) {
ErrorStat = reqInfo->status;
GoErrorDoc(reqInfo,x,err_string);
} else {
keep_alive.bKeepAlive = 0;
if(reqInfo->http_version != P_HTTP_0_9) {
strcpy(reqInfo->outh_location,err_string);
strcpy(reqInfo->outh_content_type,"text/html");
send_http_header(reqInfo);
if(!no_headers) {
begin_http_header(reqInfo,StatLine302);
fprintf(reqInfo->out,"Location: %s%c",err_string,LF);
fprintf(reqInfo->out,"Content-type: text/html%c",LF);
fputc(LF,reqInfo->out);
}
if (reqInfo->method != M_HEAD) {
title_html(reqInfo,"Document moved");
rprintf(reqInfo,
fprintf(reqInfo->out,
"This document has moved <A HREF=\"%s\">here</A>.<P>%c",
err_string,LF);
rprintf(reqInfo,"</BODY>%c",LF);
fprintf(reqInfo->out,"</BODY>%c",LF);
}
log_transaction(reqInfo);
}
break;
case SC_REDIRECT_PERM:
reqInfo->status = SC_REDIRECT_PERM;
set_stat_line(reqInfo);
if (((x=have_doc_error(reqInfo,type)) >= 0) && (!ErrorStat)) {
ErrorStat = reqInfo->status;
GoErrorDoc(reqInfo,x,err_string);
} else {
keep_alive.bKeepAlive = 0;
if(reqInfo->http_version != P_HTTP_0_9) {
strcpy(reqInfo->outh_location,err_string);
strcpy(reqInfo->outh_content_type,"text/html");
send_http_header(reqInfo);
}
if(!no_headers) {
begin_http_header(reqInfo,StatLine301);
fprintf(reqInfo->out,"Location: %s%c",err_string,LF);
fprintf(reqInfo->out,"Content-type: text/html%c",LF);
fputc(LF,reqInfo->out);
}
if (reqInfo->method != M_HEAD) {
title_html(reqInfo,"Document moved");
rprintf(reqInfo,"This document has permanently moved ");
rprintf(reqInfo,"<A HREF=\"%s\">here</A>.<P>%c</BODY>%c",
fprintf(reqInfo->out,"This document has permanently moved ");
fprintf(reqInfo->out,"<A HREF=\"%s\">here</A>.<P>%c</BODY>%c",
err_string,LF,LF);
}
log_transaction(reqInfo);
@ -393,95 +409,73 @@ int die(per_request *reqInfo, int type, char *err_string)
break;
case SC_USE_LOCAL_COPY:
reqInfo->status = SC_USE_LOCAL_COPY;
set_stat_line(reqInfo);
if (reqInfo->http_version != P_HTTP_0_9) {
send_http_header(reqInfo);
}
begin_http_header(reqInfo,StatLine304);
fputc(LF,reqInfo->out);
keep_alive.bKeepAlive = 0;
header_only = 1;
RetVal = SC_USE_LOCAL_COPY;
log_transaction(reqInfo);
break;
case SC_AUTH_REQUIRED:
reqInfo->status = SC_AUTH_REQUIRED;
set_stat_line(reqInfo);
strcpy(reqInfo->outh_www_auth, err_string);
if (((x=have_doc_error(reqInfo,type)) >= 0) && (!ErrorStat)) {
ErrorStat = reqInfo->status;
GoErrorDoc(reqInfo,x,err_string);
} else {
keep_alive.bKeepAlive = 0;
if(reqInfo->http_version != P_HTTP_0_9) {
strcpy(reqInfo->outh_content_type,"text/html");
send_http_header(reqInfo);
if(!no_headers) {
begin_http_header(reqInfo,StatLine401);
fprintf(reqInfo->out,"Content-type: text/html%c",LF);
fprintf(reqInfo->out,"WWW-Authenticate: %s%c%c",
err_string,LF,LF);
}
if (reqInfo->method != M_HEAD) {
title_html(reqInfo,"Authorization Required");
rprintf(reqInfo,"Browser not authentication-capable or %c",LF);
rprintf(reqInfo,"authentication failed.%c",LF);
rprintf(reqInfo,"</BODY>%c",LF);
fprintf(reqInfo->out,
"Browser not authentication-capable or %c",LF);
fprintf(reqInfo->out,"authentication failed.%c",LF);
fprintf(reqInfo->out,"</BODY>%c",LF);
}
log_transaction(reqInfo);
}
break;
case SC_AUTH_NO_WWW_AUTH:
reqInfo->status = SC_AUTH_REQUIRED;
set_stat_line(reqInfo);
keep_alive.bKeepAlive = 0;
if(reqInfo->http_version != P_HTTP_0_9) {
strcpy(reqInfo->outh_content_type,"text/html");
send_http_header(reqInfo);
}
if (reqInfo->method != M_HEAD) {
title_html(reqInfo,"Authorization Required");
rprintf(reqInfo,"You are not permitted to get this URL: %c",LF);
rprintf(reqInfo,"%s%c",err_string,LF);
rprintf(reqInfo,"</BODY>%c",LF);
}
log_transaction(reqInfo);
break;
case SC_BAD_REQUEST:
reqInfo->status = SC_BAD_REQUEST;
set_stat_line(reqInfo);
if (((x=have_doc_error(reqInfo,type)) >= 0) && (!ErrorStat)) {
ErrorStat = reqInfo->status;
GoErrorDoc(reqInfo,x,err_string);
} else {
error_head(reqInfo,StatLine400);
keep_alive.bKeepAlive = 0;
if (reqInfo->method != M_HEAD) {
rprintf(reqInfo,
if (!header_only) {
fprintf(reqInfo->out,
"Your client sent a query that this server could%c",LF);
rprintf(reqInfo,"not understand.<P>%c",LF);
rprintf(reqInfo,"Reason: %s<P>%c",err_string,LF);
rprintf(reqInfo,"</BODY>%c",LF);
fprintf(reqInfo->out,"not understand.<P>%c",LF);
fprintf(reqInfo->out,"Reason: %s<P>%c",err_string,LF);
fprintf(reqInfo->out,"</BODY>%c",LF);
}
log_transaction(reqInfo);
}
break;
case SC_BAD_IMAGEMAP:
reqInfo->status = SC_BAD_REQUEST;
set_stat_line(reqInfo);
if (((x=have_doc_error(reqInfo,type)) >= 0) && (!ErrorStat)) {
ErrorStat = reqInfo->status;
GoErrorDoc(reqInfo,x,err_string);
} else {
error_head(reqInfo,StatLine400);
keep_alive.bKeepAlive = 0;
if (reqInfo->method != M_HEAD) {
rprintf(reqInfo,
if (!header_only) {
fprintf(reqInfo->out,
"Server encountered error processing imagemap%c",LF);
rprintf(reqInfo,"<P>Reason: %s<P>%c",err_string,LF);
rprintf(reqInfo,"</BODY>%c",LF);
fprintf(reqInfo->out,"Reason: %s<P>%c",err_string,LF);
fprintf(reqInfo->out,"</BODY>%c",LF);
}
log_transaction(reqInfo);
}
break;
case SC_FORBIDDEN:
if (reqInfo->outh_location[0])
reqInfo->status = SC_REDIRECT_TEMP;
else
reqInfo->status = SC_FORBIDDEN;
set_stat_line(reqInfo);
reqInfo->status = SC_FORBIDDEN;
if (((x=have_doc_error(reqInfo,type)) >= 0) && (!ErrorStat)) {
ErrorStat = reqInfo->status;
GoErrorDoc(reqInfo,x,err_string);
@ -489,18 +483,17 @@ int die(per_request *reqInfo, int type, char *err_string)
error_head(reqInfo,StatLine403);
keep_alive.bKeepAlive = 0;
if (reqInfo->method != M_HEAD) {
rprintf(reqInfo,
fprintf(reqInfo->out,
"Your client does not have permission to get URL %s ",
err_string);
rprintf(reqInfo,"from this server.<P>%c",LF);
rprintf(reqInfo,"</BODY>%c",LF);
fprintf(reqInfo->out,"from this server.<P>%c",LF);
fprintf(reqInfo->out,"</BODY>%c",LF);
}
log_transaction(reqInfo);
}
break;
case SC_NOT_FOUND:
reqInfo->status = SC_NOT_FOUND;
set_stat_line(reqInfo);
if (((x=have_doc_error(reqInfo,type)) >= 0) && (!ErrorStat)) {
ErrorStat = reqInfo->status;
GoErrorDoc(reqInfo,x,err_string);
@ -508,36 +501,16 @@ int die(per_request *reqInfo, int type, char *err_string)
error_head(reqInfo,StatLine404);
keep_alive.bKeepAlive = 0;
if (reqInfo->method != M_HEAD) {
rprintf(reqInfo,
fprintf(reqInfo->out,
"The requested URL %s was not found on this server.%c",
err_string,LF);
rprintf(reqInfo,"</BODY>%c",LF);
fprintf(reqInfo->out,"</BODY>%c",LF);
}
log_transaction(reqInfo);
}
break;
case SC_SERVICE_UNAVAIL:
reqInfo->status = SC_SERVICE_UNAVAIL;
set_stat_line(reqInfo);
if (((x=have_doc_error(reqInfo,type)) >= 0) && (!ErrorStat)) {
ErrorStat = reqInfo->status;
GoErrorDoc(reqInfo,x,err_string);
} else {
error_head(reqInfo,StatLine503);
keep_alive.bKeepAlive = 0;
if (reqInfo->method != M_HEAD) {
rprintf(reqInfo,
"The requested URL %s is temporarily unavailable",
err_string);
rprintf(reqInfo,"from this server.%c",LF);
rprintf(reqInfo,"</BODY>%c",LF);
}
log_transaction(reqInfo);
}
break;
case SC_SERVER_ERROR:
reqInfo->status = SC_SERVER_ERROR;
set_stat_line(reqInfo);
die_type = DIE_NORMAL;
if (((x=have_doc_error(reqInfo,type)) >= 0) && (!ErrorStat)) {
ErrorStat = reqInfo->status;
@ -548,23 +521,22 @@ int die(per_request *reqInfo, int type, char *err_string)
keep_alive.bKeepAlive = 0;
log_error(err_string,reqInfo->hostInfo->error_log);
if (reqInfo->method != M_HEAD) {
rprintf(reqInfo,"The server encountered an internal error or%c",LF);
rprintf(reqInfo,"misconfiguration and was unable to complete %c",LF);
rprintf(reqInfo,"your request.<P>%c",LF);
rprintf(reqInfo,"Please contact the server administrator,%c",LF);
rprintf(reqInfo," %s ",reqInfo->hostInfo->server_admin);
rprintf(reqInfo,"and inform them of the time the error occurred%c",LF);
rprintf(reqInfo,", and anything you might have done that may%c",LF);
rprintf(reqInfo,"have caused the error.<P>%c",LF);
rprintf(reqInfo,"<b>Error:</b> %s%c",err_string,LF);
rprintf(reqInfo,"</BODY>%c",LF);
fprintf(reqInfo->out,"The server encountered an internal error or%c",LF);
fprintf(reqInfo->out,"misconfiguration and was unable to complete %c",LF);
fprintf(reqInfo->out,"your request.<P>%c",LF);
fprintf(reqInfo->out,"Please contact the server administrator,%c",LF);
fprintf(reqInfo->out," %s ",reqInfo->hostInfo->server_admin);
fprintf(reqInfo->out,"and inform them of the time the error occurred%c",LF);
fprintf(reqInfo->out,", and anything you might have done that may%c",LF);
fprintf(reqInfo->out,"have caused the error.<P>%c",LF);
fprintf(reqInfo->out,"<b>Error:</b> %s%c",err_string,LF);
fprintf(reqInfo->out,"</BODY>%c",LF);
}
log_transaction(reqInfo);
}
break;
case SC_NOT_IMPLEMENTED:
reqInfo->status = SC_NOT_IMPLEMENTED;
set_stat_line(reqInfo);
if (((x=have_doc_error(reqInfo,type)) >= 0) && (!ErrorStat)) {
ErrorStat = reqInfo->status;
GoErrorDoc(reqInfo,x,err_string);
@ -572,10 +544,10 @@ int die(per_request *reqInfo, int type, char *err_string)
error_head(reqInfo,StatLine501);
keep_alive.bKeepAlive = 0;
if (reqInfo->method != M_HEAD) {
rprintf(reqInfo,"We are sorry to be unable to perform the method %s",
fprintf(reqInfo->out,"We are sorry to be unable to perform the method %s",
err_string);
rprintf(reqInfo," at this time or to this document.<P>%c",LF);
rprintf(reqInfo,"</BODY>%c",LF);
fprintf(reqInfo->out," at this time or to this document.<P>%c",LF);
fprintf(reqInfo->out,"</BODY>%c",LF);
}
log_transaction(reqInfo);
}
@ -583,33 +555,30 @@ int die(per_request *reqInfo, int type, char *err_string)
case SC_NO_MEMORY:
log_error("HTTPd: memory exhausted",reqInfo->hostInfo->error_log);
reqInfo->status = SC_SERVER_ERROR;
set_stat_line(reqInfo);
die_type = DIE_NORMAL;
error_head(reqInfo,StatLine500);
keep_alive.bKeepAlive = 0;
if (reqInfo->method != M_HEAD) {
rprintf(reqInfo,"The server has temporarily run out of resources%c",LF);
rprintf(reqInfo,"for your request. Please try again at a later time.<P>%c",LF);
rprintf(reqInfo,"</BODY>%c",LF);
fprintf(reqInfo->out,"The server has temporarily run out of resources%c",LF);
fprintf(reqInfo->out,"for your request. Please try again at a later time.<P>%c",LF);
fprintf(reqInfo->out,"</BODY>%c",LF);
}
log_transaction(reqInfo);
break;
case SC_CONF_ERROR:
reqInfo->status = SC_SERVER_ERROR;
set_stat_line(reqInfo);
sprintf(arguments,"HTTPd: configuration error = %s",err_string);
sprintf(arguments,"httpd: configuration error = %s",err_string);
log_error(arguments,reqInfo->hostInfo->error_log);
error_head(reqInfo,StatLine500);
keep_alive.bKeepAlive = 0;
if (reqInfo->method != M_HEAD) {
rprintf(reqInfo,"The server has encountered a misconfiguration.%c",LF);
rprintf(reqInfo,"The error was %s.%c",err_string,LF);
rprintf(reqInfo,"</BODY>%c",LF);
fprintf(reqInfo->out,"The server has encountered a misconfiguration.%c",LF);
fprintf(reqInfo->out,"The error was %s.%c",err_string,LF);
fprintf(reqInfo->out,"</BODY>%c",LF);
}
log_transaction(reqInfo);
}
rflush(reqInfo);
freeString(arguments);
fflush(reqInfo->out);
if (!RetVal)
htexit(reqInfo,1,die_type);
return RetVal;
@ -618,7 +587,7 @@ int die(per_request *reqInfo, int type, char *err_string)
int GoErrorDoc(per_request *reqInfo, int x, char *ErrString) {
per_request *newInfo;
newInfo = continue_request(reqInfo, FORCE_GET | KEEP_ENV | KEEP_AUTH);
newInfo = continue_request(reqInfo,NEW_URL | FORCE_GET | KEEP_ENV | KEEP_AUTH);
strcpy(newInfo->url,reqInfo->hostInfo->doc_errors[x]->DocErrorFile);
if (ErrString)
sprintf(newInfo->args,"error=%s",ErrString);

View File

@ -10,7 +10,7 @@
*
************************************************************************
*
* http_log.h,v 1.18 1996/03/06 23:21:06 blong Exp
* http_log.h,v 1.15 1995/11/28 09:02:05 blong Exp
*
************************************************************************
*
@ -41,7 +41,6 @@
/* globals defined in this module */
extern const char StatLine200[];
extern const char StatLine204[];
extern const char StatLine301[];
extern const char StatLine302[];
extern const char StatLine304[];
@ -52,7 +51,6 @@ extern const char StatLine404[];
extern const char StatLine408[];
extern const char StatLine500[];
extern const char StatLine501[];
extern const char StatLine503[];
extern char error_msg[];
extern int ErrorStat;
@ -68,7 +66,7 @@ void close_logs(per_host *host);
void error_log2stderr(FILE *error_log);
void title_html(per_request *reqInfo, char *msg);
void begin_http_header(per_request *reqInfo);
void begin_http_header(per_request *reqInfo, const char *msg);
int die(per_request *reqInfo, int type, char *err_string);

View File

@ -10,14 +10,28 @@
*
************************************************************************
*
* http_mime.c,v 1.106 1996/03/13 18:28:39 blong Exp
* http_mime.c,v 1.98 1995/11/28 09:02:07 blong Exp
*
************************************************************************
*
* http_mime.c: maintains the list of mime types, encodings. Currently
* still contains functions for setting some HTTP headers, probably be
* moved eventually.
* http_mime.c: Sends/gets MIME headers for requests
*
* Based on NCSA HTTPd 1.3 by Rob McCool
*
* 03/19/95 blong
* Added set_stat_line as part of making user config error messages work
* The correct status line should now be sent back
*
* 04/20/95 blong
* Added a modified "B18" from apache patches by Rob Hartill
*
* 08/07/95 blong
* Moved scan_script_header() function to cgi.c in an attempt at
* increased modularity of the code (at least representatively)
*
* 10/30/95 blong
* Fixed get_mime_header string length problems as suggested by
* Marc Evans (Marc@Destek.NET)
*/
@ -43,13 +57,11 @@
#include <ctype.h>
#include "constants.h"
#include "fdwrap.h"
#include "allocate.h"
#include "http_mime.h"
#include "http_log.h"
#include "http_config.h"
#include "http_access.h"
#include "env.h"
#include "http_request.h"
#include "util.h"
#if defined(KRB4) || defined(KRB5)
@ -69,6 +81,27 @@ struct mime_ext *encoding_types;
struct mime_ext *Saved_Forced;
struct mime_ext *Saved_Encoding;
int content_length;
char content_type[MAX_STRING_LEN];
char content_type_in[MAX_STRING_LEN];
char content_encoding[MAX_STRING_LEN];
char location[MAX_STRING_LEN];
static char last_modified[MAX_STRING_LEN];
char auth_line[HUGE_STRING_LEN];
char called_hostname[MAX_STRING_LEN];
char *out_headers = NULL;
char *status_line = NULL;
char ims[MAX_STRING_LEN]; /* If-modified-since */
#ifdef HAVE_KERBEROS
char out_auth_header[1024];
#endif /* HAVE_KERBEROS */
void hash_insert(struct mime_ext *me) {
register int i = hash(me->ext[0]);
register struct mime_ext *p, *q;
@ -135,7 +168,7 @@ void init_mime(void)
reqInfo.out = stderr;
if(!(f = FOpen(types_confname,"r"))) {
fprintf(stderr,"HTTPd: could not open mime types file %s\n",
fprintf(stderr,"httpd: could not open mime types file %s\n",
types_confname);
perror("fopen");
exit(1);
@ -192,10 +225,11 @@ void dump_types(void)
}
}
#endif /* DEBUG */
int is_content_type(char *type) {
return(!strcmp(content_type,type));
}
void find_ct(per_request *reqInfo, char *file,
char *content_type, char *content_encoding)
{
void find_ct(per_request *reqInfo, char *file, int store_encoding) {
int i,l,l2;
struct mime_ext *p;
char fn[MAX_STRING_LEN];
@ -212,7 +246,7 @@ void find_ct(per_request *reqInfo, char *file,
while(p) {
if(!strcmp(p->ext,&fn[i])) {
fn[i-1] = '\0';
if(content_encoding != NULL) {
if(store_encoding) {
if(content_encoding[0])
sprintf(content_encoding,"%s, %s",content_encoding,
p->ct);
@ -265,20 +299,14 @@ void find_ct(per_request *reqInfo, char *file,
void probe_content_type(per_request *reqInfo, char *file)
{
find_ct(reqInfo,file,reqInfo->outh_content_type,NULL);
find_ct(reqInfo,file,0);
}
void set_content_type(per_request *reqInfo, char *file)
{
find_ct(reqInfo,file,reqInfo->outh_content_type,
reqInfo->outh_content_encoding);
find_ct(reqInfo,file,1);
}
void get_content_type(per_request *reqInfo, char *file,
char *content_type, char *content_encoding)
{
find_ct(reqInfo,file,content_type,content_encoding);
}
/* Should remove all the added types from .htaccess files when the
child sticks around */
@ -342,76 +370,217 @@ void add_encoding(per_request *reqInfo, char *fn, char *t) {
}
void set_content_length(per_request *reqInfo, int l) {
reqInfo->outh_content_length = l;
content_length = l;
}
int set_last_modified(per_request *reqInfo, time_t t) {
struct tm *tms;
/* char ts[MAX_STRING_LEN]; */
char ts[MAX_STRING_LEN];
tms = gmtime(&t);
strftime(reqInfo->outh_last_mod,MAX_STRING_LEN,HTTP_TIME_FORMAT,tms);
/* strcpy(reqInfo->outh_last_mod,ts); */
strftime(ts,MAX_STRING_LEN,HTTP_TIME_FORMAT,tms);
strcpy(last_modified,ts);
if(!reqInfo->inh_if_mod_since[0])
if(!ims[0])
return 0;
if(later_than(tms, reqInfo->inh_if_mod_since))
if(later_than(tms, ims))
return die(reqInfo,SC_USE_LOCAL_COPY,NULL);
return 0;
}
void init_header_vars(per_request *reqInfo)
{
content_type[0] = '\0';
content_type_in[0] = '\0';
last_modified[0] = '\0';
content_length = -1;
auth_line[0] = '\0';
content_encoding[0] = '\0';
location[0] = '\0';
ims[0] = '\0';
if (status_line != NULL) free(status_line);
status_line = NULL;
if (out_headers != NULL) free(out_headers);
out_headers = NULL;
#ifdef HAVE_KERBEROS
out_auth_header[0] = '\0';
#endif /* HAVE_KERBEROS */
}
/* Globals for speed because of size, these are for get_mime_headers */
static char field_type[HUGE_STRING_LEN];
static char unrec_hdr[HUGE_STRING_LEN];
static char unrec_hdr_val[HUGE_STRING_LEN];
void get_mime_headers(per_request *reqInfo)
{
char *field_val;
#ifdef DIGEST_AUTH
client_accepts_digest = assume_digest_support;
#endif /* DIGEST_AUTH */
while(getline(reqInfo->connection_socket,field_type,HUGE_STRING_LEN-1,0,
timeout) != -1) {
if(!field_type[0])
return;
if(!(field_val = strchr(field_type,':')))
continue;
*field_val++ = '\0';
while(isspace(*field_val)) ++field_val;
if(!strcasecmp(field_type,"Content-type")) {
strncpy(content_type_in,field_val,MAX_STRING_LEN);
content_type_in[MAX_STRING_LEN-1] = '\0';
continue;
}
if(!strcasecmp(field_type,"Authorization")) {
strncpy(auth_line,field_val,HUGE_STRING_LEN);
auth_line[HUGE_STRING_LEN-1]='\0';
continue;
}
if(!strcasecmp(field_type,"Host")) {
strncpy(called_hostname, field_val, MAX_STRING_LEN);
called_hostname[MAX_STRING_LEN-1] = '\0';
}
if(!strcasecmp(field_type,"Extension")) {
if (!strcasecmp(field_val, "Notify-Domain-Restriction"))
reqInfo->bNotifyDomainRestricted = 1;
#ifdef DIGEST_AUTH
else if (!strcasecmp(field_val, "Security/Digest"))
client_accepts_digest = 1;
#endif /* DIGEST_AUTH */
}
if(!strcasecmp(field_type,"Content-length")) {
sscanf(field_val,"%d",&content_length);
continue;
}
if(!strcasecmp(field_type,"Connection")) {
if (!strcasecmp(field_val, "Keep-Alive") &&
keep_alive.bAllowKeepAlive)
keep_alive.bKeepAlive = 1;
}
if(!strcasecmp(field_type,"User-agent")) {
strncpy(reqInfo->agent, field_val, HUGE_STRING_LEN);
reqInfo->agent[HUGE_STRING_LEN-1] = '\0';
}
if(!strcasecmp(field_type,"Referer")) {
strncpy(reqInfo->referer, field_val, HUGE_STRING_LEN);
reqInfo->referer[HUGE_STRING_LEN-1] = '\0';
}
if(!strcasecmp(field_type,"If-modified-since")) {
strcpy(ims,field_val);
ims[MAX_STRING_LEN-1] = '\0';
}
http2cgi(unrec_hdr, field_type);
strcpy (unrec_hdr_val, field_val);
if(reqInfo->env) {
if(!merge_header(reqInfo,unrec_hdr,field_val))
make_env_str(reqInfo,unrec_hdr,field_val);
}
else
make_env_str(reqInfo,unrec_hdr,field_val);
}
}
void dump_default_header(per_request *reqInfo)
{
fprintf(reqInfo->out,"Date: %s%c",gm_timestr_822(time(NULL)),LF);
fprintf(reqInfo->out,"Server: %s%c",SERVER_VERSION,LF);
if (reqInfo->hostInfo->annotation_server[0])
fprintf(reqInfo->out,"Annotations-cgi: %s%c",
reqInfo->hostInfo->annotation_server,LF);
/* Not part of HTTP spec, removed. */
/* fprintf(fd,"MIME-version: 1.0%c",LF); */
}
/* This needs to malloc in case a CGI script passes back its own
* status_line, so we can free without problem.
*/
char* set_stat_line(per_request *reqInfo)
{
if (reqInfo->status_line) {
freeString(reqInfo->status_line);
}
if (status_line) free(status_line);
switch (reqInfo->status) {
case 200:
reqInfo->status_line = dupStringP((char *)StatLine200,STR_REQ);
break;
case 204:
reqInfo->status_line = dupStringP((char *)StatLine204,STR_REQ);
break;
case 301:
reqInfo->status_line = dupStringP((char *)StatLine301,STR_REQ);
break;
case 302:
reqInfo->status_line = dupStringP((char *)StatLine302,STR_REQ);
status_line = strdup((char *)StatLine302);
break;
case 304:
reqInfo->status_line = dupStringP((char *)StatLine304,STR_REQ);
case 304:
status_line = strdup((char *)StatLine304);
break;
case 400:
reqInfo->status_line = dupStringP((char *)StatLine400,STR_REQ);
status_line = strdup((char *)StatLine400);
break;
case 401:
reqInfo->status_line = dupStringP((char *)StatLine401,STR_REQ);
status_line = strdup((char *)StatLine401);
break;
case 403:
reqInfo->status_line = dupStringP((char *)StatLine403,STR_REQ);
status_line = strdup((char *)StatLine403);
break;
case 404:
reqInfo->status_line = dupStringP((char *)StatLine404,STR_REQ);
case 404:
status_line = strdup((char *)StatLine404);
break;
case 500:
reqInfo->status_line = dupStringP((char *)StatLine500,STR_REQ);
status_line = strdup((char *)StatLine500);
break;
case 501:
reqInfo->status_line = dupStringP((char *)StatLine501,STR_REQ);
break;
case 503:
reqInfo->status_line = dupStringP((char *)StatLine503,STR_REQ);
status_line = strdup((char *)StatLine501);
break;
default:
reqInfo->status_line = dupStringP((char *)StatLine200,STR_REQ);
status_line = strdup((char *)StatLine200);
break;
}
return reqInfo->status_line;
return status_line;
}
void send_http_header(per_request *reqInfo)
{
if(!status_line) {
if(location[0]) {
reqInfo->status = 302;
status_line = strdup((char *)StatLine302);
}
else {
set_stat_line(reqInfo);
}
}
begin_http_header(reqInfo,status_line);
if(content_type[0])
fprintf(reqInfo->out,"Content-type: %s%c",content_type,LF);
if(last_modified[0])
fprintf(reqInfo->out,"Last-modified: %s%c",last_modified,LF);
if(content_length >= 0)
fprintf(reqInfo->out,"Content-length: %d%c",content_length,LF);
if(location[0])
fprintf(reqInfo->out,"Location: %s%c",location,LF);
if(content_encoding[0])
fprintf(reqInfo->out,"Content-encoding: %s%c",content_encoding,LF);
if (reqInfo->bNotifyDomainRestricted && reqInfo->bSatisfiedDomain)
fprintf(reqInfo->out,"Extension: Domain-Restricted%c", LF);
keep_alive.bKeepAlive = keep_alive.bKeepAlive && (content_length >= 0);
if (keep_alive.bKeepAlive && (!keep_alive.nMaxRequests ||
keep_alive.nCurrRequests + 1 <
keep_alive.nMaxRequests)) {
keep_alive.bKeepAlive = 1;
fprintf(reqInfo->out,
"Connection: Keep-Alive%cKeep-Alive: max=%d, timeout=%d%c",
LF, keep_alive.nMaxRequests, keep_alive.nTimeOut, LF);
}
if(out_headers)
fprintf(reqInfo->out,"%s",out_headers);
#ifdef HAVE_KERBEROS
if (out_auth_header[0])
fprintf (reqInfo->out, "%s", out_auth_header);
#endif /* HAVE_KERBEROS */
fprintf(reqInfo->out,"%c",LF);
fflush(reqInfo->out);
}

View File

@ -10,7 +10,7 @@
*
************************************************************************
*
* http_mime.h,v 1.19 1996/02/22 23:47:04 blong Exp
* http_mime.h,v 1.16 1995/11/28 09:02:08 blong Exp
*
************************************************************************
*
@ -32,29 +32,39 @@ struct mime_ext {
/* globals defined in this module */
extern char content_type[];
extern char content_type_in[];
extern char content_encoding[];
extern int content_length;
extern char location[];
extern char auth_line[];
extern char called_hostname[];
extern struct mime_ext *Saved_Forced;
extern struct mime_ext *Saved_Encoding;
extern struct mime_ext *forced_types;
extern struct mime_ext *encoding_types;
extern char *out_headers;
/* http_mime function prototypes */
void get_mime_headers(per_request *reqInfo);
void send_http_header(per_request *reqInfo);
void set_content_type(per_request *reqInfo, char *fn);
void probe_content_type(per_request *reqInfo, char *fn);
void set_content_length(per_request *reqInfo, int l);
void get_content_type(per_request *reqInfo, char *file,
char *content_type, char *content_encoding);
int set_last_modified(per_request *reqInfo, time_t t);
void probe_content_type(per_request *reqInfo, char *fn);
int scan_script_header(per_request *reqInfo, int pd);
void add_type(per_request *reqInfo, char *fn, char *t);
void add_encoding(per_request *reqInfo, char *fn, char *t);
void set_content_length(per_request *reqInfo, int l);
void dump_types(void);
void init_mime(void);
void kill_mime(void);
void reset_mime_vars(void);
int is_content_type(char *type);
void dump_default_header(per_request *reqInfo);
void init_header_vars(per_request *reqInfo);
extern char *status_line;
char* set_stat_line(per_request *reqInfo);
#endif /* _HTTP_MIME_H_ */

View File

@ -10,19 +10,23 @@
*
************************************************************************
*
* http_request.c,v 1.113 1996/04/05 18:55:02 blong Exp
* http_request.c,v 1.99 1995/11/06 20:58:09 blong Exp
*
************************************************************************
*
* http_request.c: functions to handle the request structure and initial
* request handling including decoding
* http_request.c: functions to get and process requests
*
* 03-21-95 Based on NCSA HTTPd 1.3 by Rob McCool
* 05-17-95 NCSA HTTPd 1.4.1
* 05-01-95 NCSA HTTPd 1.4.2
* 11-10-95 NCSA HTTPd 1.5.0
* 11-14-95 NCSA HTTPd 1.5.0a
*
* 04-19-95 blong
* Forgot to remove free(remote_ip) from here, like elsewhere
*
* 04-20-95 blong
* Added patch "B18" for redirects w/o delay by Robert Hartill
*
* 05-01-95 blong
* Added patch by Steve Abatangle (sabat@enterprise.DTS.Harris.COM)
* to log SIGPIPE and timed out differently in send_fd_timed_out
*/
@ -34,58 +38,44 @@
# include <stdlib.h>
#endif /* NO_STDLIB_H */
#include <signal.h>
#include <sys/stat.h>
#include <setjmp.h>
#include <errno.h>
#include <string.h>
#include <ctype.h>
#include <setjmp.h>
#include "constants.h"
#include "allocate.h" /* for freeString() */
#include "cgi.h" /* for exec_cgi_script() */
#include "env.h" /* for free_env() */
#include "http_access.h" /* for reset_security() */
#include "http_alias.h" /* For translate_name() */
#include "host_config.h" /* For which_host_conf(), gConfiguration */
#include "http_config.h" /* For timeout */
#include "http_log.h" /* For die(),ErrorStat */
#include "http_send.h" /* for send_node() */
#include "util.h" /* for strcasecmp(), etc */
#include "httpd.h"
#include "http_request.h"
#include "http_send.h"
#include "cgi.h"
#include "http_access.h"
#include "http_mime.h"
#include "http_config.h"
#include "host_config.h"
#include "http_log.h"
#include "http_auth.h"
#include "http_alias.h"
#include "env.h"
#include "util.h"
int req_count = 0;
int cgibuf_count = 0;
int sockbuf_count = 0;
int no_headers;
int header_only;
per_request *gCurrentRequest;
/* *sigh* Yeah, we still have some globals left. We could probably
* move these into the request structure as well . . . its hitting
* 100k in size, though.
*/
/* If RFC931 identity check is on, the remote user name */
char *remote_logname;
/* Per request information */
char the_request[HUGE_STRING_LEN];
char as_requested[HUGE_STRING_LEN];
char failed_request[HUGE_STRING_LEN];
char failed_url[HUGE_STRING_LEN];
#ifdef LOG_DURATION
time_t request_time = 0;
#endif /* LOG_DURATION */
/* String constants for the request. Numbers are in constants.h */
char *methods[METHODS] = {"GET","HEAD","POST","PUT","DELETE","SECURE",
"LINK","UNLINK"};
char *protocals[PROTOCALS] = {"HTTP","HTTP/0.9","HTTP/1.0","HTTP/1.1",
"Secure-HTTP/1.1", "Secure-HTTP/1.2"};
char *methods[METHODS] = {"GET","HEAD","POST","PUT","DELETE","LINK","UNLINK"};
char *protocals[PROTOCALS] = {"HTTP","HTTP/0.9","HTTP/1.0","HTTP/1.1"};
/* initialize_request()
* either creates, or inits a request structure passed to it.
* This assumes that a request structure passed to it was passed
* through free_request, so it doesn't have any extra pointers that
* need to be dealt with (though it still checks env, that shouldn't
* be necessary)
*/
per_request *initialize_request(per_request *reqInfo)
{
int RealInit = 0;
@ -93,46 +83,42 @@ per_request *initialize_request(per_request *reqInfo)
RealInit = (reqInfo == NULL) ? 1 : 0;
newInfo = (per_request *) malloc(sizeof(per_request));
newInfo->hostInfo = gConfiguration;
if (RealInit) {
newInfo = (per_request *) malloc(sizeof(per_request));
req_count++;
reqInfo = newInfo;
reqInfo->ownURL = TRUE;
reqInfo->ownDNS = TRUE;
reqInfo->dns_host_lookup = FALSE;
reqInfo->remote_name = NULL;
reqInfo->remote_ip = NULL;
reqInfo->remote_host = NULL;
reqInfo->next = NULL;
reqInfo->ownENV = TRUE;
reqInfo->env = NULL;
reqInfo->outh_cgi = NULL;
reqInfo->RequestFlags = 0;
reqInfo->sb = NULL;
reqInfo->ownSB = TRUE;
reqInfo->cgi_buf = NULL;
} else {
newInfo->next = reqInfo;
reqInfo = newInfo;
reqInfo->ownURL = FALSE;
reqInfo->ownDNS = FALSE;
reqInfo->dns_host_lookup = reqInfo->next->dns_host_lookup;
reqInfo->remote_name = reqInfo->next->remote_name;
reqInfo->remote_host = reqInfo->next->remote_host;
reqInfo->remote_ip = reqInfo->next->remote_ip;
reqInfo->hostInfo = reqInfo->next->hostInfo;
}
reqInfo->hostInfo = gConfiguration;
/* Can't think (now) of any case where environment should transfer
from last request during KeepAlive, but in other cases, perhaps */
if (reqInfo->ownENV && reqInfo->env) {
free_env(reqInfo);
}
reqInfo->ownENV = TRUE;
reqInfo->env = NULL;
reqInfo->env_len = NULL;
reqInfo->num_env = 0;
reqInfo->max_env = 0;
/* initialize auth stuff */
reqInfo->bNotifyDomainRestricted = 0;
reqInfo->bSatisfiedDomain = 0;
reqInfo->bSatisfiedReferer = 0;
reqInfo->auth_name = "ByPassword";
reqInfo->auth_pwfile = NULL;
@ -154,70 +140,46 @@ per_request *initialize_request(per_request *reqInfo)
/* Initialize Error codes */
ErrorStat = 0;
/* status = 200; */
reqInfo->status = SC_DOCUMENT_FOLLOWS;
reqInfo->status_line = NULL;
/* reqInfo->status_line = NULL; */
reqInfo->bytes_sent = -1;
reqInfo->auth_type[0] = '\0';
if (!reqInfo->ownURL) {
strcpy(reqInfo->url, reqInfo->next->url);
strcpy(reqInfo->args, reqInfo->next->args);
strcpy(reqInfo->filename, reqInfo->next->filename);
}
reqInfo->url[0] = '\0';
reqInfo->args[0] = '\0';
reqInfo->path_info[0] = '\0';
reqInfo->filename[0] = '\0';
reqInfo->inh_agent[0] = '\0';
reqInfo->inh_referer[0] = '\0';
reqInfo->inh_called_hostname[0] = '\0';
reqInfo->inh_if_mod_since[0] = '\0';
reqInfo->inh_auth_line[0] = '\0';
reqInfo->inh_content_type[0] = '\0';
reqInfo->inh_content_length = -1;
reqInfo->outh_location[0] = '\0';
reqInfo->outh_last_mod[0] = '\0';
reqInfo->outh_www_auth[0] = '\0';
reqInfo->outh_content_type[0] = '\0';
reqInfo->outh_content_encoding[0] = '\0';
reqInfo->outh_content_length = -1;
#ifdef CONTENT_MD5
reqInfo->outh_content_md5 = NULL;
#endif /* CONTENT_MD5 */
reqInfo->outh_cgi = NULL;
reqInfo->agent[0] = '\0';
reqInfo->referer[0] = '\0';
init_header_vars(reqInfo);
as_requested[0] = '\0';
failed_url[0] = '\0';
failed_request[0] = '\0';
local_default_type[0] = '\0';
local_default_icon[0] = '\0';
/* All but HEAD send more than a header */
header_only = 0;
/* reset keep-alive, client will indicate desire on next request */
keep_alive.bKeepAlive = 0;
return reqInfo;
}
/* continue_request()
* Used (especially in SSI and ErrorDocs) to handle "multiple"
* internal requests. Will probably be used for SHTTP requests
* since they can be wrapped multiple times.
* Will copy over all inbound http headers, clear all outbound
* http headers except outh_www_auth which depends on KEEP_AUTH
* Option values in constants.h
* Takes as options:
* KEEP_ENV : Copy ENV from passed request
* KEEP_AUTH : Copy auth info from passed request
* FORCE_GET : Unless a HEAD request, change to GET request
* (don't POST to ErrorDoc)
* COPY_URL : Copy URL from passed request
* NEW_SOCK_BUF: Set sb to NULL to cause a new sock buf to be created
*/
per_request *continue_request(per_request *reqInfo, int options) {
per_request *newInfo;
newInfo = (per_request *)malloc(sizeof(per_request));
req_count++;
newInfo->status = reqInfo->status;
newInfo->status_line = NULL;
if (options & KEEP_ENV) {
newInfo->ownENV = FALSE;
@ -235,10 +197,6 @@ per_request *continue_request(per_request *reqInfo, int options) {
if (options & KEEP_AUTH) {
strcpy(newInfo->auth_type,reqInfo->auth_type);
strcpy(newInfo->auth_user,reqInfo->auth_user);
strcpy(newInfo->auth_group,reqInfo->auth_group);
strcpy(newInfo->inh_auth_line,reqInfo->inh_auth_line);
strcpy(newInfo->outh_www_auth,reqInfo->outh_www_auth);
newInfo->auth_name = reqInfo->auth_name;
newInfo->auth_pwfile = reqInfo->auth_pwfile;
newInfo->auth_grpfile = reqInfo->auth_grpfile;
@ -249,13 +207,8 @@ per_request *continue_request(per_request *reqInfo, int options) {
newInfo->auth_digestfile_type = newInfo->auth_digestfile_type;
#endif /* DIGEST_AUTH */
newInfo->bSatisfiedDomain = reqInfo->bSatisfiedDomain;
newInfo->bSatisfiedReferer = reqInfo->bSatisfiedReferer;
} else {
newInfo->auth_type[0] = '\0';
newInfo->auth_user[0] = '\0';
newInfo->auth_group[0] = '\0';
newInfo->inh_auth_line[0] = '\0';
newInfo->outh_www_auth[0] = '\0';
newInfo->auth_name = NULL;
newInfo->auth_pwfile = NULL;
newInfo->auth_grpfile = NULL;
@ -266,7 +219,6 @@ per_request *continue_request(per_request *reqInfo, int options) {
newInfo->auth_digestfile_type = 0;
#endif /* DIGEST_AUTH */
newInfo->bSatisfiedDomain = FALSE;
newInfo->bSatisfiedReferer = FALSE;
}
newInfo->bNotifyDomainRestricted = reqInfo->bNotifyDomainRestricted;
newInfo->bytes_sent = 0;
@ -280,53 +232,39 @@ per_request *continue_request(per_request *reqInfo, int options) {
newInfo->http_version = reqInfo->http_version;
newInfo->ownDNS = FALSE;
newInfo->dns_host_lookup = reqInfo->dns_host_lookup;
newInfo->remote_host = reqInfo->remote_host;
newInfo->remote_name = reqInfo->remote_name;
newInfo->remote_ip = reqInfo->remote_ip;
newInfo->hostInfo = reqInfo->hostInfo;
if (options & COPY_URL) {
strcpy(newInfo->url, reqInfo->url);
strcpy(newInfo->args, reqInfo->args);
strcpy(newInfo->path_info, reqInfo->path_info);
strcpy(newInfo->filename, reqInfo->filename);
if (options & NEW_DNS) {
newInfo->ownDNS = TRUE;
newInfo->dns_host_lookup = FALSE;
newInfo->remote_host = NULL;
newInfo->remote_name = NULL;
newInfo->remote_ip = NULL;
newInfo->hostInfo = NULL;
} else {
newInfo->ownDNS = FALSE;
newInfo->dns_host_lookup = reqInfo->dns_host_lookup;
newInfo->remote_host = reqInfo->remote_host;
newInfo->remote_name = reqInfo->remote_name;
newInfo->remote_ip = reqInfo->remote_ip;
newInfo->hostInfo = reqInfo->hostInfo;
}
if (options & NEW_URL) {
newInfo->ownURL = TRUE;
newInfo->url[0] = '\0';
newInfo->args[0] = '\0';
newInfo->path_info[0] = '\0';
newInfo->filename[0] = '\0';
} else {
newInfo->ownURL = FALSE;
strcpy(newInfo->url, reqInfo->url);
strcpy(newInfo->args, reqInfo->args);
strcpy(newInfo->filename, reqInfo->filename);
}
/* Copy all in headers */
strcpy(newInfo->inh_agent,reqInfo->inh_agent);
strcpy(newInfo->inh_referer,reqInfo->inh_referer);
strcpy(newInfo->inh_called_hostname,reqInfo->inh_called_hostname);
strcpy(newInfo->inh_if_mod_since,reqInfo->inh_if_mod_since);
strcpy(newInfo->inh_content_type,reqInfo->inh_content_type);
newInfo->inh_content_length = reqInfo->inh_content_length;
/* Zero all out headers : outh_www_auth is handled in auth above */
newInfo->outh_location[0] = '\0';
newInfo->outh_last_mod[0] = '\0';
newInfo->outh_content_type[0] = '\0';
newInfo->outh_content_encoding[0] = '\0';
newInfo->outh_content_length = -1;
newInfo->outh_cgi = NULL;
strcpy(newInfo->referer,reqInfo->referer);
strcpy(newInfo->agent,reqInfo->agent);
newInfo->connection_socket = reqInfo->connection_socket;
newInfo->in = reqInfo->in;
newInfo->out = reqInfo->out;
if (options & NEW_SOCK_BUF) {
newInfo->ownSB = TRUE;
newInfo->sb = NULL;
} else {
newInfo->ownSB = FALSE;
newInfo->sb = reqInfo->sb;
}
newInfo->cgi_buf = NULL;
newInfo->next = reqInfo;
@ -334,61 +272,27 @@ per_request *continue_request(per_request *reqInfo, int options) {
return newInfo;
}
/* free_request()
* Clears the request structure linked list.
* Options: (from constants.h)
* ONLY_LAST : deletes only the top most (most recent)
* NOT_LAST : Don't delete the last one (so we don't have to malloc again)
*/
void free_request(per_request *reqInfo,int options) {
per_request *tmp = reqInfo;
while (reqInfo != NULL) {
/* We'll just let the freeAllStrings clean up these instead. */
reqInfo->remote_name = NULL;
reqInfo->remote_host = NULL;
reqInfo->remote_ip = NULL;
#ifdef CONTENT_MD5
if (reqInfo->outh_content_md5 != NULL) free(reqInfo->outh_content_md5);
#endif /* CONTENT_MD5 */
if (reqInfo->outh_cgi != NULL) free(reqInfo->outh_cgi);
if (reqInfo->ownDNS) {
if (reqInfo->remote_name != NULL) free(reqInfo->remote_name);
if (reqInfo->remote_host != NULL) free(reqInfo->remote_host);
if (reqInfo->remote_ip != NULL) free(reqInfo->remote_ip);
}
if (reqInfo->ownENV && reqInfo->env) {
free_env(reqInfo);
}
if (reqInfo->ownSB && reqInfo->sb) {
free(reqInfo->sb);
reqInfo->sb = NULL;
sockbuf_count--;
}
if (reqInfo->cgi_buf) {
free(reqInfo->cgi_buf);
reqInfo->cgi_buf = NULL;
cgibuf_count--;
}
/* I have no idea how this is possible, but it is happening */
if (reqInfo == reqInfo->next) reqInfo->next = NULL;
/* Don't clear the last one */
if ((reqInfo->next == NULL) && (options & NOT_LAST)) {
reqInfo->ownDNS = TRUE;
reqInfo->dns_host_lookup = FALSE;
return;
}
tmp = reqInfo->next;
free(reqInfo);
req_count--;
reqInfo = tmp;
gCurrentRequest = reqInfo;
if (options & ONLY_LAST) return;
}
}
/* decode_request()
* given an HTTP request line as a string, decodes it into
* METHOD URL?ARGS PROTOCAL
* Then calls get_http_headers() to get the rfc822 style headers
*/
void decode_request(per_request *reqInfo, char *request)
{
char *protocal;
@ -415,22 +319,20 @@ void decode_request(per_request *reqInfo, char *request)
protocal = strtok (NULL, "\r");
if(!protocal) {
no_headers = 1;
reqInfo->http_version = P_HTTP_0_9;
}
else {
if (!strcmp(protocal,protocals[P_HTTP_1_0]))
no_headers = 0;
if (!strcmp(protocal,"HTTP/1.0"))
reqInfo->http_version = P_HTTP_1_0;
else if (!strcmp(protocal,protocals[P_HTTP_1_0]))
else if (!strcmp(protocal,"HTTP/1.1"))
reqInfo->http_version = P_HTTP_1_1;
else if (!strcasecmp(protocal,protocals[P_SHTTP_1_1]))
reqInfo->http_version = P_SHTTP_1_1;
else if (!strcasecmp(protocal,protocals[P_SHTTP_1_2]))
reqInfo->http_version = P_SHTTP_1_2;
else reqInfo->http_version = P_OTHER;
/* dummy call to eat LF at end of protocal */
strtok (NULL, "\n");
get_http_headers(reqInfo);
get_mime_headers(reqInfo);
}
/* fprintf(stderr,"method:%s url:%s args:%s prot:%s\n",method,
@ -438,113 +340,59 @@ void decode_request(per_request *reqInfo, char *request)
}
/* Returns a method number for a given method string. SHTTP requires
* case independent (as per standard network protocal). HTTP is broken,
* and is case dependent.
*/
int MapMethod (char* method)
void get_request(per_request *reqInfo)
{
if(!strcmp(method,methods[M_HEAD]))
return M_HEAD;
else if(!strcmp(method,methods[M_GET]))
return M_GET;
else if(!strcmp(method,methods[M_POST]))
return M_POST;
else if(!strcmp(method,methods[M_PUT]))
return M_PUT;
else if(!strcmp(method,methods[M_DELETE]))
return M_DELETE;
else if(!strcasecmp(method,methods[M_SECURE]))
return M_SECURE;
else
return M_INVALID;
signal(SIGPIPE,send_fd_timed_out);
if (getline(reqInfo->connection_socket, as_requested, HUGE_STRING_LEN,
1, timeout) == -1)
return;
if(!as_requested[0])
return;
strcpy(the_request, as_requested);
#ifdef SETPROCTITLE
setproctitle(the_request);
#endif /* SETPROCTITLE */
decode_request(reqInfo, as_requested);
unescape_url(reqInfo->url);
/* Moved this to later so we can read the headers first for HTTP/1.1
Host: support */
which_host_conf(reqInfo);
if (reqInfo->ownDNS) {
/* Only when ownDNS set do we find out the remote host name info
and by which name the server was called */
get_remote_host(reqInfo);
}
if(reqInfo->method == M_HEAD)
header_only=1;
else if(reqInfo->method == M_GET) {
}
process_request(reqInfo);
}
/* Globals for speed because of size, these are for get_http_headers */
static char field_type[HUGE_STRING_LEN];
static char unrec_hdr[HUGE_STRING_LEN];
static char unrec_hdr_val[HUGE_STRING_LEN];
/* get_http_headers() (formerly get_mime_headers)
* Read line by line off from the client, and if we recognize a header,
* add it to reqInfo, otherwise let it go through to become an
* environment variable for CGI scripts. Also, SHTTP headers all start
* with SHTTP, so we pass them through to the SHTTP library.
* The Content-Type, Content-Length and Authorization headers don't get
* made into CGI variables (Content-Type, Content-Length are already
* defined in the CGI spec, and Authorization would be a security risk.)
*/
void get_http_headers(per_request *reqInfo)
int MapMethod (char* method)
{
char *field_val;
int options = 0;
while(getline(reqInfo->sb,field_type,HUGE_STRING_LEN-1,options,
timeout) != -1) {
if(!field_type[0])
return;
if(!(field_val = strchr(field_type,':')))
continue;
*field_val++ = '\0';
while(isspace(*field_val)) ++field_val;
if(!strcasecmp(field_type,"Content-type")) {
strncpy(reqInfo->inh_content_type,field_val,MAX_STRING_LEN);
reqInfo->inh_content_type[MAX_STRING_LEN-1] = '\0';
continue;
} else
if(!strcasecmp(field_type,"Authorization")) {
strncpy(reqInfo->inh_auth_line,field_val,HUGE_STRING_LEN);
reqInfo->inh_auth_line[HUGE_STRING_LEN-1]='\0';
continue;
} else
if(!strcasecmp(field_type,"Host")) {
strncpy(reqInfo->inh_called_hostname, field_val, MAX_STRING_LEN);
reqInfo->inh_called_hostname[MAX_STRING_LEN-1] = '\0';
} else
if(!strcasecmp(field_type,"Extension")) {
if (!strcasecmp(field_val, "Notify-Domain-Restriction"))
reqInfo->bNotifyDomainRestricted = 1;
#ifdef DIGEST_AUTH
/* Should we do something if we get this header? Maybe set a flag
* to know that a client doesn't accept this type of authentication?
*/
/* else if (!strcasecmp(field_val, "Security/Digest")); */
#endif /* DIGEST_AUTH */
} else
if(!strcasecmp(field_type,"Content-length")) {
sscanf(field_val,"%d",&(reqInfo->inh_content_length));
continue;
} else
if(!strcasecmp(field_type,"Connection")) {
if (!strcasecmp(field_val, "Keep-Alive") &&
keep_alive.bAllowKeepAlive)
keep_alive.bKeepAlive = 1;
} else
if(!strcasecmp(field_type,"User-agent")) {
strncpy(reqInfo->inh_agent, field_val, HUGE_STRING_LEN);
reqInfo->inh_agent[HUGE_STRING_LEN-1] = '\0';
} else
if(!strcasecmp(field_type,"Referer")) {
strncpy(reqInfo->inh_referer, field_val, HUGE_STRING_LEN);
reqInfo->inh_referer[HUGE_STRING_LEN-1] = '\0';
} else
if(!strcasecmp(field_type,"If-modified-since")) {
strncpy(reqInfo->inh_if_mod_since,field_val, MAX_STRING_LEN);
reqInfo->inh_if_mod_since[MAX_STRING_LEN-1] = '\0';
}
http2cgi(unrec_hdr, field_type);
strcpy (unrec_hdr_val, field_val);
if(reqInfo->env) {
if(!merge_header(reqInfo,unrec_hdr,field_val))
make_env_str(reqInfo,unrec_hdr,field_val);
}
else
make_env_str(reqInfo,unrec_hdr,field_val);
}
if(!strcmp(method,"HEAD"))
return M_HEAD;
else if(!strcmp(method,"GET"))
return M_GET;
else if(!strcmp(method,"POST"))
return M_POST;
else if(!strcmp(method,"PUT"))
return M_PUT;
else if(!strcmp(method,"DELETE"))
return M_DELETE;
else
return M_INVALID;
}
/* Split from get_request (the former process_request) so that we can call
@ -560,6 +408,7 @@ void process_request(per_request *reqInfo)
case A_STD_DOCUMENT:
if ((reqInfo->method == M_HEAD) &&
(reqInfo->http_version == P_HTTP_0_9)) {
header_only = 0;
reqInfo->method = M_GET;
die(reqInfo,SC_BAD_REQUEST,"Invalid HTTP/0.9 method.");
}
@ -576,62 +425,3 @@ void process_request(per_request *reqInfo)
break;
}
}
/* RequestMain()
* The start of the request cycle. This routine starts reading off
* the socket, and also calls the messages for decoding (decode_request()),
* figuring out which virtual host (which_host_conf()), and getting the
* DNS info (get_remote_host()). It then calls process_request() to
* handle things once it has all of the information from the client
* (with the exception of an entity body). These are split so that
* process_request() can be called internally in the server to handle
* new request types (internal redirect handling and ErrorDoc)
*/
void RequestMain(per_request *reqInfo)
{
int options = 0;
signal(SIGPIPE,send_fd_timed_out);
#ifdef LOG_DURATION
request_time = 0;
#endif /* LOG_DURATION */
if (reqInfo->sb == NULL) {
reqInfo->sb = new_sock_buf(reqInfo,reqInfo->in);
sockbuf_count++;
}
if (getline(reqInfo->sb, as_requested, HUGE_STRING_LEN,
options, timeout) == -1)
return;
if(!as_requested[0])
return;
#ifdef LOG_DURATION
request_time = time(NULL);
#endif /* LOG_DURATION */
strcpy(the_request, as_requested);
#ifdef SETPROCTITLE
setproctitle(the_request);
#endif /* SETPROCTITLE */
decode_request(reqInfo, as_requested);
unescape_url(reqInfo->url);
/* Moved this to later so we can read the headers first for HTTP/1.1
* Host: support
*/
which_host_conf(reqInfo);
if (reqInfo->dns_host_lookup == FALSE) {
/* Only when we haven't done DNS do we call get_remote_host().
* If we aren't supposed to, get_remote_host() will not do it.
*/
get_remote_host(reqInfo);
}
process_request(reqInfo);
}

View File

@ -10,7 +10,7 @@
*
************************************************************************
*
* http_request.h,v 1.20 1996/04/05 18:55:04 blong Exp
* http_request.h,v 1.14 1995/11/09 01:48:21 blong Exp
*
************************************************************************
*
@ -20,37 +20,31 @@
#ifndef _HTTP_REQUEST_H_
#define _HTTP_REQUEST_H_
#include <setjmp.h>
/* globals defined in this module */
extern per_request *gCurrentRequest;
extern int no_headers;
extern char *remote_logname;
extern char failed_request[];
extern char failed_url[];
extern int header_only;
extern char the_request[];
/* Continue Request Options */
#define COPY_URL 1
#define FORCE_GET 2
#define NOT_LAST 4
#define NEW_URL 1
#define NEW_DNS 2
#define FORCE_GET 4
#define ONLY_LAST 8
#define KEEP_ENV 16
#define KEEP_AUTH 32
#define NEW_SOCK_BUF 64
extern int req_count;
extern int cgibuf_count;
extern int sockbuf_count;
/* function prototypes */
per_request *initialize_request(per_request *reqInfo);
per_request *continue_request(per_request *reqInfo, int options);
void free_request(per_request *reqInfo, int options);
void get_http_headers(per_request *reqInfo);
void process_request(per_request *reqInfo);
void RequestMain(per_request *reqInfo);
void get_request(per_request *reqInfo);
int MapMethod (char* method);
#endif /* _HTTP_REQUEST_H_ */

View File

@ -10,14 +10,25 @@
*
************************************************************************
*
* http_send.c,v 1.34 1996/04/05 18:55:06 blong Exp
* http_send.c,v 1.22 1995/11/28 09:02:09 blong Exp
*
************************************************************************
*
* http_send.c: handles sending of regular files and determining which
* type of request it is if its not for a regular file
*
* Based on NCSA HTTPd 1.3 by Rob McCool
*
* 04-08-95 blong
* Fixed security hole which allowed a trailing slash on CGI_MAGIC_TYPE
* cgi anywhere scripts to send back the script contents. Now the
* trailing slash is added to the PATH_INFO, and the script is run.
* Oh yeah, and don't forget about directories.
*
* 09-01-95 blong
* Fixed bug under AIX 3.2.5 where last part of file is garbled using
* fwrite, but works fine with write. I didn't say I understood it,
* but the fix seems to work.
*/
@ -28,13 +39,6 @@
#ifndef NO_STDLIB_H
# include <stdlib.h>
#endif /* NO_STDLIB_H */
#ifdef HAVE_STDARG
# include <stdarg.h>
#else
# ifdef HAVE_VARARGS
# include <varargs.h>
# endif /* HAVE_VARARGS */
#endif /* HAVE_STDARG */
#include <string.h>
#include <sys/stat.h>
#include <errno.h>
@ -43,7 +47,6 @@
#include <ctype.h>
#include "constants.h"
#include "fdwrap.h"
#include "allocate.h"
#include "http_send.h"
#include "cgi.h"
#include "imagemap.h"
@ -57,13 +60,17 @@
#include "http_dir.h"
#include "httpd.h"
#include "util.h"
#include "blackout.h"
int num_includes;
static void (*exit_callback)(void);
void send_node(per_request *reqInfo)
{
struct stat finfo;
char pa[MAX_STRING_LEN];
int length = 0;
register x = 0;
int allow;
char allow_options;
@ -71,32 +78,32 @@ void send_node(per_request *reqInfo)
exit_callback = NULL;
/* It is no longer necessary to move all but one of the trailing slashes
* to the path_info string, since all multiple slashes are now compressed
* to one as a security precaution.
*/
/* Remove all but 1 of the trailing slashes from the filename in order
to fix security hole. Place them in the path alias (pa) array */
if(stat(reqInfo->filename,&finfo) == -1) {
ErrReturn = extract_path_info(reqInfo,&finfo);
length = strlen(reqInfo->filename);
while ((length>1) && (reqInfo->filename[length-1] == '/') &&
(reqInfo->filename[length-2] == '/') && (x < MAX_STRING_LEN)) {
pa[x] = '/';
x++;
reqInfo->filename[length-1] = '\0';
length--;
}
evaluate_access(reqInfo,&finfo,&allow,&allow_options);
if (ErrReturn) {
if(ErrReturn == ENOENT) {
log_reason(reqInfo,"file does not exist",reqInfo->filename);
die(reqInfo,SC_NOT_FOUND,reqInfo->url);
/* Check for AFS/NFS problems, and send back an unavailable message instead
* Larry Schwimmer (schwim@cyclone.stanford.edu)
*/
} else if ((ErrReturn == ETIMEDOUT) || (ErrReturn == ENODEV)) {
log_reason(reqInfo, "file temporarily unavailable",
reqInfo->filename);
die(reqInfo,SC_SERVICE_UNAVAIL,reqInfo->url);
} else {
log_reason(reqInfo,"(3) file permissions deny server access",
reqInfo->filename);
die(reqInfo,SC_FORBIDDEN,reqInfo->url);
pa[x] = '\0';
if(stat(reqInfo->filename,&finfo) == -1) {
if ((ErrReturn = extract_path_info(reqInfo,pa,&finfo))) {
if(ErrReturn == ENOENT) {
log_reason(reqInfo,"file does not exist",reqInfo->filename);
die(reqInfo,SC_NOT_FOUND,reqInfo->url);
} else {
log_reason(reqInfo,"(3) file permissions deny server access",
reqInfo->filename);
die(reqInfo,SC_FORBIDDEN,reqInfo->url);
}
}
}
evaluate_access(reqInfo,&finfo,&allow,&allow_options);
if(!allow) {
log_reason(reqInfo,"client denied by server configuration",
reqInfo->filename);
@ -104,26 +111,17 @@ void send_node(per_request *reqInfo)
}
if (S_ISDIR(finfo.st_mode)) {
send_dir(reqInfo,&finfo,allow_options);
send_dir(reqInfo,&finfo,pa,allow_options);
} else if (S_ISREG(finfo.st_mode)) {
x = strlen(reqInfo->filename);
/* Remove the trailing slash if its not a directory */
if (reqInfo->filename[x-1] == '/') {
if (reqInfo->path_info[0] == '\0') {
reqInfo->path_info[0] = '/';
reqInfo->path_info[1] = '\0';
}
reqInfo->filename[x-1] = '\0';
}
probe_content_type(reqInfo,reqInfo->filename);
if (!strcmp(reqInfo->outh_content_type, CGI_MAGIC_TYPE))
send_cgi(reqInfo,&finfo,allow_options);
if (!strcmp(content_type, CGI_MAGIC_TYPE))
send_cgi(reqInfo,&finfo,pa,allow_options);
#ifdef IMAGEMAP_SUPPORT
else if (!strcmp(reqInfo->outh_content_type, IMAGEMAP_MAGIC_TYPE))
send_imagemap(reqInfo,&finfo,allow_options);
else if (!strcmp(content_type, IMAGEMAP_MAGIC_TYPE))
send_imagemap(reqInfo,&finfo,pa,allow_options);
#endif /* IMAGEMAP_SUPPORT */
else
send_file(reqInfo,&finfo,allow_options);
send_file(reqInfo,&finfo,pa,allow_options);
} else {
log_reason(reqInfo,"improper file type",reqInfo->filename);
/* device driver or pipe, no permission */
@ -131,12 +129,10 @@ void send_node(per_request *reqInfo)
}
}
void send_file(per_request *reqInfo, struct stat *fi, char allow_options)
void send_file(per_request *reqInfo, struct stat *fi,
char *path_args, char allow_options)
{
FILE *f;
#ifdef BLACKOUT_CODE
int isblack = FALSE;
#endif /* BLACKOUT_CODE */
if ((reqInfo->method != M_GET) && (reqInfo->method != M_HEAD)) {
sprintf(error_msg,"%s to non-script",methods[reqInfo->method]);
@ -144,22 +140,23 @@ void send_file(per_request *reqInfo, struct stat *fi, char allow_options)
}
set_content_type(reqInfo,reqInfo->filename);
if((allow_options & OPT_INCLUDES) && (!reqInfo->outh_content_encoding[0])) {
if((allow_options & OPT_INCLUDES) && (!content_encoding[0])) {
#ifdef XBITHACK
if((fi->st_mode & S_IXUSR) ||
(!strcmp(reqInfo->outh_content_type,INCLUDES_MAGIC_TYPE))) {
(!strcmp(content_type,INCLUDES_MAGIC_TYPE))) {
#else
if(!strcmp(reqInfo->outh_content_type,INCLUDES_MAGIC_TYPE)) {
if(!strcmp(content_type,INCLUDES_MAGIC_TYPE)) {
#endif /* XBITHACK */
reqInfo->bytes_sent = 0;
send_parsed_file(reqInfo, allow_options & OPT_INCNOEXEC);
send_parsed_file(reqInfo,path_args,
allow_options & OPT_INCNOEXEC);
log_transaction(reqInfo);
return;
}
}
if (reqInfo->path_info[0]) {
strcat(reqInfo->filename,reqInfo->path_info);
strcat(reqInfo->url,reqInfo->path_info);
if (path_args[0]) {
strcat(reqInfo->filename,path_args);
strcat(reqInfo->url,path_args);
sprintf(error_msg,"No file matching URL: %s",reqInfo->url);
log_reason(reqInfo, error_msg, reqInfo->filename);
die(reqInfo,SC_NOT_FOUND,reqInfo->url);
@ -184,75 +181,49 @@ void send_file(per_request *reqInfo, struct stat *fi, char allow_options)
}
}
reqInfo->bytes_sent = 0;
#ifdef BLACKOUT_CODE
if (!strcmp(reqInfo->outh_content_type,BLACKOUT_MAGIC_TYPE)) {
isblack = TRUE;
strcpy(reqInfo->outh_content_type,"text/html");
}
#endif /* BLACKOUT_CODE */
if(reqInfo->http_version != P_HTTP_0_9) {
/* No length dependent headers since black is parsed */
#ifdef BLACKOUT_CODE
if (isblack == FALSE) {
#endif /* BLACKOUT_CODE */
#ifdef CONTENT_MD5
reqInfo->outh_content_md5 = (unsigned char *)md5digest(f);
#endif /* CONTENT_MD5 */
if(!no_headers) {
set_content_length(reqInfo,fi->st_size);
if (set_last_modified(reqInfo,fi->st_mtime)) {
FClose(f);
return;
}
}
if (reqInfo->http_version != P_HTTP_0_9) {
send_http_header(reqInfo);
}
#ifdef BLACKOUT_CODE
send_http_header(reqInfo);
}
#endif /* BLACKOUT_CODE */
if(reqInfo->method != M_HEAD) {
#ifdef BLACKOUT_CODE
if (isblack == TRUE)
send_fp_black(reqInfo,f,NULL);
else
#endif /* BLACKOUT_CODE */
num_includes = 0;
if(!header_only)
send_fp(reqInfo,f,NULL);
}
log_transaction(reqInfo);
FClose(f);
}
/* Globals for speed */
static char ifile[HUGE_STRING_LEN];
static char temp_name[HUGE_STRING_LEN];
void send_dir(per_request *reqInfo,struct stat *finfo, char allow_options) {
void send_dir(per_request *reqInfo,struct stat *finfo, char *pa,
char allow_options) {
char *name_ptr, *end_ptr;
char *ifile, *temp_name;
ifile = newString(HUGE_STRING_LEN,STR_TMP);
temp_name = newString(HUGE_STRING_LEN,STR_TMP);
/* Path Alias (pa) array should now have the trailing slash */
/* if (pa[0] != '/') { */
if ((reqInfo->filename[strlen(reqInfo->filename) - 1] != '/') &&
(reqInfo->path_info[0] != '/')) {
(pa[0] != '/')) {
char url[HUGE_STRING_LEN];
strcpy_dir(ifile,reqInfo->url);
construct_url(temp_name,reqInfo->hostInfo,ifile);
escape_url(temp_name);
die(reqInfo,SC_REDIRECT_PERM,temp_name);
construct_url(url,reqInfo->hostInfo,ifile);
escape_url(url);
die(reqInfo,SC_REDIRECT_PERM,url);
}
/* Don't allow PATH_INFO to directory indexes as a compromise for
error messages for files which don't exist */
if ((reqInfo->path_info[0] != '\0') || (strlen(reqInfo->path_info) > 1)) {
strcat(reqInfo->filename,reqInfo->path_info);
strcat(reqInfo->url,reqInfo->path_info);
if ((pa[0] != '\0') || (strlen(pa) > 1)) {
strcat(reqInfo->filename,pa);
strcat(reqInfo->url,pa);
sprintf(error_msg,"No file matching URL: %s",reqInfo->url);
log_reason(reqInfo, error_msg, reqInfo->filename);
freeString(temp_name);
freeString(ifile);
die(reqInfo,SC_NOT_FOUND,reqInfo->url);
}
@ -272,40 +243,30 @@ void send_dir(per_request *reqInfo,struct stat *finfo, char allow_options) {
make_full_path(reqInfo->filename,name_ptr,ifile);
if(stat(ifile,finfo) == -1) {
if(! *end_ptr && (allow_options & OPT_INDEXES)) {
if (reqInfo->path_info[0]) {
strcat(reqInfo->filename,reqInfo->path_info);
strcat(reqInfo->url,reqInfo->path_info);
if (pa[0]) {
strcat(reqInfo->filename,pa);
strcat(reqInfo->url,pa);
log_reason(reqInfo,"file does not exist",reqInfo->filename);
freeString(ifile);
freeString(temp_name);
die(reqInfo,SC_NOT_FOUND,reqInfo->url);
}
if ((reqInfo->method != M_GET) && (reqInfo->method != M_HEAD)) {
sprintf(error_msg,"%s to non-script",methods[reqInfo->method]);
freeString(ifile);
freeString(temp_name);
die(reqInfo,SC_NOT_IMPLEMENTED,error_msg);
}
index_directory(reqInfo);
freeString(ifile);
freeString(temp_name);
return;
} else if (! *end_ptr) {
log_reason(reqInfo,"(2) file permissions deny server access",
reqInfo->filename);
freeString(ifile);
freeString(temp_name);
die(reqInfo,SC_FORBIDDEN,reqInfo->url);
}
} else {
strcpy(reqInfo->filename,ifile);
probe_content_type(reqInfo,reqInfo->filename);
if(!strcmp(reqInfo->outh_content_type,CGI_MAGIC_TYPE))
send_cgi(reqInfo,finfo,allow_options);
if(!strcmp(content_type,CGI_MAGIC_TYPE))
send_cgi(reqInfo,finfo,pa,allow_options);
else
send_file(reqInfo,finfo,allow_options);
freeString(ifile);
freeString(temp_name);
send_file(reqInfo,finfo,pa, allow_options);
return;
}
name_ptr = end_ptr;
@ -313,158 +274,45 @@ void send_dir(per_request *reqInfo,struct stat *finfo, char allow_options) {
}
/* Search down given translated URL searching for actual file name and filling
* in path_info string. Doesn't make any claims about file type, must be
* handled elsewhere.
* Returns 0 on success, errno on failure
*/
int extract_path_info(per_request *reqInfo, struct stat *finfo)
in path_args string. Doesn't make any claims about file type, must be
handled elsewhere.
Returns 0 on success, errno on failure
*/
int extract_path_info(per_request *reqInfo, char *path_args,
struct stat *finfo)
{
register int x,max;
char *str;
str = newString(HUGE_STRING_LEN,STR_TMP);
char t[HUGE_STRING_LEN];
max=count_dirs(reqInfo->filename);
for(x=max ; x > 0 ; x--) {
make_dirstr(reqInfo->filename,x+1,str);
if(!(stat(str,finfo))) {
int l=strlen(str);
strcat(reqInfo->path_info,&(reqInfo->filename[l]));
make_dirstr(reqInfo->filename,x+1,t);
if(!(stat(t,finfo))) {
int l=strlen(t);
strcat(path_args,&(reqInfo->filename[l]));
reqInfo->filename[l] = '\0';
reqInfo->url[strlen(reqInfo->url) - strlen(reqInfo->path_info)]='\0';
freeString(str);
reqInfo->url[strlen(reqInfo->url) - strlen(path_args)] = '\0';
return 0;
}
}
freeString(str);
return errno;
}
/* Dump the headers of the per_request structure to the client.
* Will also set the status line if it hasn't already been set,
* will set to 302 if location, 401 if auth required, 200 otherwise.
* Will dump the following headers:
* Date GMT Date in rfc 822 format
* Server SERVER_VERSION
* Annotations-cgi reqInfo->hostInfo->annotation_server
* Location reqInfo->outh_location
* Last-modified reqInfo->outh_last_mod
* Content-type reqInfo->outh_content_type
* Content-length reqInfo->outh_content_length
* Content-encoding reqInfo->outh_content_encoding
* Content-MD5 reqInfo->outh_content_md5
* WWW-Authenticate reqInfo->outh_www_auth
* Extension: Domain-Restricted reqInfo->bNotifyDomainRestricted &&
* reqInfo->bSatisfiedDomain
* Connection: Keep-Alive keep_alive. stuff
* Keep-Alive: max= timeout= same
* other headers from CGI reqInfo->outh_cgi
* We don't dump the MIME-Version header that NCSA HTTP/1.3 did, because
* the server is not mime-compliant.
*
* Should we only give back HTTP/1.0 headers to 1.0 clients? The docs are
* unclear on this, and almost all clients (even ones supporting 1.1 features)
* are sending HTTP/1.0 anyways, so we will for now.
*/
void send_http_header(per_request *reqInfo)
{
if(!reqInfo->status_line) {
/* Special Cases */
if(reqInfo->outh_location[0])
reqInfo->status = SC_REDIRECT_TEMP;
if(reqInfo->outh_www_auth[0])
reqInfo->status = SC_AUTH_REQUIRED;
set_stat_line(reqInfo);
}
rprintf(reqInfo,"%s %s%c%c",protocals[reqInfo->http_version],
reqInfo->status_line,CR,LF);
rprintf(reqInfo,"Date: %s%c%c",gm_timestr_822(time(NULL)),CR,LF);
rprintf(reqInfo,"Server: %s%c%c",SERVER_VERSION,CR,LF);
if (reqInfo->hostInfo->annotation_server[0])
rprintf(reqInfo,"Annotations-cgi: %s%c%c",
reqInfo->hostInfo->annotation_server,CR,LF);
if(reqInfo->outh_location[0])
rprintf(reqInfo,"Location: %s%c%c",
reqInfo->outh_location,CR,LF);
if(reqInfo->outh_last_mod[0])
rprintf(reqInfo,"Last-modified: %s%c%c",
reqInfo->outh_last_mod,CR,LF);
if(reqInfo->outh_content_type[0])
rprintf(reqInfo,"Content-type: %s%c%c",
reqInfo->outh_content_type,CR,LF);
/* If we know the content_length, we can fulfill byte range requests */
if(reqInfo->outh_content_length >= 0) {
/* Not yet, working on it */
/* rprintf(reqInfo,"Accept-Ranges: bytes%c%c",CR,LF); */
rprintf(reqInfo,"Content-length: %d%c%c",
reqInfo->outh_content_length,CR,LF);
}
if(reqInfo->outh_content_encoding[0])
rprintf(reqInfo,"Content-encoding: %s%c%c",
reqInfo->outh_content_encoding,CR,LF);
#ifdef CONTENT_MD5
if(reqInfo->outh_content_md5)
rprintf(reqInfo,"Content-MD5: %s%c%c",
reqInfo->outh_content_md5,CR,LF);
#endif /* CONTENT_MD5 */
if(reqInfo->outh_www_auth[0])
rprintf(reqInfo,"WWW-Authenticate: %s%c%c",
reqInfo->outh_www_auth,CR,LF);
if (reqInfo->bNotifyDomainRestricted && reqInfo->bSatisfiedDomain)
rprintf(reqInfo,"Extension: Domain-Restricted%c%c",CR,LF);
keep_alive.bKeepAlive = keep_alive.bKeepAlive &&
(reqInfo->outh_content_length >= 0);
if (keep_alive.bKeepAlive && (!keep_alive.nMaxRequests ||
keep_alive.nCurrRequests + 1 <
keep_alive.nMaxRequests)) {
keep_alive.bKeepAlive = 1;
rprintf(reqInfo,
"Connection: Keep-Alive%c%cKeep-Alive: max=%d, timeout=%d%c%c",
CR,LF, keep_alive.nMaxRequests, keep_alive.nTimeOut,CR,LF);
}
if(reqInfo->outh_cgi)
rprintf(reqInfo,"%s",reqInfo->outh_cgi);
rprintf(reqInfo,"%c%c",CR,LF);
/* CLF doesn't include the headers, I don't think, so clear the information
* on what has been sent so far (byte count wise)
*/
reqInfo->bytes_sent = 0;
/* rflush(reqInfo); */
}
/* Time out function for send_fd and send_fp
* Logs whether an Abort or Time out occurs, logs how much has been sent,
* Does some cleanup (CloseAll) and either exits of jumps back
*/
void send_fd_timed_out(int sigcode)
{
char *errstr;
char errstr[MAX_STRING_LEN];
errstr = newString(HUGE_STRING_LEN,STR_TMP);
if(exit_callback) (*exit_callback)();
if (sigcode != SIGPIPE) {
sprintf(errstr,"HTTPd: send timed out for %s, URL: %s",
(gCurrentRequest->remote_name ?
gCurrentRequest->remote_name : "remote host"),
(gCurrentRequest->url ? gCurrentRequest->url : "-"));
sprintf(errstr,"httpd: send timed out for %s, URL: %s",
(gCurrentRequest->remote_name ?
gCurrentRequest->remote_name : "remote host"),
(gCurrentRequest->url ? gCurrentRequest->url : "-"));
}
else {
sprintf(errstr,"HTTPd: send aborted for %s, URL: %s",
(gCurrentRequest->remote_name ?
gCurrentRequest->remote_name : "remote host"),
sprintf(errstr,"httpd: send aborted for %s, URL: %s",
(gCurrentRequest->remote_name ?
gCurrentRequest->remote_name : "remote host"),
(gCurrentRequest->url ? gCurrentRequest->url : "-"));
}
log_error(errstr,gCurrentRequest->hostInfo->error_log);
@ -487,25 +335,22 @@ void send_fd_timed_out(int sigcode)
}
}
/* send_fp(): sends a file pointer to the socket. Uses fread to read,
* but uses non-buffered I/O for writes (write())
*
* We'll make it return the number of bytes sent
* so that we know if we need to send a body by default
*/
/*
We'll make it return the number of bytes sent
so that we know if we need to send a body by default
*/
long send_fp(per_request *reqInfo, FILE *f, void (*onexit)(void))
{
char *buf;
char buf[IOBUFSIZE];
long total_bytes_sent;
register int n,o,w;
buf = newString(IOBUFSIZE,STR_TMP);
exit_callback = onexit;
signal(SIGALRM,send_fd_timed_out);
signal(SIGPIPE,send_fd_timed_out);
total_bytes_sent = 0;
rflush(reqInfo);
fflush(reqInfo->out);
while (1) {
alarm(timeout);
if((n=fread(buf,sizeof(char),IOBUFSIZE,f)) < 1) {
@ -521,8 +366,8 @@ long send_fp(per_request *reqInfo, FILE *f, void (*onexit)(void))
* For now, we'll just replace, but may have to #define one or the other
* depending on the system.
*/
w = write(fileno(reqInfo->out),&buf[o],n);
if (w < 0) {
/* w=fwrite(&buf[o],sizeof(char),n,reqInfo->out); */
if ((w=write(fileno(reqInfo->out),&buf[o],n)) < 0) {
if (errno != EINTR) break;
}
n-=w;
@ -530,50 +375,9 @@ long send_fp(per_request *reqInfo, FILE *f, void (*onexit)(void))
total_bytes_sent += w;
}
}
/* fflush(reqInfo->out); */
alarm(0);
signal(SIGALRM,SIG_IGN);
signal(SIGPIPE,SIG_IGN);
freeString(buf);
return total_bytes_sent;
}
/* rprintf() will print out to the socket, using buffered I/O
*/
int rprintf(per_request *reqInfo, char *format, ...)
{
va_list argList;
int x;
#ifndef HAVE_VARARGS
va_start(argList,format);
#else
va_start(argList);
#endif /* HAVE_VARARGS */
x = vfprintf(reqInfo->out, format, argList);
va_end(argList);
reqInfo->bytes_sent += x;
return x;
}
/* rputs() for drop into fputs(), for now.
*/
int rputs(char *string, per_request *reqInfo)
{
reqInfo->bytes_sent += strlen(string);
return fputs(string,reqInfo->out);
}
int rputc(int ch, per_request *reqInfo)
{
(reqInfo->bytes_sent)++;
return putc(ch, reqInfo->out);
}
int rflush(per_request *reqInfo)
{
return fflush(reqInfo->out);
}

View File

@ -10,7 +10,7 @@
*
************************************************************************
*
* http_send.h,v 1.10 1996/03/27 20:44:12 blong Exp
* http_send.h,v 1.6 1995/11/28 09:02:11 blong Exp
*
************************************************************************
*
@ -22,17 +22,14 @@
/* function prototypes */
void send_node(per_request *reqInfo);
void send_file(per_request *reqInfo, struct stat *fi, char allow_options);
void send_dir(per_request *reqInfo,struct stat *finfo, char allow_options);
int extract_path_info(per_request *reqInfo, struct stat *finfo);
void send_file(per_request *reqInfo, struct stat *fi,
char *path_args, char allow_options);
void send_dir(per_request *reqInfo,struct stat *finfo, char *pa,
char allow_options);
int extract_path_info(per_request *reqInfo, char *path_args,
struct stat *finfo);
long send_fp(per_request *reqInfo, FILE *f, void (*onexit)(void));
void send_fd_timed_out(int);
void send_http_header(per_request *reqInfo);
int rprintf(per_request *reqInfo, char *format, ...);
int rputs(char *string, per_request *reqInfo);
int rputc(int ch, per_request *reqInfo);
int rflush(per_request *reqInfo);
#endif /* _HTTP_SEND_H_ */

View File

@ -10,7 +10,7 @@
*
************************************************************************
*
* httpd.c,v 1.131 1996/04/05 18:55:09 blong Exp
* httpd.c,v 1.115 1995/11/28 09:02:12 blong Exp
*
************************************************************************
*
@ -18,12 +18,36 @@
*
*
* 03-21-93 Rob McCool wrote original code (up to NCSA HTTPd 1.3)
* 05-17-95 NCSA HTTPd 1.4.1
* 05-01-95 NCSA HTTPd 1.4.2
* 11-10-95 NCSA HTTPd 1.5.0
* 11-14-95 NCSA HTTPd 1.5.0a
* 03-21-96 NCSA HTTPd 1.5.0c
*
* 03-06-95 blong
* changed server number for child-alone processes to 0 and changed name
* of processes
*
* 03-10-95 blong
* Added numerous speed hacks proposed by Robert S. Thau (rst@ai.mit.edu)
* including set group before fork, and call gettime before to fork
* to set up libraries.
*
* 04-28-95 guillory
* Changed search pattern on child processes to better distribute load
*
* 04-30-95 blong
* added patch by Kevin Steves (stevesk@mayfield.hp.com) to fix
* rfc931 logging. We were passing sa_client, but this information
* wasn't known yet at the time of the pass to the child. Now uses
* getpeername in child_main to find this information.
*
* 08-16-95 blong
* added patch by Vince Tkac (tkac@oclc.org) to allow restart when
* a relative path is used on the command line with -f
*
* 10-26-95 blong
* added a RESOURCE_LIMIT compiletime option which limits the number
* of possible servers running to MaxServers
*
* 10-26-95 blong
* added patch by Stuart Lynne (sl@wimsey.com) to turn the proc title
* into a tachometer
*/
@ -63,11 +87,10 @@
# include <sys/select.h>
#endif /* NEED_SELECT_H */
#ifndef NO_SYS_RESOURCE_H
# include <sys/resource.h>
#include <sys/resource.h>
#endif /* NO_SYS_RESOURCE_H */
#include "constants.h"
#include "fdwrap.h"
#include "allocate.h"
#include "httpd.h"
#include "http_request.h"
#include "http_config.h"
@ -78,31 +101,25 @@
#include "http_dir.h"
#include "http_ipc.h"
#include "http_mime.h"
#include "http_send.h"
#include "util.h"
JMP_BUF jmpbuffer;
JMP_BUF restart_buffer;
int servernum=0;
int mainSocket;
pid_t pgrp;
int debug_mode = FALSE;
/* Current global information per child, will need to be made
* non-global for threading
*/
#ifndef NOT_READY
int Child=0;
int Alone=0;
/* To keep from being clobbered with setjmp */
JMP_BUF jmpbuffer;
int csd = -1;
KeepAliveData keep_alive; /* global keep alive info */
#endif /* NOT_READY */
/* To keep from being clobbered with setjmp */
static per_request *reqInfo = NULL;
ChildInfo *Children;
int num_children = 0;
KeepAliveData keep_alive; /* global keep alive info */
#ifndef NO_PASS
char donemsg[]="DONE";
ChildInfo *Children;
int num_children = 0;
#endif /* NO_PASS */
#if defined(KRB4) || defined(KRB5)
@ -118,7 +135,7 @@ void htexit(per_request *reqInfo, int status, int die_type)
if(standalone || keep_alive.bKeepAlive) siglongjmp(jmpbuffer,die_type);
#endif /* NO_SIGLONGJMP */
else {
rflush(reqInfo);
fflush(reqInfo->out);
exit(status);
}
}
@ -142,20 +159,20 @@ void detach(void)
if((x = fork()) > 0)
exit(0);
else if(x == -1) {
fprintf(stderr,"HTTPd: unable to fork new process\n");
fprintf(stderr,"httpd: unable to fork new process\n");
perror("fork");
exit(1);
}
#ifndef NO_SETSID
if((pgrp=setsid()) == -1) {
fprintf(stderr,"HTTPd: setsid failed\n");
fprintf(stderr,"httpd: setsid failed\n");
perror("setsid");
exit(1);
}
#else
if((pgrp=setpgrp(getpid(),0)) == -1) {
fprintf(stderr,"HTTPd: setpgrp failed\n");
fprintf(stderr,"httpd: setpgrp failed\n");
perror("setpgrp");
exit(1);
}
@ -208,7 +225,7 @@ void seg_fault(void)
close_all_logs();
chdir(core_dir);
abort();
/* exit(1); */
exit(1);
}
void dump_debug(void) {
@ -217,8 +234,6 @@ void dump_debug(void) {
log_error("HTTPd: caught USR1, dumping debugging information",
gConfiguration->error_log);
fprintf(gConfiguration->error_log," ReqInfo: %d\tSockbuf: %d\tCGbuf: %d\n",
req_count,sockbuf_count,cgibuf_count);
tmp = gCurrentRequest;
while (tmp != NULL) {
fprintf(gConfiguration->error_log," Status: %d \t\t Bytes: %ld\n",tmp->status,
@ -232,11 +247,11 @@ void dump_debug(void) {
fprintf(gConfiguration->error_log," Host: %s \t IP: %s\n",
tmp->remote_host, tmp->remote_ip);
fprintf(gConfiguration->error_log," Content-type: %s \t Content-Length: %d\n",
tmp->outh_content_type, tmp->outh_content_length);
content_type, content_length);
fprintf(gConfiguration->error_log," Refererer: %s\n",
tmp->inh_referer);
tmp->referer);
fprintf(gConfiguration->error_log," User Agent: %s\n",
tmp->inh_agent);
tmp->agent);
if (tmp->hostInfo->server_hostname)
fprintf(gConfiguration->error_log," ServerName: %s\n",
tmp->hostInfo->server_hostname);
@ -318,9 +333,6 @@ void set_group_privs(void)
fakeit.out = stdout;
fakeit.hostInfo = gConfiguration;
/* Only change if root. Changed to geteuid() so that setuid scripts, etc
* can start the server and change from root
*/
if (!geteuid()) {
/* Change standalone so that on error, we die, instead of siglongjmp */
tmp_stand = standalone;
@ -358,7 +370,6 @@ void speed_hack_libs(void)
char buf[MAX_STRING_LEN];
strftime (buf, MAX_STRING_LEN, "%d/%b/%Y:%H:%M:%S", dummy_time);
strftime (buf, MAX_STRING_LEN, "%d/%b/%Y:%H:%M:%S", other_dummy_time);
}
/*
@ -367,7 +378,7 @@ void speed_hack_libs(void)
* another request is ready, or the timeout period is up.
*/
int wait_keepalive(int csd, KeepAliveData *kad)
int WaitForRequest (int csd, KeepAliveData *kad)
{
fd_set listen_set;
struct timeval ka_timeout;
@ -390,31 +401,20 @@ int wait_keepalive(int csd, KeepAliveData *kad)
}
}
void CompleteRequest(per_request *reqInfo, int pipe)
void CompleteRequest (per_request *reqInfo, int pipe)
{
/* Changed from shutdown(csd,2) to allow kernel to finish sending data
* required on OSF/1 2.0 (Achille Hui (eillihca@drizzle.stanford.edu)) */
/* shutdown(csd,0); */
shutdown(csd,2);
required on OSF/1 2.0 (Achille Hui (eillihca@drizzle.stanford.edu)) */
shutdown(csd,0);
close(csd);
#ifndef NO_PASS
if (pipe >= 0) {
write(pipe,donemsg,sizeof(donemsg));
if (reqInfo != NULL) reqInfo->RequestFlags = 0;
free_request(reqInfo,NOT_LAST);
CloseAll();
freeAllStrings(STR_REQ);
kill_indexing(FI_LOCAL);
/* current_process_size("CompleteRequest/2"); */
#ifdef QUANTIFY
/* quantify_save_data(); */
#endif /* QUANTIFY */
free_request(reqInfo,0);
} else
#endif /* NO_PASS */
#ifdef QUANTIFY
/* quantify_save_data(); */
#endif /* QUANTIFY */
#ifdef PROFILE
exit (2);
#else
@ -425,19 +425,11 @@ void CompleteRequest(per_request *reqInfo, int pipe)
void child_alone(int csd, struct sockaddr_in *sa_server,
CLIENT_SOCK_ADDR *sa_client)
{
static per_request *reqInfo = NULL;
#ifndef THREADED
close(mainSocket);
#endif /* THREADED */
#ifdef PROFILE
moncontrol(1);
#endif /* PROFILE */
#ifdef QUANTIFY
/* quantify_clear_data(); */
quantify_start_recording_data();
#endif /* QUANTIFY */
Child = Alone = 1;
standalone = 0;
@ -452,12 +444,12 @@ void child_alone(int csd, struct sockaddr_in *sa_server,
}
}
#ifndef THREADED
/* this should check error status, but it's not crucial */
close(0);
close(1);
dup2(csd,0);
dup2(csd,1);
#endif /* THREADED */
remote_logname = (!do_rfc931 ? NULL :
rfc931((struct sockaddr_in *)sa_client,
@ -468,46 +460,49 @@ void child_alone(int csd, struct sockaddr_in *sa_server,
#else
if (sigsetjmp(jmpbuffer,1) != 0) {
#endif /* NO_SIGLONGJMP */
/* wait_keepalive returns 0 if timeout */
/* WaitForRequests returns 0 if timeout */
/* CompleteRequest doesn't return */
rflush(gCurrentRequest);
fflush(gCurrentRequest->out);
kill_indexing(FI_LOCAL);
if ((keep_alive.nMaxRequests
&& (++keep_alive.nCurrRequests >= keep_alive.nMaxRequests)) ||
!wait_keepalive(csd, &keep_alive)) {
!WaitForRequest(csd, &keep_alive)) {
CompleteRequest(gCurrentRequest,-1);
reqInfo = NULL;
}
}
while (1) {
reqInfo = initialize_request(reqInfo);
reqInfo->connection_socket = 0;
reqInfo->in = 0;
reqInfo->out = stdout;
RequestMain(reqInfo);
rflush(reqInfo);
get_request(reqInfo);
fflush(reqInfo->out);
kill_indexing(FI_LOCAL);
if (!keep_alive.bKeepAlive) {
CompleteRequest(reqInfo,-1);
reqInfo = NULL;
} else if ((keep_alive.nMaxRequests
&& (++keep_alive.nCurrRequests >= keep_alive.nMaxRequests))
|| !wait_keepalive(csd, &keep_alive)) {
|| !WaitForRequest(csd, &keep_alive)) {
CompleteRequest(reqInfo,-1);
reqInfo = NULL;
}
}
}
#ifndef NO_PASS
/* to keep from being clobbered by setjmp */
static int x;
static int val; /* indicates if keep_alive should remain active */
static int nFirst = 0;
#ifdef FD_LINUX
static int switch_uid = 0;
#endif /* FD_LINUX */
void child_main(int parent_pipe, SERVER_SOCK_ADDR *sa_server)
{
static per_request *reqInfo = NULL;
close(mainSocket);
#ifdef PROFILE
@ -515,8 +510,7 @@ void child_main(int parent_pipe, SERVER_SOCK_ADDR *sa_server)
#endif /* PROFILE */
#ifdef QUANTIFY
/* quantify_clear_data(); */
quantify_start_recording_data();
quantify_clear_data();
#endif /* QUANTIFY */
/* Only try to switch if we're running as root */
@ -553,14 +547,12 @@ void child_main(int parent_pipe, SERVER_SOCK_ADDR *sa_server)
standalone = 1;
}
#ifndef THREADED
for(x=0;x<num_children;x++) {
if (parent_pipe != Children[x].parentfd) close(Children[x].parentfd);
if (parent_pipe != Children[x].childfd) close(Children[x].childfd);
}
free(Children);
#endif /* THREADED */
#ifdef NO_SIGLONGJMP
if ((val = setjmp(jmpbuffer)) != 0) {
@ -568,58 +560,60 @@ void child_main(int parent_pipe, SERVER_SOCK_ADDR *sa_server)
if ((val = sigsetjmp(jmpbuffer,1)) != 0) {
#endif /* NO_SIGLONGJMP */
reqInfo = gCurrentRequest;
rflush(reqInfo);
fflush(reqInfo->out);
kill_indexing(FI_LOCAL);
if (val == DIE_KEEPALIVE) {
/* returns 0 if timeout during multiple request session */
if ((keep_alive.nMaxRequests
&& (++keep_alive.nCurrRequests >= keep_alive.nMaxRequests))
|| !wait_keepalive(csd, &keep_alive)) {
|| !WaitForRequest(csd, &keep_alive)) {
keep_alive.bKeepAlive = 0;
CompleteRequest(reqInfo,parent_pipe);
reqInfo = NULL;
}
}
else { /* in case it was in effect. probably a better place to reset */
keep_alive.bKeepAlive = 0;
CompleteRequest(reqInfo,parent_pipe);
reqInfo = NULL;
}
}
while (1) {
alarm (0);
if (!keep_alive.bKeepAlive) {
if (!nFirst || !keep_alive.bKeepAlive) {
GetDescriptor (parent_pipe);
remote_logname = GetRemoteLogName(sa_server);
nFirst = 1;
keep_alive.nCurrRequests = 0;
if (reqInfo != NULL) reqInfo->RequestFlags = 0;
}
reqInfo = initialize_request(reqInfo);
reqInfo->connection_socket = 0;
reqInfo->in = 0;
reqInfo->out = stdout;
RequestMain(reqInfo);
rflush(reqInfo);
get_request(reqInfo);
fflush(reqInfo->out);
kill_indexing(FI_LOCAL);
if (!keep_alive.bKeepAlive) {
CompleteRequest(reqInfo,parent_pipe);
reqInfo = NULL;
nFirst = 0;
} else if ((keep_alive.nMaxRequests
&& (++keep_alive.nCurrRequests >= keep_alive.nMaxRequests))
|| !wait_keepalive(csd, &keep_alive)) {
|| !WaitForRequest(csd, &keep_alive)) {
keep_alive.bKeepAlive = 0;
nFirst = 0;
CompleteRequest(reqInfo,parent_pipe);
reqInfo = NULL;
}
}
}
#ifndef NO_PASS
void GetDescriptor(int parent_pipe)
void GetDescriptor (int parent_pipe)
{
#ifndef THREADED
dup2(parent_pipe,0);
dup2(parent_pipe,1);
#endif /* THREADED */
#ifdef SETPROCTITLE
setproctitle("idle");
#endif /* SETPROCTITLE */
@ -653,15 +647,11 @@ void GetDescriptor(int parent_pipe)
close(parent_pipe);
exit(1);
}
#ifndef THREADED
close(0);
close(1);
dup2(csd,0);
dup2(csd,1);
#endif /* THREADED */
}
#endif /* NO_PASS */
char* GetRemoteLogName (SERVER_SOCK_ADDR *sa_server)
{
@ -678,17 +668,15 @@ char* GetRemoteLogName (SERVER_SOCK_ADDR *sa_server)
return NULL;
}
#ifndef NO_PASS
int make_child(int argc, char **argv, int childnum,
SERVER_SOCK_ADDR *sa_server)
{
int fd[2];
int pid;
#ifdef SETPROCTITLE
char namestr[30];
#endif /* SETPROCTITLE */
pid = 1;
servernum = childnum;
#ifndef NEED_SPIPE
if (socketpair(AF_UNIX, SOCK_STREAM, 0, fd) == -1) {
#else
@ -710,21 +698,20 @@ int make_child(int argc, char **argv, int childnum,
}
if (!pid) {
/* Child */
close(Children[childnum].childfd);
#ifdef BSD
signal(SIGCHLD,(void (*)())ign);
#else
signal(SIGCHLD,SIG_IGN);
#endif /* BSD */
#ifdef SETPROCTITLE
sprintf(namestr,"child %d",childnum);
#ifdef SETPROCTITLE
/* inststr(argv,argc,namestr); */
setproctitle(namestr);
#endif /* SETPROCTITLE */
Child = 1;
child_main(Children[childnum].parentfd, sa_server);
} else {
/* Parent */
close(Children[childnum].parentfd);
}
}
@ -740,14 +727,14 @@ void initialize_socket(SERVER_SOCK_ADDR *sa_server,
int keepalive_value = 1;
if ((mainSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP)) == -1) {
fprintf(stderr,"HTTPd: could not get socket\n");
fprintf(stderr,"httpd: could not get socket\n");
perror("socket");
exit(1);
}
if((setsockopt(mainSocket,SOL_SOCKET,SO_REUSEADDR,(char *)&one,
sizeof(one))) == -1) {
fprintf(stderr,"HTTPd: could not set socket option SO_REUSEADDR\n");
fprintf(stderr,"httpd: could not set socket option SO_REUSEADDR\n");
perror("setsockopt");
exit(1);
}
@ -759,7 +746,7 @@ void initialize_socket(SERVER_SOCK_ADDR *sa_server,
if((setsockopt(mainSocket,SOL_SOCKET,SO_KEEPALIVE,(void *)&keepalive_value,
sizeof(keepalive_value))) == -1) {
fprintf(stderr,"HTTPd: could not set socket option SO_KEEPALIVE\n");
fprintf(stderr,"httpd: could not set socket option SO_KEEPALIVE\n");
perror("setsockopt");
exit(1);
}
@ -774,7 +761,7 @@ void initialize_socket(SERVER_SOCK_ADDR *sa_server,
fprintf(stderr,"HTTPd: cound not bind to address %s port %d\n",
inet_ntoa(gConfiguration->address_info),port);
else
fprintf(stderr,"HTTPd: could not bind to port %d\n",port);
fprintf(stderr,"httpd: could not bind to port %d\n",port);
perror("bind");
exit(1);
}
@ -794,13 +781,12 @@ void standalone_main(int argc, char **argv)
static SERVER_SOCK_ADDR sa_server;
static CLIENT_SOCK_ADDR sa_client;
static int one = 1;
static int pid = 0;
#ifdef TACHOMETER
static int Requests[MAX_TACHOMETER];
static time_t Request_time = 0L;
static int i;
static char Request_title[64];
#endif /* TACHOMETER */
#endif
@ -808,8 +794,9 @@ void standalone_main(int argc, char **argv)
process to ensure proper time zone settings */
tzset();
if (debug_mode == FALSE)
detach();
#if !defined(PROFILE) && !defined(QUANTIFY)
detach();
#endif /* PROFILE */
sprintf(error_msg,"HTTPd: Starting as %s",argv[0]);
x = 1;
@ -829,7 +816,6 @@ void standalone_main(int argc, char **argv)
#endif /* SETPROCTITLE */
while(!Exit) {
/* current_process_size("Starting"); */
initialize_socket(&sa_server,&sa_client);
set_signals();
speed_hack_libs();
@ -837,11 +823,9 @@ void standalone_main(int argc, char **argv)
#ifndef NO_PASS
num_children = 0;
if (debug_mode == FALSE) {
Children = (ChildInfo *) malloc(sizeof(ChildInfo)*(max_servers+1));
while (num_children < start_servers) {
make_child(argc, argv, num_children++, &sa_server);
}
Children = (ChildInfo *) malloc(sizeof(ChildInfo)*(max_servers+1));
while (num_children < start_servers) {
make_child(argc, argv, num_children++, &sa_server);
}
#endif /* NO_PASS */
@ -951,13 +935,10 @@ void standalone_main(int argc, char **argv)
} /* if (make_child) else ... */
} else {
/* Already have as many children as compiled for.*/
if (debug_mode == FALSE)
pid = fork();
else
Exit = TRUE;
if (!pid) {
if (!fork()) {
/* inststr(argv, argc, "httpd-alone"); */
child_alone(csd,&sa_server,&sa_client);
}
} /* fork */
} /* if (num_children < max_servers) ... else ... */
} else {
Children[free_child].busy = 1;
@ -971,11 +952,8 @@ void standalone_main(int argc, char **argv)
} else
#endif /* NO_PASS */
{
if (debug_mode == FALSE)
pid = fork();
else
Exit = TRUE;
if (!pid) {
if (!fork()) {
/* inststr(argv, argc, "httpd-alone"); */
child_alone(csd,&sa_server,&sa_client);
} /* fork */
close(csd);
@ -1001,7 +979,7 @@ void standalone_main(int argc, char **argv)
avg1, avg5/5, avg30/30);
setproctitle(Request_title);
}
#endif /* TACHOMETER */
#endif
} /* If good accept */
} /* if mainSocket ready for read */
} /* if select */
@ -1027,7 +1005,6 @@ void standalone_main(int argc, char **argv)
free(Children);
#endif /* NO_PASS */
free_host_conf();
freeAllStrings(STR_HUP);
read_config(error_log);
set_group_privs();
log_error("HTTPd: successful restart",error_log);
@ -1038,28 +1015,10 @@ void standalone_main(int argc, char **argv)
} /* while (!Exit) */
} /* standalone_main */
void default_banner(FILE* fout)
{
fprintf(fout,"NCSA HTTPd %s\n",SERVER_SOURCE);
fprintf(fout,"Licensed material. Portions of this work are\n");
fprintf(fout,"Copyright (C) 1995-1996 Board of Trustees of the University of Illinois\n");
fprintf(fout,"Copyright (C) 1995-1996 The Apache Group\n");
#ifdef DIGEST_AUTH
fprintf(fout,"Copyright (C) 1989-1993 RSA Data Security, Inc.\n");
#endif /* DIGEST_AUTH */
#ifdef DIGEST_AUTH
fprintf(fout,"Copyright (C) 1993-1994 Carnegie Mellon University\n");
fprintf(fout,"Copyright (C) 1991 Bell Communications Research, Inc. (Bellcore)\n");
fprintf(fout,"Copyright (C) 1994 Spyglass, Inc.\n");
#endif /* DIGEST_AUTH */
fflush(fout);
}
void usage(char *bin)
{
default_banner(stderr);
fprintf(stderr,"\nDocumentation online at http://hoohoo.ncsa.uiuc.edu/\n\n");
fprintf(stderr,"NCSA HTTPd %s\n",SERVER_SOURCE);
fprintf(stderr,"Documentation online at http://hoohoo.ncsa.uiuc.edu/\n\n");
fprintf(stderr,"Compiled in Options:\n");
#ifdef SETPROCTITLE
@ -1083,9 +1042,6 @@ void usage(char *bin)
#ifdef DIGEST_AUTH
fprintf(stderr,"\tDIGEST_AUTH\n");
#endif /* DIGEST_AUTH */
#ifdef CONTENT_MD5
fprintf(stderr,"\tCONTENT_MD5\n");
#endif /* CONTENT_MD5 */
#ifdef KRB4
fprintf(stderr,"\tKRB4\n");
#endif /* KRB4 */
@ -1097,13 +1053,12 @@ void usage(char *bin)
fprintf(stderr,"\n");
#ifdef HAVE_KERBEROS
fprintf(stderr,"Usage: %s [-d directory] [-f file] [-k file] [-K file] [-vX]\n",bin);
fprintf(stderr,"Usage: %s [-d directory] [-f file] [-k file] [-K file] [-v]\n",bin);
#else
fprintf(stderr,"Usage: %s [-d directory] [-f file] [-vX]\n",bin);
fprintf(stderr,"Usage: %s [-d directory] [-f file] [-v]\n",bin);
#endif /* HAVE_KERBEROS */
fprintf(stderr,"-d directory\t : specify an alternate initial ServerRoot\n");
fprintf(stderr,"-f file\t\t : specify an alternate ServerConfigFile\n");
fprintf(stderr,"-X\t\t : Answer one request for debugging, don't fork\n");
fprintf(stderr,"-v\t\t : version information (this screen)\n");
#ifdef KRB4
fprintf(stderr,"-k file\t\t : specify an alternate Kerberos V4 svrtab file\n");
@ -1121,7 +1076,6 @@ int main (int argc, char **argv, char **envp)
{
int c;
/* FIRST */
#ifdef RLIMIT_NOFILE
/* If defined (not user defined, but in sys/resource.h), this will attempt
* to set the max file descriptors per process as high as allowed under
@ -1148,20 +1102,16 @@ int main (int argc, char **argv, char **envp)
moncontrol(0);
#endif /* PROFILE */
/* First things first */
strcpy(server_root,HTTPD_ROOT);
make_full_path(server_root,SERVER_CONFIG_FILE,server_confname);
#ifdef HAVE_KERBEROS
while((c = getopt(argc,argv,"d:f:vk:K:Xs")) != -1) {
while((c = getopt(argc,argv,"d:f:vk:K:")) != -1) {
#else
while((c = getopt(argc,argv,"d:f:vXs")) != -1) {
while((c = getopt(argc,argv,"d:f:v")) != -1) {
#endif /* HAVE_KERBEROS */
switch(c) {
case 'X':
debug_mode = TRUE;
printf("Debug On\n");
break;
case 'd':
strcpy(server_root,optarg);
make_full_path(server_root,SERVER_CONFIG_FILE,server_confname);
@ -1196,27 +1146,17 @@ int main (int argc, char **argv, char **envp)
break;
#endif /* KRB5 */
#endif /* HAVE_KERBEROS */
case '?':
usage(argv[0]);
}
}
/* Global Initialization:
* Currently for File Descriptor Table and allocater
*/
InitFdTable();
initialize_allocate();
read_config(stderr);
/* Passed arguments stage, dump baloney */
#ifndef SUPPRESS_BANNER
if (standalone) default_banner(stdout);
#endif /* SUPPRESS_BANNER */
#ifdef SETPROCTITLE
initproctitle(process_name, argc, argv, envp);
#endif /* SETPROCTITLE */
set_group_privs();
get_local_host();
@ -1234,15 +1174,14 @@ int main (int argc, char **argv, char **envp)
group_id = getgid();
reqInfo->connection_socket = 0;
reqInfo->in = 0;
reqInfo->out = stdout;
port = get_portnum(reqInfo,fileno(reqInfo->out));
if(do_rfc931)
remote_logname = get_remote_logname(reqInfo->out);
RequestMain(reqInfo);
rflush(reqInfo);
get_request(reqInfo);
fflush(reqInfo->out);
}
close_all_logs();

View File

@ -10,7 +10,7 @@
*
************************************************************************
*
* httpd.h,v 1.97 1996/03/27 20:44:19 blong Exp
* httpd.h,v 1.91 1995/11/28 09:02:14 blong Exp
*
************************************************************************
*
@ -25,28 +25,16 @@
#define _HTTPD_H_
#include <setjmp.h>
#include "http_request.h"
typedef struct _ChildInfo {
int parentfd;
int childfd;
int pid;
int busy;
#ifdef NOT_READY
int status;
KeepAliveData keep_alive; /* Child's keep alive info */
int csd; /* Current Socket Descriptor */
JMP_BUF restart_child; /* Return buffer for siglongjmp */
per_request *gCurrentRequest; /* Current Request of Child */
#endif /* NOT_READY */
} ChildInfo;
#ifndef NOT_READY
extern KeepAliveData keep_alive; /* global keep alive info */
extern JMP_BUF jmpbuffer; /* Return buffer for siglongjmp */
extern int csd; /* Current Socket Descriptor */
#endif /* NOT_READY */
extern JMP_BUF jmpbuffer; /* Return buffer for siglongjmp */
/* function prototypes */

View File

@ -6,8 +6,6 @@ httpd \- NCSA HTTPd (hypertext transfer protocol daemon)
[
.B \-v
] [
.B \-X
] [
.BI \-d " serverroot"
] [
.BI \-f " config"
@ -34,10 +32,6 @@ the ServerRoot. The default is \fBconf/httpd.conf\fP.
.B \-v
Print the version of httpd, including compiled defaults and
command line options.
.TP
.B \-X
Execute in single request debugging mode, with no fork, no detach.
Useful for profiling and debugging.
.SH FILES
.PD 0
.B /usr/local/etc/httpd/conf/httpd.conf

View File

@ -1,4 +1,3 @@
/* zippy.c
*
* Print a quotation from Zippy the Pinhead.

View File

@ -10,7 +10,7 @@
*
************************************************************************
*
* $Id: imagemap.c,v 1.16 1996/04/05 21:14:15 blong Exp $
* imagemap.c,v 1.7 1995/11/28 09:02:16 blong Exp
*
************************************************************************
*
@ -30,59 +30,34 @@
#include <sys/stat.h>
#include <ctype.h>
#include "constants.h"
#include "fdwrap.h"
#include "allocate.h"
#include "http_log.h"
#include "http_config.h"
#include "http_request.h"
#include "fdwrap.h"
#include "imagemap.h"
#include "cgi.h"
#ifdef IMAGEMAP_SUPPORT
/* Error messages for imagemaps */
extern int port;
#define IMAP_ERR_INCORRECT_ARGS 1
#define IMAP_ERR_INCORRECT_COORDS 2
#define IMAP_ERR_CERN_MISSING_RIGHT_PAREN 3
char *imagemap_errors[] = {
"IMAP: Imagemap request requires two coordinates as arguments",
"IMAP: Imagemap args missing y value",
"IMAP: Imagemap args missing right paren"};
/* NCSA Imagemap files use: method URL coord1 coord2
* CERN Imagemap files use: method (coord1) (coord2) URL
* This version of imagemap will probably work with either in the same file,
* as long as a full line is in one format or the other.
*/
int send_imagemap(per_request* reqInfo, struct stat* fi, char allow_options)
int send_imagemap(per_request* reqInfo, struct stat* fi, char* path_args,
char allow_options)
{
char *input, *def, *szPoint, *url, *type;
char input[MAX_STRING_LEN], def[MAX_STRING_LEN];
char szPoint[MAX_STRING_LEN];
double testpoint[2], pointarray[MAXVERTS][2];
int i, j, k;
int error_num = 0;
FILE *fp;
char *t;
double dist, mindist = -1;
int sawpoint = 0;
int sawparen = 0;
int Found = 0;
input = newString(HUGE_STRING_LEN,STR_TMP);
def = newString(MAX_STRING_LEN,STR_TMP);
szPoint = newString(MAX_STRING_LEN,STR_TMP);
type = newString(MAX_STRING_LEN,STR_TMP);
url = newString(MAX_STRING_LEN,STR_TMP);
def[0] = '\0';
strcpy(szPoint, reqInfo->args);
if(!(t = strchr(szPoint,','))) {
error_num = IMAP_ERR_INCORRECT_ARGS;
goto imagemap_error;
log_reason(reqInfo,
"Your client doesn't support image mapping properly.",
reqInfo->filename);
die(reqInfo, SC_BAD_IMAGEMAP, reqInfo->url);
}
*t++ = '\0';
@ -92,114 +67,70 @@ int send_imagemap(per_request* reqInfo, struct stat* fi, char allow_options)
if(!(fp=FOpen(reqInfo->filename,"r"))){
log_reason(reqInfo, "File permissions deny server access",
reqInfo->filename);
freeString(input);
freeString(def);
freeString(szPoint);
freeString(url);
freeString(type);
die(reqInfo, SC_FORBIDDEN, reqInfo->url);
}
while (!Found && fgets(input,HUGE_STRING_LEN,fp)) {
while (fgets(input,MAX_STRING_LEN,fp)) {
char type[MAX_STRING_LEN];
char url[MAX_STRING_LEN];
char num[10];
/* Skip lines with # as comments and blank lines */
if((input[0] == '#') || (!input[0]))
continue;
type[0] = '\0';url[0] = '\0';
/* Copy the shape keyword into type */
for(i=0;!isspace(input[i]) && (input[i]);i++)
for(i=0;isname(input[i]) && (input[i]);i++)
type[i] = input[i];
type[i] = '\0';
/* Forward to next word */
while(isspace(input[i])) ++i;
/* If no coordinates, must be url for default, or NCSA format */
if (input[i] != '(') {
for(j=0;input[i] && !isspace(input[i]);++i,++j)
for(j=0;input[i] && isname(input[i]);++i,++j)
url[j] = input[i];
url[j] = '\0';
}
url[j] = '\0';
/* Handle default keyword */
if(!strcmp(type,"default") && !sawpoint) {
strcpy(def,url);
continue;
}
/* Looking for Coordinates */
k=0;
while (input[i]) {
/* Move over spaces and commas */
while (isspace(input[i]) || input[i] == ',')
i++;
/* Under CERN, coordinates are in parenthesis */
if (input[i] == '(') {
sawparen = 1;
while (isspace(input[++i]));
}
/* Copy digits into num array */
j = 0;
while (isdigit(input[i]))
num[j++] = input[i++];
num[j] = '\0';
if (!j) break;
pointarray[k][X] = (double) atoi(num);
/* Skip to next digit */
while (isspace(input[i]) || input[i] == ',')
i++;
/* Copy other number into num */
j = 0;
while (isdigit(input[i]))
num[j++] = input[i++];
num[j] = '\0';
if (!j && !sawparen && k > 0) {
pointarray[k++][Y] = -127;
break;
}
if (j)
if (num[0] != '\0')
pointarray[k][X] = (double) atoi(num);
else
break;
while (isspace(input[i]) || input[i] == ',')
i++;
j = 0;
while (isdigit(input[i]))
num[j++] = input[i++];
num[j] = '\0';
if (num[0] != '\0')
pointarray[k++][Y] = (double) atoi(num);
else {
error_num = IMAP_ERR_INCORRECT_COORDS;
FClose(fp);
goto imagemap_error;
FClose(fp);
log_reason(reqInfo, "Imagemap args missing y value.",
reqInfo->filename);
die(reqInfo, SC_BAD_IMAGEMAP, reqInfo->url);
}
/* End of parenthesis for coordinates under CERN */
if (input[i] == ')') {
i++;
sawparen = 0;
} else if (sawparen) {
error_num = IMAP_ERR_CERN_MISSING_RIGHT_PAREN;
FClose(fp);
goto imagemap_error;
}
}
if (url[0] == '\0' && input[i]) {
while (isspace(input[i])) i++;
for (j = 0; input[i] && !isspace(input[i]); ++i, ++j)
url[j] = input[i];
url[j] = '\0';
}
pointarray[k][X] = -1;
if(!strncmp(type, "poly", 4))
if(!strcmp(type,"poly"))
if(pointinpoly(testpoint,pointarray))
Found = 1;
if(!strncmp(type, "circ", 4))
sendmesg(reqInfo, url, fp);
if(!strcmp(type,"circle"))
if(pointincircle(testpoint,pointarray))
Found = 1;
if(!strncmp(type, "rect", 4))
sendmesg(reqInfo, url, fp);
if(!strcmp(type,"rect"))
if(pointinrect(testpoint,pointarray))
Found = 1;
sendmesg(reqInfo, url, fp);
if(!strcmp(type,"point")) {
/* Don't need to take square root. */
dist = ((testpoint[X] - pointarray[0][X])
@ -214,69 +145,30 @@ int send_imagemap(per_request* reqInfo, struct stat* fi, char allow_options)
sawpoint++;
}
}
if(Found) {
sendmesg(reqInfo, url, fp);
goto imagemap_ok;
} else {
if(def[0]) {
if(def[0])
sendmesg(reqInfo, def, fp);
goto imagemap_ok;
}
}
FClose(fp);
/* No reason to log each of these as an "error" */
/* log_reason(reqInfo, "No default defined in imagemap.",
reqInfo->filename); */
FClose(fp);
freeString(input);
freeString(def);
freeString(szPoint);
freeString(url);
freeString(type);
die(reqInfo, SC_NO_CONTENT, reqInfo->url);
return 0;
imagemap_ok:
FClose(fp);
freeString(input);
freeString(def);
freeString(szPoint);
freeString(url);
freeString(type);
return 1;
imagemap_error:
freeString(input);
freeString(def);
freeString(szPoint);
freeString(url);
freeString(type);
log_reason(reqInfo,imagemap_errors[error_num-1],reqInfo->filename);
die(reqInfo,SC_BAD_IMAGEMAP,imagemap_errors[error_num-1]);
return -1;
}
void sendmesg(per_request* reqInfo, char *url, FILE *fp)
void sendmesg(per_request* reqInfo, char *url, FILE* fp)
{
char *loc, *furl;
loc = newString(HUGE_STRING_LEN,STR_REQ);
furl = newString(HUGE_STRING_LEN,STR_REQ);
char loc[HUGE_STRING_LEN];
FClose(fp);
if (!strchr(url, ':')) { /*** If not a full URL ***/
if (url[0] != '/') { /*** Relative URL ***/
char *last = strrchr(reqInfo->url,'/');
int x = 0, y = 0;
while (((reqInfo->url+x) <= last) && (y < HUGE_STRING_LEN)) {
loc[y] = *(reqInfo->url+x);
x++; y++;
}
loc[y] = '\0';
} else {
strncpy(loc,url,HUGE_STRING_LEN);
}
construct_url(furl, reqInfo->hostInfo, loc);
die(reqInfo,SC_REDIRECT_TEMP,furl);
if (port == 80) /*** It is a virtual URL ***/
sprintf(loc, "http://%s", reqInfo->hostInfo->server_hostname);
else /* only add port if it's not the default */
sprintf(loc, "http://%s:%d",reqInfo->hostInfo->server_hostname,
port);
strcat(loc,url);
die(reqInfo,SC_REDIRECT_TEMP,loc);
} else {
die(reqInfo,SC_REDIRECT_TEMP,url);
}
@ -292,16 +184,11 @@ int pointincircle(double point[2], double coords[MAXVERTS][2])
{
int radius1, radius2;
/* If given a radius instead of a coordinate */
if (coords[1][Y] == -127)
radius1 = coords[1][X];
else
radius1 = ((coords[0][Y] - coords[1][Y]) *
(coords[0][Y] - coords[1][Y])) +
((coords[0][X] - coords[1][X]) *
(coords[0][X] - coords[1][X]));
radius1 = ((coords[0][Y] - coords[1][Y]) * (coords[0][Y] -
coords[1][Y])) + ((coords[0][X] - coords[1][X]) * (coords[0][X] -
coords[1][X]));
radius2 = ((coords[0][Y] - point[Y]) * (coords[0][Y] - point[Y])) +
((coords[0][X] - point[X]) * (coords[0][X] - point[X]));
((coords[0][X] - point[X]) * (coords[0][X] - point[X]));
return (radius2 <= radius1);
}
@ -371,4 +258,9 @@ int pointinpoly(double point[2], double pgon[MAXVERTS][2])
return (inside_flag);
}
int isname(char c)
{
return (!isspace(c));
}
#endif /* IMAGEMAP_SUPPORT */

View File

@ -10,7 +10,7 @@
*
************************************************************************
*
* imagemap.h,v 1.6 1996/04/05 18:55:18 blong Exp
* imagemap.h,v 1.3 1995/10/06 19:15:56 blong Exp
*
************************************************************************
*
@ -22,13 +22,11 @@
#ifndef _IMAGEMAP_H
#define _IMAGEMAP_H 1
#define MAXLINE 500
#define MAXVERTS 100
#define X 0
#define Y 1
#define IMAP_NCSA 1
#define IMAP_CERN 2
void sendmesg(per_request* reqInfo, char *url, FILE* fp);
int pointinpoly(double point[2], double pgon[MAXVERTS][2]);
int pointincircle(double point[2], double coords[MAXVERTS][2]);
@ -36,6 +34,7 @@ int pointinrect(double point[2], double coords[MAXVERTS][2]);
int isname(char);
int send_imagemap(per_request* reqInfo, struct stat* fi, char allow_options);
int send_imagemap(per_request* reqInfo, struct stat* fi, char* path_args,
char allow_options);
#endif /* _IMAGE_MAP_H */

127
src/md5.c
View File

@ -1,46 +1,13 @@
/************************************************************************
* NCSA HTTPd Server
* Software Development Group
* National Center for Supercomputing Applications
* University of Illinois at Urbana-Champaign
* 605 E. Springfield, Champaign, IL 61820
* httpd@ncsa.uiuc.edu
*
* Copyright (C) 1995, Board of Trustees of the University of Illinois
*
************************************************************************
*
* md5.c,v 1.6 1996/03/06 23:21:21 blong Exp
*
************************************************************************
*
* md5.c: NCSA HTTPd code which uses the md5c.c RSA Code
*
* Original Code Copyright (C) 1994, Jeff Hostetler, Spyglass, Inc.
* Portions of Content-MD5 code Copyright (C) 1993, 1994 by Carnegie Mellon
* University (see Copyright below).
* Portions of Content-MD5 code Copyright (C) 1991 Bell Communications
* Research, Inc. (Bellcore) (see Copyright below).
* Portions extracted from mpack, John G. Myers - jgm+@cmu.edu
* Content-MD5 Code contributed by Martin Hamilton (martin@net.lut.ac.uk)
*
*/
/* md5.c --Module Interface to MD5. */
/* Jeff Hostetler, Spyglass, Inc., 1994. */
#include "config.h"
#include "portability.h"
#include "constants.h"
#include <stdio.h>
#include <string.h>
#ifndef SHTTP
#include "global.h"
#endif /* SHTTP */
#include "md5.h"
void md5 (unsigned char *string, char result[33])
@ -64,97 +31,3 @@ void md5 (unsigned char *string, char result[33])
return;
}
#ifdef CONTENT_MD5
/* these portions extracted from mpack, John G. Myers - jgm+@cmu.edu */
/* (C) Copyright 1993,1994 by Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify, distribute, and sell this software
* and its documentation for any purpose is hereby granted without
* fee, provided that the above copyright notice appear in all copies
* and that both that copyright notice and this permission notice
* appear in supporting documentation, and that the name of Carnegie
* Mellon University not be used in advertising or publicity
* pertaining to distribution of the software without specific,
* written prior permission. Carnegie Mellon University makes no
* representations about the suitability of this software for any
* purpose. It is provided "as is" without express or implied
* warranty.
*
* CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*/
/*
* Copyright (c) 1991 Bell Communications Research, Inc. (Bellcore)
*
* Permission to use, copy, modify, and distribute this material
* for any purpose and without fee is hereby granted, provided
* that the above copyright notice and this permission notice
* appear in all copies, and that the name of Bellcore not be
* used in advertising or publicity pertaining to this
* material without the specific, prior written permission
* of an authorized representative of Bellcore. BELLCORE
* MAKES NO REPRESENTATIONS ABOUT THE ACCURACY OR SUITABILITY
* OF THIS MATERIAL FOR ANY PURPOSE. IT IS PROVIDED "AS IS",
* WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.
*/
static char basis_64[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
char *md5contextTo64(context)
MD5_CTX *context;
{
unsigned char digest[18];
char *encodedDigest;
int i;
char *p;
encodedDigest = (char *)malloc(25 * sizeof(char));
MD5Final(digest, context);
digest[sizeof(digest)-1] = digest[sizeof(digest)-2] = 0;
p = encodedDigest;
for (i=0; i < sizeof(digest); i+=3) {
*p++ = basis_64[digest[i]>>2];
*p++ = basis_64[((digest[i] & 0x3)<<4) | ((digest[i+1] & 0xF0)>>4)];
*p++ = basis_64[((digest[i+1] & 0xF)<<2) | ((digest[i+2] & 0xC0)>>6)];+ *p++ = basis_64[digest[i+2] & 0x3F];
}
*p-- = '\0';
*p-- = '=';
*p-- = '=';
return encodedDigest;
}
char *md5digest(infile)
FILE *infile;
{
MD5_CTX context;
char buf[1000];
long length = 0;
int nbytes;
MD5Init(&context);
while (nbytes = fread(buf, 1, sizeof(buf), infile)) {
length += nbytes;
MD5Update(&context, buf, nbytes);
}
rewind(infile);
return md5contextTo64(&context);
}
#endif /* CONTENT_MD5 */

View File

@ -10,7 +10,7 @@
*
************************************************************************
*
* portability.h,v 1.32 1996/03/27 20:44:29 blong Exp
* portability.h,v 1.29 1995/11/28 09:02:18 blong Exp
*
************************************************************************
*
@ -37,6 +37,7 @@ char *crypt(char *pw, char *salt);
#define FD_BSD
#define MIX_SOCKADDR
#define bzero(a,b) memset(a,0,b)
#define getwd(d) getcwd(d,MAX_STRING_LEN)
#define JMP_BUF sigjmp_buf
#define DIR_FILENO(p) ((p)->dd_fd)
#define NEED_CRYPT_H
@ -57,6 +58,7 @@ char *crypt(char *pw, char *salt);
#ifndef _HPUX_SOURCE
# define _HPUX_SOURCE
#endif /* _HPUX_SOURCE */
#define getwd(d) getcwd(d,MAX_STRING_LEN)
#define JMP_BUF sigjmp_buf
#define DIR_FILENO(p) ((p)->dd_fd)
@ -69,7 +71,6 @@ char *crypt(char *pw, char *salt);
#define JMP_BUF sigjmp_buf
#define DIR_FILENO(p) ((p)->dd_fd)
#define HEAD_CRYPT
#define MISSING_HEADERS
#elif defined(AIX4)
#undef BSD
@ -197,10 +198,6 @@ typedef int pid_t;
typedef int mode_t;
#define JMP_BUF jmp_buf
#define DIR_FILENO(p) ((p)->dd_fd)
/* The following might be required for some versions of NeXTStep on
* some platforms.
*/
/* #include <netinet/in_systm.h> */
#elif defined(LINUX)
@ -218,11 +215,11 @@ typedef int mode_t;
#undef NEED_STRDUP
#define MIX_SOCKADDR
/* This are defined, in linux/time.h included from sys/time.h, as of 1.2.8 */
#ifdef NEVER_DEFINED
#ifdef 0
# define FD_SET __FD_SET
# define FD_ZERO __FD_ZERO
# define FD_ISSET __FD_ISSET
#endif /* NEVER_DEFINED */
#endif /* 0 */
#define JMP_BUF sigjmp_buf
#elif defined(NETBSD) || defined(__NetBSD__)
@ -255,6 +252,7 @@ typedef int mode_t;
#undef NO_SETSID
#define NEED_INITGROUPS
#define CALL_TZSET
#define getwd(d) getcwd(d,MAX_STRING_LEN)
#define JMP_BUF sigjmp_buf
#define MIX_SOCKADDR
@ -262,6 +260,7 @@ typedef int mode_t;
#define BSD
#define FD_BSD
#define NEED_STRDUP
#define getwd(d) getcwd(d,MAX_STRING_LEN)
#define NEED_SYS_MALLOC_H
#include <sys/types.h>
#define JMP_BUF sigjmp_buf
@ -295,6 +294,7 @@ typedef int mode_t;
#define NEED_STRNCASECMP
#define bzero(a,b) memset(a,0,b)
#define JMP_BUF sigjmp_buf
#define getwd(d) getcwd(d,MAX_STRING_LEN)
#define S_ISLNK(m) (((m)&(S_IFMT)) == (S_IFLNK))
#elif defined(__bsdi__)
@ -350,6 +350,7 @@ typedef int mode_t;
#endif
#define lstat stat
#define strftime(buf,bufsize,fmt,tm) ascftime(buf,fmt,tm)
#define getwd(d) getcwd(d,MAX_STRING_LEN)
#define readlink(a,b,c) -1
typedef int uid_t;
typedef int gid_t;
@ -411,9 +412,6 @@ extern char *getenv();
# define DIR_TYPE direct
#endif /* !defined(NeXT) && !defined(CONVEXOS) && !defined(APOLLO) */
#if !defined(HAVE_STDARG) && !defined(HAVE_VARARGS)
# define HAVE_STDARG
#endif /* !defined(HAVE_STDARG) && !defined(HAVE_VARARGS) */
#ifndef JMP_BUF
# define JMP_BUF sigjmp_buf
@ -437,34 +435,4 @@ typedef struct sockaddr CLIENT_SOCK_ADDR;
typedef struct sockaddr_in CLIENT_SOCK_ADDR;
#endif /* MIX_SOCKADDR */
#ifdef AIX_BROKEN_HEADERS
/* string.h */
int strcasecmp(const char *, const char *);
int strncasecmp(const char *, const char *, size_t);
#include <sys/socket.h>
int accept(int, struct sockaddr *, int *);
int bind(int, struct sockaddr *, int);
int connect(int, struct sockaddr *, int);
int getpeername(int, struct sockaddr *, int *);
int getsockname(int, struct sockaddr *, int *);
int getsockopt(int, int, int, char *, int *);
int listen(int, int);
int recv(int, char *, int, int);
int recvfrom(int, char *, int, int, struct sockaddr *, int *);
int send(int, const char *, int, int);
int sendto(int, const char *, int, int, struct sockaddr *, int);
int setsockopt(int, int, int, const char *, int);
int socket(int, int, int);
int recvmsg(int, struct msghdr *, int);
int sendmsg(int, struct msghdr *, int);
int shutdown(int, int);
int socketpair(int, int, int, int *);
int killpg(int ProcessGroup, int Signal);
int initgroups(char* User, int BaseGID);
void bzero(char* String, int Length);
int gethostname(char* Name, int NameLength);
char *crypt(char* PW, char *Salt);
#endif /* AIX_BROKEN_HEADERS */
#endif /* _PORTABILITY_H_ */

View File

@ -10,12 +10,68 @@
*
************************************************************************
*
* util.c,v 1.115 1996/03/27 20:44:30 blong Exp
* util.c,v 1.106 1995/11/28 09:02:21 blong Exp
*
************************************************************************
*
* util.c: string utility things, and other utilities
*
* 03-23-93 Rob McCool
* Original code up to version 1.3 from Rob McCool
*
* 02-16-95 cvarela
* Fixed stack hole in strsubfirst
*
* 03-06-95 blong
* Added inststr from bdflush-1.5 for Linux to set the name of
* the running processes
*
* 03-10-95 blong
* Added buffered getline for all but POST requests as suggested by
* Robert S. Thau (rst@ai.mit.edu)
*
* 03-20-95 blong & cvarela
* Fixed make_env_str so that it doesn't modify the pointers
*
* 04-03-95 blong
* May have fixed problems (esp. under Solaris 2.3) with playing
* with library memory in get_remote_name
*
* 04-13-95 guillory
* added strncpy_dir that limits the length of a directory copy
* also added strncpy for same reason
*
* 04-29-95 blong
* added patch by Kevin Steves (stevesk@mayfield.hp.com) for inststr
* under HPUX which uses the pstat command
*
* 06-01-95 blong
* added patch by Vince Skahan (vds7789@aw101.iasl.ca.boeing.com)
* to fix Apollo DomainOS timezone handling
*
* 09-02-95 blong
* added patch by Gioacchino La Vecchia (gio@di.unipi.it) to make
* full host name in get_local_host() to keep from needing to use
* the ServerName configuration directive
*
* 09-11-95 mshapiro
* replaced atoi() in uname2id() and gname2id with scan_long() to
* convert user_id and group_id from #n to uid_t, gid_t.
* If the config file had contained #non-digit then atoi() would
* have returned 0 and the server would have been run as root.
*
* 09-12-95 blong
* removed get_local_host() patch, because its the wrong thing to
* do. Use the ServerName directive, thats what its there for.
*
* 11-02-95 mshapiro
* recoded no2slash() to perform the following replacecments
* sequences of / (//, ///, etc) with a single /
* all occurenences of /./ with a single /
* remove ./ at the beginning of the name
* replace /. at the end of the name with a single /
*
* added a call to no2slash() at the beginning of getparents()
*
*/
@ -55,7 +111,6 @@
# include <sys/time.h>
#endif
#include "constants.h"
#include "allocate.h"
#include "util.h"
#include "http_request.h"
#include "http_config.h"
@ -431,7 +486,7 @@ void no2slash(char *name)
while (s[0] == '/' && s[1] == '/')
{
p = s;
while ((p[0] = p[1]))
while (p[0] = p[1])
p++;
}
@ -441,7 +496,7 @@ void no2slash(char *name)
while (s[0] =='/' && s[1] == '.' && s[2] == '/')
{
p = s;
while ((p[0] = p[2]))
while (p[0] = p[2])
p++;
}
@ -449,7 +504,7 @@ void no2slash(char *name)
if (name[0] == '.' && name[1] == '/')
{
p = name;
while ((p[0] = p[2]))
while (p[0] = p[2])
p++;
}
@ -547,8 +602,7 @@ void getline_timed_out(int sig)
{
char errstr[MAX_STRING_LEN];
sprintf(errstr,"timed out waiting for %s",
gCurrentRequest->remote_name ? gCurrentRequest->remote_name : "-");
sprintf(errstr,"timed out waiting for %s", gCurrentRequest->remote_name);
log_error(errstr,gCurrentRequest->hostInfo->error_log);
if (!standalone) {
fclose(stdin);
@ -563,115 +617,60 @@ void getline_timed_out(int sig)
}
}
sock_buf *new_sock_buf(per_request *reqInfo, int sd)
{
sock_buf *tmp;
if (!(tmp = (sock_buf *)malloc(sizeof(sock_buf)))) {
die(reqInfo,SC_NO_MEMORY,"new_sock_buf");
}
tmp->status = SB_NEW;
tmp->sd = sd;
return tmp;
}
/* Modified by Trung Dung (tdung@OpenMarket.com) to handle RFC822
* line wraps
* This routine is currently not thread safe.
* This routine may be thread safe. (blong 3/13/96)
*/
int getline(sock_buf *sb, char *s, int n, int options, unsigned int timeout)
int getline(int sd, char *s, int n, int reset, unsigned int timeout)
{
char *endp = s + n - 1;
int have_alarmed = 0;
/* static int buf_posn, buf_good; */
static int buf_posn, buf_good;
int buf_start;
/* static char buffer[HUGE_STRING_LEN]; */
static char buffer[HUGE_STRING_LEN];
int c;
int ret;
int size;
buf_start = sb->buf_posn;
if ((options & G_RESET_BUF) || (sb->status == SB_NEW)) {
buf_start = sb->buf_posn = sb->buf_good = 0;
sb->buffer[0] = '\0';
buf_start = buf_posn;
if (reset == 1) {
buf_start = buf_posn = buf_good = 0;
buffer[0] = '\0';
}
else if (options & G_FLUSH) {
while (sb->buf_posn < sb->buf_good)
*s++ = sb->buffer[(sb->buf_posn)++];
else if (reset == 2) {
while (buf_posn < buf_good)
*s++ = buffer[buf_posn++];
*s = '\0';
sb->status = SB_FLUSHED;
return sb->buf_posn - buf_start;
}
if (options & G_SINGLE_CHAR) {
size = 1;
} else {
size = HUGE_STRING_LEN;
return buf_posn - buf_start;
}
do {
if (sb->buf_posn == sb->buf_good) {
if (buf_posn == buf_good) {
have_alarmed = 1;
signal(SIGALRM,getline_timed_out);
alarm(timeout);
ret=read(sb->sd, sb->buffer, size);
if (ret <= 0) {
if ((ret=read(sd, buffer, HUGE_STRING_LEN)) <= 0) {
if (ret == -1 && errno == EINTR)
continue; /* Solaris... */
else {
sb->status = SB_ERROR;
if (have_alarmed) { alarm(0); signal(SIGALRM,SIG_IGN); }
/* just always return -1, instead of 0 */
return -1;
}
}
sb->status = SB_READ;
sb->buf_good = ret;
buf_start -= sb->buf_posn;
sb->buf_posn = 0;
/* ADC hack below ZZZ */
/*
if (ret >0) {
for (c = 0; c < ret; c++)
fputc(sb->buffer[c],stderr);
c = 0;
}
*/
buf_good = ret;
buf_start -= buf_posn;
buf_posn = 0;
}
c = sb->buffer[(sb->buf_posn)++];
if ((c == '\r') && (sb->buffer[sb->buf_posn] == '\n') &&
(sb->buf_posn + 1 < sb->buf_good) &&
((sb->buffer[sb->buf_posn + 1] == ' ') ||
(sb->buffer[sb->buf_posn + 1] == '\t')))
{
*s++ = c;
*s++ = '\n';
*s++ = sb->buffer[sb->buf_posn + 1];
sb->buf_posn += 2;
}
else if ((c == '\n') && (sb->buf_posn < sb->buf_good) &&
((sb->buffer[sb->buf_posn] == ' ') ||
(sb->buffer[sb->buf_posn] == '\t')))
{
*s++ = '\n';
*s++ = sb->buffer[sb->buf_posn];
sb->buf_posn += 1;
}
else if (c == LF) break;
else if (c != CR) *s++ = c;
c = buffer[buf_posn++];
if (c == LF) break;
if (c != CR) *s++ = c;
} while (s < endp);
if (have_alarmed) { alarm(0); signal(SIGALRM,SIG_IGN); }
*s = '\0';
return sb->buf_posn - buf_start;
return buf_posn - buf_start;
}
void splitURL(char *line, char *url, char *args) {
@ -761,7 +760,7 @@ void escape_shell_cmd(char *cmd) {
l=strlen(cmd);
for(x=0;cmd[x];x++) {
if(ind("&;`'\"|*?~<>^()[]{}$\\\x0A",cmd[x]) != -1){
if(ind("&;`'\"|*?~<>^()[]{}$\\",cmd[x]) != -1){
for(y=l+1;y>x;y--)
cmd[y] = cmd[y-1];
l++; /* length has been increased */
@ -1040,14 +1039,14 @@ uid_t uname2id(char *name) {
{
if (!scan_long (&name[1], &id))
{
fprintf(stderr,"HTTPd: bad user id %s\n",name);
fprintf(stderr,"httpd: bad user id %s\n",name);
exit(1);
}
return (uid_t) id ;
}
if(!(ent = getpwnam(name))) {
fprintf(stderr,"HTTPd: bad user name %s\n",name);
fprintf(stderr,"httpd: bad user name %s\n",name);
exit(1);
}
return(ent->pw_uid);
@ -1061,14 +1060,14 @@ gid_t gname2id(char *name) {
{
if (!scan_long (&name[1], &id))
{
fprintf(stderr,"HTTPd: group id %s\n",name);
fprintf(stderr,"httpd: bad group id %s\n",name);
exit(1);
}
return (gid_t) id ;
}
if(!(ent = getgrnam(name))) {
fprintf(stderr,"HTTPd: bad group name %s\n",name);
fprintf(stderr,"httpd: bad group name %s\n",name);
exit(1);
}
return(ent->gr_gid);
@ -1103,6 +1102,8 @@ int get_remote_host_min(per_request *reqInfo) {
struct in_addr *iaddr;
struct hostent *hptr;
reqInfo->ownDNS = TRUE;
len = sizeof(struct sockaddr);
if ((getpeername(reqInfo->connection_socket, &addr, &len)) < 0) {
@ -1112,20 +1113,14 @@ int get_remote_host_min(per_request *reqInfo) {
iaddr = &(((struct sockaddr_in *)&addr)->sin_addr);
hptr = gethostbyaddr((char *)iaddr, sizeof(struct in_addr), AF_INET);
if(hptr) {
if (reqInfo->remote_host) {
freeString(reqInfo->remote_host);
}
reqInfo->remote_host = dupStringP(hptr->h_name,STR_REQ);
if (reqInfo->remote_host) free(reqInfo->remote_host);
reqInfo->remote_host = strdup(hptr->h_name);
str_tolower(reqInfo->remote_host);
if (reqInfo->remote_name) {
freeString(reqInfo->remote_name);
}
reqInfo->remote_name = dupStringP(reqInfo->remote_host,STR_REQ);
if (reqInfo->remote_name) free(reqInfo->remote_name);
reqInfo->remote_name = strdup(reqInfo->remote_host);
} else {
/* shouldn't be necessary, but just in case */
if (reqInfo->remote_host) {
freeString(reqInfo->remote_host);
}
if (reqInfo->remote_host) free(reqInfo->remote_host);
reqInfo->remote_host = NULL;
}
reqInfo->dns_host_lookup = TRUE;
@ -1139,13 +1134,15 @@ void get_remote_host(per_request *reqInfo)
struct in_addr *iaddr;
struct hostent *hptr;
reqInfo->ownDNS = TRUE;
len = sizeof(struct sockaddr);
if ((getpeername(reqInfo->connection_socket, &addr, &len)) < 0) {
reqInfo->remote_name = dupStringP("UNKNOWN_HOST",STR_REQ);
reqInfo->remote_ip = dupStringP("UNKNOWN_IP",STR_REQ);
reqInfo->remote_host = dupStringP("UNKNOWN_HOST",STR_REQ);
return;
reqInfo->remote_name = strdup("UNKNOWN_HOST");
reqInfo->remote_ip = strdup("UNKNOWN_IP");
reqInfo->remote_host = strdup("UNKNOWN_HOST");
return;
}
iaddr = &(((struct sockaddr_in *)&addr)->sin_addr);
@ -1154,18 +1151,14 @@ void get_remote_host(per_request *reqInfo)
{
hptr = gethostbyaddr((char *)iaddr, sizeof(struct in_addr), AF_INET);
if(hptr) {
reqInfo->remote_host = dupStringP(hptr->h_name,STR_REQ);
reqInfo->remote_host = strdup(hptr->h_name);
str_tolower(reqInfo->remote_host);
if (reqInfo->remote_name) {
freeString(reqInfo->remote_name);
}
reqInfo->remote_name = dupStringP(reqInfo->remote_host,STR_REQ);
if (reqInfo->remote_name) free(reqInfo->remote_name);
reqInfo->remote_name = strdup(reqInfo->remote_host);
} else reqInfo->remote_host = NULL;
reqInfo->dns_host_lookup = TRUE;
} else {
if (reqInfo->remote_host != NULL) freeString(reqInfo->remote_host);
} else
reqInfo->remote_host = NULL;
}
if (reqInfo->hostInfo->dns_mode == DNS_MAX) {
/* Grrr. Check THAT name to make sure it's really the name of the addr. */
@ -1182,20 +1175,18 @@ void get_remote_host(per_request *reqInfo)
}
if((!hptr) || (!(*haddr)))
if (reqInfo->remote_host) {
freeString(reqInfo->remote_host);
free(reqInfo->remote_host);
reqInfo->remote_host = NULL;
}
}
}
reqInfo->remote_ip = dupStringP(inet_ntoa(*iaddr),STR_REQ);
reqInfo->remote_ip = strdup(inet_ntoa(*iaddr));
if(!reqInfo->remote_host){
if (reqInfo->remote_name) {
freeString(reqInfo->remote_name);
}
reqInfo->remote_name = dupStringP(reqInfo->remote_ip,STR_REQ);
if (reqInfo->remote_name) free(reqInfo->remote_name);
reqInfo->remote_name = strdup(reqInfo->remote_ip);
}
if (!reqInfo->remote_name){
reqInfo->remote_name = dupStringP("UNKNOWN_HOST",STR_REQ);
reqInfo->remote_name = strdup("UNKNOWN_HOST");
}
}
@ -1237,7 +1228,7 @@ void get_local_host()
gethostname(str, len);
if((!(p=gethostbyname(str))) ||
(!(gConfiguration->server_hostname = find_fqdn(p)))) {
fprintf(stderr,"HTTPd: cannot determine local host name.\n");
fprintf(stderr,"httpd: cannot determine local host name.\n");
fprintf(stderr,"Use ServerName to set it manually.\n");
exit(1);
}
@ -1260,16 +1251,13 @@ void get_local_addr(per_request *reqInfo) {
sizeof(struct in_addr));
}
/* Modified: Tue Sep 5 23:18:01 1995
* This function now understands the "https" directive and the
* default SSL port of 443.
*/
void construct_url(char *full_url, per_host *host, char *url)
{
if (port == DEFAULT_PORT)
sprintf(full_url,"%s://%s%s", "http",host->server_hostname,url);
else
sprintf(full_url,"%s://%s:%d%s", "http",host->server_hostname,port,url);
void construct_url(char *full_url, per_host *host, char *url) {
/* Since 80 is default port */
if (port == 80) {
sprintf(full_url,"http://%s%s",host->server_hostname,url);
} else {
sprintf(full_url,"http://%s:%d%s",host->server_hostname,port,url);
}
}
/* aaaack but it's fast and const should make it shared text page. */

View File

@ -10,7 +10,7 @@
*
************************************************************************
*
* util.h,v 1.18 1996/03/27 20:44:32 blong Exp
* util.h,v 1.14 1995/11/28 09:02:22 blong Exp
*
************************************************************************
*
@ -24,12 +24,6 @@
#include <time.h>
#include <sys/stat.h>
/* getline options */
#define G_RESET_BUF 1
#define G_FLUSH 2
#define G_SINGLE_CHAR 4
/* util function prototypes */
void inststr(char *dst[], int argc, char *src);
void initproctitle(char *start, int argc, char **argv, char **envp);
@ -49,8 +43,7 @@ void getparents(char *name);
void no2slash(char *name);
uid_t uname2id(char *name);
gid_t gname2id(char *name);
int getline(sock_buf *sb, char *s, int n, int options, unsigned int timeout);
sock_buf *new_sock_buf(per_request *reqInfo, int sd);
int getline(int sd, char *s, int n, int reset, unsigned int timeout);
int eat_ws (FILE* fp);
int cfg_getline(char *s, int n, FILE *f);
void getword(char *word, char *line, char stop);

View File

@ -27,7 +27,7 @@ INCLUDES = -I../src
#--------------------------------------------------------------------------
SUPPORT = htpasswd unescape inc2shtml htdigest dbm2std std2dbm dbmdigest \
dbmgroup dbmpasswd webgrab
dbmgroup dbmpasswd
.c.o:
$(CC) -c $(CFLAGS) $(INCLUDES) $<
@ -67,14 +67,14 @@ sgi5:
make all CC=cc CFLAGS="-DIRIX"
solaris:
make all CC=gcc CFLAGS="-DSOLARIS2" EXTRA_LIBS="-lnsl -lsocket"
make all CC=gcc CFLAGS="-DSOLARIS2"
sunos:
make all CC=gcc CFLAGS="-DSUNOS"
svr4:
make all CC=cc CFLAGS="-I/usr/include -I/usr/ucbinclude -DSVR4" \
EXTRA_LIBS="-lc -L/usr/ucblib -ldbm -lucb -lnsl -lsocket"
EXTRA_LIBS="-lc -L/usr/ucblib -ldbm -lucb"
ultrix:
make all CC=gcc CFLAGS="-DULTRIX"
@ -114,8 +114,6 @@ unescape: unescape.c
inc2shtml: inc2shtml.c
$(CC) $(CFLAGS) $(INCLUDES) inc2shtml.c -o inc2shtml
webgrab: webgrab.c
$(CC) $(CFLAGS) $(INCLUDES) webgrab.c -o webgrab $(EXTRA_LIBS)
clean:
rm -f $(SUPPORT) $(DIGESTOBJS) tags TAGS *.o

View File

@ -1,205 +0,0 @@
/***************************************************************************\
* webgrab - v1.0 - Copyright 1995, Brian J. Swetland *
* *
* Free for any personal or non-comercial use. Use at your own risk. *
\***************************************************************************/
#include <stdio.h>
#include <fcntl.h>
#ifdef __bsdi__
# include <sys/malloc.h>
#else
# ifndef NeXT
# include <malloc.h>
# endif
#endif
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <netdb.h>
#include <string.h>
#define VERSION "1.3"
/* strdup isn't portable, so we make our own. */
char *strd(char *s) {
char *d;
d=(char *)malloc(strlen(s) + 1);
strcpy(d,s);
return(d);
}
/* parses URL looking like blah://host[:port][/path]
will ignore anything before the first : and terminate path when it
hits >, ", or whitespace -- returns portno or 0 if bad url */
int parseURL(char *url, char **host, char **path)
{
char *p, *pp;
int port;
p = url;
/* skip anything up to the first : (the one after http, etc) */
while(*p && *p!=':') p++;
if(!*p)
return 0;
/* REQUIRE two '/'s */
if(!(*(++p) && (*p =='/') && *(++p) && (*p == '/')))
return 0;
p++;
/* mark the beginning of the hostname */
pp = p;
/* hostname is terminated by a '/' or '>','"',or whitespace */
while(*p && *p!=':' && *p!='/' && *p!='"' && *p!='>' && !isspace(*p))
p++;
*host = (char *) malloc(p-pp+1);
strncpy(*host,pp,p-pp);
(*host)[p-pp]=0;
/* optionally read a portnumber */
if(*p==':'){
p++;
port = 0;
while(*p && isdigit(*p)){
port = port*10 + (*p-'0');
p++;
}
if(!*p || *p!='/') {
free(*host);
return 0;
}
} else {
port = 80;
}
/* still more */
if(*p && (*p=='/')){
pp = p;
while(*p && *p!='"' && *p!='>' && !isspace(*p)) p++;
*p = 0;
*path = strd(pp);
} else {
*path = strd("/");
}
return port;
}
void usage(char *argv)
{
printf("\nWebgrab: The Command Line Browser\tVersion %s \n",VERSION);
printf("Usage: %s [-shr] <url>\n",argv);
printf("\t-s\t: Suppress Headers\n");
printf("\t-h\t: Headers Only\n");
printf("\t<url>\t: URL to retrieve (in http:// format)\n");
printf("\t-r\t: Read HTTP headers from stdin\n\n");
exit(1);
}
int main(int argc, char *argv[])
{
int s, i, port;
struct sockaddr_in sa;
struct hostent *hp;
FILE *fpo,*fpi;
char buf[1024];
char *path,*host;
int ignore=0,head=0,readin=0;
if(argc<2 || (argv[1][0]=='-'&&argc<3)){
usage(argv[0]);
}
if(argv[1][0]=='-'){
for(path=&argv[1][1];*path;path++)
switch(*path){
case 'r':
readin = 1;
break;
case 's':
ignore = 1;
break;
case 'h':
head = 1;
break;
}
s = 2;
} else {
s = 1;
}
if(!(port=parseURL(argv[s], &host, &path))){
fprintf(stderr,"error: invalid url\n");
exit(1);
}
/* find the server */
if(!(hp = gethostbyname(host))) {
fprintf(stderr,"error: can't get host %s.\n",host);
exit(1);
}
/* Setup the socket */
/* bzero((char *)&sa, sizeof(sa)); */
memset(&sa, 0, sizeof(sa));
sa.sin_port = htons(port);
/* bcopy((char *)hp->h_addr, (char *)&sa.sin_addr, hp->h_length); */
memcpy((char *)&sa.sin_addr, (char *)hp->h_addr, hp->h_length);
sa.sin_family = hp->h_addrtype;
/* allocate the socket */
if((s = socket(hp->h_addrtype, SOCK_STREAM, 0)) < 0){
fprintf(stderr,"error: can't get socket\n");
exit(1);
}
/* connect to the server */
if(connect(s, &sa, sizeof(sa)) < 0){
close(s);
fprintf(stderr,"error: can't connect\n");
exit(1);
}
fpo = fdopen(s,"w");
fpi = fdopen(s,"r");
fprintf(fpo,"%s %s HTTP/1.0\r\n",head?"HEAD":"GET",path);
if (readin) {
/* copy headers from stdin ... */
while(!feof(stdin)){
i = fread(buf,1,1024,stdin);
if(i) fwrite(buf,1,i,fpo);
if(feof(stdin)) break;
}
} else {
/* send our normal header info */
fputs("User-Agent: WebGrab/1.2 (commandline forever)\r\n",fpo);
}
fputs("\r\n",fpo);
fflush(fpo);
/* IGNORE HEADERS */
while(!feof(fpi)){
fgets(buf,1024,fpi);
if(!ignore) fprintf(stdout,"%s",buf);
if(feof(fpi) || buf[0]<' ') break;
}
while(!feof(fpi)){
i = fread(buf,1,1024,fpi);
if(i) fwrite(buf,1,i,stdout);
if(feof(fpi)) break;
}
close(s);
exit(0);
}