mirror of
https://github.com/NishiOwO/ncsa-httpd.git
synced 2025-04-21 16:54:46 +00:00
NCSA HTTPd 1.1
This commit is contained in:
parent
4e19b9e4a0
commit
9572b626b7
27
cgi-bin/archie
Executable file
27
cgi-bin/archie
Executable file
@ -0,0 +1,27 @@
|
||||
#!/bin/sh
|
||||
|
||||
ARCHIE=/usr/local/bin/archie
|
||||
|
||||
|
||||
echo Content-type: text/html
|
||||
echo
|
||||
|
||||
if [ -x $ARCHIE ]; then
|
||||
if [ $# = 0 ]; then
|
||||
cat << EOM
|
||||
<TITLE>Archie Gateway</TITLE>
|
||||
<H1>Archie Gateway</H1>
|
||||
|
||||
<ISINDEX>
|
||||
|
||||
This is a gateway to archie. Type search query in your browser's search
|
||||
dialog.<P>
|
||||
EOM
|
||||
else
|
||||
echo \<PRE\>
|
||||
$ARCHIE "$*"
|
||||
fi
|
||||
else
|
||||
echo Cannot find archie on this system.
|
||||
fi
|
||||
|
28
cgi-bin/calendar
Executable file
28
cgi-bin/calendar
Executable file
@ -0,0 +1,28 @@
|
||||
#!/bin/sh
|
||||
|
||||
CAL=/bin/cal
|
||||
|
||||
echo Content-type: text/html
|
||||
echo
|
||||
|
||||
if [ -x $CAL ]; then
|
||||
if [ $# = 0 ]; then
|
||||
cat << EOM
|
||||
<TITLE>Calendar</TITLE>
|
||||
<H1>Calendar</H1>
|
||||
|
||||
<ISINDEX>
|
||||
|
||||
To look up a calendar month, type the month followed by a space then the year.<P>
|
||||
Example: <code>3 1993</code> would give the calendar for March 1993.
|
||||
|
||||
EOM
|
||||
else
|
||||
echo \<PRE\>
|
||||
$CAL $*
|
||||
fi
|
||||
else
|
||||
echo Cannot find cal on this system.
|
||||
fi
|
||||
|
||||
|
14
cgi-bin/date
Executable file
14
cgi-bin/date
Executable file
@ -0,0 +1,14 @@
|
||||
#!/bin/sh
|
||||
|
||||
DATE=`which date`
|
||||
|
||||
echo Content-type: text/plain
|
||||
echo
|
||||
|
||||
if [ -x $DATE ]; then
|
||||
$DATE
|
||||
else
|
||||
echo Cannot find date command on this system.
|
||||
fi
|
||||
|
||||
|
26
cgi-bin/finger
Executable file
26
cgi-bin/finger
Executable file
@ -0,0 +1,26 @@
|
||||
#!/bin/sh
|
||||
|
||||
FINGER=`which finger`
|
||||
|
||||
echo Content-type: text/html
|
||||
echo
|
||||
|
||||
if [ -x $FINGER ]; then
|
||||
if [ $# = 0 ]; then
|
||||
cat << EOM
|
||||
<TITLE>Finger Gateway</TITLE>
|
||||
<H1>Finger Gateway</H1>
|
||||
|
||||
<ISINDEX>
|
||||
|
||||
This is a gateway to "finger". Type a user@host combination in your browser's
|
||||
search dialog.<P>
|
||||
EOM
|
||||
else
|
||||
echo \<PRE\>
|
||||
$FINGER "$*"
|
||||
fi
|
||||
else
|
||||
echo Cannot find finger on this system.
|
||||
fi
|
||||
|
14
cgi-bin/fortune
Executable file
14
cgi-bin/fortune
Executable file
@ -0,0 +1,14 @@
|
||||
#!/bin/sh
|
||||
|
||||
FORTUNE=`which fortune`
|
||||
|
||||
echo Content-type: text/plain
|
||||
echo
|
||||
|
||||
if [ -x $FORTUNE ]; then
|
||||
$FORTUNE
|
||||
else
|
||||
echo Cannot find fortune command on this system.
|
||||
fi
|
||||
|
||||
|
BIN
cgi-bin/imagemap
Executable file
BIN
cgi-bin/imagemap
Executable file
Binary file not shown.
29
cgi-bin/nph-test-cgi
Executable file
29
cgi-bin/nph-test-cgi
Executable file
@ -0,0 +1,29 @@
|
||||
#!/bin/sh
|
||||
|
||||
echo HTTP/1.0 200 OK
|
||||
echo Content-type: text/plain
|
||||
echo Server: $SERVER_SOFTWARE
|
||||
echo
|
||||
|
||||
echo CGI/1.0 test script report:
|
||||
echo
|
||||
|
||||
echo argc is $#. argv is "$*".
|
||||
echo
|
||||
|
||||
echo SERVER_SOFTWARE = $SERVER_SOFTWARE
|
||||
echo SERVER_NAME = $SERVER_NAME
|
||||
echo GATEWAY_INTERFACE = $GATEWAY_INTERFACE
|
||||
echo SERVER_PROTOCOL = $SERVER_PROTOCOL
|
||||
echo SERVER_PORT = $SERVER_PORT
|
||||
echo REQUEST_METHOD = $REQUEST_METHOD
|
||||
echo HTTP_ACCEPT = "$HTTP_ACCEPT"
|
||||
echo PATH_INFO = $PATH_INFO
|
||||
echo PATH_TRANSLATED = $PATH_TRANSLATED
|
||||
echo SCRIPT_NAME = $SCRIPT_NAME
|
||||
echo QUERY_STRING = $QUERY_STRING
|
||||
echo REMOTE_HOST = $REMOTE_HOST
|
||||
echo REMOTE_ADDR = $REMOTE_ADDR
|
||||
echo REMOTE_USER = $REMOTE_USER
|
||||
echo CONTENT_TYPE = $CONTENT_TYPE
|
||||
echo CONTENT_LENGTH = $CONTENT_LENGTH
|
29
cgi-bin/test-cgi
Executable file
29
cgi-bin/test-cgi
Executable file
@ -0,0 +1,29 @@
|
||||
#!/bin/sh
|
||||
|
||||
echo Content-type: text/plain
|
||||
echo
|
||||
|
||||
echo CGI/1.0 test script report:
|
||||
echo
|
||||
|
||||
echo argc is $#. argv is "$*".
|
||||
echo
|
||||
|
||||
echo PATH = $PATH
|
||||
echo SERVER_SOFTWARE = $SERVER_SOFTWARE
|
||||
echo SERVER_NAME = $SERVER_NAME
|
||||
echo GATEWAY_INTERFACE = $GATEWAY_INTERFACE
|
||||
echo SERVER_PROTOCOL = $SERVER_PROTOCOL
|
||||
echo SERVER_PORT = $SERVER_PORT
|
||||
echo REQUEST_METHOD = $REQUEST_METHOD
|
||||
echo HTTP_ACCEPT = "$HTTP_ACCEPT"
|
||||
echo PATH_INFO = $PATH_INFO
|
||||
echo PATH_TRANSLATED = $PATH_TRANSLATED
|
||||
echo SCRIPT_NAME = $SCRIPT_NAME
|
||||
echo QUERY_STRING = $QUERY_STRING
|
||||
echo REMOTE_HOST = $REMOTE_HOST
|
||||
echo REMOTE_ADDR = $REMOTE_ADDR
|
||||
echo REMOTE_USER = $REMOTE_USER
|
||||
echo AUTH_TYPE = $AUTH_TYPE
|
||||
echo CONTENT_TYPE = $CONTENT_TYPE
|
||||
echo CONTENT_LENGTH = $CONTENT_LENGTH
|
56
cgi-bin/test-cgi.tcl
Executable file
56
cgi-bin/test-cgi.tcl
Executable file
@ -0,0 +1,56 @@
|
||||
#!/usr/local/bin/tclsh
|
||||
# tcl-cgi.tcl
|
||||
# robert.bagwill@nist.gov, no warranty, no rights reserved
|
||||
# print out command line args, stdin, and environment variables
|
||||
#
|
||||
set envvars {SERVER_SOFTWARE SERVER_NAME GATEWAY_INTERFACE SERVER_PROTOCOL SERVER_PORT REQUEST_METHOD PATH_INFO PATH_TRANSLATED SCRIPT_NAME QUERY_STRING REMOTE_HOST REMOTE_ADDR REMOTE_USER AUTH_TYPE CONTENT_TYPE CONTENT_LENGTH HTTP_ACCEPT}
|
||||
|
||||
puts "Content-type: text/HTML\n"
|
||||
puts "<HTML>"
|
||||
puts "<HEAD>"
|
||||
puts "<TITLE>CGI/1.0 TCL script report:</TITLE>"
|
||||
puts "</HEAD>"
|
||||
|
||||
puts "<BODY>"
|
||||
puts "<H1>Command Line Arguments</H1>"
|
||||
puts "argc is $argc. argv is $argv."
|
||||
puts ""
|
||||
|
||||
puts "<H1>Message</H1>"
|
||||
puts "<PRE>"
|
||||
set message [split [read stdin $env(CONTENT_LENGTH)] &]
|
||||
foreach pair $message {
|
||||
set name [lindex [split $pair =] 0]
|
||||
set val [lindex [split $pair =] 1]
|
||||
regsub -all {\+} $val { } val
|
||||
# kludge to unescape chars
|
||||
regsub -all {\%0A} $val \n\t val
|
||||
regsub -all {\%2C} $val {,} val
|
||||
regsub -all {\%27} $val {'} val
|
||||
puts "$name\t= $val"
|
||||
}
|
||||
puts "</PRE>"
|
||||
|
||||
puts "<H1>Environment Variables</H1>"
|
||||
puts "<DL>"
|
||||
foreach var $envvars {
|
||||
if {[info exists env($var)]} {
|
||||
puts -nonewline "<DT>$var"
|
||||
eval {set val $env($var)}
|
||||
if {[llength $val] > 1} {
|
||||
puts "<DD>"
|
||||
foreach subval [lsort $val] {
|
||||
puts "$subval"
|
||||
}
|
||||
} else {
|
||||
puts "<DD>$val"
|
||||
}
|
||||
}
|
||||
}
|
||||
puts "</DL>"
|
||||
puts "</BODY>"
|
||||
puts "</HTML>"
|
||||
######################
|
||||
# end of tcl-cgi.tcl
|
||||
######################
|
||||
|
14
cgi-bin/uptime
Executable file
14
cgi-bin/uptime
Executable file
@ -0,0 +1,14 @@
|
||||
#!/bin/sh
|
||||
|
||||
UPTIME=`which uptime`
|
||||
|
||||
echo Content-type: text/plain
|
||||
echo
|
||||
|
||||
if [ -x $UPTIME ]; then
|
||||
$UPTIME
|
||||
else
|
||||
echo Cannot find uptime command on this system.
|
||||
fi
|
||||
|
||||
|
87
cgi-bin/wais.pl
Executable file
87
cgi-bin/wais.pl
Executable file
@ -0,0 +1,87 @@
|
||||
#!/usr/local/bin/perl
|
||||
#
|
||||
# wais.pl -- WAIS search interface
|
||||
#
|
||||
# wais.pl,v 1.1 1993/12/31 09:30:56 robm Exp
|
||||
#
|
||||
# Tony Sanders <sanders@bsdi.com>, Nov 1993
|
||||
#
|
||||
# Example configuration (in local.conf):
|
||||
# map topdir wais.pl &do_wais($top, $path, $query, "database", "title")
|
||||
#
|
||||
|
||||
$waisq = "/usr/local/bin/waisq";
|
||||
$waisd = "/u/Web/wais-sources";
|
||||
$src = "www";
|
||||
$title = "NCSA httpd documentation";
|
||||
|
||||
sub send_index {
|
||||
print "Content-type: text/html\n\n";
|
||||
|
||||
print "<HEAD>\n<TITLE>Index of ", $title, "</TITLE>\n</HEAD>\n";
|
||||
print "<BODY>\n<H1>", $title, "</H1>\n";
|
||||
|
||||
print "This is an index of the information on this server. Please\n";
|
||||
print "type a query in the search dialog.\n<P>";
|
||||
print "You may use compound searches, such as: <CODE>environment AND cgi</CODE>\n";
|
||||
print "<ISINDEX>";
|
||||
}
|
||||
|
||||
sub do_wais {
|
||||
# local($top, $path, $query, $src, $title) = @_;
|
||||
|
||||
do { &'send_index; return; } unless defined @ARGV;
|
||||
local(@query) = @ARGV;
|
||||
local($pquery) = join(" ", @query);
|
||||
|
||||
print "Content-type: text/html\n\n";
|
||||
|
||||
open(WAISQ, "-|") || exec ($waisq, "-c", $waisd,
|
||||
"-f", "-", "-S", "$src.src", "-g", @query);
|
||||
|
||||
print "<HEAD>\n<TITLE>Search of ", $title, "</TITLE>\n</HEAD>\n";
|
||||
print "<BODY>\n<H1>", $title, "</H1>\n";
|
||||
|
||||
print "Index \`$src\' contains the following\n";
|
||||
print "items relevant to \`$pquery\':<P>\n";
|
||||
print "<DL>\n";
|
||||
|
||||
local($hits, $score, $headline, $lines, $bytes, $type, $date);
|
||||
while (<WAISQ>) {
|
||||
/:score\s+(\d+)/ && ($score = $1);
|
||||
/:number-of-lines\s+(\d+)/ && ($lines = $1);
|
||||
/:number-of-bytes\s+(\d+)/ && ($bytes = $1);
|
||||
/:type "(.*)"/ && ($type = $1);
|
||||
/:headline "(.*)"/ && ($headline = $1); # XXX
|
||||
/:date "(\d+)"/ && ($date = $1, $hits++, &docdone);
|
||||
}
|
||||
close(WAISQ);
|
||||
print "</DL>\n";
|
||||
|
||||
if ($hits == 0) {
|
||||
print "Nothing found.\n";
|
||||
}
|
||||
print "</BODY>\n";
|
||||
}
|
||||
|
||||
sub docdone {
|
||||
if ($headline =~ /Search produced no result/) {
|
||||
print "<HR>";
|
||||
print $headline, "<P>\n<PRE>";
|
||||
# the following was &'safeopen
|
||||
open(WAISCAT, "$waisd/$src.cat") || die "$src.cat: $!";
|
||||
while (<WAISCAT>) {
|
||||
s#(Catalog for database:)\s+.*#$1 <A HREF="/$top/$src.src">$src.src</A>#;
|
||||
s#Headline:\s+(.*)#Headline: <A HREF="$1">$1</A>#;
|
||||
print;
|
||||
}
|
||||
close(WAISCAT);
|
||||
print "\n</PRE>\n";
|
||||
} else {
|
||||
print "<DT><A HREF=\"$headline\">$headline</A>\n";
|
||||
print "<DD>Score: $score, Lines: $lines, Bytes: $bytes\n";
|
||||
}
|
||||
$score = $headline = $lines = $bytes = $type = $date = '';
|
||||
}
|
||||
|
||||
eval '&do_wais';
|
61
cgi-src/Makefile
Executable file
61
cgi-src/Makefile
Executable file
@ -0,0 +1,61 @@
|
||||
# For gcc
|
||||
CC= gcc
|
||||
# For ANSI compilers
|
||||
#CC= cc
|
||||
|
||||
#For Optimization
|
||||
#CFLAGS= -O2
|
||||
#For debugging
|
||||
CFLAGS= -g
|
||||
|
||||
RM= /bin/rm -f
|
||||
#--- You shouldn't have to edit anything else. ---
|
||||
|
||||
.c.o:
|
||||
$(CC) -c $(CFLAGS) $<
|
||||
|
||||
all: query post-query imagemap jj phf
|
||||
|
||||
ibm:
|
||||
make all CC=gcc
|
||||
|
||||
sun:
|
||||
make all CC=gcc
|
||||
|
||||
hp:
|
||||
make all CC=gcc
|
||||
|
||||
sgi:
|
||||
make all CC=cc
|
||||
|
||||
decmips:
|
||||
make all CC=cc
|
||||
|
||||
decaxp:
|
||||
make all CC=cc
|
||||
|
||||
tar: query post-query imagemap jj phf
|
||||
$(RM) post-query.o util.o imagerect.o jj.o phf.o
|
||||
|
||||
post-query: post-query.o util.o
|
||||
$(CC) post-query.o util.o -o ../cgi-bin/post-query
|
||||
|
||||
query: query.o util.o
|
||||
$(CC) query.o util.o -o ../cgi-bin/query
|
||||
|
||||
imagemap: imagemap.o util.o
|
||||
$(CC) imagemap.o util.o -o ../cgi-bin/imagemap
|
||||
|
||||
jj: jj.o util.o
|
||||
$(CC) jj.o util.o -o ../cgi-bin/jj
|
||||
|
||||
phf: phf.o util.o
|
||||
$(CC) phf.o util.o -o ../cgi-bin/phf
|
||||
|
||||
change-passwd: change-passwd.o util.o
|
||||
$(CC) change-passwd.o util.o -o ../cgi-bin/change-passwd
|
||||
|
||||
|
||||
clean:
|
||||
rm -f *.o ../cgi-bin/post-query ../cgi-bin/query ../cgi-bin/change-passwd ../cgi-bin/phf ../cgi-bin/jj
|
||||
|
171
cgi-src/change-passwd.c
Normal file
171
cgi-src/change-passwd.c
Normal file
@ -0,0 +1,171 @@
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/signal.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define USER_FILE "/usr/local/etc/httpd/conf/.htpasswd"
|
||||
#define WIZARD "surobm"
|
||||
|
||||
char *makeword(char *line, char stop);
|
||||
char *fmakeword(FILE *f, char stop, int *len);
|
||||
char x2c(char *what);
|
||||
void unescape_url(char *url);
|
||||
void plustospace(char *str);
|
||||
|
||||
char *crypt(char *pw, char *salt); /* why aren't these prototyped in include */
|
||||
|
||||
|
||||
char *tn;
|
||||
|
||||
/* From local_passwd.c (C) Regents of Univ. of California blah blah */
|
||||
static unsigned char itoa64[] = /* 0 ... 63 => ascii - 64 */
|
||||
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||
|
||||
to64(s, v, n)
|
||||
register char *s;
|
||||
register long v;
|
||||
register int n;
|
||||
{
|
||||
while (--n >= 0) {
|
||||
*s++ = itoa64[v&0x3f];
|
||||
v >>= 6;
|
||||
}
|
||||
}
|
||||
|
||||
void change_password(char *user, char *pw, FILE *f) {
|
||||
char *cpw, salt[3];
|
||||
|
||||
(void)srand((int)time((time_t *)NULL));
|
||||
to64(&salt[0],rand(),2);
|
||||
cpw = crypt(pw,salt);
|
||||
free(pw);
|
||||
fprintf(f,"%s:%s\n",user,cpw);
|
||||
}
|
||||
|
||||
void putline(FILE *f,char *l) {
|
||||
int x;
|
||||
|
||||
for(x=0;l[x];x++) fputc(l[x],f);
|
||||
fputc('\n',f);
|
||||
}
|
||||
|
||||
main(int argc, char *argv[]) {
|
||||
register int x;
|
||||
int cl,found,create;
|
||||
char *u,*t1,*t2,*p1,*p2,*user, command[256], line[256], l[256], w[256];
|
||||
FILE *tfp,*f;
|
||||
|
||||
tn = NULL;
|
||||
|
||||
printf("Content-type: text/html%c%c",10,10);
|
||||
|
||||
if(strcmp(getenv("REQUEST_METHOD"),"POST")) {
|
||||
printf("This script should be referenced with a METHOD of POST.\n");
|
||||
printf("If you don't understand this, see this ");
|
||||
printf("<A HREF=\"http://www.ncsa.uiuc.edu/SDG/Software/Mosaic/Docs/fill-out-forms/overview.html\">forms overview</A>.%c",10);
|
||||
exit(1);
|
||||
}
|
||||
if(strcmp(getenv("CONTENT_TYPE"),"application/x-www-form-urlencoded")) {
|
||||
printf("This script can only be used to decode form results. \n");
|
||||
exit(1);
|
||||
}
|
||||
cl = atoi(getenv("CONTENT_LENGTH"));
|
||||
|
||||
user=NULL;
|
||||
p1=NULL;
|
||||
p2=NULL;
|
||||
create=0;
|
||||
for(x=0;cl && (!feof(stdin));x++) {
|
||||
t1 = fmakeword(stdin,'&',&cl);
|
||||
t2 = makeword(t1,'=');
|
||||
unescape_url(t1);
|
||||
unescape_url(t2);
|
||||
if(!strcmp(t2,"user")) {
|
||||
if(!user)
|
||||
user = t1;
|
||||
else {
|
||||
printf("This script was accessed from the wrong form.\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else if(!strcmp(t2,"newpasswd1")) {
|
||||
if(!p1)
|
||||
p1 = t1;
|
||||
else {
|
||||
printf("This script was accessed from the wrong form.\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else if(!strcmp(t2,"newpasswd2")) {
|
||||
if(!p2)
|
||||
p2 = t1;
|
||||
else {
|
||||
printf("This script was accessed from the wrong form.\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
printf("This script was accessed from the wrong form.\n");
|
||||
printf("Unrecognized directive %s.\n",t2);
|
||||
exit(1);
|
||||
}
|
||||
free(t2);
|
||||
}
|
||||
u=getenv("REMOTE_USER");
|
||||
if((strcmp(u,WIZARD)) && (strcmp(user,u))) {
|
||||
printf("<TITLE>User Mismatch</TITLE>");
|
||||
printf("<H1>User Mismatch</H1>");
|
||||
printf("The username you gave does not correspond with the ");
|
||||
printf("user you authenticated as.\n");
|
||||
exit(1);
|
||||
}
|
||||
if(strcmp(p1,p2)) {
|
||||
printf("<TITLE>Password Mismatch</TITLE>");
|
||||
printf("<H1>Password Mismatch</H1>");
|
||||
printf("The two copies of your the password do not match. Please");
|
||||
printf(" try again.");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
tn = tmpnam(NULL);
|
||||
if(!(tfp = fopen(tn,"w"))) {
|
||||
fprintf(stderr,"Could not open temp file.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if(!(f = fopen(USER_FILE,"r"))) {
|
||||
fprintf(stderr,
|
||||
"Could not open passwd file for reading.\n",USER_FILE);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
found = 0;
|
||||
while(!(getline(line,256,f))) {
|
||||
if(found || (line[0] == '#') || (!line[0])) {
|
||||
putline(tfp,line);
|
||||
continue;
|
||||
}
|
||||
strcpy(l,line);
|
||||
getword(w,l,':');
|
||||
if(strcmp(user,w)) {
|
||||
putline(tfp,line);
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
change_password(user,p1,tfp);
|
||||
found=1;
|
||||
}
|
||||
}
|
||||
if((!found) && (create))
|
||||
change_password(user,p1,tfp);
|
||||
fclose(f);
|
||||
fclose(tfp);
|
||||
sprintf(command,"cp %s %s",tn,USER_FILE);
|
||||
system(command);
|
||||
unlink(tn);
|
||||
printf("<TITLE>Successful Change</TITLE>");
|
||||
printf("<H1>Successful Change</H1>");
|
||||
printf("Your password has been successfully changed.<P>");
|
||||
exit(0);
|
||||
}
|
250
cgi-src/imagemap.c
Normal file
250
cgi-src/imagemap.c
Normal file
@ -0,0 +1,250 @@
|
||||
/*
|
||||
** mapper 1.2
|
||||
** 7/26/93 Kevin Hughes, kevinh@pulua.hcc.hawaii.edu
|
||||
** "macmartinized" polygon code copyright 1992 by Eric Haines, erich@eye.com
|
||||
** All suggestions, help, etc. gratefully accepted!
|
||||
**
|
||||
** 1.1 : Better formatting, added better polygon code.
|
||||
** 1.2 : Changed isname(), added config file specification.
|
||||
**
|
||||
** 11/13/93: Rob McCool, robm@ncsa.uiuc.edu
|
||||
**
|
||||
** Rewrote configuration stuff for NCSA /htbin script
|
||||
**
|
||||
** 12/05/93: Rob McCool, robm@ncsa.uiuc.edu
|
||||
**
|
||||
** Made CGI/1.0 compliant.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define CONF_FILE "/usr/local/etc/httpd/conf/imagemap.conf"
|
||||
|
||||
#define MAXLINE 500
|
||||
#define MAXVERTS 100
|
||||
#define X 0
|
||||
#define Y 1
|
||||
|
||||
int isname(char);
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char input[MAXLINE], *mapname, def[MAXLINE], conf[80];
|
||||
double testpoint[2], pointarray[MAXVERTS][2];
|
||||
int i, j, k;
|
||||
FILE *fp;
|
||||
char *t;
|
||||
|
||||
if (argc != 2)
|
||||
servererr("Wrong number of arguments, client may not support ISMAP.");
|
||||
mapname=getenv("PATH_INFO");
|
||||
|
||||
if((!mapname) || (!mapname[0]))
|
||||
servererr("No map name given. Please read the <A HREF=\"http://hoohoo.ncsa.uiuc.edu/docs/setup/admin/Imagemap.html\">instructions</A>.<P>");
|
||||
|
||||
|
||||
mapname++;
|
||||
if(!(t = strchr(argv[1],',')))
|
||||
servererr("Your client doesn't support image mapping properly.");
|
||||
*t++ = '\0';
|
||||
testpoint[X] = (double) atoi(argv[1]);
|
||||
testpoint[Y] = (double) atoi(t);
|
||||
|
||||
if ((fp = fopen(CONF_FILE, "r")) == NULL)
|
||||
servererr("Couldn't open configuration file.");
|
||||
|
||||
while(!(getline(input,MAXLINE,fp))) {
|
||||
char confname[MAXLINE];
|
||||
if((input[0] == '#') || (!input[0]))
|
||||
continue;
|
||||
for(i=0;isname(input[i]) && (input[i] != ':');i++)
|
||||
confname[i] = input[i];
|
||||
confname[i] = '\0';
|
||||
if(!strcmp(confname,mapname))
|
||||
break;
|
||||
}
|
||||
if(feof(fp))
|
||||
servererr("Map not found in configuration file.");
|
||||
|
||||
fclose(fp);
|
||||
while(isspace(input[i]) || input[i] == ':') ++i;
|
||||
|
||||
for(j=0;input[i] && isname(input[i]);++i,++j)
|
||||
conf[j] = input[i];
|
||||
conf[j] = '\0';
|
||||
|
||||
if(!(fp=fopen(conf,"r")))
|
||||
servererr("Couldn't open map file.");
|
||||
|
||||
while(!(getline(input,MAXLINE,fp))) {
|
||||
char type[MAXLINE];
|
||||
char url[MAXLINE];
|
||||
char num[10];
|
||||
|
||||
if((input[0] == '#') || (!input[0]))
|
||||
continue;
|
||||
|
||||
type[0] = '\0';url[0] = '\0';
|
||||
|
||||
for(i=0;isname(input[i]) && (input[i]);i++)
|
||||
type[i] = input[i];
|
||||
type[i] = '\0';
|
||||
|
||||
while(isspace(input[i])) ++i;
|
||||
for(j=0;input[i] && isname(input[i]);++i,++j)
|
||||
url[j] = input[i];
|
||||
url[j] = '\0';
|
||||
|
||||
if(!strcmp(type,"default")) {
|
||||
strcpy(def,url);
|
||||
continue;
|
||||
}
|
||||
|
||||
k=0;
|
||||
while (input[i]) {
|
||||
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][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 {
|
||||
fclose(fp);
|
||||
servererr("Missing y value.");
|
||||
}
|
||||
}
|
||||
pointarray[k][X] = -1;
|
||||
if(!strcmp(type,"poly"))
|
||||
if(pointinpoly(testpoint,pointarray))
|
||||
sendmesg(url);
|
||||
if(!strcmp(type,"circle"))
|
||||
if(pointincircle(testpoint,pointarray))
|
||||
sendmesg(url);
|
||||
if(!strcmp(type,"rect"))
|
||||
if(pointinrect(testpoint,pointarray))
|
||||
sendmesg(url);
|
||||
}
|
||||
if(def[0])
|
||||
sendmesg(def);
|
||||
servererr("No default specified.");
|
||||
}
|
||||
|
||||
sendmesg(char *url)
|
||||
{
|
||||
printf("Location: %s%c%c",url,10,10);
|
||||
printf("This document has moved <A HREF=\"%s\">here</A>%c",url,10);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int pointinrect(double point[2], double coords[MAXVERTS][2])
|
||||
{
|
||||
return ((point[X] >= coords[0][X] && point[X] <= coords[1][X]) &&
|
||||
(point[Y] >= coords[0][Y] && point[Y] <= coords[1][Y]));
|
||||
}
|
||||
|
||||
int pointincircle(double point[2], double coords[MAXVERTS][2])
|
||||
{
|
||||
int radius1, radius2;
|
||||
|
||||
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]));
|
||||
return (radius2 <= radius1);
|
||||
}
|
||||
|
||||
int pointinpoly(double point[2], double pgon[MAXVERTS][2])
|
||||
{
|
||||
int i, numverts, inside_flag, xflag0;
|
||||
int crossings;
|
||||
double *p, *stop;
|
||||
double tx, ty, y;
|
||||
|
||||
for (i = 0; pgon[i][X] != -1 && i < MAXVERTS; i++)
|
||||
;
|
||||
numverts = i;
|
||||
crossings = 0;
|
||||
|
||||
tx = point[X];
|
||||
ty = point[Y];
|
||||
y = pgon[numverts - 1][Y];
|
||||
|
||||
p = (double *) pgon + 1;
|
||||
if ((y >= ty) != (*p >= ty)) {
|
||||
if ((xflag0 = (pgon[numverts - 1][X] >= tx)) ==
|
||||
(*(double *) pgon >= tx)) {
|
||||
if (xflag0)
|
||||
crossings++;
|
||||
}
|
||||
else {
|
||||
crossings += (pgon[numverts - 1][X] - (y - ty) *
|
||||
(*(double *) pgon - pgon[numverts - 1][X]) /
|
||||
(*p - y)) >= tx;
|
||||
}
|
||||
}
|
||||
|
||||
stop = pgon[numverts];
|
||||
|
||||
for (y = *p, p += 2; p < stop; y = *p, p += 2) {
|
||||
if (y >= ty) {
|
||||
while ((p < stop) && (*p >= ty))
|
||||
p += 2;
|
||||
if (p >= stop)
|
||||
break;
|
||||
if ((xflag0 = (*(p - 3) >= tx)) == (*(p - 1) >= tx)) {
|
||||
if (xflag0)
|
||||
crossings++;
|
||||
}
|
||||
else {
|
||||
crossings += (*(p - 3) - (*(p - 2) - ty) *
|
||||
(*(p - 1) - *(p - 3)) / (*p - *(p - 2))) >= tx;
|
||||
}
|
||||
}
|
||||
else {
|
||||
while ((p < stop) && (*p < ty))
|
||||
p += 2;
|
||||
if (p >= stop)
|
||||
break;
|
||||
if ((xflag0 = (*(p - 3) >= tx)) == (*(p - 1) >= tx)) {
|
||||
if (xflag0)
|
||||
crossings++;
|
||||
}
|
||||
else {
|
||||
crossings += (*(p - 3) - (*(p - 2) - ty) *
|
||||
(*(p - 1) - *(p - 3)) / (*p - *(p - 2))) >= tx;
|
||||
}
|
||||
}
|
||||
}
|
||||
inside_flag = crossings & 0x01;
|
||||
return (inside_flag);
|
||||
}
|
||||
|
||||
servererr(char *msg)
|
||||
{
|
||||
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>");
|
||||
printf("%s", msg);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
int isname(char c)
|
||||
{
|
||||
return (!isspace(c));
|
||||
}
|
259
cgi-src/jj.c
Normal file
259
cgi-src/jj.c
Normal file
@ -0,0 +1,259 @@
|
||||
/*
|
||||
* Submarine ordering form through FAX gateway
|
||||
*
|
||||
* Rob McCool
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#if 1
|
||||
#define JJ_FAX "JIMMY_JOHNS_3440603@fax.uiuc.edu"
|
||||
#else
|
||||
#define JJ_FAX "robm@imsa.edu"
|
||||
#endif
|
||||
|
||||
#define PASSWORD "SDGROCKS"
|
||||
#define LF 10
|
||||
|
||||
void getword(char *word, char *line, char stop);
|
||||
char x2c(char *what);
|
||||
void unescape_url(char *url);
|
||||
void plustospace(char *str);
|
||||
|
||||
|
||||
char *sublist[] = {
|
||||
"The Pepe Gourmet Sub",
|
||||
"Big John Gourmet Sub",
|
||||
"Sorry Charlie Gourmet Sub",
|
||||
"Turkey Tom Gourmet Sub",
|
||||
"Vito Gourmet Sub",
|
||||
"Vegetarian Gourmet Sub",
|
||||
"Gourmet Smoked Ham Club",
|
||||
"Billy Club",
|
||||
"Italian Night Club",
|
||||
"Hunter's Club",
|
||||
"Country Club",
|
||||
"The Beach Club"
|
||||
};
|
||||
|
||||
char *slimlist[] = {
|
||||
"Ham and Cheese",
|
||||
"Rare Roast Beef",
|
||||
"California Tuna",
|
||||
"Sliced Turkey",
|
||||
"Salami and Capacola",
|
||||
"Double Provolone"
|
||||
};
|
||||
|
||||
char *sidelist[] = {
|
||||
"Lay's Potato Chips",
|
||||
"Jumbo Kosher Dill"
|
||||
};
|
||||
|
||||
char *poplist[] = {
|
||||
"Pepsi",
|
||||
"Mountain Dew",
|
||||
"Diet Pepsi",
|
||||
"Iced Tea"
|
||||
};
|
||||
|
||||
void dump_form() {
|
||||
printf("<TITLE>Form for Submarine Order</TITLE>%c",LF);
|
||||
printf("<H1>Jimmy John's Submarine Order Form</H1>%c",LF);
|
||||
printf("This form will send a faxed order to Jimmy John's in Champaign. Proper password is requred%c",LF);
|
||||
printf("for order to be submitted, otherwise a copy of the order that would have been submitted will%c",LF);
|
||||
printf("will be displayed.<P>%c",LF);
|
||||
printf("<HR>%c",LF);
|
||||
printf("<FORM ACTION=\"http://hoohoo.ncsa.uiuc.edu:80/htbin/jj\">%c",LF);
|
||||
printf("Password: <INPUT TYPE=\"text\" NAME=\"pwd\" MAXLENGTH=\"20\"><P>%c",LF);
|
||||
printf("<H3>Sub Type</H3>%c",LF);
|
||||
printf("Select which you would like of the following:<P>%c",LF);
|
||||
printf("<INPUT TYPE=\"checkbox\" NAME=\"sub\" VALUE=\"0\">%s:%c",sublist[0],LF);
|
||||
printf("Smoked virginia ham and provolone cheese topped with lettuce, tomato, and mayo.<P>%c",LF);
|
||||
printf("<INPUT TYPE=\"checkbox\" NAME=\"sub\" VALUE=\"1\">%s:%c",sublist[1],LF);
|
||||
printf("Medium rare shaved roast beef topped with mayo, lettuce, and tomato.<P>%c",LF);
|
||||
printf("<INPUT TYPE=\"checkbox\" NAME=\"sub\" VALUE=\"2\">%s:%c",sublist[2],LF);
|
||||
printf("Tuna, mixed with celery, onions, and sauce, topped with lettuce,%c",LF);
|
||||
printf("tomato, and alfalfa sprouts.<P>%c",LF);
|
||||
printf("<INPUT TYPE=\"checkbox\" NAME=\"sub\" VALUE=\"3\">%s:%c",sublist[3],LF);
|
||||
printf("Turkey breast topped with lettuce, mayo, alfalfa sprouts, and mayo.<P>%c",LF);
|
||||
printf("<INPUT TYPE=\"checkbox\" NAME=\"sub\" VALUE=\"4\">%s:%c",sublist[4],LF);
|
||||
printf("Genoa salami and provolone cheese topped with capacola, onion, lettuce, tomato, and Italian sauce.<P>%c",LF);
|
||||
printf("<INPUT TYPE=\"checkbox\" NAME=\"sub\" VALUE=\"5\">%s:%c",sublist[5],LF);
|
||||
printf("Layers of provolone cheese, separated by avocado, sprouts, lettuce, tomato, and mayo.<P>%c",LF);
|
||||
printf("<INPUT TYPE=\"checkbox\" NAME=\"sub\" VALUE=\"6\">%s:%c",sublist[6],LF);
|
||||
printf("1/4 pound of smoked ham, provolone cheese, topped with lettuce,%c",LF);
|
||||
printf("tomato, and mayo.<P>%c",LF);
|
||||
printf("<INPUT TYPE=\"checkbox\" NAME=\"sub\" VALUE=\"7\">%s:%c",sublist[7],LF);
|
||||
printf("Shaved roast beef, provolone cheese, french dijon mustard, topped with shaved ham, lettuce,%c",LF);
|
||||
printf("tomato, and mayo.<P>%c",LF);
|
||||
printf("<INPUT TYPE=\"checkbox\" NAME=\"sub\" VALUE=\"8\">%s:%c",sublist[8],LF);
|
||||
printf("Genoa salami, Italian capacola, smoked ham, and provolone cheese topped with lettuce,%c",LF);
|
||||
printf("tomato, onions, mayo, and Italian sauce.<P>%c",LF);
|
||||
printf("<INPUT TYPE=\"checkbox\" NAME=\"sub\" VALUE=\"9\">%s:%c",sublist[9],LF);
|
||||
printf("1/4 pound of sliced roast beef, provolone cheese, topped with lettuce, tomato, and mayo.<P>%c",LF);
|
||||
printf("<INPUT TYPE=\"checkbox\" NAME=\"sub\" VALUE=\"10\">%s:%c",sublist[10],LF);
|
||||
printf("Turkey breast, smoked ham, and provolonecheese topped with lettuce, tomato, and mayo.<P>%c",LF);
|
||||
printf("<INPUT TYPE=\"checkbox\" NAME=\"sub\" VALUE=\"11\">%s:%c",sublist[11],LF);
|
||||
printf("Turkey breast, avocado, and cheese topped with lettuce, mayo, alfalfa, and tomato.<P>%c",LF);
|
||||
printf("<H3>Slim Jim Subs</H3>%c",LF);
|
||||
printf("Subs without veggies or sauce.<P>%c",LF);
|
||||
printf("<INPUT TYPE=\"checkbox\" NAME=\"slj\" VALUE=\"0\">%s<P>%c",slimlist[0],LF);
|
||||
printf("<INPUT TYPE=\"checkbox\" NAME=\"slj\" VALUE=\"1\">%s<P>%c",slimlist[1],LF);
|
||||
printf("<INPUT TYPE=\"checkbox\" NAME=\"slj\" VALUE=\"2\">%s<P>%c",slimlist[2],LF);
|
||||
printf("<INPUT TYPE=\"checkbox\" NAME=\"slj\" VALUE=\"3\">%s<P>%c",slimlist[3],LF);
|
||||
printf("<INPUT TYPE=\"checkbox\" NAME=\"slj\" VALUE=\"4\">%s<P>%c",slimlist[4],LF);
|
||||
printf("<INPUT TYPE=\"checkbox\" NAME=\"slj\" VALUE=\"5\">%s<P>%c",slimlist[5],LF);
|
||||
printf("<H3>Side orders</H3>%c",LF);
|
||||
printf("<INPUT TYPE=\"checkbox\" NAME=\"sde\" VALUE=\"0\">%s<P>%c",sidelist[0],LF);
|
||||
printf("<INPUT TYPE=\"checkbox\" NAME=\"sde\" VALUE=\"1\">%s<P>%c",sidelist[1],LF);
|
||||
printf("<H3>Drinks</H3>%c",LF);
|
||||
printf("<INPUT TYPE=\"checkbox\" NAME=\"pop\" VALUE=\"0\">%s<P>%c",poplist[0],LF);
|
||||
printf("<INPUT TYPE=\"checkbox\" NAME=\"pop\" VALUE=\"1\">%s<P>%c",poplist[1],LF);
|
||||
printf("<INPUT TYPE=\"checkbox\" NAME=\"pop\" VALUE=\"2\">%s<P>%c",poplist[2],LF);
|
||||
printf("<INPUT TYPE=\"checkbox\" NAME=\"pop\" VALUE=\"3\">%s<P>%c",poplist[3],LF);
|
||||
printf("<H3>Your Address, Phone Number, and Name</H3>%c",LF);
|
||||
printf("<INPUT TYPE=\"text\" NAME=\"name\" MAXLENGTH=\"32\">Name<P>%c",LF);
|
||||
printf("<INPUT TYPE=\"text\" NAME=\"adr\" MAXLENGTH=\"64\">Address<P>%c",LF);
|
||||
printf("<INPUT TYPE=\"text\" NAME=\"phone\" MAXLENGTH=\"10\">Phone Number<P>%c",LF);
|
||||
printf("<INPUT type=\"submit\">%c",LF);
|
||||
printf("</FORM>%c",LF);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void print_error(char *reason) {
|
||||
printf("<TITLE>Order Not Submitted</TITLE>%c",LF);
|
||||
printf("<H1>Order Not Submitted</H1>%c",LF);
|
||||
printf("Your order has not been submitted, because %s.<P>%c",reason,LF);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
main(int argc, char *argv[]) {
|
||||
register int x,m=0;
|
||||
char *cl;
|
||||
char w[256];
|
||||
char tfile[L_tmpnam];
|
||||
int subs,slims,sides,drinks,allow;
|
||||
char name[32];
|
||||
char phone[10];
|
||||
char address[64];
|
||||
FILE *tfp,*order;
|
||||
|
||||
printf("Content-type: text/html%c%c",LF,LF);
|
||||
|
||||
cl=getenv("QUERY_STRING");
|
||||
if((!cl) || (!cl[0]))
|
||||
dump_form();
|
||||
|
||||
tmpnam(tfile);
|
||||
if(!(tfp=fopen(tfile,"w"))) {
|
||||
printf("<TITLE>Server Error</TITLE>%c",LF);
|
||||
printf("<H1>Server Error</H1>%c",LF);
|
||||
printf("Server unable to get a temporary file. Please try again later.<P>%c",LF);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
subs=0;slims=0;sides=0;drinks=0;allow=0;
|
||||
name[0]='\0';
|
||||
phone[0]='\0';
|
||||
address[0]='\0';
|
||||
|
||||
for(x=0;cl[0] != '\0'; x++) {
|
||||
m=x;
|
||||
getword(w,cl,'=');
|
||||
plustospace(w);
|
||||
unescape_url(w);
|
||||
if(!strcmp(w,"pwd")) {
|
||||
getword(w,cl,'&');
|
||||
plustospace(w);
|
||||
unescape_url(w);
|
||||
allow=(strcmp(w,PASSWORD) ? 0 : 1);
|
||||
}
|
||||
if(!strcmp(w,"sub")) {
|
||||
getword(w,cl,'&');
|
||||
plustospace(w);
|
||||
unescape_url(w);
|
||||
subs |= (1 << atoi(w));
|
||||
}
|
||||
else if(!strcmp(w,"slj")) {
|
||||
getword(w,cl,'&');
|
||||
plustospace(w);
|
||||
unescape_url(w);
|
||||
slims |= (1 << atoi(w));
|
||||
}
|
||||
else if(!strcmp(w,"sde")) {
|
||||
getword(w,cl,'&');
|
||||
plustospace(w);
|
||||
unescape_url(w);
|
||||
sides |= (1 << atoi(w));
|
||||
}
|
||||
else if(!strcmp(w,"pop")) {
|
||||
getword(w,cl,'&');
|
||||
plustospace(w);
|
||||
unescape_url(w);
|
||||
drinks |= (1 << atoi(w));
|
||||
}
|
||||
else if(!strcmp(w,"name")) {
|
||||
getword(w,cl,'&');
|
||||
plustospace(w);
|
||||
unescape_url(w);
|
||||
strcpy(name,w);
|
||||
}
|
||||
else if(!strcmp(w,"phone")) {
|
||||
getword(w,cl,'&');
|
||||
plustospace(w);
|
||||
unescape_url(w);
|
||||
strcpy(phone,w);
|
||||
}
|
||||
else if(!strcmp(w,"adr")) {
|
||||
getword(w,cl,'&');
|
||||
plustospace(w);
|
||||
unescape_url(w);
|
||||
strcpy(address,w);
|
||||
}
|
||||
}
|
||||
|
||||
if(!name[0]) print_error("you didn't give your name");
|
||||
if(!address[0]) print_error("you didn't give your address");
|
||||
if(!phone[0]) print_error("you didn't give your phone number");
|
||||
if((!subs) && (!slims) && (!sides) && (!drinks)) print_error("you didn't order anything");
|
||||
|
||||
if(allow) {
|
||||
char t[256];
|
||||
sprintf(t,"/bin/mail %s",JJ_FAX);
|
||||
if(!(order=popen(t,"w")))
|
||||
print_error("the server was unable to open a pipe to mail");
|
||||
printf("<TITLE>Order Sent</TITLE>%c",LF);
|
||||
printf("<H1>Order Sent</H1>%c",LF);
|
||||
printf("Your order has been sent to the UIUC e-mail to FAX gateway.<P>%c",LF);
|
||||
} else {
|
||||
printf("<TITLE>Your Order</TITLE>%c",LF);
|
||||
printf("<H1>Your Order</H1>%c",LF);
|
||||
printf("This is how your order would have looked if it had been sent.<P><PLAINTEXT>%c",LF);
|
||||
order=stdout;
|
||||
}
|
||||
|
||||
fprintf(order,"My name is %s, and I would like to have the following%c",
|
||||
name,LF);
|
||||
fprintf(order,"order delivered to %s:%c%c",address,LF,LF);
|
||||
for(x=0;x<12;x++)
|
||||
if(subs & (1 << x))
|
||||
fprintf(order,"\t(1) %s%c",sublist[x],LF);
|
||||
for(x=0;x<6;x++)
|
||||
if(slims & (1 << x))
|
||||
fprintf(order,"\t(1) %s Slim Jim%c",slimlist[x],LF);
|
||||
for(x=0;x<2;x++)
|
||||
if(sides & (1 << x))
|
||||
fprintf(order,"\t(1) %s%c",sidelist[x],LF);
|
||||
for(x=0;x<4;x++)
|
||||
if(drinks & (1 << x))
|
||||
fprintf(order,"\t(1) %s%c",poplist[x],LF);
|
||||
fprintf(order,"%cPlease feel free to call me at %s if there is any%c",LF,
|
||||
phone,LF);
|
||||
fprintf(order,"problem. Thank you.%c%c.%c",LF,LF,LF);
|
||||
fclose(order);
|
||||
exit(0);
|
||||
}
|
195
cgi-src/phf.c
Executable file
195
cgi-src/phf.c
Executable file
@ -0,0 +1,195 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define LF 10
|
||||
#define HTML_BREAK printf("<P>%c", LF);
|
||||
typedef struct {
|
||||
char name[128];
|
||||
char val[128];
|
||||
} entry;
|
||||
|
||||
typedef struct {
|
||||
char qfield[256];
|
||||
int qlen;
|
||||
char qname[256];
|
||||
} fields;
|
||||
|
||||
void getword(char *word, char *line, char stop);
|
||||
char x2c(char *what);
|
||||
void unescape_url(char *url);
|
||||
void plustospace(char *str);
|
||||
void send_fd(FILE *f, FILE *fd);
|
||||
void send_doc(int which);
|
||||
|
||||
static fields idxfields[] = { {"Qalias", 32, "Alias"},
|
||||
{"Qname", 256, "Name" },
|
||||
{"Qemail", 128, "E-mail Address"},
|
||||
{"Qnickname", 120, "Nickname"},
|
||||
{"Qoffice_phone", 60, "Office Phone Number"},
|
||||
{"Qcallsign", 16, "HAM Callsign"},
|
||||
{"Qproxy", 64, "Proxy"},
|
||||
{"Qhigh_school", 30, "High School"},
|
||||
{"Qslip", 256, "SLIP Address"},
|
||||
{NULL, 0, NULL}
|
||||
};
|
||||
|
||||
static fields othersearchfields[] = { {"Qcurriculum", 64, "Curriculum"},
|
||||
{"Qphone", 64, "Phone Number" },
|
||||
{"Qaddress", 128, "Address"},
|
||||
{"Qoffice_address", 128, "Office Address"},
|
||||
{"Qhome_address", 128, "Home Address"},
|
||||
{"Qpermanent_address", 128, "Permanent Address"},
|
||||
{"Qpermanent_phone", 60, "Permanent Phone"},
|
||||
{"Qdepartment", 64, "Department"},
|
||||
{"Qtitle", 64, "Title"},
|
||||
{"Qproject", 256, "Project"},
|
||||
{"Qother", 256, "Other"},
|
||||
{"Qbirthday", 24, "Birthday"},
|
||||
{"Qcolleges", 120, "Colleges Attended"},
|
||||
{"Qleft_uiuc", 24, "Date/Month Person left UIUC"},
|
||||
{NULL, 0, NULL},
|
||||
};
|
||||
|
||||
void send_doc(int which) {
|
||||
int x;
|
||||
|
||||
printf("<TITLE>Form for CSO PH query</TITLE>%c", LF);
|
||||
printf("<H1>Form for CSO PH query</H1>%c", LF);
|
||||
printf("This form will send a PH query to the specified ph server.%c", LF);
|
||||
HTML_BREAK
|
||||
printf("<HR>%c", LF);
|
||||
|
||||
printf("<FORM ACTION=\"http://%s:%s%s\">%c", getenv("SERVER_NAME"),
|
||||
getenv("SERVER_PORT"), getenv("SCRIPT_NAME"), LF);
|
||||
|
||||
printf("PH Server:<INPUT TYPE=\"text\" NAME=\"Jserver\" VALUE=\"ns.uiuc.edu\" MAXLENGTH=\"256\">%c", LF);
|
||||
HTML_BREAK
|
||||
|
||||
printf("<H3>At least one of these fields must be specified:</H3><UL>%c",LF);
|
||||
for(x=0; idxfields[x].qlen != 0; x++)
|
||||
printf("<LI><INPUT TYPE=\"text\" NAME=\"%s\" MAXLENGTH=\"%d\">%s%c"
|
||||
,idxfields[x].qfield, idxfields[x].qlen, idxfields[x].qname,LF);
|
||||
|
||||
printf("</UL>%c", LF);
|
||||
|
||||
if (!(which&0x10)) {
|
||||
printf("<A HREF=\"%s?Jform=%d\"><H3>Show additional fields to narrow query</H3></A>%c", getenv("SCRIPT_NAME"), (which | 0x10), LF);
|
||||
}
|
||||
else {
|
||||
printf("<H3>Additional fields to narrow query:</H3><UL>%c",LF);
|
||||
|
||||
for(x=0; othersearchfields[x].qlen != 0; x++)
|
||||
printf("<LI><INPUT TYPE=\"text\" NAME=\"%s\" MAXLENGTH=\"%d\">%s%c"
|
||||
,othersearchfields[x].qfield, othersearchfields[x].qlen,
|
||||
othersearchfields[x].qname,LF);
|
||||
|
||||
printf("</UL>%c", LF);
|
||||
|
||||
printf("<A HREF=\"%s?Jform=%d\">Show fewer query fields</A>%c", getenv("SCRIPT_NAME"), (which & 0x01), LF);
|
||||
}
|
||||
|
||||
HTML_BREAK
|
||||
|
||||
if (!(which & 0x01)) {
|
||||
printf("<A HREF=\"%s?Jform=%d\"><H3>Return more than default fields</H3></A>%c", getenv("SCRIPT_NAME"), (which | 0x01), LF);
|
||||
}
|
||||
else {
|
||||
printf("<H3>Fields to return:</H3><UL>%c", LF);
|
||||
|
||||
for(x=0; idxfields[x].qlen != 0; x++)
|
||||
printf("<LI><INPUT TYPE=\"checkbox\" NAME=\"return\" VALUE=\"%s\">%s%c", &(idxfields[x].qfield[1]), idxfields[x].qname, LF);
|
||||
|
||||
for(x=0; othersearchfields[x].qlen != 0; x++)
|
||||
printf("<LI><INPUT TYPE=\"checkbox\" NAME=\"return\" VALUE=\"%s\">%s%c", &(othersearchfields[x].qfield[1]), othersearchfields[x].qname, LF);
|
||||
|
||||
printf("</UL>%c", LF);
|
||||
|
||||
printf("<A HREF=\"%s?Jform=%d\">Return default fields</A>%c", getenv("SCRIPT_NAME"), (which & 0x10), LF);
|
||||
}
|
||||
|
||||
HTML_BREAK
|
||||
printf("<INPUT TYPE=\"submit\">%c", LF);
|
||||
printf("</FORM>%c", LF);
|
||||
|
||||
printf("<HR>%c<ADDRESS>", LF);
|
||||
printf("Questions, comments to: <a href=\"http://www.ncsa.uiuc.edu/SDG/People/jbrowne/jbrowne.html\">Jim Browne</a>%c", LF);
|
||||
printf("</ADDRESS>%c", LF);
|
||||
|
||||
}
|
||||
|
||||
main(int argc, char *argv[]) {
|
||||
entry entries[64];
|
||||
register int x,m=0;
|
||||
char *cl;
|
||||
char returnstr[1024], typestr[4098], commandstr[8192], serverstr[256];
|
||||
int atleastonereturn = 0, atleastonequery = 0, which = 0;
|
||||
FILE *phfp;
|
||||
|
||||
printf("Content-type: text/html%c%c",LF,LF);
|
||||
|
||||
strcpy(returnstr, "return ");
|
||||
strcpy(typestr, " ");
|
||||
|
||||
cl = getenv("QUERY_STRING");
|
||||
|
||||
if((!cl) || (!cl[0])) {
|
||||
send_doc(0);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for(x=0;cl[0] != '\0';x++) {
|
||||
m=x;
|
||||
getword(entries[x].val,cl,'&');
|
||||
plustospace(entries[x].val);
|
||||
unescape_url(entries[x].val);
|
||||
getword(entries[x].name,entries[x].val,'=');
|
||||
}
|
||||
|
||||
for(x=0; x <= m; x++) {
|
||||
/* printf("%s = %s %c", entries[x].name, entries[x].val, LF); */
|
||||
|
||||
if (!strcmp(entries[x].name, "return")) {
|
||||
strcat(returnstr, entries[x].val);
|
||||
strcat(returnstr, " ");
|
||||
atleastonereturn = 1;
|
||||
}
|
||||
else if ((entries[x].name[0] == 'Q') && strlen(entries[x].val)) {
|
||||
strcat(typestr, &(entries[x].name[1]));
|
||||
strcat(typestr, "=");
|
||||
strcat(typestr, entries[x].val);
|
||||
strcat(typestr, " ");
|
||||
atleastonequery = 1;
|
||||
}
|
||||
else if (!strcmp(entries[x].name, "Jserver"))
|
||||
strcpy(serverstr, entries[x].val);
|
||||
else if (!strcmp(entries[x].name, "Jform"))
|
||||
if (sscanf(entries[x].val, "%d", &which)) {
|
||||
send_doc(which);
|
||||
exit(1);
|
||||
}
|
||||
else exit(1);
|
||||
}
|
||||
|
||||
printf("<H1>Query Results</H1>%c", LF);
|
||||
HTML_BREAK
|
||||
|
||||
if (!atleastonequery) printf("<B>You did not enter a query!</B>%c",LF);
|
||||
else {
|
||||
strcpy(commandstr, "/usr/local/bin/ph -m ");
|
||||
if (strlen(serverstr)) {
|
||||
strcat(commandstr, " -s ");
|
||||
strcat(commandstr, serverstr);
|
||||
strcat(commandstr, " ");
|
||||
}
|
||||
strcat(commandstr, typestr);
|
||||
if (atleastonereturn) strcat(commandstr, returnstr);
|
||||
|
||||
printf("%s%c", commandstr, LF);
|
||||
printf("<PRE>%c", LF);
|
||||
|
||||
phfp = popen(commandstr,"r");
|
||||
send_fd(phfp, stdout);
|
||||
|
||||
printf("</PRE>%c", LF);
|
||||
}
|
||||
}
|
56
cgi-src/post-query.c
Normal file
56
cgi-src/post-query.c
Normal file
@ -0,0 +1,56 @@
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define MAX_ENTRIES 10000
|
||||
|
||||
typedef struct {
|
||||
char *name;
|
||||
char *val;
|
||||
} entry;
|
||||
|
||||
char *makeword(char *line, char stop);
|
||||
char *fmakeword(FILE *f, char stop, int *len);
|
||||
char x2c(char *what);
|
||||
void unescape_url(char *url);
|
||||
void plustospace(char *str);
|
||||
|
||||
|
||||
main(int argc, char *argv[]) {
|
||||
entry entries[MAX_ENTRIES];
|
||||
register int x,m=0;
|
||||
int cl;
|
||||
|
||||
printf("Content-type: text/html%c%c",10,10);
|
||||
|
||||
if(strcmp(getenv("REQUEST_METHOD"),"POST")) {
|
||||
printf("This script should be referenced with a METHOD of POST.\n");
|
||||
printf("If you don't understand this, see this ");
|
||||
printf("<A HREF=\"http://www.ncsa.uiuc.edu/SDG/Software/Mosaic/Docs/fill-out-forms/overview.html\">forms overview</A>.%c",10);
|
||||
exit(1);
|
||||
}
|
||||
if(strcmp(getenv("CONTENT_TYPE"),"application/x-www-form-urlencoded")) {
|
||||
printf("This script can only be used to decode form results. \n");
|
||||
exit(1);
|
||||
}
|
||||
cl = atoi(getenv("CONTENT_LENGTH"));
|
||||
|
||||
for(x=0;cl && (!feof(stdin));x++) {
|
||||
m=x;
|
||||
entries[x].val = fmakeword(stdin,'&',&cl);
|
||||
plustospace(entries[x].val);
|
||||
unescape_url(entries[x].val);
|
||||
entries[x].name = makeword(entries[x].val,'=');
|
||||
}
|
||||
|
||||
printf("<H1>Query Results</H1>");
|
||||
printf("You submitted the following name/value pairs:<p>%c",10);
|
||||
printf("<ul>%c",10);
|
||||
|
||||
for(x=0; x <= m; x++)
|
||||
printf("<li> <code>%s = %s</code>%c",entries[x].name,
|
||||
entries[x].val,10);
|
||||
printf("</ul>%c",10);
|
||||
}
|
54
cgi-src/query.c
Executable file
54
cgi-src/query.c
Executable file
@ -0,0 +1,54 @@
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef struct {
|
||||
char name[128];
|
||||
char val[128];
|
||||
} entry;
|
||||
|
||||
void getword(char *word, char *line, char stop);
|
||||
char x2c(char *what);
|
||||
void unescape_url(char *url);
|
||||
void plustospace(char *str);
|
||||
|
||||
|
||||
|
||||
main(int argc, char *argv[]) {
|
||||
entry entries[10000];
|
||||
register int x,m=0;
|
||||
char *cl;
|
||||
|
||||
printf("Content-type: text/html%c%c",10,10);
|
||||
|
||||
if(strcmp(getenv("REQUEST_METHOD"),"GET")) {
|
||||
printf("This script should be referenced with a METHOD of GET.\n");
|
||||
printf("If you don't understand this, see this ");
|
||||
printf("<A HREF=\"http://www.ncsa.uiuc.edu/SDG/Software/Mosaic/Docs/fill-out-forms/overview.html\">forms overview</A>.%c",10);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
cl = getenv("QUERY_STRING");
|
||||
if(cl == NULL) {
|
||||
printf("No query information to decode.\n");
|
||||
exit(1);
|
||||
}
|
||||
for(x=0;cl[0] != '\0';x++) {
|
||||
m=x;
|
||||
getword(entries[x].val,cl,'&');
|
||||
plustospace(entries[x].val);
|
||||
unescape_url(entries[x].val);
|
||||
getword(entries[x].name,entries[x].val,'=');
|
||||
}
|
||||
|
||||
printf("<H1>Query Results</H1>");
|
||||
printf("You submitted the following name/value pairs:<p>%c",10);
|
||||
printf("<ul>%c",10);
|
||||
|
||||
for(x=0; x <= m; x++)
|
||||
printf("<li> <code>%s = %s</code>%c",entries[x].name,
|
||||
entries[x].val,10);
|
||||
printf("</ul>%c",10);
|
||||
}
|
122
cgi-src/util.c
Normal file
122
cgi-src/util.c
Normal file
@ -0,0 +1,122 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#define LF 10
|
||||
#define CR 13
|
||||
|
||||
void getword(char *word, char *line, char stop) {
|
||||
int x = 0,y;
|
||||
|
||||
for(x=0;((line[x]) && (line[x] != stop));x++)
|
||||
word[x] = line[x];
|
||||
|
||||
word[x] = '\0';
|
||||
if(line[x]) ++x;
|
||||
y=0;
|
||||
|
||||
while(line[y++] = line[x++]);
|
||||
}
|
||||
|
||||
char *makeword(char *line, char stop) {
|
||||
int x = 0,y;
|
||||
char *word = (char *) malloc(sizeof(char) * (strlen(line) + 1));
|
||||
|
||||
for(x=0;((line[x]) && (line[x] != stop));x++)
|
||||
word[x] = line[x];
|
||||
|
||||
word[x] = '\0';
|
||||
if(line[x]) ++x;
|
||||
y=0;
|
||||
|
||||
while(line[y++] = line[x++]);
|
||||
return word;
|
||||
}
|
||||
|
||||
char *fmakeword(FILE *f, char stop, int *cl) {
|
||||
int wsize;
|
||||
char *word;
|
||||
int ll;
|
||||
|
||||
wsize = 102400;
|
||||
ll=0;
|
||||
word = (char *) malloc(sizeof(char) * (wsize + 1));
|
||||
|
||||
while(1) {
|
||||
word[ll] = (char)fgetc(f);
|
||||
if(ll==wsize) {
|
||||
word[ll+1] = '\0';
|
||||
wsize+=102400;
|
||||
word = (char *)realloc(word,sizeof(char)*(wsize+1));
|
||||
}
|
||||
--(*cl);
|
||||
if((word[ll] == stop) || (feof(f)) || (!(*cl))) {
|
||||
if(word[ll] != stop) ll++;
|
||||
word[ll] = '\0';
|
||||
return word;
|
||||
}
|
||||
++ll;
|
||||
}
|
||||
}
|
||||
|
||||
char x2c(char *what) {
|
||||
register char digit;
|
||||
|
||||
digit = (what[0] >= 'A' ? ((what[0] & 0xdf) - 'A')+10 : (what[0] - '0'));
|
||||
digit *= 16;
|
||||
digit += (what[1] >= 'A' ? ((what[1] & 0xdf) - 'A')+10 : (what[1] - '0'));
|
||||
return(digit);
|
||||
}
|
||||
|
||||
void unescape_url(char *url) {
|
||||
register int x,y;
|
||||
|
||||
for(x=0,y=0;url[y];++x,++y) {
|
||||
if((url[x] = url[y]) == '%') {
|
||||
url[x] = x2c(&url[y+1]);
|
||||
y+=2;
|
||||
}
|
||||
}
|
||||
url[x] = '\0';
|
||||
}
|
||||
|
||||
void plustospace(char *str) {
|
||||
register int x;
|
||||
|
||||
for(x=0;str[x];x++) if(str[x] == '+') str[x] = ' ';
|
||||
}
|
||||
|
||||
int rind(char *s, char c) {
|
||||
register int x;
|
||||
for(x=strlen(s) - 1;x != -1; x--)
|
||||
if(s[x] == c) return x;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int getline(char *s, int n, FILE *f) {
|
||||
register int i=0;
|
||||
|
||||
while(1) {
|
||||
s[i] = (char)fgetc(f);
|
||||
|
||||
if(s[i] == CR)
|
||||
s[i] = fgetc(f);
|
||||
|
||||
if((s[i] == 0x4) || (s[i] == LF) || (i == (n-1))) {
|
||||
s[i] = '\0';
|
||||
return (feof(f) ? 1 : 0);
|
||||
}
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
void send_fd(FILE *f, FILE *fd)
|
||||
{
|
||||
int num_chars=0;
|
||||
char c;
|
||||
|
||||
while (1) {
|
||||
c = fgetc(f);
|
||||
if(feof(f))
|
||||
return;
|
||||
fputc(c,fd);
|
||||
}
|
||||
}
|
36
conf/access.conf-dist
Normal file
36
conf/access.conf-dist
Normal file
@ -0,0 +1,36 @@
|
||||
# access.conf: Global access configuration
|
||||
# Online docs at http://hoohoo.ncsa.uiuc.edu/
|
||||
# I suggest you consult them; this is important and confusing stuff.
|
||||
|
||||
# /usr/local/etc/httpd/ should be changed to whatever you set ServerRoot to.
|
||||
<Directory /usr/local/etc/httpd/cgi-bin>
|
||||
Options Indexes FollowSymLinks
|
||||
</Directory>
|
||||
|
||||
# This should be changed to whatever you set DocumentRoot to.
|
||||
|
||||
<Directory /usr/local/etc/httpd/htdocs>
|
||||
|
||||
# This may also be "None", "All", or any combination of "Indexes",
|
||||
# "Includes", or "FollowSymLinks"
|
||||
|
||||
Options Indexes FollowSymLinks
|
||||
|
||||
# This controls which options the .htaccess files in directories can
|
||||
# override. Can also be "None", or any combination of "Options", "FileInfo",
|
||||
# "AuthConfig", and "Limit"
|
||||
|
||||
AllowOverride All
|
||||
|
||||
# Controls who can get stuff from this server.
|
||||
|
||||
<Limit GET>
|
||||
order allow,deny
|
||||
allow from all
|
||||
</Limit>
|
||||
|
||||
</Directory>
|
||||
|
||||
# You may place any other directories you wish to have access
|
||||
# information for after this one.
|
||||
|
59
conf/httpd.conf-dist
Normal file
59
conf/httpd.conf-dist
Normal file
@ -0,0 +1,59 @@
|
||||
# This is the main server configuration file. It is best to
|
||||
# leave the directives in this file in the order they are in, or
|
||||
# things may not go the way you'd like. See URL http://hoohoo.ncsa.uiuc.edu/
|
||||
# for instructions.
|
||||
|
||||
# Do NOT simply read the instructions in here without understanding
|
||||
# what they do, if you are unsure consult the online docs. You have been
|
||||
# warned.
|
||||
|
||||
# Rob McCool (comments, questions to httpd@ncsa.uiuc.edu)
|
||||
|
||||
# ServerType is either inetd, or standalone.
|
||||
|
||||
ServerType standalone
|
||||
|
||||
# If you are running from inetd, go to "ServerAdmin".
|
||||
|
||||
# Port: The port the standalone listens to. For ports < 1023, you will
|
||||
# need httpd to be run as root initially.
|
||||
|
||||
Port 80
|
||||
|
||||
# If you wish httpd to run as a different user or group, you must run
|
||||
# httpd as root initially and it will switch.
|
||||
|
||||
# User/Group: The name (or #number) of the user/group to run httpd as.
|
||||
|
||||
User nobody
|
||||
Group #-1
|
||||
|
||||
# ServerAdmin: Your address, where problems with the server should be
|
||||
# e-mailed.
|
||||
|
||||
ServerAdmin you@your.address
|
||||
|
||||
# ServerRoot: The directory the server's config, error, and log files
|
||||
# are kept in
|
||||
|
||||
ServerRoot /usr/local/etc/httpd
|
||||
|
||||
# ErrorLog: The location of the error log file. If this does not start
|
||||
# with /, ServerRoot is prepended to it.
|
||||
|
||||
ErrorLog logs/error_log
|
||||
|
||||
# TransferLog: The location of the transfer log file. If this does not
|
||||
# start with /, ServerRoot is prepended to it.
|
||||
|
||||
TransferLog logs/access_log
|
||||
|
||||
# PidFile: The file the server should log its pid to
|
||||
PidFile logs/httpd.pid
|
||||
|
||||
# ServerName allows you to set a host name which is sent back to clients for
|
||||
#your server if it's different than the one the program would get (i.e. use
|
||||
#"www" instead of the host's real name).
|
||||
|
||||
#ServerName new.host.name
|
||||
|
82
conf/mime.types
Normal file
82
conf/mime.types
Normal file
@ -0,0 +1,82 @@
|
||||
# This is a comment. I love comments.
|
||||
|
||||
|
||||
application/activemessage
|
||||
application/andrew-inset
|
||||
application/applefile
|
||||
application/atomicmail
|
||||
application/dca-rft
|
||||
application/dec-dx
|
||||
application/mac-binhex40
|
||||
application/macwriteii
|
||||
application/msword
|
||||
application/news-message-id
|
||||
application/news-transmission
|
||||
application/octet-stream bin
|
||||
application/oda oda
|
||||
application/pdf pdf
|
||||
application/postscript ai eps ps
|
||||
application/remote-printing
|
||||
application/rtf rtf
|
||||
application/slate
|
||||
application/x-mif mif
|
||||
application/wita
|
||||
application/wordperfect5.1
|
||||
application/x-csh csh
|
||||
application/x-dvi dvi
|
||||
application/x-hdf hdf
|
||||
application/x-latex latex
|
||||
application/x-netcdf nc cdf
|
||||
application/x-sh sh
|
||||
application/x-tcl tcl
|
||||
application/x-tex tex
|
||||
application/x-texinfo texinfo texi
|
||||
application/x-troff t tr roff
|
||||
application/x-troff-man man
|
||||
application/x-troff-me me
|
||||
application/x-troff-ms ms
|
||||
application/x-wais-source src
|
||||
application/zip zip
|
||||
application/x-bcpio bcpio
|
||||
application/x-cpio cpio
|
||||
application/x-gtar gtar
|
||||
application/x-shar shar
|
||||
application/x-sv4cpio sv4cpio
|
||||
application/x-sv4crc sv4crc
|
||||
application/x-tar tar
|
||||
application/x-ustar ustar
|
||||
audio/basic au snd
|
||||
audio/x-aiff aif aiff aifc
|
||||
audio/x-wav wav
|
||||
image/gif gif
|
||||
image/ief ief
|
||||
image/jpeg jpeg jpg jpe
|
||||
image/tiff tiff tif
|
||||
image/x-cmu-raster ras
|
||||
image/x-portable-anymap pnm
|
||||
image/x-portable-bitmap pbm
|
||||
image/x-portable-graymap pgm
|
||||
image/x-portable-pixmap ppm
|
||||
image/x-rgb rgb
|
||||
image/x-xbitmap xbm
|
||||
image/x-xpixmap xpm
|
||||
image/x-xwindowdump xwd
|
||||
message/external-body
|
||||
message/news
|
||||
message/partial
|
||||
message/rfc822
|
||||
multipart/alternative
|
||||
multipart/appledouble
|
||||
multipart/digest
|
||||
multipart/mixed
|
||||
multipart/parallel
|
||||
text/html html
|
||||
text/plain txt
|
||||
text/richtext rtx
|
||||
text/tab-separated-values tsv
|
||||
text/x-setext etx
|
||||
video/mpeg mpeg mpg mpe
|
||||
video/quicktime qt mov
|
||||
video/x-msvideo avi
|
||||
video/x-sgi-movie movie
|
||||
|
88
conf/srm.conf-dist
Normal file
88
conf/srm.conf-dist
Normal file
@ -0,0 +1,88 @@
|
||||
# With this document, you define the name space that users see of your http
|
||||
# server.
|
||||
|
||||
# Rob (robm@ncsa.uiuc.edu)
|
||||
|
||||
|
||||
# DocumentRoot: The directory out of which you will serve your
|
||||
# documents. By default, all requests are taken from this directory, but
|
||||
# symbolic links and aliases may be used to point to other locations.
|
||||
|
||||
DocumentRoot /usr/local/etc/httpd/htdocs
|
||||
|
||||
# UserDir: The name of the directory which is appended onto a user's home
|
||||
# directory if a ~user request is recieved.
|
||||
|
||||
UserDir public_html
|
||||
|
||||
# DirectoryIndex: Name of the file to use as a pre-written HTML
|
||||
# directory index
|
||||
|
||||
DirectoryIndex index.html
|
||||
|
||||
# FancyIndexing is whether you want fancy directory indexing or standard
|
||||
|
||||
FancyIndexing on
|
||||
|
||||
# AddIcon tells the server which icon to show for different files or filename
|
||||
# extensions
|
||||
|
||||
AddIcon /icons/text.xbm .html .txt
|
||||
AddIcon /icons/image.xbm .gif .jpg .xbm .tiff
|
||||
AddIcon /icons/sound.xbm .au
|
||||
AddIcon /icons/movie.xbm .mpg
|
||||
AddIcon /icons/binary.xbm .bin
|
||||
AddIcon /icons/back.xbm ..
|
||||
AddIcon /icons/menu.xbm **DIRECTORY**
|
||||
|
||||
# DefaultIcon is which icon to show for files which do not have an icon
|
||||
# explicitly set.
|
||||
|
||||
DefaultIcon /icons/unknown.xbm
|
||||
|
||||
# AddDescription allows you to place a short description after a file in
|
||||
# server-generated indexes.
|
||||
# Format: AddDescription "description" filename
|
||||
|
||||
# ReadmeName is the name of the README file the server will look for by
|
||||
# default. Format: ReadmeName name
|
||||
#
|
||||
# The server will first look for name.html, include it if found, and it will
|
||||
# then look for name and include it as plaintext if found.
|
||||
|
||||
ReadmeName README
|
||||
|
||||
# IndexIgnore is a set of filenames which directory indexing should ignore
|
||||
# Format: IndexIgnore name1 name2...
|
||||
|
||||
IndexIgnore /.htaccess ~ #
|
||||
|
||||
# AccessFileName: The name of the file to look for in each directory
|
||||
# for access control information.
|
||||
|
||||
AccessFileName .htaccess
|
||||
|
||||
# DefaultType is the default MIME type for documents which the server
|
||||
# cannot find the type of from filename extensions.
|
||||
|
||||
DefaultType text/plain
|
||||
|
||||
# AddType allows you to tweak mime.types without actually editing it, or to
|
||||
# make certain files to be certain types.
|
||||
# Format: AddType type/subtype ext1
|
||||
|
||||
# Redirect allows you to tell clients about documents which used to exist in
|
||||
# your server's namespace, but do not anymore. This allows you to tell the
|
||||
# clients where to look for the relocated document.
|
||||
# Format: Redirect fakename url
|
||||
|
||||
|
||||
# Aliases: Add here as many aliases as you need, up to 20. The format is
|
||||
# Alias fakename realname
|
||||
|
||||
Alias /icons/ /usr/local/etc/httpd/icons/
|
||||
|
||||
# ScriptAlias: This controls which directories contain server scripts.
|
||||
# Format: ScriptAlias fakename realname
|
||||
|
||||
ScriptAlias /cgi-bin/ /usr/local/etc/httpd/cgi-bin/
|
9
icons/back.xbm
Normal file
9
icons/back.xbm
Normal file
@ -0,0 +1,9 @@
|
||||
#define back_width 20
|
||||
#define back_height 23
|
||||
static char back_bits[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0f,
|
||||
0x00, 0x80, 0x0f, 0x00, 0x80, 0x0f, 0x00, 0x80, 0x0f, 0x00, 0x80, 0x0f,
|
||||
0x00, 0x80, 0x0f, 0x60, 0x80, 0x0f, 0x70, 0x80, 0x0f, 0x78, 0x00, 0x00,
|
||||
0xfc, 0xff, 0x0f, 0xfe, 0xff, 0x07, 0xff, 0xff, 0x03, 0xfe, 0xff, 0x01,
|
||||
0xfc, 0xff, 0x00, 0x78, 0x00, 0x00, 0x70, 0x00, 0x00, 0x60, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
8
icons/ball.xbm
Normal file
8
icons/ball.xbm
Normal file
@ -0,0 +1,8 @@
|
||||
#define ball_width 19
|
||||
#define ball_height 19
|
||||
static unsigned char ball_bits[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0f, 0x00, 0xe0, 0x3f, 0x00,
|
||||
0xf0, 0x7f, 0x00, 0x78, 0xfc, 0x00, 0x38, 0xf8, 0x00, 0x7c, 0xfe, 0x01,
|
||||
0xfc, 0xff, 0x01, 0xfc, 0xff, 0x01, 0xfc, 0xff, 0x01, 0xfc, 0xff, 0x01,
|
||||
0xf8, 0xff, 0x00, 0xf8, 0xff, 0x00, 0xf0, 0x7f, 0x00, 0xe0, 0x3f, 0x00,
|
||||
0x80, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, };
|
9
icons/binary.xbm
Normal file
9
icons/binary.xbm
Normal file
@ -0,0 +1,9 @@
|
||||
#define gopher_binary_width 20
|
||||
#define gopher_binary_height 23
|
||||
static char gopher_binary_bits[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xff, 0x3f, 0x00, 0x01, 0x60, 0x00, 0x01, 0xa0, 0x00, 0x71, 0x26, 0x01,
|
||||
0xd9, 0x26, 0x02, 0xd9, 0xe6, 0x07, 0xd9, 0xc6, 0x0f, 0xd9, 0x06, 0x0c,
|
||||
0x71, 0x06, 0x0c, 0x01, 0x00, 0x0c, 0x99, 0x03, 0x0c, 0xd9, 0x06, 0x0c,
|
||||
0xd9, 0x06, 0x0c, 0xd9, 0x06, 0x0c, 0xd9, 0x06, 0x0c, 0x99, 0x03, 0x0c,
|
||||
0x01, 0x00, 0x0c, 0xff, 0xff, 0x0f, 0xfe, 0xff, 0x0f};
|
9
icons/ftp.xbm
Normal file
9
icons/ftp.xbm
Normal file
@ -0,0 +1,9 @@
|
||||
#define gopher_ftp_width 20
|
||||
#define gopher_ftp_height 23
|
||||
static char gopher_ftp_bits[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xfe, 0xff, 0x07, 0x02, 0x00, 0x0c, 0xba, 0xf7, 0x0c, 0xba, 0xf7, 0x0d,
|
||||
0x1a, 0xb3, 0x0d, 0x3a, 0xb3, 0x0d, 0x3a, 0xf3, 0x0d, 0x1a, 0xf3, 0x0c,
|
||||
0x1a, 0x33, 0x0c, 0x1a, 0x33, 0x0c, 0x02, 0x00, 0x0c, 0xfe, 0xff, 0x0f,
|
||||
0xfc, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0xfe, 0xff, 0x07,
|
||||
0xff, 0xff, 0x0f, 0xfe, 0xff, 0x07, 0x04, 0x00, 0x02};
|
9
icons/image.xbm
Normal file
9
icons/image.xbm
Normal file
@ -0,0 +1,9 @@
|
||||
#define image_width 20
|
||||
#define image_height 23
|
||||
static char image_bits[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xff, 0x3f, 0x00, 0x01, 0x60, 0x00, 0xfd, 0xa0, 0x00, 0xfd, 0x20, 0x01,
|
||||
0xfd, 0x20, 0x02, 0xfd, 0xe8, 0x07, 0xfd, 0xdc, 0x0f, 0xfd, 0x3e, 0x0c,
|
||||
0x01, 0x7f, 0x0c, 0x81, 0xff, 0x0c, 0x01, 0x00, 0x0c, 0x81, 0x0f, 0x0c,
|
||||
0xc1, 0x1f, 0x0c, 0xc1, 0x1f, 0x0c, 0xc1, 0x1f, 0x0c, 0x81, 0x0f, 0x0c,
|
||||
0x01, 0x00, 0x0c, 0xff, 0xff, 0x0f, 0xfe, 0xff, 0x0f};
|
9
icons/index.xbm
Normal file
9
icons/index.xbm
Normal file
@ -0,0 +1,9 @@
|
||||
#define gopher_index_width 20
|
||||
#define gopher_index_height 23
|
||||
static char gopher_index_bits[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xff, 0xff, 0x07, 0x01, 0x00, 0x0c, 0x81, 0x0f, 0x0c, 0x41, 0x18, 0x0c,
|
||||
0x21, 0x33, 0x0c, 0xa1, 0x25, 0x0c, 0xc1, 0x24, 0x0c, 0x01, 0x32, 0x0c,
|
||||
0x01, 0x19, 0x0c, 0x81, 0x0c, 0x0c, 0x81, 0x06, 0x0c, 0x01, 0x07, 0x0c,
|
||||
0x01, 0x07, 0x0c, 0x81, 0x0c, 0x0c, 0x81, 0x0e, 0x0c, 0x01, 0x07, 0x0c,
|
||||
0x01, 0x00, 0x0c, 0xff, 0xff, 0x0f, 0xfe, 0xff, 0x0f};
|
9
icons/menu.xbm
Normal file
9
icons/menu.xbm
Normal file
@ -0,0 +1,9 @@
|
||||
#define gopher_menu_width 20
|
||||
#define gopher_menu_height 23
|
||||
static char gopher_menu_bits[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xf8, 0x01, 0x00, 0x04, 0x02, 0x00, 0x02, 0x04, 0x00, 0x01, 0xf8, 0x01,
|
||||
0x01, 0x00, 0x02, 0x01, 0x00, 0x04, 0x01, 0x00, 0x0e, 0x01, 0x00, 0x0d,
|
||||
0x01, 0x00, 0x0e, 0x01, 0x00, 0x0d, 0x01, 0x00, 0x0e, 0x01, 0x00, 0x0d,
|
||||
0x01, 0x00, 0x0e, 0x01, 0x00, 0x0d, 0x01, 0x00, 0x0e, 0x55, 0x55, 0x0d,
|
||||
0xaa, 0xaa, 0x0e, 0xfc, 0xff, 0x07, 0xf8, 0xff, 0x03};
|
9
icons/movie.xbm
Normal file
9
icons/movie.xbm
Normal file
@ -0,0 +1,9 @@
|
||||
#define gopher_movie_width 20
|
||||
#define gopher_movie_height 23
|
||||
static char gopher_movie_bits[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xff, 0xff, 0x07, 0xf9, 0xff, 0x0c, 0x19, 0xe0, 0x0c, 0x1f, 0xc0, 0x0f,
|
||||
0x19, 0xe0, 0x0c, 0x19, 0xc0, 0x0c, 0x1f, 0xe0, 0x0f, 0x59, 0xd5, 0x0c,
|
||||
0xf9, 0xff, 0x0c, 0xff, 0xff, 0x0f, 0x19, 0xe0, 0x0c, 0x19, 0xc0, 0x0c,
|
||||
0x1f, 0xe0, 0x0f, 0x19, 0xc0, 0x0c, 0x19, 0xe0, 0x0c, 0x5f, 0xd5, 0x0f,
|
||||
0xf9, 0xff, 0x0c, 0xff, 0xff, 0x0f, 0xfe, 0xff, 0x0f};
|
9
icons/sound.xbm
Normal file
9
icons/sound.xbm
Normal file
@ -0,0 +1,9 @@
|
||||
#define gopher_sound_width 20
|
||||
#define gopher_sound_height 23
|
||||
static char gopher_sound_bits[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xff, 0xff, 0x07, 0x01, 0x00, 0x0c, 0x01, 0x40, 0x0c, 0x01, 0x91, 0x0c,
|
||||
0x81, 0x21, 0x0d, 0x41, 0x49, 0x0d, 0x3d, 0x51, 0x0d, 0x05, 0x55, 0x0d,
|
||||
0x05, 0x55, 0x0d, 0x05, 0x55, 0x0d, 0x3d, 0x55, 0x0d, 0x7d, 0x51, 0x0d,
|
||||
0xc1, 0x49, 0x0d, 0x81, 0x21, 0x0d, 0x01, 0x91, 0x0c, 0x01, 0x40, 0x0c,
|
||||
0x01, 0x00, 0x0c, 0xff, 0xff, 0x0f, 0xfe, 0xff, 0x0f};
|
9
icons/telnet.xbm
Normal file
9
icons/telnet.xbm
Normal file
@ -0,0 +1,9 @@
|
||||
#define gopher_telnet_width 20
|
||||
#define gopher_telnet_height 23
|
||||
static char gopher_telnet_bits[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xfe, 0xff, 0x07, 0x02, 0x00, 0x0c, 0x7a, 0x37, 0x0c, 0x7a, 0x37, 0x0c,
|
||||
0x32, 0x33, 0x0c, 0x32, 0x37, 0x0c, 0x32, 0x37, 0x0c, 0x32, 0x33, 0x0c,
|
||||
0x32, 0xf7, 0x0c, 0x32, 0xf7, 0x0c, 0x02, 0x00, 0x0c, 0xfe, 0xff, 0x0f,
|
||||
0xfc, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0xfe, 0xff, 0x07,
|
||||
0xff, 0xff, 0x0f, 0xfe, 0xff, 0x07, 0x04, 0x00, 0x02};
|
9
icons/text.xbm
Normal file
9
icons/text.xbm
Normal file
@ -0,0 +1,9 @@
|
||||
#define gopher_text_width 20
|
||||
#define gopher_text_height 23
|
||||
static char gopher_text_bits[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xff, 0x3f, 0x00, 0x01, 0x60, 0x00, 0x01, 0xa0, 0x00, 0xf9, 0x27, 0x01,
|
||||
0x01, 0x20, 0x02, 0xf1, 0xe7, 0x07, 0x01, 0xc0, 0x0f, 0xf9, 0x07, 0x0c,
|
||||
0x01, 0x00, 0x0c, 0xe1, 0x07, 0x0c, 0x01, 0x00, 0x0c, 0xf9, 0x07, 0x0c,
|
||||
0x01, 0x00, 0x0c, 0xe1, 0x07, 0x0c, 0x01, 0x00, 0x0c, 0xf9, 0x07, 0x0c,
|
||||
0x01, 0x00, 0x0c, 0xff, 0xff, 0x0f, 0xfe, 0xff, 0x0f};
|
9
icons/unknown.xbm
Normal file
9
icons/unknown.xbm
Normal file
@ -0,0 +1,9 @@
|
||||
#define unknown_width 20
|
||||
#define unknown_height 23
|
||||
static char unknown_bits[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xff, 0x3f, 0x00, 0x01, 0x60, 0x00, 0x01, 0xa0, 0x00, 0x01, 0x20, 0x01,
|
||||
0x01, 0x20, 0x02, 0x01, 0xe0, 0x07, 0x01, 0xc0, 0x0f, 0x01, 0x00, 0x0c,
|
||||
0x01, 0x00, 0x0c, 0x01, 0x00, 0x0c, 0x01, 0x00, 0x0c, 0x01, 0x00, 0x0c,
|
||||
0x01, 0x00, 0x0c, 0x01, 0x00, 0x0c, 0x01, 0x00, 0x0c, 0x01, 0x00, 0x0c,
|
||||
0x01, 0x00, 0x0c, 0xff, 0xff, 0x0f, 0xfe, 0xff, 0x0f};
|
100
src/Makefile
Normal file
100
src/Makefile
Normal file
@ -0,0 +1,100 @@
|
||||
# Makefile for NCSA's httpd.
|
||||
|
||||
# For normal machines with ANSI compilers
|
||||
#CC= cc
|
||||
# For Suns or other non-ANSI platforms. Please make sure your gcc is
|
||||
# 2.0 or later, as 1.40 seems to create bad code for the Sun 4.
|
||||
CC= gcc
|
||||
|
||||
# For optimization
|
||||
#CFLAGS= -O2
|
||||
# For debugging information
|
||||
#CFLAGS= -g -DPEM_AUTH
|
||||
CFLAGS= -g
|
||||
|
||||
# Place here any extra libraries you may need to link to. You
|
||||
# shouldn't have to.
|
||||
EXTRA_LIBS=
|
||||
|
||||
# AUX_CFLAGS are system-specific control flags.
|
||||
# NOTE: IF YOU DO NOT CHOOSE ONE OF THESE, EDIT httpd.h AND CHOOSE
|
||||
# SETTINGS FOR THE SYSTEM FLAGS. IF YOU DON'T, BAD THINGS WILL HAPPEN.
|
||||
|
||||
# For SunOS 4
|
||||
AUX_CFLAGS= -DSUNOS4
|
||||
# For Solaris 2. NOTE: Lots of problems have been identified with compiling
|
||||
# httpd under Solaris. Use with caution. If you see aberrant behavior with
|
||||
# httpd under Solaris 2, please mail us.
|
||||
#AUX_CFLAGS= -DSOLARIS2
|
||||
#EXTRA_LIBS= -lsocket -lnsl
|
||||
# For SGI IRIX. Use the EXTRA_LIBS line if you're using NIS and want
|
||||
# user-supported directories
|
||||
#AUX_CFLAGS= -DIRIX
|
||||
#EXTRA_LIBS= -lsun
|
||||
# For HP-UX
|
||||
#AUX_CFLAGS= -DHPUX
|
||||
# For AIX
|
||||
#AUX_CFLAGS= -DAIX
|
||||
# For Ultrix
|
||||
#AUX_CFLAGS= -DULTRIX
|
||||
# For DEC OSF/1
|
||||
#AUX_CFLAGS= -DOSF1
|
||||
# For NeXT
|
||||
#AUX_CFLAGS= -DNEXT
|
||||
# For Sequent
|
||||
#AUX_CFLAGS= -DSEQUENT
|
||||
# For Linux -m486 ONLY IF YOU HAVE 486 BINARY SUPPORT IN KERNEL
|
||||
#AUX_CFLAGS= -DLINUX
|
||||
# For A/UX
|
||||
#AUX_CFLAGS= -DAUX
|
||||
|
||||
# Place here any flags you may need upon linking, such as a flag to
|
||||
# prevent dynamic linking (if desired)
|
||||
LFLAGS=
|
||||
|
||||
# You shouldn't have to edit anything else.
|
||||
|
||||
OBJS=http_config.o httpd.o http_request.o util.o http_dir.o \
|
||||
http_alias.o http_log.o http_mime.o http_access.o http_auth.o \
|
||||
http_get.o http_put.o http_script.o rfc931.o
|
||||
|
||||
.c.o:
|
||||
$(CC) -c $(CFLAGS) $(AUX_CFLAGS) $<
|
||||
|
||||
all: httpd
|
||||
|
||||
ibm:
|
||||
make tar AUX_CFLAGS=-DAIX CC=gcc CFLAGS=-O2
|
||||
|
||||
sun:
|
||||
make tar AUX_CFLAGS=-DSUNOS4 CC=gcc CFLAGS=-O2
|
||||
|
||||
hp:
|
||||
make tar AUX_CFLAGS=-DHPUX CC=gcc CFLAGS=-O2
|
||||
|
||||
sgi:
|
||||
make tar AUX_CFLAGS=-DIRIX EXTRA_LIBS=-lsun CC=cc CFLAGS=-O2
|
||||
|
||||
decmips:
|
||||
make tar AUX_CFLAGS=-DULTRIX CC=cc CFLAGS=-O2
|
||||
|
||||
decaxp:
|
||||
make tar AUX_CFLAGS=-DOSF1 CC=cc CFLAGS=-O2
|
||||
|
||||
httpd: $(OBJS)
|
||||
$(CC) $(LFLAGS) -o httpd $(OBJS) $(EXTRA_LIBS)
|
||||
|
||||
purify: $(OBJS)
|
||||
purify -logfile=/X11/robm/httpd/logs/pure_log \
|
||||
-program-name=/X11/robm/httpd/src/httpd \
|
||||
$(CC) $(LFLAGS) -o httpd $(OBJS) $(EXTRA_LIBS)
|
||||
|
||||
tar: $(OBJS)
|
||||
$(CC) $(LFLAGS) -o ../httpd $(OBJS) $(EXTRA_LIBS)
|
||||
rm -f $(OBJS)
|
||||
|
||||
|
||||
$(OBJS): Makefile httpd.h
|
||||
|
||||
clean:
|
||||
rm -f ../httpd httpd $(OBJS) *pure*
|
100
src/Makefile~
Normal file
100
src/Makefile~
Normal file
@ -0,0 +1,100 @@
|
||||
# Makefile for NCSA's httpd.
|
||||
|
||||
# For normal machines with ANSI compilers
|
||||
#CC= cc
|
||||
# For Suns or other non-ANSI platforms. Please make sure your gcc is
|
||||
# 2.0 or later, as 1.40 seems to create bad code for the Sun 4.
|
||||
CC= gcc
|
||||
|
||||
# For optimization
|
||||
#CFLAGS= -O2
|
||||
# For debugging information
|
||||
CFLAGS= -g -DPEM_AUTH
|
||||
#CFLAGS= -g
|
||||
|
||||
# Place here any extra libraries you may need to link to. You
|
||||
# shouldn't have to.
|
||||
EXTRA_LIBS=
|
||||
|
||||
# AUX_CFLAGS are system-specific control flags.
|
||||
# NOTE: IF YOU DO NOT CHOOSE ONE OF THESE, EDIT httpd.h AND CHOOSE
|
||||
# SETTINGS FOR THE SYSTEM FLAGS. IF YOU DON'T, BAD THINGS WILL HAPPEN.
|
||||
|
||||
# For SunOS 4
|
||||
AUX_CFLAGS= -DSUNOS4
|
||||
# For Solaris 2. NOTE: Lots of problems have been identified with compiling
|
||||
# httpd under Solaris. Use with caution. If you see aberrant behavior with
|
||||
# httpd under Solaris 2, please mail us.
|
||||
#AUX_CFLAGS= -DSOLARIS2
|
||||
#EXTRA_LIBS= -lsocket -lnsl
|
||||
# For SGI IRIX. Use the EXTRA_LIBS line if you're using NIS and want
|
||||
# user-supported directories
|
||||
#AUX_CFLAGS= -DIRIX
|
||||
#EXTRA_LIBS= -lsun
|
||||
# For HP-UX
|
||||
#AUX_CFLAGS= -DHPUX
|
||||
# For AIX
|
||||
#AUX_CFLAGS= -DAIX
|
||||
# For Ultrix
|
||||
#AUX_CFLAGS= -DULTRIX
|
||||
# For DEC OSF/1
|
||||
#AUX_CFLAGS= -DOSF1
|
||||
# For NeXT
|
||||
#AUX_CFLAGS= -DNEXT
|
||||
# For Sequent
|
||||
#AUX_CFLAGS= -DSEQUENT
|
||||
# For Linux -m486 ONLY IF YOU HAVE 486 BINARY SUPPORT IN KERNEL
|
||||
#AUX_CFLAGS= -DLINUX
|
||||
# For A/UX
|
||||
#AUX_CFLAGS= -DAUX
|
||||
|
||||
# Place here any flags you may need upon linking, such as a flag to
|
||||
# prevent dynamic linking (if desired)
|
||||
LFLAGS=
|
||||
|
||||
# You shouldn't have to edit anything else.
|
||||
|
||||
OBJS=http_config.o httpd.o http_request.o util.o http_dir.o \
|
||||
http_alias.o http_log.o http_mime.o http_access.o http_auth.o \
|
||||
http_get.o http_put.o http_script.o rfc931.o
|
||||
|
||||
.c.o:
|
||||
$(CC) -c $(CFLAGS) $(AUX_CFLAGS) $<
|
||||
|
||||
all: httpd
|
||||
|
||||
ibm:
|
||||
make tar AUX_CFLAGS=-DAIX CC=gcc CFLAGS=-O2
|
||||
|
||||
sun:
|
||||
make tar AUX_CFLAGS=-DSUNOS4 CC=gcc CFLAGS=-O2
|
||||
|
||||
hp:
|
||||
make tar AUX_CFLAGS=-DHPUX CC=gcc CFLAGS=-O2
|
||||
|
||||
sgi:
|
||||
make tar AUX_CFLAGS=-DIRIX EXTRA_LIBS=-lsun CC=cc CFLAGS=-O2
|
||||
|
||||
decmips:
|
||||
make tar AUX_CFLAGS=-DULTRIX CC=cc CFLAGS=-O2
|
||||
|
||||
decaxp:
|
||||
make tar AUX_CFLAGS=-DOSF1 CC=cc CFLAGS=-O2
|
||||
|
||||
httpd: $(OBJS)
|
||||
$(CC) $(LFLAGS) -o httpd $(OBJS) $(EXTRA_LIBS)
|
||||
|
||||
purify: $(OBJS)
|
||||
purify -logfile=/X11/robm/httpd/logs/pure_log \
|
||||
-program-name=/X11/robm/httpd/src/httpd \
|
||||
$(CC) $(LFLAGS) -o httpd $(OBJS) $(EXTRA_LIBS)
|
||||
|
||||
tar: $(OBJS)
|
||||
$(CC) $(LFLAGS) -o ../httpd $(OBJS) $(EXTRA_LIBS)
|
||||
rm -f $(OBJS)
|
||||
|
||||
|
||||
$(OBJS): Makefile httpd.h
|
||||
|
||||
clean:
|
||||
rm -f ../httpd httpd $(OBJS) *pure*
|
185
src/http_access.c
Normal file
185
src/http_access.c
Normal file
@ -0,0 +1,185 @@
|
||||
/*
|
||||
* http_access: Security options etc.
|
||||
*
|
||||
* Rob McCool
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "httpd.h"
|
||||
|
||||
int in_domain(char *domain, char *what) {
|
||||
int dl=strlen(domain);
|
||||
int wl=strlen(what);
|
||||
|
||||
if((wl-dl) >= 0)
|
||||
return(!strcmp(domain,&what[wl-dl]));
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
int in_ip(char *domain, char *what) {
|
||||
return(!strncmp(domain,what,strlen(domain)));
|
||||
}
|
||||
|
||||
int find_allow(int x, int m) {
|
||||
register int y;
|
||||
|
||||
if(sec[x].num_allow[m] < 0)
|
||||
return 1;
|
||||
|
||||
for(y=0;y<sec[x].num_allow[m];y++) {
|
||||
if(!strcmp("all",sec[x].allow[m][y]))
|
||||
return 1;
|
||||
if(remote_host && isalpha(remote_host[0]))
|
||||
if(in_domain(sec[x].allow[m][y],remote_host))
|
||||
return 1;
|
||||
if(in_ip(sec[x].allow[m][y],remote_ip))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int find_deny(int x, int m) {
|
||||
register int y;
|
||||
|
||||
if(sec[x].num_deny[m] < 0)
|
||||
return 1;
|
||||
|
||||
for(y=0;y<sec[x].num_deny[m];y++) {
|
||||
if(!strcmp("all",sec[x].deny[m][y]))
|
||||
return 1;
|
||||
if(remote_host && isalpha(remote_host[0]))
|
||||
if(in_domain(sec[x].deny[m][y],remote_host))
|
||||
return 1;
|
||||
if(in_ip(sec[x].deny[m][y],remote_ip))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void check_dir_access(int x, int m, int *w, int *n) {
|
||||
if(sec[x].auth_type)
|
||||
auth_type = sec[x].auth_type;
|
||||
if(sec[x].auth_name)
|
||||
auth_name = sec[x].auth_name;
|
||||
if(sec[x].auth_pwfile)
|
||||
auth_pwfile = sec[x].auth_pwfile;
|
||||
if(sec[x].auth_grpfile)
|
||||
auth_grpfile = sec[x].auth_grpfile;
|
||||
|
||||
if(sec[x].order[m] == ALLOW_THEN_DENY) {
|
||||
if(find_allow(x,m))
|
||||
*w=1;
|
||||
if(find_deny(x,m))
|
||||
*w=0;
|
||||
if(sec[x].num_auth[m])
|
||||
*n=x;
|
||||
} else {
|
||||
if(find_deny(x,m))
|
||||
*w=0;
|
||||
if(find_allow(x,m))
|
||||
*w=1;
|
||||
if(sec[x].num_auth[m])
|
||||
*n=x;
|
||||
}
|
||||
}
|
||||
|
||||
void evaluate_access(char *p, struct stat *finfo, int m, int *allow,
|
||||
char *allow_options,FILE *out)
|
||||
{
|
||||
int will_allow, need_auth, num_dirs;
|
||||
char opts[MAX_STRING_LEN], override[MAX_STRING_LEN];
|
||||
char path[MAX_STRING_LEN], d[MAX_STRING_LEN];
|
||||
register int x,y,z,n;
|
||||
|
||||
if(S_ISDIR(finfo->st_mode)) strcpy_dir(path,p);
|
||||
else strcpy(path,p);
|
||||
|
||||
num_dirs = count_dirs(path);
|
||||
will_allow=1;need_auth=-1;
|
||||
auth_type=NULL;auth_name=NULL;auth_pwfile=NULL;auth_grpfile=NULL;
|
||||
user[0] = '\0';
|
||||
for(x=0;x<num_dirs;x++) {
|
||||
opts[x] = OPT_ALL;
|
||||
override[x] = OR_ALL;
|
||||
}
|
||||
|
||||
for(x=0;x<num_sec;x++) {
|
||||
if(!strncmp(path,sec[x].d,strlen(sec[x].d))) {
|
||||
for(y=count_dirs(sec[x].d) - 1;y<num_dirs;y++) {
|
||||
if(!(sec[x].opts & OPT_UNSET))
|
||||
opts[y] = sec[x].opts;
|
||||
override[y] = sec[x].override;
|
||||
}
|
||||
check_dir_access(x,m,&will_allow,&need_auth);
|
||||
}
|
||||
}
|
||||
n=num_dirs-1;
|
||||
if((override[n]) || (!(opts[n] & OPT_SYM_LINKS))) {
|
||||
for(x=0;x<num_dirs;x++) {
|
||||
y = num_sec;
|
||||
make_dirstr(path,x+1,d);
|
||||
if(!(opts[x] & OPT_SYM_LINKS)) {
|
||||
struct stat fi;
|
||||
lstat(d,&fi);
|
||||
if(!(S_ISDIR(fi.st_mode))) {
|
||||
char errstr[MAX_STRING_LEN];
|
||||
sprintf(errstr,"httpd: will not follow link %s",d);
|
||||
log_error(errstr);
|
||||
*allow=0;
|
||||
*allow_options = OPT_NONE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(override[x]) {
|
||||
parse_htaccess(d,override[x],out);
|
||||
if(num_sec != y) {
|
||||
for(z=count_dirs(sec[y].d) - 1;z<num_dirs;z++) {
|
||||
if(!(sec[y].opts & OPT_UNSET))
|
||||
opts[z] = sec[y].opts;
|
||||
override[z] = sec[y].override;
|
||||
}
|
||||
check_dir_access(y,m,&will_allow,&need_auth);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if((!(S_ISDIR(finfo->st_mode))) && (!(opts[n] & OPT_SYM_LINKS))) {
|
||||
struct stat fi;
|
||||
lstat(path,&fi);
|
||||
if(!(S_ISREG(fi.st_mode))) {
|
||||
char errstr[MAX_STRING_LEN];
|
||||
sprintf(errstr,"httpd: will not follow link %s",path);
|
||||
log_error(errstr);
|
||||
*allow=0;
|
||||
*allow_options = OPT_NONE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
*allow = will_allow;
|
||||
if(will_allow) {
|
||||
*allow_options = opts[num_dirs-1];
|
||||
if(need_auth >= 0)
|
||||
check_auth(&sec[need_auth],m,out);
|
||||
}
|
||||
else *allow_options = 0;
|
||||
}
|
||||
|
||||
void kill_security() {
|
||||
register int x,y,m;
|
||||
|
||||
for(x=0;x<num_sec;x++) {
|
||||
free(sec[x].d);
|
||||
for(m=0;m<METHODS;m++) {
|
||||
for(y=0;y<sec[x].num_allow[m];y++)
|
||||
free(sec[x].allow[m][y]);
|
||||
for(y=0;y<sec[x].num_deny[m];y++)
|
||||
free(sec[x].deny[m][y]);
|
||||
for(y=0;y<sec[x].num_auth[m];y++)
|
||||
free(sec[x].auth[m][y]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
114
src/http_alias.c
Normal file
114
src/http_alias.c
Normal file
@ -0,0 +1,114 @@
|
||||
/*
|
||||
* http_alias.c: Stuff for dealing with directory aliases
|
||||
*
|
||||
* Rob McCool
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "httpd.h"
|
||||
|
||||
typedef struct {
|
||||
char fake[MAX_STRING_LEN];
|
||||
char real[MAX_STRING_LEN];
|
||||
int script;
|
||||
} alias;
|
||||
|
||||
static int num_a = 0;
|
||||
static alias a[MAX_ALIASES];
|
||||
static int num_v = 0;
|
||||
static alias v[MAX_ALIASES];
|
||||
|
||||
/* To send stat() information to http_script.c */
|
||||
int dirs_in_alias;
|
||||
|
||||
void reset_aliases() {
|
||||
num_a = 0;
|
||||
num_v = 0;
|
||||
}
|
||||
|
||||
void add_alias(char *f, char *r, int is_script) {
|
||||
strcpy(a[num_a].fake,f);
|
||||
|
||||
a[num_a].script = is_script;
|
||||
if(r[0] != '/')
|
||||
make_full_path((is_script ? server_root : document_root),r,
|
||||
a[num_a++].real);
|
||||
else
|
||||
strcpy(a[num_a++].real,r);
|
||||
}
|
||||
|
||||
void add_redirect(char *f, char *url) {
|
||||
strcpy(v[num_v].fake,f);
|
||||
strcpy(v[num_v++].real,url);
|
||||
}
|
||||
|
||||
int translate_name(char *name, FILE *fd) {
|
||||
register int x,l;
|
||||
char w[MAX_STRING_LEN];
|
||||
char t[MAX_STRING_LEN];
|
||||
struct passwd *pw;
|
||||
|
||||
getparents(name);
|
||||
|
||||
for(x=0;x<num_v;x++) {
|
||||
l=strlen(v[x].fake);
|
||||
if(!strncmp(name,v[x].fake,l)) {
|
||||
strsubfirst(l,name,v[x].real);
|
||||
return REDIRECT_URL;
|
||||
}
|
||||
}
|
||||
|
||||
for(x=0; x < num_a; x++) {
|
||||
l=strlen(a[x].fake);
|
||||
if(!strncmp(name,a[x].fake,l)) {
|
||||
strsubfirst(l,name,a[x].real);
|
||||
dirs_in_alias = count_dirs(a[x].real);
|
||||
return(a[x].script);
|
||||
}
|
||||
}
|
||||
|
||||
if((user_dir[0]) && (name[0] == '/') && (name[1] == '~')) {
|
||||
char fake[MAX_STRING_LEN],real[MAX_STRING_LEN],dname[MAX_STRING_LEN];
|
||||
|
||||
strcpy(dname,&name[2]);
|
||||
getword(w,dname,'/');
|
||||
if(!(pw=getpwnam(w)))
|
||||
die(NOT_FOUND,name,fd);
|
||||
fake[0] = '/';
|
||||
fake[1] = '~';
|
||||
strcpy(&fake[2],w);
|
||||
make_full_path(pw->pw_dir,user_dir,real);
|
||||
add_alias(fake,real,STD_DOCUMENT);
|
||||
strsubfirst(strlen(w) + 2,name,real);
|
||||
return STD_DOCUMENT;
|
||||
}
|
||||
/* no alias, add document root */
|
||||
strsubfirst(0,name,document_root);
|
||||
return STD_DOCUMENT;
|
||||
}
|
||||
|
||||
void unmunge_name(char *name) {
|
||||
register int x,l;
|
||||
|
||||
l=strlen(document_root);
|
||||
if(!strncmp(name,document_root,l)) {
|
||||
strsubfirst(l,name,"");
|
||||
if(!name[0]) {
|
||||
name[0] = '/';
|
||||
name[1] = '\0';
|
||||
}
|
||||
return;
|
||||
}
|
||||
for(x=0;x < num_a; x++) {
|
||||
l=strlen(a[x].real);
|
||||
if(!strncmp(name,a[x].real,l)) {
|
||||
strsubfirst(l,name,a[x].fake);
|
||||
if(!name[0]) {
|
||||
name[0] = '/';
|
||||
name[1] = '\0';
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
333
src/http_auth.c
Normal file
333
src/http_auth.c
Normal file
@ -0,0 +1,333 @@
|
||||
/*
|
||||
* http_auth: authentication
|
||||
*
|
||||
* Rob McCool
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "httpd.h"
|
||||
|
||||
char user[MAX_STRING_LEN];
|
||||
|
||||
#ifdef PEM_AUTH
|
||||
int doing_pem;
|
||||
static char pem_user[MAX_STRING_LEN];
|
||||
#define ENCODING_NONE -1
|
||||
#define ENCODING_PEM 1
|
||||
#define ENCODING_PGP 2
|
||||
#endif
|
||||
|
||||
void auth_bong(char *s, FILE *out) {
|
||||
char errstr[MAX_STRING_LEN];
|
||||
|
||||
/* debugging */
|
||||
if(s) {
|
||||
sprintf(errstr,"%s authorization: %s",remote_name,s);
|
||||
log_error(errstr);
|
||||
}
|
||||
if(!strcasecmp(auth_type,"Basic")) {
|
||||
sprintf(errstr,"Basic realm=\"%s\"",auth_name);
|
||||
die(AUTH_REQUIRED,errstr,out);
|
||||
}
|
||||
#ifdef PEM_AUTH
|
||||
if(!strcasecmp(auth_type,"PEM")) {
|
||||
sprintf(errstr,"PEM entity=\"%s\"",
|
||||
auth_pem_entity);
|
||||
die(AUTH_REQUIRED,errstr,out);
|
||||
}
|
||||
if(!strcasecmp(auth_type,"PGP")) {
|
||||
sprintf(errstr,"PGP entity=\"%s\"",auth_pgp_entity);
|
||||
die(AUTH_REQUIRED,errstr,out);
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
sprintf(errstr,"Unknown authorization method %s",auth_type);
|
||||
die(SERVER_ERROR,errstr,out);
|
||||
}
|
||||
}
|
||||
|
||||
void check_auth(security_data *sec, int m, FILE *out) {
|
||||
char at[MAX_STRING_LEN];
|
||||
char ad[MAX_STRING_LEN];
|
||||
char sent_pw[MAX_STRING_LEN];
|
||||
char real_pw[MAX_STRING_LEN];
|
||||
char t[MAX_STRING_LEN];
|
||||
char w[MAX_STRING_LEN];
|
||||
char errstr[MAX_STRING_LEN];
|
||||
register int x;
|
||||
int grpstatus;
|
||||
|
||||
if(!auth_type) {
|
||||
sprintf(errstr,
|
||||
"httpd: authorization required for %s but not configured",sec->d);
|
||||
die(SERVER_ERROR,errstr,out);
|
||||
}
|
||||
|
||||
if(!strcasecmp(auth_type,"Basic")) {
|
||||
if(!auth_name) {
|
||||
sprintf(errstr,"httpd: need AuthName for %s",sec->d);
|
||||
die(SERVER_ERROR,errstr,out);
|
||||
}
|
||||
if(!auth_line[0])
|
||||
auth_bong(NULL,out);
|
||||
if(!auth_pwfile) {
|
||||
sprintf(errstr,"httpd: need AuthUserFile for %s",sec->d);
|
||||
die(SERVER_ERROR,errstr,out);
|
||||
}
|
||||
sscanf(auth_line,"%s %s",at,t);
|
||||
if(strcmp(at,auth_type))
|
||||
auth_bong("type mismatch",out);
|
||||
uudecode(t,(unsigned char *)ad,MAX_STRING_LEN);
|
||||
getword(user,ad,':');
|
||||
strcpy(sent_pw,ad);
|
||||
if(!get_pw(user,real_pw)) {
|
||||
sprintf(errstr,"user %s not found",user);
|
||||
auth_bong(errstr,out);
|
||||
}
|
||||
/* anyone know where the prototype for crypt is? */
|
||||
if(strcmp(real_pw,(char *)crypt(sent_pw,real_pw))) {
|
||||
sprintf(errstr,"user %s: password mismatch",user);
|
||||
auth_bong(errstr,out);
|
||||
}
|
||||
}
|
||||
#ifdef PEM_AUTH
|
||||
else if(!strcasecmp(auth_type,"PEM")) {
|
||||
/* see if we're already handling the request... */
|
||||
switch(doing_pem) {
|
||||
case ENCODING_NONE:
|
||||
auth_bong(NULL,out);
|
||||
case ENCODING_PGP:
|
||||
auth_bong("request with pgp for pem-protected directory",out);
|
||||
default:
|
||||
strcpy(user,pem_user);
|
||||
}
|
||||
}
|
||||
else if(!strcasecmp(auth_type,"PGP")) {
|
||||
switch(doing_pem) {
|
||||
case ENCODING_NONE:
|
||||
auth_bong(NULL,out);
|
||||
case ENCODING_PEM:
|
||||
auth_bong("request with pem for pgp-protected directory",out);
|
||||
default:
|
||||
strcpy(user,pem_user);
|
||||
}
|
||||
strcpy(user,pem_user);
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
sprintf(errstr,"unknown authorization type %s for %s",auth_type,
|
||||
sec->d);
|
||||
auth_bong(errstr,out);
|
||||
}
|
||||
|
||||
/* Common stuff: Check for valid user */
|
||||
if(auth_grpfile)
|
||||
grpstatus = init_group(auth_grpfile,out);
|
||||
else
|
||||
grpstatus = 0;
|
||||
|
||||
for(x=0;x<sec->num_auth[m];x++) {
|
||||
strcpy(t,sec->auth[m][x]);
|
||||
getword(w,t,' ');
|
||||
if(!strcmp(w,"valid-user"))
|
||||
goto found;
|
||||
if(!strcmp(w,"user")) {
|
||||
while(t[0]) {
|
||||
getword(w,t,' ');
|
||||
if(!strcmp(user,w))
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
else if(!strcmp(w,"group")) {
|
||||
if(!grpstatus) {
|
||||
sprintf(errstr,"group required for %s, bad groupfile",
|
||||
sec->d);
|
||||
auth_bong(errstr,out);
|
||||
}
|
||||
while(t[0]) {
|
||||
getword(w,t,' ');
|
||||
if(in_group(user,w))
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
else
|
||||
auth_bong("require not followed by user or group",out);
|
||||
}
|
||||
if(grpstatus) kill_group();
|
||||
sprintf(errstr,"user %s denied",user);
|
||||
auth_bong(errstr,out);
|
||||
found:
|
||||
if(grpstatus)
|
||||
kill_group();
|
||||
}
|
||||
|
||||
#ifdef PEM_AUTH
|
||||
|
||||
static int encrypt_pid,decrypt_pid;
|
||||
static char tn[L_tmpnam];
|
||||
|
||||
void pem_cleanup(int status, FILE *out) {
|
||||
if(doing_pem != ENCODING_NONE) {
|
||||
fclose(out);
|
||||
waitpid(decrypt_pid,NULL,0);
|
||||
waitpid(encrypt_pid,NULL,0);
|
||||
unlink(tn);
|
||||
}
|
||||
}
|
||||
|
||||
int pem_decrypt(int sfd, char *req, FILE **out) {
|
||||
int tfd,nr,pid,p[2],decrypt_fd,pem,pgp;
|
||||
char w[MAX_STRING_LEN],w2[MAX_STRING_LEN];
|
||||
char c;
|
||||
FILE *tmp;
|
||||
char *decrypt,*encrypt,*entity;
|
||||
|
||||
doing_pem = ENCODING_NONE;
|
||||
if(strcmp(req,"/"))
|
||||
return -1;
|
||||
|
||||
pem = !(strcmp(content_type,"application/x-www-pem-request"));
|
||||
pgp = !(strcmp(content_type,"application/x-www-pgp-request"));
|
||||
if((!pem) && (!pgp))
|
||||
return -1;
|
||||
|
||||
auth_type = (pem ? "PEM" : "PGP");
|
||||
|
||||
sscanf(auth_line,"%s %s",w,w2);
|
||||
|
||||
if(pem) {
|
||||
if(strcasecmp(w,"PEM"))
|
||||
auth_bong("PEM content in reply to non-PEM request",*out);
|
||||
}
|
||||
else {
|
||||
if(strcasecmp(w,"PGP"))
|
||||
auth_bong("PGP content in reply to non-PGP request",*out);
|
||||
}
|
||||
|
||||
getword(w,w2,'=');
|
||||
if(strcasecmp(w,"entity"))
|
||||
auth_bong("Garbled entity line",*out);
|
||||
|
||||
auth_type = NULL; /* prevent its being freed later */
|
||||
if(w2[0] == '\"')
|
||||
getword(pem_user,&w2[1],'\"');
|
||||
else
|
||||
strcpy(pem_user,w2);
|
||||
|
||||
escape_shell_cmd(pem_user); /* protect from security threats */
|
||||
if(pem) {
|
||||
decrypt = auth_pem_decrypt;
|
||||
encrypt = auth_pem_encrypt;
|
||||
entity = auth_pem_entity;
|
||||
}
|
||||
else {
|
||||
decrypt = auth_pgp_decrypt;
|
||||
encrypt = auth_pgp_encrypt;
|
||||
entity = auth_pgp_entity;
|
||||
}
|
||||
|
||||
if((!encrypt[0]) || (!decrypt[0]) || (!entity[0]))
|
||||
die(SERVER_ERROR,"PEM/PGP authorization required but not configured",
|
||||
*out);
|
||||
|
||||
tmpnam(tn);
|
||||
if((tfd = open(tn,O_WRONLY|O_CREAT,S_IRUSR|S_IWUSR)) == -1)
|
||||
die(SERVER_ERROR,"Could not open a temp file for writing",*out);
|
||||
|
||||
nr=0;
|
||||
while(nr != content_length) {
|
||||
char buf[1024];
|
||||
int n,t;
|
||||
t = content_length-nr;
|
||||
if((n = read(sfd,buf,(t > 1024 ? 1024 : t))) < 1) {
|
||||
close(tfd);
|
||||
unlink(tn);
|
||||
die(SERVER_ERROR,"Failed to read the full encrypted request",*out);
|
||||
}
|
||||
if(write(tfd,buf,n) != n) {
|
||||
close(tfd);
|
||||
unlink(tn);
|
||||
die(SERVER_ERROR,"Could not write to temp file",*out);
|
||||
}
|
||||
nr+=n;
|
||||
}
|
||||
close(tfd);
|
||||
/* this is done here instead of below for error recovery */
|
||||
if((tfd = open(tn,O_RDONLY)) == -1) {
|
||||
unlink(tn);
|
||||
die(SERVER_ERROR,"Could not open temp file for reading",*out);
|
||||
}
|
||||
|
||||
if(pipe(p) == -1)
|
||||
die(SERVER_ERROR,"Could not create IPC pipe",*out);
|
||||
if((pid = fork()) == -1)
|
||||
die(SERVER_ERROR,"Could not fork a new process",*out);
|
||||
|
||||
if(!pid) {
|
||||
char *argv0;
|
||||
close(p[0]);
|
||||
signal(SIGHUP,SIG_DFL);
|
||||
if(tfd != STDIN_FILENO) {
|
||||
dup2(tfd,STDIN_FILENO);
|
||||
close(tfd);
|
||||
}
|
||||
if(p[1] != STDOUT_FILENO) {
|
||||
dup2(p[1],STDOUT_FILENO);
|
||||
close(p[1]);
|
||||
}
|
||||
if(!(argv0 = strrchr(decrypt,'/')))
|
||||
argv0 = decrypt;
|
||||
else
|
||||
++argv0;
|
||||
if(execlp(decrypt,argv0,pem_user,(char *)0) == -1)
|
||||
die(SERVER_ERROR,"Could not exec decrypt command",*out); /* !!! */
|
||||
}
|
||||
close(tfd);
|
||||
close(p[1]);
|
||||
|
||||
decrypt_fd = p[0];
|
||||
decrypt_pid = pid;
|
||||
|
||||
/* create encryption stream */
|
||||
if(pipe(p) == -1)
|
||||
die(SERVER_ERROR,"Could not open an IPC pipe",*out);
|
||||
if((pid = fork()) == -1)
|
||||
die(SERVER_ERROR,"Could not fork new process",*out);
|
||||
|
||||
if(!pid) {
|
||||
char *argv0;
|
||||
signal(SIGHUP,SIG_DFL);
|
||||
close(p[1]);
|
||||
if(fileno(*out) != STDOUT_FILENO) {
|
||||
dup2(fileno(*out),STDOUT_FILENO);
|
||||
fclose(*out);
|
||||
}
|
||||
if(p[0] != STDIN_FILENO) {
|
||||
dup2(p[0],STDIN_FILENO);
|
||||
close(p[0]);
|
||||
}
|
||||
if(!(argv0 = strrchr(encrypt,'/')))
|
||||
argv0 = encrypt;
|
||||
else
|
||||
++argv0;
|
||||
if(execlp(encrypt,argv0,pem_user,(char*)0) == -1)
|
||||
die(SERVER_ERROR,"Could not exec encrypt command",*out); /*!!!*/
|
||||
}
|
||||
close(p[0]);
|
||||
tmp = *out;
|
||||
if(!(*out = fdopen(p[1],"w")))
|
||||
die(SERVER_ERROR,"Could not open stream to encrypt command",tmp);
|
||||
strcpy(content_type,(pem ? "application/x-www-pem-reply" :
|
||||
"application/x-www-pgp-reply"));
|
||||
doing_pem = (pem ? ENCODING_PEM : ENCODING_PGP);
|
||||
location[0] = '\0';
|
||||
set_content_length(-1);
|
||||
send_http_header(tmp);
|
||||
fclose(tmp);
|
||||
|
||||
encrypt_pid = pid;
|
||||
return(decrypt_fd);
|
||||
}
|
||||
|
||||
#endif
|
879
src/http_config.c
Normal file
879
src/http_config.c
Normal file
@ -0,0 +1,879 @@
|
||||
/*
|
||||
* http_config.c: auxillary functions for reading httpd's config file
|
||||
* and converting filenames into a namespace
|
||||
*
|
||||
* Rob McCool
|
||||
*
|
||||
*/
|
||||
|
||||
#include "httpd.h"
|
||||
|
||||
|
||||
/* Server config globals */
|
||||
int standalone;
|
||||
int port;
|
||||
uid_t user_id;
|
||||
gid_t group_id;
|
||||
char server_root[MAX_STRING_LEN];
|
||||
char error_fname[MAX_STRING_LEN];
|
||||
char xfer_fname[MAX_STRING_LEN];
|
||||
char pid_fname[MAX_STRING_LEN];
|
||||
char server_admin[MAX_STRING_LEN];
|
||||
char *server_hostname;
|
||||
char srm_confname[MAX_STRING_LEN];
|
||||
char server_confname[MAX_STRING_LEN];
|
||||
char access_confname[MAX_STRING_LEN];
|
||||
char types_confname[MAX_STRING_LEN];
|
||||
int timeout;
|
||||
int do_rfc931;
|
||||
#ifdef PEM_AUTH
|
||||
char auth_pem_decrypt[MAX_STRING_LEN];
|
||||
char auth_pem_encrypt[MAX_STRING_LEN];
|
||||
char auth_pem_entity[MAX_STRING_LEN];
|
||||
char auth_pgp_decrypt[MAX_STRING_LEN];
|
||||
char auth_pgp_encrypt[MAX_STRING_LEN];
|
||||
char auth_pgp_entity[MAX_STRING_LEN];
|
||||
#endif
|
||||
|
||||
void process_server_config() {
|
||||
FILE *cfg;
|
||||
char l[MAX_STRING_LEN],w[MAX_STRING_LEN];
|
||||
int n=0;
|
||||
|
||||
standalone = 1;
|
||||
port = DEFAULT_PORT;
|
||||
user_id = uname2id(DEFAULT_USER);
|
||||
group_id = gname2id(DEFAULT_GROUP);
|
||||
/* ServerRoot set in httpd.c */
|
||||
make_full_path(server_root,DEFAULT_ERRORLOG,error_fname);
|
||||
make_full_path(server_root,DEFAULT_XFERLOG,xfer_fname);
|
||||
make_full_path(server_root,DEFAULT_PIDLOG,pid_fname);
|
||||
strcpy(server_admin,DEFAULT_ADMIN);
|
||||
server_hostname = NULL;
|
||||
make_full_path(server_root,RESOURCE_CONFIG_FILE,srm_confname);
|
||||
/* server_confname set in httpd.c */
|
||||
make_full_path(server_root,ACCESS_CONFIG_FILE,access_confname);
|
||||
make_full_path(server_root,TYPES_CONFIG_FILE,types_confname);
|
||||
|
||||
timeout = DEFAULT_TIMEOUT;
|
||||
do_rfc931 = DEFAULT_RFC931;
|
||||
#ifdef PEM_AUTH
|
||||
auth_pem_encrypt[0] = '\0';
|
||||
auth_pem_decrypt[0] = '\0';
|
||||
auth_pem_entity[0] = '\0';
|
||||
auth_pgp_encrypt[0] = '\0';
|
||||
auth_pgp_decrypt[0] = '\0';
|
||||
auth_pgp_entity[0] = '\0';
|
||||
#endif
|
||||
|
||||
if(!(cfg = fopen(server_confname,"r"))) {
|
||||
fprintf(stderr,"httpd: could not open server config. file %s\n",server_confname);
|
||||
perror("fopen");
|
||||
exit(1);
|
||||
}
|
||||
/* Parse server config file. Remind me to learn yacc. */
|
||||
while(!(cfg_getline(l,MAX_STRING_LEN,cfg))) {
|
||||
++n;
|
||||
if((l[0] != '#') && (l[0] != '\0')) {
|
||||
cfg_getword(w,l);
|
||||
|
||||
if(!strcasecmp(w,"ServerType")) {
|
||||
if(!strcasecmp(l,"inetd")) standalone=0;
|
||||
else if(!strcasecmp(l,"standalone")) standalone=1;
|
||||
else {
|
||||
fprintf(stderr,"Syntax error on line %d of %s:\n",n,server_confname);
|
||||
fprintf(stderr,"ServerType is either inetd or standalone.\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else if(!strcasecmp(w,"Port")) {
|
||||
cfg_getword(w,l);
|
||||
port = atoi(w);
|
||||
}
|
||||
else if(!strcasecmp(w,"User")) {
|
||||
cfg_getword(w,l);
|
||||
user_id = uname2id(w);
|
||||
}
|
||||
else if(!strcasecmp(w,"Group")) {
|
||||
cfg_getword(w,l);
|
||||
group_id = gname2id(w);
|
||||
}
|
||||
else if(!strcasecmp(w,"ServerAdmin")) {
|
||||
cfg_getword(w,l);
|
||||
strcpy(server_admin,w);
|
||||
}
|
||||
else if(!strcasecmp(w,"ServerName")) {
|
||||
cfg_getword(w,l);
|
||||
if(server_hostname)
|
||||
free(server_hostname);
|
||||
if(!(server_hostname = strdup(w)))
|
||||
die(NO_MEMORY,"process_resource_config",stderr);
|
||||
}
|
||||
else if(!strcasecmp(w,"ServerRoot")) {
|
||||
cfg_getword(w,l);
|
||||
if(!is_directory(w)) {
|
||||
fprintf(stderr,"Syntax error on line %d of %s:\n",n,server_confname);
|
||||
fprintf(stderr,"%s is not a valid directory.\n",w);
|
||||
exit(1);
|
||||
}
|
||||
strcpy(server_root,w);
|
||||
make_full_path(server_root,DEFAULT_ERRORLOG,error_fname);
|
||||
make_full_path(server_root,DEFAULT_XFERLOG,xfer_fname);
|
||||
make_full_path(server_root,DEFAULT_PIDLOG,pid_fname);
|
||||
make_full_path(server_root,RESOURCE_CONFIG_FILE,srm_confname);
|
||||
make_full_path(server_root,ACCESS_CONFIG_FILE,access_confname);
|
||||
make_full_path(server_root,TYPES_CONFIG_FILE,types_confname);
|
||||
}
|
||||
else if(!strcasecmp(w,"ErrorLog")) {
|
||||
cfg_getword(w,l);
|
||||
if(w[0] != '/')
|
||||
make_full_path(server_root,w,error_fname);
|
||||
else
|
||||
strcpy(error_fname,w);
|
||||
}
|
||||
else if(!strcasecmp(w,"TransferLog")) {
|
||||
cfg_getword(w,l);
|
||||
if(w[0] != '/')
|
||||
make_full_path(server_root,w,xfer_fname);
|
||||
else strcpy(xfer_fname,w);
|
||||
}
|
||||
else if(!strcasecmp(w,"PidFile")) {
|
||||
cfg_getword(w,l);
|
||||
if(w[0] != '/')
|
||||
make_full_path(server_root,w,pid_fname);
|
||||
else strcpy(pid_fname,w);
|
||||
}
|
||||
else if(!strcasecmp(w,"AccessConfig")) {
|
||||
cfg_getword(w,l);
|
||||
if(w[0] != '/')
|
||||
make_full_path(server_root,w,access_confname);
|
||||
else strcpy(access_confname,w);
|
||||
}
|
||||
else if(!strcasecmp(w,"ResourceConfig")) {
|
||||
cfg_getword(w,l);
|
||||
if(w[0] != '/')
|
||||
make_full_path(server_root,w,srm_confname);
|
||||
else strcpy(srm_confname,w);
|
||||
}
|
||||
else if(!strcasecmp(w,"TypesConfig")) {
|
||||
cfg_getword(w,l);
|
||||
if(w[0] != '/')
|
||||
make_full_path(server_root,w,types_confname);
|
||||
else strcpy(types_confname,w);
|
||||
}
|
||||
else if(!strcasecmp(w,"Timeout"))
|
||||
timeout = atoi(l);
|
||||
else if(!strcasecmp(w,"IdentityCheck")) {
|
||||
cfg_getword(w,l);
|
||||
if(!strcmp(w,"on"))
|
||||
do_rfc931 = 1;
|
||||
else if(!strcmp(w,"off"))
|
||||
do_rfc931 = 0;
|
||||
else {
|
||||
fprintf(stderr,"Syntax error on line %d of %s:\n",n,
|
||||
srm_confname);
|
||||
fprintf(stderr,"IdentityCheck must be on or off.\n");
|
||||
}
|
||||
}
|
||||
#ifdef PEM_AUTH
|
||||
else if(!strcasecmp(w,"PEMEncryptCmd")) {
|
||||
cfg_getword(w,l);
|
||||
strcpy(auth_pem_encrypt,w);
|
||||
}
|
||||
else if(!strcasecmp(w,"PEMDecryptCmd")) {
|
||||
cfg_getword(w,l);
|
||||
strcpy(auth_pem_decrypt,w);
|
||||
}
|
||||
else if(!strcasecmp(w,"PEMServerEntity")) {
|
||||
cfg_getword(w,l);
|
||||
strcpy(auth_pem_entity,w);
|
||||
}
|
||||
else if(!strcasecmp(w,"PGPEncryptCmd")) {
|
||||
cfg_getword(w,l);
|
||||
strcpy(auth_pgp_encrypt,w);
|
||||
}
|
||||
else if(!strcasecmp(w,"PGPDecryptCmd")) {
|
||||
cfg_getword(w,l);
|
||||
strcpy(auth_pgp_decrypt,w);
|
||||
}
|
||||
else if(!strcasecmp(w,"PGPServerEntity")) {
|
||||
cfg_getword(w,l);
|
||||
strcpy(auth_pgp_entity,w);
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
fprintf(stderr,"Syntax error on line %d of %s:\n",n,server_confname);
|
||||
fprintf(stderr,"Unknown keyword %s.\n",w);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose(cfg);
|
||||
}
|
||||
|
||||
/* Document config globals */
|
||||
char user_dir[MAX_STRING_LEN];
|
||||
char index_name[MAX_STRING_LEN];
|
||||
char access_name[MAX_STRING_LEN];
|
||||
char document_root[MAX_STRING_LEN];
|
||||
char default_type[MAX_STRING_LEN];
|
||||
char default_icon[MAX_STRING_LEN];
|
||||
int fancy_indexing;
|
||||
char readme_fname[MAX_STRING_LEN];
|
||||
|
||||
void process_resource_config() {
|
||||
FILE *cfg;
|
||||
char l[MAX_STRING_LEN],w[MAX_STRING_LEN];
|
||||
int n=0;
|
||||
|
||||
strcpy(user_dir,DEFAULT_USER_DIR);
|
||||
strcpy(index_name,DEFAULT_INDEX);
|
||||
strcpy(access_name,DEFAULT_ACCESS_FNAME);
|
||||
strcpy(document_root,DOCUMENT_LOCATION);
|
||||
strcpy(default_type,DEFAULT_TYPE);
|
||||
default_icon[0] = '\0';
|
||||
fancy_indexing = DEFAULT_INDEXING;
|
||||
readme_fname[0] = '\0';
|
||||
|
||||
if(!(cfg = fopen(srm_confname,"r"))) {
|
||||
fprintf(stderr,"httpd: could not open document config. file %s\n",
|
||||
srm_confname);
|
||||
perror("fopen");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
while(!(cfg_getline(l,MAX_STRING_LEN,cfg))) {
|
||||
++n;
|
||||
if((l[0] != '#') && (l[0] != '\0')) {
|
||||
cfg_getword(w,l);
|
||||
|
||||
if(!strcasecmp(w,"ScriptAlias")) {
|
||||
char w2[MAX_STRING_LEN];
|
||||
|
||||
cfg_getword(w,l);
|
||||
cfg_getword(w2,l);
|
||||
if((w[0] == '\0') || (w2[0] == '\0')) {
|
||||
fprintf(stderr,"Syntax error on line %d of %s:\n",n,
|
||||
srm_confname);
|
||||
fprintf(stderr,
|
||||
"ScriptAlias must be followed by a fakename, one space, then a realname.\n");
|
||||
exit(1);
|
||||
}
|
||||
add_alias(w,w2,SCRIPT_CGI);
|
||||
}
|
||||
else if(!strcasecmp(w,"OldScriptAlias")) {
|
||||
char w2[MAX_STRING_LEN];
|
||||
|
||||
cfg_getword(w,l);
|
||||
cfg_getword(w2,l);
|
||||
if((w[0] == '\0') || (w2[0] == '\0')) {
|
||||
fprintf(stderr,"Syntax error on line %d of %s:\n",n,
|
||||
srm_confname);
|
||||
fprintf(stderr,
|
||||
"ScriptAlias must be followed by a fakename, one space, then a realname.\n");
|
||||
exit(1);
|
||||
}
|
||||
add_alias(w,w2,SCRIPT_NCSA);
|
||||
}
|
||||
else if(!strcasecmp(w,"UserDir")) {
|
||||
cfg_getword(w,l);
|
||||
if(!strcmp(w,"DISABLED"))
|
||||
user_dir[0] = '\0';
|
||||
else
|
||||
strcpy(user_dir,w);
|
||||
}
|
||||
else if(!strcasecmp(w,"DirectoryIndex")) {
|
||||
cfg_getword(w,l);
|
||||
strcpy(index_name,w);
|
||||
}
|
||||
else if(!strcasecmp(w,"DefaultType")) {
|
||||
cfg_getword(w,l);
|
||||
strcpy(default_type,w);
|
||||
}
|
||||
else if(!strcasecmp(w,"AccessFileName")) {
|
||||
cfg_getword(w,l);
|
||||
strcpy(access_name,w);
|
||||
}
|
||||
else if(!strcasecmp(w,"DocumentRoot")) {
|
||||
cfg_getword(w,l);
|
||||
if(!is_directory(w)) {
|
||||
fprintf(stderr,"Syntax error on line %d of %s:\n",n,
|
||||
srm_confname);
|
||||
fprintf(stderr,"%s is not a valid directory.\n",w);
|
||||
exit(1);
|
||||
}
|
||||
strcpy(document_root,w);
|
||||
}
|
||||
else if(!strcasecmp(w,"Alias")) {
|
||||
char w2[MAX_STRING_LEN];
|
||||
|
||||
cfg_getword(w,l);
|
||||
cfg_getword(w2,l);
|
||||
if((w[0] == '\0') || (w2[0] == '\0')) {
|
||||
fprintf(stderr,"Syntax error on line %d of %s:\n",n,
|
||||
srm_confname);
|
||||
fprintf(stderr,
|
||||
"Alias must be followed by a fakename, one space, then a realname.\n");
|
||||
exit(1);
|
||||
}
|
||||
add_alias(w,w2,STD_DOCUMENT);
|
||||
}
|
||||
else if(!strcasecmp(w,"AddType")) {
|
||||
char w2[MAX_STRING_LEN];
|
||||
cfg_getword(w,l);
|
||||
cfg_getword(w2,l);
|
||||
if((w[0] == '\0') || (w2[0] == '\0')) {
|
||||
fprintf(stderr,"Syntax error on line %d of %s:\n",n,
|
||||
srm_confname);
|
||||
fprintf(stderr,
|
||||
"AddType must be followed by a type, one space, then a file or extension.\n");
|
||||
exit(1);
|
||||
}
|
||||
add_type(w2,w,stderr);
|
||||
}
|
||||
else if(!strcasecmp(w,"AddEncoding")) {
|
||||
char w2[MAX_STRING_LEN];
|
||||
cfg_getword(w,l);
|
||||
cfg_getword(w2,l);
|
||||
if((w[0] == '\0') || (w2[0] == '\0')) {
|
||||
fprintf(stderr,"Syntax error on line %d of %s:\n",n,
|
||||
srm_confname);
|
||||
fprintf(stderr,
|
||||
"AddEncoding must be followed by a type, one space, then a file or extension.\n");
|
||||
exit(1);
|
||||
}
|
||||
add_encoding(w2,w,stderr);
|
||||
}
|
||||
else if(!strcasecmp(w,"Redirect")) {
|
||||
char w2[MAX_STRING_LEN];
|
||||
cfg_getword(w,l);
|
||||
cfg_getword(w2,l);
|
||||
if((w[0] == '\0') || (w2[0] == '\0') || (!is_url(w2))) {
|
||||
fprintf(stderr,"Syntax error on line %d of %s:\n",n,
|
||||
srm_confname);
|
||||
fprintf(stderr,
|
||||
"Redirect must be followed by a document, one space, then a URL.\n");
|
||||
exit(1);
|
||||
}
|
||||
add_redirect(w,w2);
|
||||
}
|
||||
else if(!strcasecmp(w,"FancyIndexing")) {
|
||||
cfg_getword(w,l);
|
||||
if(!strcmp(w,"on"))
|
||||
fancy_indexing = 1;
|
||||
else if(!strcmp(w,"off"))
|
||||
fancy_indexing = 0;
|
||||
else {
|
||||
fprintf(stderr,"Syntax error on line %d of %s:\n",n,
|
||||
srm_confname);
|
||||
fprintf(stderr,"FancyIndexing must be on or off.\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else if(!strcasecmp(w,"AddDescription")) {
|
||||
char desc[MAX_STRING_LEN];
|
||||
int fq;
|
||||
if((fq = ind(l,'\"')) == -1) {
|
||||
fprintf(stderr,"Syntax error on line %d of %s:\n",n,
|
||||
srm_confname);
|
||||
fprintf(stderr,"AddDescription must have quotes around the description.\n");
|
||||
exit(1);
|
||||
}
|
||||
else {
|
||||
getword(desc,&l[++fq],'\"');
|
||||
cfg_getword(w,&l[fq]);
|
||||
add_desc(desc,w,stderr);
|
||||
}
|
||||
}
|
||||
else if(!strcasecmp(w,"IndexIgnore")) {
|
||||
while(l[0]) {
|
||||
cfg_getword(w,l);
|
||||
add_ignore(w,stderr);
|
||||
}
|
||||
}
|
||||
else if(!strcasecmp(w,"AddIcon")) {
|
||||
char w2[MAX_STRING_LEN];
|
||||
cfg_getword(w2,l);
|
||||
while(l[0]) {
|
||||
cfg_getword(w,l);
|
||||
add_icon(w2,w,stderr);
|
||||
}
|
||||
}
|
||||
else if(!strcasecmp(w,"DefaultIcon")) {
|
||||
cfg_getword(w,l);
|
||||
strcpy(default_icon,w);
|
||||
}
|
||||
else if(!strcasecmp(w,"ReadmeName")) {
|
||||
cfg_getword(w,l);
|
||||
strcpy(readme_fname,w);
|
||||
}
|
||||
else {
|
||||
fprintf(stderr,"Syntax error on line %d of %s:\n",n,srm_confname);
|
||||
fprintf(stderr,"Unknown keyword %s.\n",w);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose(cfg);
|
||||
}
|
||||
|
||||
|
||||
/* Auth Globals */
|
||||
char *auth_type;
|
||||
char *auth_name;
|
||||
char *auth_pwfile;
|
||||
char *auth_grpfile;
|
||||
|
||||
/* Access Globals*/
|
||||
int num_sec;
|
||||
security_data sec[MAX_SECURITY];
|
||||
|
||||
void access_syntax_error(int n, char *err, char *file, FILE *out) {
|
||||
if(!file) {
|
||||
fprintf(stderr,"Syntax error on line %d of access config. file.\n",n);
|
||||
fprintf(stderr,"%s\n",err);
|
||||
exit(1);
|
||||
}
|
||||
else {
|
||||
char e[MAX_STRING_LEN];
|
||||
sprintf(e,"httpd: syntax error or override violation in access control file %s, reason: %s",file,err);
|
||||
die(SERVER_ERROR,e,out);
|
||||
}
|
||||
}
|
||||
|
||||
int parse_access_dir(FILE *f, int line, char or, char *dir,
|
||||
char *file, FILE *out)
|
||||
{
|
||||
char l[MAX_STRING_LEN];
|
||||
char t[MAX_STRING_LEN];
|
||||
char w[MAX_STRING_LEN];
|
||||
char w2[MAX_STRING_LEN];
|
||||
int n=line;
|
||||
register int x,i;
|
||||
|
||||
x = num_sec;
|
||||
|
||||
sec[x].opts=OPT_UNSET;
|
||||
sec[x].override = or;
|
||||
if(!(sec[x].d = (char *)malloc((sizeof(char)) * (strlen(dir) + 2))))
|
||||
die(NO_MEMORY,"parse_access_dir",out);
|
||||
strcpy_dir(sec[x].d,dir);
|
||||
sec[x].auth_type = NULL;
|
||||
sec[x].auth_name = NULL;
|
||||
sec[x].auth_pwfile = NULL;
|
||||
sec[x].auth_grpfile = NULL;
|
||||
for(i=0;i<METHODS;i++) {
|
||||
sec[x].order[i] = DENY_THEN_ALLOW;
|
||||
sec[x].num_allow[i]=0;
|
||||
sec[x].num_deny[i]=0;
|
||||
sec[x].num_auth[i] = 0;
|
||||
}
|
||||
|
||||
while(!(cfg_getline(l,MAX_STRING_LEN,f))) {
|
||||
++n;
|
||||
if((l[0] == '#') || (!l[0])) continue;
|
||||
cfg_getword(w,l);
|
||||
|
||||
if(!strcasecmp(w,"AllowOverride")) {
|
||||
if(file)
|
||||
access_syntax_error(n,"override violation",file,out);
|
||||
sec[x].override = OR_NONE;
|
||||
while(l[0]) {
|
||||
cfg_getword(w,l);
|
||||
if(!strcasecmp(w,"Limit"))
|
||||
sec[x].override |= OR_LIMIT;
|
||||
else if(!strcasecmp(w,"Options"))
|
||||
sec[x].override |= OR_OPTIONS;
|
||||
else if(!strcasecmp(w,"FileInfo"))
|
||||
sec[x].override |= OR_FILEINFO;
|
||||
else if(!strcasecmp(w,"AuthConfig"))
|
||||
sec[x].override |= OR_AUTHCFG;
|
||||
else if(!strcasecmp(w,"None"))
|
||||
sec[x].override = OR_NONE;
|
||||
else if(!strcasecmp(w,"All"))
|
||||
sec[x].override = OR_ALL;
|
||||
else {
|
||||
access_syntax_error(n,
|
||||
"Unknown keyword in AllowOverride directive.",file,out);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(!strcasecmp(w,"Options")) {
|
||||
if(!(or & OR_OPTIONS))
|
||||
access_syntax_error(n,"override violation",file,out);
|
||||
sec[x].opts = OPT_NONE;
|
||||
while(l[0]) {
|
||||
cfg_getword(w,l);
|
||||
if(!strcasecmp(w,"Indexes"))
|
||||
sec[x].opts |= OPT_INDEXES;
|
||||
else if(!strcasecmp(w,"Includes"))
|
||||
sec[x].opts |= OPT_INCLUDES;
|
||||
else if(!strcasecmp(w,"FollowSymLinks"))
|
||||
sec[x].opts |= OPT_SYM_LINKS;
|
||||
else if(!strcasecmp(w,"None"))
|
||||
sec[x].opts = OPT_NONE;
|
||||
else if(!strcasecmp(w,"All"))
|
||||
sec[x].opts = OPT_ALL;
|
||||
else {
|
||||
access_syntax_error(n,
|
||||
"Unknown keyword in Options directive.",file,out);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(!strcasecmp(w,"AuthName")) {
|
||||
if(!(or & OR_AUTHCFG))
|
||||
access_syntax_error(n,"override violation",file,out);
|
||||
if(sec[x].auth_name)
|
||||
free(sec[x].auth_name);
|
||||
if(!(sec[x].auth_name = strdup(l)))
|
||||
die(NO_MEMORY,"parse_access_dir",out);
|
||||
}
|
||||
else if(!strcasecmp(w,"AuthType")) {
|
||||
if(!(or & OR_AUTHCFG))
|
||||
access_syntax_error(n,"override violation",file,out);
|
||||
cfg_getword(w,l);
|
||||
if(sec[x].auth_type)
|
||||
free(sec[x].auth_type);
|
||||
if(!(sec[x].auth_type = strdup(w)))
|
||||
die(NO_MEMORY,"parse_access_dir",out);
|
||||
}
|
||||
else if(!strcasecmp(w,"AuthUserFile")) {
|
||||
if(!(or & OR_AUTHCFG))
|
||||
access_syntax_error(n,"override violation",file,out);
|
||||
cfg_getword(w,l);
|
||||
if(sec[x].auth_pwfile)
|
||||
free(sec[x].auth_pwfile);
|
||||
if(!(sec[x].auth_pwfile = strdup(w)))
|
||||
die(NO_MEMORY,"parse_access_dir",out);
|
||||
}
|
||||
else if(!strcasecmp(w,"AuthGroupFile")) {
|
||||
if(!(or & OR_AUTHCFG))
|
||||
access_syntax_error(n,"override violation",file,out);
|
||||
cfg_getword(w,l);
|
||||
if(sec[x].auth_grpfile)
|
||||
free(sec[x].auth_grpfile);
|
||||
if(!(sec[x].auth_grpfile = strdup(w)))
|
||||
die(NO_MEMORY,"parse_access_dir",out);
|
||||
}
|
||||
else if(!strcasecmp(w,"AddType")) {
|
||||
if(!(or & OR_FILEINFO))
|
||||
access_syntax_error(n,"override violation",file,out);
|
||||
cfg_getword(w,l);
|
||||
cfg_getword(w2,l);
|
||||
if((w[0] == '\0') || (w2[0] == '\0')) {
|
||||
access_syntax_error(n,
|
||||
"AddType must be followed by a type, one space, then a file or extension.",
|
||||
file,out);
|
||||
}
|
||||
add_type(w2,w,out);
|
||||
}
|
||||
else if(!strcasecmp(w,"AddEncoding")) {
|
||||
if(!(or & OR_FILEINFO))
|
||||
access_syntax_error(n,"override violation",file,out);
|
||||
cfg_getword(w,l);
|
||||
cfg_getword(w2,l);
|
||||
if((w[0] == '\0') || (w2[0] == '\0')) {
|
||||
access_syntax_error(n,
|
||||
"AddEncoding must be followed by a type, one space, then a file or extension.",
|
||||
file,out);
|
||||
}
|
||||
add_encoding(w2,w,out);
|
||||
}
|
||||
else if(!strcasecmp(w,"AddDescription")) {
|
||||
int fq;
|
||||
if(!(or & OR_FILEINFO))
|
||||
access_syntax_error(n,"override violation",file,out);
|
||||
if((fq = ind(l,'\"')) == -1) {
|
||||
access_syntax_error(n,
|
||||
"AddDescription must have quotes around the description.\n",
|
||||
file,out);
|
||||
}
|
||||
else {
|
||||
getword(w2,&l[++fq],'\"');
|
||||
cfg_getword(w,&l[fq]);
|
||||
add_desc(w2,w,stderr);
|
||||
}
|
||||
}
|
||||
else if(!strcasecmp(w,"IndexIgnore")) {
|
||||
if(!(or & OR_FILEINFO))
|
||||
access_syntax_error(n,"override violation",file,out);
|
||||
while(l[0]) {
|
||||
cfg_getword(w,l);
|
||||
add_ignore(w,out);
|
||||
}
|
||||
}
|
||||
else if(!strcasecmp(w,"AddIcon")) {
|
||||
if(!(or & OR_FILEINFO))
|
||||
access_syntax_error(n,"override violation",file,out);
|
||||
cfg_getword(w2,l);
|
||||
while(l[0]) {
|
||||
cfg_getword(w,l);
|
||||
add_icon(w2,w,out);
|
||||
}
|
||||
}
|
||||
else if(!strcasecmp(w,"ReadmeName")) {
|
||||
if(!(or & OR_FILEINFO))
|
||||
access_syntax_error(n,"override violation",file,out);
|
||||
cfg_getword(w,l);
|
||||
strcpy(readme_fname,w);
|
||||
}
|
||||
else if(!strcasecmp(w,"DefaultIcon")) {
|
||||
if(!(or & OR_FILEINFO))
|
||||
access_syntax_error(n,"override violation",file,out);
|
||||
cfg_getword(w,l);
|
||||
strcpy(default_icon,w);
|
||||
}
|
||||
else if(!strcasecmp(w,"Redirect")) {
|
||||
if(!(or & OR_FILEINFO))
|
||||
access_syntax_error(n,"override violation",file,out);
|
||||
cfg_getword(w,l);
|
||||
cfg_getword(w2,l);
|
||||
if((w[0] == '\0') || (w2[0] == '\0') || (!is_url(w2))) {
|
||||
access_syntax_error(n,
|
||||
"Redirect must be followed by a document, one space, then a URL.",file,out);
|
||||
}
|
||||
if(!file)
|
||||
add_redirect(w,w2);
|
||||
else
|
||||
access_syntax_error(n,
|
||||
"Redirect no longer supported from .htaccess files.",file,out);
|
||||
}
|
||||
else if(!strcasecmp(w,"<Limit")) {
|
||||
int m[METHODS];
|
||||
|
||||
if(!(or & OR_LIMIT))
|
||||
access_syntax_error(n,"override violation",file,out);
|
||||
for(i=0;i<METHODS;i++) m[i] = 0;
|
||||
getword(w2,l,'>');
|
||||
while(w2[0]) {
|
||||
cfg_getword(w,w2);
|
||||
if(!strcasecmp(w,"GET")) m[M_GET]=1;
|
||||
else if(!strcasecmp(w,"PUT")) m[M_PUT]=1;
|
||||
else if(!strcasecmp(w,"POST")) m[M_POST]=1;
|
||||
}
|
||||
while(1) {
|
||||
if(cfg_getline(l,MAX_STRING_LEN,f))
|
||||
access_syntax_error(n,"Limit missing /Limit",file,out);
|
||||
n++;
|
||||
if((l[0] == '#') || (!l[0])) continue;
|
||||
|
||||
if(!strcasecmp(l,"</Limit>"))
|
||||
break;
|
||||
cfg_getword(w,l);
|
||||
if(!strcasecmp(w,"order")) {
|
||||
if(!strcasecmp(l,"allow,deny")) {
|
||||
for(i=0;i<METHODS;i++)
|
||||
if(m[i])
|
||||
sec[x].order[i] = ALLOW_THEN_DENY;
|
||||
}
|
||||
else if(!strcasecmp(l,"deny,allow")) {
|
||||
for(i=0;i<METHODS;i++)
|
||||
if(m[i])
|
||||
sec[x].order[i] = DENY_THEN_ALLOW;
|
||||
}
|
||||
else
|
||||
access_syntax_error(n,"Unknown order.",file,out);
|
||||
}
|
||||
else if((!strcasecmp(w,"allow"))) {
|
||||
cfg_getword(w,l);
|
||||
if(strcmp(w,"from"))
|
||||
access_syntax_error(n,
|
||||
"allow must be followed by from.",
|
||||
file,out);
|
||||
while(1) {
|
||||
cfg_getword(w,l);
|
||||
if(!w[0]) break;
|
||||
for(i=0;i<METHODS;i++)
|
||||
if(m[i]) {
|
||||
int q=sec[x].num_allow[i]++;
|
||||
if(!(sec[x].allow[i][q] = strdup(w)))
|
||||
die(NO_MEMORY,"parse_access_dir",out);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(!strcasecmp(w,"require")) {
|
||||
for(i=0;i<METHODS;i++)
|
||||
if(m[i]) {
|
||||
int q=sec[x].num_auth[i]++;
|
||||
if(!(sec[x].auth[i][q] = strdup(l)))
|
||||
die(NO_MEMORY,"parse_access_dir",out);
|
||||
}
|
||||
}
|
||||
else if((!strcasecmp(w,"deny"))) {
|
||||
cfg_getword(w,l);
|
||||
if(strcmp(w,"from"))
|
||||
access_syntax_error(n,
|
||||
"deny must be followed by from.",
|
||||
file,out);
|
||||
while(1) {
|
||||
cfg_getword(w,l);
|
||||
if(!w[0]) break;
|
||||
for(i=0;i<METHODS;i++)
|
||||
if(m[i]) {
|
||||
int q=sec[x].num_deny[i]++;
|
||||
if(!(sec[x].deny[i][q] = strdup(w)))
|
||||
die(NO_MEMORY,"parse_access_dir",out);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
access_syntax_error(n,"Unknown keyword in Limit region.",
|
||||
file,out);
|
||||
}
|
||||
}
|
||||
else if(!strcasecmp(w,"</Directory>"))
|
||||
break;
|
||||
else {
|
||||
char errstr[MAX_STRING_LEN];
|
||||
sprintf(errstr,"Unknown method %s",w);
|
||||
access_syntax_error(n,errstr,file,out);
|
||||
return;
|
||||
}
|
||||
}
|
||||
++num_sec;
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
void parse_htaccess(char *path, char override, FILE *out) {
|
||||
FILE *f;
|
||||
char t[MAX_STRING_LEN];
|
||||
char d[MAX_STRING_LEN];
|
||||
int x;
|
||||
|
||||
strcpy(d,path);
|
||||
make_full_path(d,access_name,t);
|
||||
|
||||
if((f=fopen(t,"r"))) {
|
||||
parse_access_dir(f,-1,override,d,t,out);
|
||||
fclose(f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void process_access_config() {
|
||||
FILE *f;
|
||||
char l[MAX_STRING_LEN];
|
||||
char w[MAX_STRING_LEN];
|
||||
int n;
|
||||
|
||||
num_sec = 0;n=0;
|
||||
if(!(f=fopen(access_confname,"r"))) {
|
||||
fprintf(stderr,"httpd: could not open access configuration file %s.\n",
|
||||
access_confname);
|
||||
perror("fopen");
|
||||
exit(1);
|
||||
}
|
||||
while(!(cfg_getline(l,MAX_STRING_LEN,f))) {
|
||||
++n;
|
||||
if((l[0] == '#') || (!l[0])) continue;
|
||||
cfg_getword(w,l);
|
||||
if(strcasecmp(w,"<Directory")) {
|
||||
fprintf(stderr,
|
||||
"Syntax error on line %d of access config. file.\n",n);
|
||||
fprintf(stderr,"Unknown directive %s.\n",w);
|
||||
exit(1);
|
||||
}
|
||||
getword(w,l,'>');
|
||||
n=parse_access_dir(f,n,OR_ALL,w,NULL,stderr);
|
||||
}
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
int get_pw(char *user, char *pw) {
|
||||
FILE *f;
|
||||
char errstr[MAX_STRING_LEN];
|
||||
char l[MAX_STRING_LEN];
|
||||
char w[MAX_STRING_LEN];
|
||||
|
||||
if(!(f=fopen(auth_pwfile,"r"))) {
|
||||
sprintf(errstr,"Could not open user file %s",auth_pwfile);
|
||||
die(SERVER_ERROR,errstr,stdout); /* AAAAAAAAGH stdout */
|
||||
}
|
||||
while(!(cfg_getline(l,MAX_STRING_LEN,f))) {
|
||||
if((l[0] == '#') || (!l[0])) continue;
|
||||
getword(w,l,':');
|
||||
|
||||
if(!strcmp(user,w)) {
|
||||
strcpy(pw,l);
|
||||
fclose(f);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
struct ge {
|
||||
char *name;
|
||||
char *members;
|
||||
struct ge *next;
|
||||
};
|
||||
|
||||
static struct ge *grps;
|
||||
|
||||
int init_group(char *grpfile, FILE *out) {
|
||||
FILE *f;
|
||||
struct ge *p;
|
||||
char l[MAX_STRING_LEN],w[MAX_STRING_LEN];
|
||||
|
||||
if(!(f=fopen(grpfile,"r")))
|
||||
return 0;
|
||||
|
||||
grps = NULL;
|
||||
while(!(cfg_getline(l,MAX_STRING_LEN,f))) {
|
||||
if((l[0] == '#') || (!l[0])) continue;
|
||||
getword(w,l,':');
|
||||
if(!(p = (struct ge *) malloc (sizeof(struct ge))))
|
||||
die(NO_MEMORY,"init_group",out);
|
||||
if(!(p->name = strdup(w)))
|
||||
die(NO_MEMORY,"init_group",out);
|
||||
if(!(p->members = strdup(l)))
|
||||
die(NO_MEMORY,"init_group",out);
|
||||
p->next = grps;
|
||||
grps = p;
|
||||
}
|
||||
fclose(f);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int in_group(char *user, char *group) {
|
||||
struct ge *p = grps;
|
||||
char l[MAX_STRING_LEN],w[MAX_STRING_LEN];
|
||||
|
||||
while(p) {
|
||||
if(!strcmp(p->name,group)) {
|
||||
strcpy(l,p->members);
|
||||
while(l[0]) {
|
||||
getword(w,l,' ');
|
||||
if(!strcmp(w,user))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
p=p->next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void kill_group() {
|
||||
struct ge *p = grps, *q;
|
||||
|
||||
while(p) {
|
||||
free(p->name);
|
||||
free(p->members);
|
||||
q=p;
|
||||
p=p->next;
|
||||
free(q);
|
||||
}
|
||||
}
|
||||
|
||||
void read_config()
|
||||
{
|
||||
reset_aliases();
|
||||
process_server_config();
|
||||
init_mime();
|
||||
init_indexing();
|
||||
process_resource_config();
|
||||
process_access_config();
|
||||
}
|
321
src/http_dir.c
Normal file
321
src/http_dir.c
Normal file
@ -0,0 +1,321 @@
|
||||
/*
|
||||
* http_dir.c: Handles the on-the-fly html index generation
|
||||
*
|
||||
* Rob McCool
|
||||
* 3/23/93
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/* httpd.h includes proper directory file */
|
||||
#include "httpd.h"
|
||||
|
||||
struct ent {
|
||||
char *name;
|
||||
char *icon;
|
||||
char *desc;
|
||||
size_t size;
|
||||
struct ent *next;
|
||||
};
|
||||
|
||||
struct item {
|
||||
char *msg;
|
||||
char *fn;
|
||||
struct item *next;
|
||||
};
|
||||
|
||||
static struct item *icon_list, *desc_list, *ign_list;
|
||||
|
||||
void init_indexing() {
|
||||
icon_list = NULL;
|
||||
desc_list = NULL;
|
||||
ign_list = NULL;
|
||||
}
|
||||
|
||||
void kill_item_list(struct item *p) {
|
||||
struct item *q;
|
||||
|
||||
while(p) {
|
||||
if(p->msg) free(p->msg);
|
||||
if(p->fn) free(p->fn);
|
||||
q = p;
|
||||
p = p->next;
|
||||
free(q);
|
||||
}
|
||||
}
|
||||
|
||||
void kill_indexing() {
|
||||
kill_item_list(icon_list);
|
||||
kill_item_list(desc_list);
|
||||
kill_item_list(ign_list);
|
||||
}
|
||||
|
||||
void add_icon(char *icon, char *ext, FILE *out) {
|
||||
struct item *p;
|
||||
|
||||
if(!(p = (struct item *)malloc(sizeof(struct item))))
|
||||
die(NO_MEMORY,"add_icon",out);
|
||||
if(!(p->msg = strdup(icon)))
|
||||
die(NO_MEMORY,"add_icon",out);
|
||||
if(!(p->fn = strdup(ext)))
|
||||
die(NO_MEMORY,"add_icon",out);
|
||||
p->next = icon_list;
|
||||
icon_list = p;
|
||||
}
|
||||
|
||||
char *find_icon(char *path) {
|
||||
struct item *p = icon_list;
|
||||
int pl, el;
|
||||
|
||||
pl = strlen(path);
|
||||
while(p) {
|
||||
el = strlen(p->fn);
|
||||
if(el <= pl)
|
||||
if(!strcmp(&path[pl - el],p->fn))
|
||||
return p->msg;
|
||||
p = p->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void add_desc(char *desc, char *ext, FILE *out) {
|
||||
struct item *p;
|
||||
|
||||
if(!(p = (struct item *)malloc(sizeof(struct item))))
|
||||
die(NO_MEMORY,"add_desc",out);
|
||||
if(!(p->msg = strdup(desc)))
|
||||
die(NO_MEMORY,"add_desc",out);
|
||||
if(!(p->fn = strdup(ext)))
|
||||
die(NO_MEMORY,"add_desc",out);
|
||||
p->next = desc_list;
|
||||
desc_list = p;
|
||||
}
|
||||
|
||||
char *find_desc(char *path) {
|
||||
struct item *p = desc_list;
|
||||
int pl, el;
|
||||
|
||||
pl = strlen(path);
|
||||
while(p) {
|
||||
el = strlen(p->fn);
|
||||
if(el <= pl)
|
||||
if(!strcmp(&path[pl - el],p->fn))
|
||||
return p->msg;
|
||||
p = p->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void add_ignore(char *ext,FILE *out) {
|
||||
struct item *p;
|
||||
|
||||
if(!(p = (struct item *)malloc(sizeof(struct item))))
|
||||
die(NO_MEMORY,"add_ignore",out);
|
||||
p->msg = NULL;
|
||||
if(!(p->fn = strdup(ext)))
|
||||
die(NO_MEMORY,"add_ignore",out);
|
||||
p->next = ign_list;
|
||||
ign_list = p;
|
||||
}
|
||||
|
||||
int ignore_entry(char *path) {
|
||||
struct item *p;
|
||||
int pl,el;
|
||||
|
||||
pl = strlen(path);
|
||||
p = ign_list;
|
||||
while(p) {
|
||||
el = strlen(p->fn);
|
||||
if(el <= pl)
|
||||
if(!strcmp(&path[pl - el],p->fn))
|
||||
return 1;
|
||||
p = p->next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void insert_readme(char *name, FILE *fd) {
|
||||
char fn[MAX_STRING_LEN];
|
||||
FILE *r;
|
||||
struct stat finfo;
|
||||
int plaintext=0;
|
||||
|
||||
if(!readme_fname[0])
|
||||
return;
|
||||
make_full_path(name,readme_fname,fn);
|
||||
strcat(fn,".html");
|
||||
if(stat(fn,&finfo) == -1) {
|
||||
fn[strlen(fn)-5] = '\0';
|
||||
if(stat(fn,&finfo) == -1)
|
||||
return;
|
||||
plaintext=1;
|
||||
fprintf(fd,"<HR><PRE>%c",LF);
|
||||
}
|
||||
else fprintf(fd,"<HR>");
|
||||
if(!(r = fopen(fn,"r")))
|
||||
return;
|
||||
send_fd(r,fd,"");
|
||||
fclose(r);
|
||||
if(plaintext)
|
||||
fprintf(fd,"</PRE>%c",LF);
|
||||
}
|
||||
|
||||
struct ent *make_dir_entry(char *path, char *name, FILE *out) {
|
||||
struct ent *p;
|
||||
struct stat finfo;
|
||||
char t[MAX_STRING_LEN];
|
||||
|
||||
if((name[0] == '.') && (!name[1]))
|
||||
return(NULL);
|
||||
|
||||
make_full_path(path,name,t);
|
||||
if(ignore_entry(t))
|
||||
return(NULL);
|
||||
|
||||
if(!(p=(struct ent *)malloc(sizeof(struct ent))))
|
||||
die(NO_MEMORY,"make_dir_entry",out);
|
||||
if(!(p->name=strdup(name)))
|
||||
die(NO_MEMORY,"make_dir_entry",out);
|
||||
|
||||
if(fancy_indexing) {
|
||||
p->icon = find_icon(t);
|
||||
if((!fancy_indexing) || stat(t,&finfo) == -1) {
|
||||
p->size = -1;
|
||||
}
|
||||
else {
|
||||
if(S_ISDIR(finfo.st_mode)) {
|
||||
if(!p->icon)
|
||||
p->icon = find_icon("**DIRECTORY**");
|
||||
p->size = -1;
|
||||
}
|
||||
else
|
||||
p->size = finfo.st_size;
|
||||
}
|
||||
p->desc = find_desc(t);
|
||||
}
|
||||
else {
|
||||
p->icon = NULL;
|
||||
p->desc = NULL;
|
||||
p->size = -1;
|
||||
}
|
||||
return(p);
|
||||
}
|
||||
|
||||
void output_directories(struct ent **ar,int n,char *name,FILE *fd)
|
||||
{
|
||||
int x;
|
||||
char blorf[MAX_STRING_LEN];
|
||||
|
||||
if(name[0] == '\0') {
|
||||
name[0] = '/'; name[1] = '\0';
|
||||
}
|
||||
/* aaaaargh Solaris sucks. */
|
||||
fflush(fd);
|
||||
for(x=0;x<n;x++) {
|
||||
fprintf(fd,"<%s>%c",(fancy_indexing ? "DD" : "LI"),LF);
|
||||
if(fancy_indexing && ((ar[x]->icon) || default_icon[0])) {
|
||||
fprintf(fd,"<IMG SRC=\"%s\"> ",
|
||||
ar[x]->icon ? ar[x]->icon : default_icon);
|
||||
}
|
||||
if(strcmp(ar[x]->name,"..")) {
|
||||
make_full_path(name,ar[x]->name,blorf);
|
||||
escape_url(blorf);
|
||||
fprintf(fd,"<A NAME=\"%s\" HREF=\"%s\">%s</A>",ar[x]->name,
|
||||
blorf,ar[x]->name);
|
||||
}
|
||||
else {
|
||||
make_full_path(name,"..",blorf);
|
||||
getparents(blorf);
|
||||
if(blorf[0] == '\0') {
|
||||
blorf[0] = '/'; blorf[1] = '\0';
|
||||
}
|
||||
escape_url(blorf);
|
||||
fprintf(fd,"<A HREF=\"%s\">%s</A>",blorf,"Parent Directory");
|
||||
}
|
||||
if(fancy_indexing) {
|
||||
if(ar[x]->desc)
|
||||
fprintf(fd," : %s",ar[x]->desc,LF);
|
||||
if(ar[x]->size != -1)
|
||||
fprintf(fd," (%d bytes)",ar[x]->size);
|
||||
}
|
||||
fputc(LF,fd);
|
||||
}
|
||||
}
|
||||
|
||||
int dsortf(struct ent **s1,struct ent **s2)
|
||||
{
|
||||
return(strcmp((*s1)->name,(*s2)->name));
|
||||
}
|
||||
|
||||
|
||||
void index_directory(char *name, FILE *fd)
|
||||
{
|
||||
DIR *d;
|
||||
struct DIR_TYPE *dstruct;
|
||||
int num_ent=0,x;
|
||||
struct ent *head,*p,*q;
|
||||
struct ent **ar;
|
||||
char unmunged_name[MAX_STRING_LEN];
|
||||
|
||||
strcpy(unmunged_name,name);
|
||||
unmunge_name(unmunged_name);
|
||||
|
||||
if(!(d=opendir(name)))
|
||||
die(FORBIDDEN,unmunged_name,fd);
|
||||
|
||||
strcpy(content_type,"text/html");
|
||||
if(!assbackwards)
|
||||
send_http_header(fd);
|
||||
|
||||
if(header_only) return;
|
||||
|
||||
/* Spew HTML preamble */
|
||||
fprintf(fd,"<HEAD><TITLE>Index of %s</TITLE></HEAD>",unmunged_name);
|
||||
fputc(LF,fd);
|
||||
fprintf(fd,"<BODY><H1>Index of %s</H1>",unmunged_name);
|
||||
fputc(LF,fd);
|
||||
|
||||
fprintf(fd,fancy_indexing ? "<DL>%c" : "<UL>%c",LF);
|
||||
|
||||
/*
|
||||
* Since we don't know how many dir. entries there are, put them into a
|
||||
* linked list and then arrayificate them so qsort can use them.
|
||||
*/
|
||||
head=NULL;
|
||||
while(dstruct=readdir(d)) {
|
||||
if(p = make_dir_entry(name,dstruct->d_name,fd)) {
|
||||
p->next=head;
|
||||
head=p;
|
||||
num_ent++;
|
||||
}
|
||||
}
|
||||
if(!(ar=(struct ent **) malloc(num_ent*sizeof(struct ent *))))
|
||||
die(NO_MEMORY,"index_directory",fd);
|
||||
p=head;
|
||||
x=0;
|
||||
while(p) {
|
||||
ar[x++]=p;
|
||||
p = p->next;
|
||||
}
|
||||
|
||||
qsort((void *)ar,num_ent,sizeof(struct ent *),
|
||||
#ifdef ULTRIX_BRAIN_DEATH
|
||||
(int (*))dsortf);
|
||||
#else
|
||||
(int (*)(const void *,const void *))dsortf);
|
||||
#endif
|
||||
output_directories(ar,num_ent,unmunged_name,fd);
|
||||
free(ar);
|
||||
q = head;
|
||||
while(q) {
|
||||
p=q->next;
|
||||
free(q->name);
|
||||
free(q);
|
||||
q=p;
|
||||
}
|
||||
closedir(d);
|
||||
fprintf(fd,fancy_indexing ? "</DL>" : "</UL>");
|
||||
if(fancy_indexing)
|
||||
insert_readme(name,fd);
|
||||
fprintf(fd,"</BODY>");
|
||||
}
|
120
src/http_get.c
Normal file
120
src/http_get.c
Normal file
@ -0,0 +1,120 @@
|
||||
/*
|
||||
* http_get.c: Handles things associated with GET
|
||||
*
|
||||
* Rob McCool
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "httpd.h"
|
||||
|
||||
|
||||
int header_only;
|
||||
int num_includes;
|
||||
int allow;
|
||||
char allow_options;
|
||||
|
||||
|
||||
void send_file(char *file, FILE *fd, char *args) {
|
||||
FILE *f;
|
||||
struct stat finfo;
|
||||
|
||||
if(!(f=fopen(file,"r"))) {
|
||||
log_reason("file permissions deny server access",file);
|
||||
unmunge_name(file);
|
||||
die(FORBIDDEN,file,fd); /* we've already established that it exists */
|
||||
}
|
||||
set_content_type(file);
|
||||
if(!assbackwards) {
|
||||
fstat(fileno(f),&finfo);
|
||||
if(!((allow_options & OPT_INCLUDES) && is_content_type("text/html")))
|
||||
set_content_length(finfo.st_size);
|
||||
set_last_modified(finfo.st_mtime);
|
||||
send_http_header(fd);
|
||||
}
|
||||
num_includes=0;
|
||||
if(!header_only)
|
||||
send_fd(f,fd,args);
|
||||
}
|
||||
|
||||
|
||||
void send_node(char *file, char *args, FILE *fd)
|
||||
{
|
||||
struct stat finfo;
|
||||
|
||||
if(stat(file,&finfo) == -1) {
|
||||
if(errno==ENOENT) {
|
||||
log_reason("file does not exist",file);
|
||||
unmunge_name(file);
|
||||
die(NOT_FOUND,file,fd);
|
||||
}
|
||||
else {
|
||||
log_reason("file permissions deny server access",file);
|
||||
unmunge_name(file);
|
||||
die(FORBIDDEN,file,fd);
|
||||
}
|
||||
}
|
||||
evaluate_access(file,&finfo,M_GET,&allow,&allow_options, fd);
|
||||
if(!allow) {
|
||||
log_reason("client denied by server configuration",file);
|
||||
unmunge_name(file);
|
||||
die(FORBIDDEN,file,fd);
|
||||
}
|
||||
|
||||
if(S_ISDIR(finfo.st_mode)) {
|
||||
char ifile[MAX_STRING_LEN];
|
||||
|
||||
make_full_path(file,index_name,ifile);
|
||||
if(stat(ifile,&finfo) == -1) {
|
||||
if(allow_options & OPT_INDEXES)
|
||||
index_directory(file,fd);
|
||||
else {
|
||||
log_reason("file permissions deny server access",file);
|
||||
unmunge_name(file);
|
||||
die(FORBIDDEN,file,fd);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(file[strlen(file) - 1] != '/') {
|
||||
char url[MAX_STRING_LEN];
|
||||
strcpy_dir(ifile,file);
|
||||
unmunge_name(ifile);
|
||||
construct_url(url,ifile);
|
||||
die(REDIRECT,url,fd);
|
||||
}
|
||||
send_file(ifile,fd,args);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if(S_ISREG(finfo.st_mode))
|
||||
send_file(file,fd,args);
|
||||
else {
|
||||
log_reason("improper file type",file);
|
||||
unmunge_name(file);
|
||||
die(FORBIDDEN,file,fd); /* device driver or pipe, no permission */
|
||||
}
|
||||
}
|
||||
|
||||
void process_get(int in, FILE *out, char *m, char *url, char *args) {
|
||||
int s;
|
||||
|
||||
if(assbackwards && header_only) {
|
||||
header_only = 0;
|
||||
die(BAD_REQUEST,"Invalid HTTP/0.9 method.",out);
|
||||
}
|
||||
s=translate_name(url,out);
|
||||
switch(s) {
|
||||
case STD_DOCUMENT:
|
||||
send_node(url,args,out);
|
||||
return;
|
||||
case REDIRECT_URL:
|
||||
die(REDIRECT,url,out);
|
||||
case SCRIPT_NCSA:
|
||||
exec_get_NCSA(url,args,out);
|
||||
return;
|
||||
case SCRIPT_CGI:
|
||||
exec_cgi_script(m,url,args,in,out);
|
||||
return;
|
||||
}
|
||||
}
|
179
src/http_log.c
Normal file
179
src/http_log.c
Normal file
@ -0,0 +1,179 @@
|
||||
/*
|
||||
* http_log.c: Dealing with the logs and errors
|
||||
*
|
||||
* Rob McCool
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "httpd.h"
|
||||
|
||||
static FILE *error_log;
|
||||
static FILE *xfer_log;
|
||||
|
||||
void open_logs() {
|
||||
if(!(error_log = fopen(error_fname,"a"))) {
|
||||
fprintf(stderr,"httpd: could not open error log file %s.\n",
|
||||
error_fname);
|
||||
perror("fopen");
|
||||
exit(1);
|
||||
}
|
||||
/* Make sure nasty scripts or includes send errors here */
|
||||
if(fileno(error_log) != STDERR_FILENO)
|
||||
dup2(fileno(error_log),STDERR_FILENO);
|
||||
if(!(xfer_log = fopen(xfer_fname,"a"))) {
|
||||
fprintf(stderr,"httpd: could not open transfer log file %s.\n",
|
||||
xfer_fname);
|
||||
perror("fopen");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void close_logs() {
|
||||
fclose(xfer_log);
|
||||
fclose(error_log);
|
||||
fclose(stderr);
|
||||
}
|
||||
|
||||
void log_pid() {
|
||||
FILE *pid_file;
|
||||
|
||||
if(!(pid_file = fopen(pid_fname,"w"))) {
|
||||
fprintf(stderr,"httpd: could not log pid to file %s\n",pid_fname);
|
||||
exit(1);
|
||||
}
|
||||
fprintf(pid_file,"%d\n",getpid());
|
||||
fclose(pid_file);
|
||||
}
|
||||
|
||||
void log_transaction(char *cmd_line) {
|
||||
if(!do_rfc931)
|
||||
fprintf(xfer_log, "%s [%s] %s\n", remote_name, get_time(), cmd_line);
|
||||
else
|
||||
fprintf(xfer_log, "%s@%s [%s] %s\n", remote_logname, remote_name,
|
||||
get_time(), cmd_line);
|
||||
fclose(xfer_log); /* we should be done with it... */
|
||||
}
|
||||
|
||||
void log_error(char *err) {
|
||||
fprintf(error_log, "[%s] %s\n",get_time(),err);
|
||||
fclose(error_log);
|
||||
}
|
||||
|
||||
void log_reason(char *reason, char *file) {
|
||||
char t[MAX_STRING_LEN];
|
||||
|
||||
sprintf(t,"httpd: access to %s failed for %s, reason: %s",
|
||||
file,remote_name,reason);
|
||||
log_error(t);
|
||||
}
|
||||
|
||||
void begin_http_header(FILE *fd, char *msg) {
|
||||
fprintf(fd,"%s %s%c",SERVER_PROTOCOL,msg,LF);
|
||||
dump_default_header(fd);
|
||||
}
|
||||
|
||||
void error_head(FILE *fd, char *err) {
|
||||
if(!assbackwards) {
|
||||
begin_http_header(fd,err);
|
||||
fprintf(fd,"Content-type: text/html%c",LF);
|
||||
fprintf(fd,"%c",LF);
|
||||
}
|
||||
if(!header_only) {
|
||||
fprintf(fd,"<HEAD><TITLE>%s</TITLE></HEAD>%c",err,LF);
|
||||
fprintf(fd,"<BODY><H1>%s</H1>%c",err,LF);
|
||||
}
|
||||
}
|
||||
|
||||
void title_html(FILE *fd, char *msg) {
|
||||
fprintf(fd,"<HEAD><TITLE>%s</TITLE></HEAD>%c",msg,LF);
|
||||
fprintf(fd,"<BODY><H1>%s</H1>%c",msg,LF);
|
||||
}
|
||||
|
||||
void die(int type, char *err_string, FILE *fd) {
|
||||
char t[MAX_STRING_LEN];
|
||||
|
||||
switch(type) {
|
||||
case REDIRECT:
|
||||
if(!assbackwards) {
|
||||
begin_http_header(fd,"302 Found");
|
||||
fprintf(fd,"Location: %s%c",err_string,LF);
|
||||
fprintf(fd,"Content-type: text/html%c",LF);
|
||||
fputc(LF,fd);
|
||||
}
|
||||
if(header_only) break;
|
||||
title_html(fd,"Document moved");
|
||||
fprintf(fd,"This document has moved <A HREF=\"%s\">here</A>.<P>%c",
|
||||
err_string,LF);
|
||||
break;
|
||||
case AUTH_REQUIRED:
|
||||
if(!assbackwards) {
|
||||
begin_http_header(fd,"401 Unauthorized");
|
||||
fprintf(fd,"WWW-Authenticate: %s%c%c",err_string,LF,LF);
|
||||
}
|
||||
if(header_only) break;
|
||||
title_html(fd,"Authorization Required");
|
||||
fprintf(fd,"Browser not authentication-capable or %c",LF);
|
||||
fprintf(fd,"authentication failed.%c",LF);
|
||||
break;
|
||||
case BAD_REQUEST:
|
||||
error_head(fd,"400 Bad Request");
|
||||
if(header_only) break;
|
||||
fprintf(fd,"Your client sent a query that this server could not%c",LF);
|
||||
fprintf(fd,"understand.<P>%c",LF);
|
||||
fprintf(fd,"Reason: %s<P>%c",err_string,LF);
|
||||
break;
|
||||
case FORBIDDEN:
|
||||
error_head(fd,"403 Forbidden");
|
||||
if(header_only) break;
|
||||
fprintf(fd,"Your client does not have permission to get URL %s ",
|
||||
err_string);
|
||||
fprintf(fd,"from this server.<P>%c",LF);
|
||||
break;
|
||||
case NOT_FOUND:
|
||||
error_head(fd,"404 Not Found");
|
||||
if(header_only) break;
|
||||
fprintf(fd,"The requested URL %s was not found on this server.<P>%c",
|
||||
err_string,LF);
|
||||
break;
|
||||
case SERVER_ERROR:
|
||||
error_head(fd,"500 Server Error");
|
||||
log_error(err_string);
|
||||
if(header_only)
|
||||
break;
|
||||
fprintf(fd,"The server encountered an internal error or%c",LF);
|
||||
fprintf(fd,"misconfiguration and was unable to complete your%c",LF);
|
||||
fprintf(fd,"request.<P>%c",LF);
|
||||
fprintf(fd,"Please contact the server administrator,%c",LF);
|
||||
fprintf(fd," %s ",server_admin);
|
||||
fprintf(fd,"and inform them of the time the error occured, and%c",LF);
|
||||
fprintf(fd,"anything you might have done that may have caused%c",LF);
|
||||
fprintf(fd,"the error.<P>%c",LF);
|
||||
break;
|
||||
case INCLUDE_ERROR:
|
||||
/* error_head(fd,"500 Server Error"); */
|
||||
log_error(err_string);
|
||||
if(header_only) break;
|
||||
fprintf(fd,"[we're sorry, the following error has occurred: %s]%c",
|
||||
err_string,LF);
|
||||
fflush(fd);
|
||||
htexit(1,fd);
|
||||
break;
|
||||
case NOT_IMPLEMENTED:
|
||||
error_head(fd,"501 Not Implemented");
|
||||
if(header_only) break;
|
||||
fprintf(fd,"We are sorry to be unable to perform the method %s",
|
||||
err_string);
|
||||
fprintf(fd," at this time.<P>%c",LF);
|
||||
fprintf(fd,"If you would like to see this capability in future%c",LF);
|
||||
fprintf(fd,"releases, send the method which failed, why you%c",LF);
|
||||
fprintf(fd,"would like to have it, and the server version %s%c",
|
||||
SERVER_VERSION,LF);
|
||||
fprintf(fd,"to <ADDRESS>%s</ADDRESS><P>%c",SERVER_SUPPORT,LF);
|
||||
break;
|
||||
}
|
||||
if(!header_only)
|
||||
fprintf(fd,"</BODY>%c",LF);
|
||||
fflush(fd);
|
||||
htexit(1,fd);
|
||||
}
|
315
src/http_mime.c
Normal file
315
src/http_mime.c
Normal file
@ -0,0 +1,315 @@
|
||||
/*
|
||||
* http_mime.c: Sends/gets MIME headers for requests
|
||||
*
|
||||
* Rob McCool
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "httpd.h"
|
||||
|
||||
struct mime_ext {
|
||||
char *ext;
|
||||
char *ct;
|
||||
struct mime_ext *next;
|
||||
};
|
||||
|
||||
#define hash(i) (isalpha(i) ? (tolower(i)) - 'a' : 26)
|
||||
|
||||
/* Hash table */
|
||||
struct mime_ext *types[27];
|
||||
struct mime_ext *forced_types;
|
||||
struct mime_ext *encoding_types;
|
||||
|
||||
int content_length;
|
||||
char content_type[MAX_STRING_LEN];
|
||||
|
||||
char location[MAX_STRING_LEN];
|
||||
static char last_modified[MAX_STRING_LEN];
|
||||
static char content_encoding[MAX_STRING_LEN];
|
||||
char http_accept[HUGE_STRING_LEN];
|
||||
|
||||
char auth_line[MAX_STRING_LEN];
|
||||
|
||||
void hash_insert(struct mime_ext *me) {
|
||||
register int i = hash(me->ext[0]);
|
||||
register struct mime_ext *p, *q;
|
||||
|
||||
if(!(q=types[i])) {
|
||||
types[i]=me;
|
||||
return;
|
||||
}
|
||||
if((!(p=q->next)) && (strcmp(q->ext,me->ext) >= 0)) {
|
||||
types[i]=me;
|
||||
me->next=q;
|
||||
return;
|
||||
}
|
||||
while(p) {
|
||||
if(strcmp(p->ext,me->ext) >= 0) break;
|
||||
q=p;
|
||||
p=p->next;
|
||||
}
|
||||
me->next=p;
|
||||
q->next=me;
|
||||
}
|
||||
|
||||
void kill_mime() {
|
||||
register struct mime_ext *p,*q;
|
||||
register int x;
|
||||
|
||||
for(x=0;x<27;x++) {
|
||||
p=types[x];
|
||||
while(p) {
|
||||
free(p->ext);
|
||||
free(p->ct);
|
||||
q=p;
|
||||
p=p->next;
|
||||
free(q);
|
||||
}
|
||||
}
|
||||
p=forced_types;
|
||||
while(p) {
|
||||
free(p->ext);
|
||||
free(p->ct);
|
||||
q=p;
|
||||
p=p->next;
|
||||
free(q);
|
||||
}
|
||||
p=encoding_types;
|
||||
while(p) {
|
||||
free(p->ext);
|
||||
free(p->ct);
|
||||
q=p;
|
||||
p=p->next;
|
||||
free(q);
|
||||
}
|
||||
}
|
||||
|
||||
void init_mime() {
|
||||
char l[MAX_STRING_LEN],w[MAX_STRING_LEN],*ct;
|
||||
FILE *f;
|
||||
register struct mime_ext *me;
|
||||
register int x,y;
|
||||
|
||||
if(!(f = fopen(types_confname,"r"))) {
|
||||
fprintf(stderr,"httpd: could not open mime types file %s\n",
|
||||
types_confname);
|
||||
perror("fopen");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for(x=0;x<27;x++)
|
||||
types[x] = NULL;
|
||||
forced_types = NULL;
|
||||
encoding_types = NULL;
|
||||
|
||||
while(!(cfg_getline(l,MAX_STRING_LEN,f))) {
|
||||
if(l[0] == '#') continue;
|
||||
cfg_getword(w,l);
|
||||
if(!(ct = (char *)malloc(sizeof(char) * (strlen(w) + 1))))
|
||||
die(NO_MEMORY,"init_mime",stderr);
|
||||
strcpy(ct,w);
|
||||
|
||||
while(l[0]) {
|
||||
cfg_getword(w,l);
|
||||
if(!(me = (struct mime_ext *)malloc(sizeof(struct mime_ext))))
|
||||
die(NO_MEMORY,"init_mime",stderr);
|
||||
if(!(me->ext = (char *)malloc(sizeof(char) * (strlen(w)+1))))
|
||||
die(NO_MEMORY,"init_mime",stderr);
|
||||
for(x=0;w[x];x++)
|
||||
me->ext[x] = (islower(w[x]) ? w[x] : tolower(w[x]));
|
||||
me->ext[x] = '\0';
|
||||
if(!(me->ct=strdup(ct)))
|
||||
die(NO_MEMORY,"init_mime",stderr);
|
||||
me->next=NULL;
|
||||
hash_insert(me);
|
||||
}
|
||||
free(ct);
|
||||
}
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
void dump_types() {
|
||||
struct mime_ext *p;
|
||||
register int x;
|
||||
|
||||
for(x=0;x<27;x++) {
|
||||
p=types[x];
|
||||
while(p) {
|
||||
printf("ext %s: %s\n",p->ext,p->ct);
|
||||
p=p->next;
|
||||
}
|
||||
}
|
||||
p=forced_types;
|
||||
while(p) {
|
||||
printf("file %s: %s\n",p->ext,p->ct);
|
||||
p=p->next;
|
||||
}
|
||||
}
|
||||
|
||||
int is_content_type(char *type) {
|
||||
return(!strcmp(content_type,type));
|
||||
}
|
||||
|
||||
void set_content_type(char *file) {
|
||||
int i,l,l2;
|
||||
struct mime_ext *p;
|
||||
char fn[MAX_STRING_LEN];
|
||||
|
||||
strcpy(fn,file);
|
||||
if((i=rind(fn,'.')) >= 0) {
|
||||
++i;
|
||||
l=strlen(fn);
|
||||
p = encoding_types;
|
||||
|
||||
while(p) {
|
||||
if(!strcmp(p->ext,&fn[i])) {
|
||||
fn[i-1] = '\0';
|
||||
if(content_encoding[0])
|
||||
sprintf(content_encoding,"%s, %s",content_encoding,p->ct);
|
||||
else
|
||||
strcpy(content_encoding,p->ct);
|
||||
if((i=rind(fn,'.')) < 0)
|
||||
break;
|
||||
++i;
|
||||
l=strlen(fn);
|
||||
p=encoding_types;
|
||||
}
|
||||
else
|
||||
p=p->next;
|
||||
}
|
||||
}
|
||||
p=forced_types;
|
||||
l=strlen(fn);
|
||||
|
||||
while(p) {
|
||||
l2=l-strlen(p->ext);
|
||||
if((l2 >= 0) && (!strcasecmp(p->ext,&fn[l2]))) {
|
||||
strcpy(content_type,p->ct);
|
||||
return;
|
||||
}
|
||||
p=p->next;
|
||||
}
|
||||
|
||||
if((i = rind(fn,'.')) < 0) {
|
||||
strcpy(content_type,default_type);
|
||||
return;
|
||||
}
|
||||
++i;
|
||||
p=types[hash(fn[i])];
|
||||
|
||||
while(p) {
|
||||
if(!strcasecmp(p->ext,&fn[i])) {
|
||||
strcpy(content_type,p->ct);
|
||||
return;
|
||||
}
|
||||
p=p->next;
|
||||
}
|
||||
strcpy(content_type,default_type);
|
||||
}
|
||||
|
||||
int scan_script_header(FILE *f, FILE *fd) {
|
||||
char l[MAX_STRING_LEN];
|
||||
char w[MAX_STRING_LEN];
|
||||
|
||||
while(1) {
|
||||
if(getline(l,MAX_STRING_LEN,fileno(f),timeout))
|
||||
die(SERVER_ERROR,"httpd: malformed header from script",fd);
|
||||
|
||||
if(l[0] == '\0') return is_url(location);
|
||||
getword(w,l,':');
|
||||
if(!strcasecmp(w,"Content-type"))
|
||||
sscanf(l,"%s",content_type);
|
||||
else if(!strcasecmp(w,"Location"))
|
||||
sscanf(l,"%s",location);
|
||||
}
|
||||
}
|
||||
|
||||
void add_type(char *fn, char *t, FILE *out) {
|
||||
struct mime_ext *n;
|
||||
|
||||
if(!(n=(struct mime_ext *)malloc(sizeof(struct mime_ext))))
|
||||
die(NO_MEMORY,"add_type",out);
|
||||
|
||||
if(!(n->ext = strdup(fn)))
|
||||
die(NO_MEMORY,"add_type",out);
|
||||
if(!(n->ct = strdup(t)))
|
||||
die(NO_MEMORY,"add_type",out);
|
||||
n->next = forced_types;
|
||||
forced_types = n;
|
||||
}
|
||||
|
||||
void add_encoding(char *fn, char *t,FILE *out) {
|
||||
struct mime_ext *n;
|
||||
|
||||
if(!(n=(struct mime_ext *)malloc(sizeof(struct mime_ext))))
|
||||
die(NO_MEMORY,"add_encoding",out);
|
||||
|
||||
if(!(n->ext = strdup(fn)))
|
||||
die(NO_MEMORY,"add_encoding",out);
|
||||
if(!(n->ct = strdup(t)))
|
||||
die(NO_MEMORY,"add_encoding",out);
|
||||
n->next = encoding_types;
|
||||
encoding_types = n;
|
||||
}
|
||||
|
||||
void set_content_length(int l) {
|
||||
content_length = l;
|
||||
}
|
||||
|
||||
void set_last_modified(time_t t) {
|
||||
strcpy(last_modified,gm_timestr_822(t));
|
||||
}
|
||||
|
||||
void get_mime_headers(int fd) {
|
||||
char l[MAX_STRING_LEN];
|
||||
char w[MAX_STRING_LEN];
|
||||
|
||||
content_type[0] = '\0';
|
||||
last_modified[0] = '\0';
|
||||
content_length = -1;
|
||||
auth_line[0] = '\0';
|
||||
content_encoding[0] = '\0';
|
||||
http_accept[0] = '\0';
|
||||
location[0] = '\0';
|
||||
|
||||
while(!(getline(l,MAX_STRING_LEN,fd,timeout))) {
|
||||
getword(w,l,':');
|
||||
if(!strcasecmp(w,"Content-type"))
|
||||
sscanf(l,"%s",content_type);
|
||||
else if(!strcasecmp(w,"Authorization"))
|
||||
strcpy(auth_line,l);
|
||||
else if(!strcasecmp(w,"Content-length"))
|
||||
sscanf(l,"%d",&content_length);
|
||||
else if(!strcasecmp(w,"Accept")) {
|
||||
if(http_accept[0])
|
||||
sprintf(http_accept,"%s, %s%c",http_accept,l,'\0');
|
||||
else
|
||||
strcpy(http_accept,l);
|
||||
}
|
||||
else if(!l[0])
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void dump_default_header(FILE *fd) {
|
||||
fprintf(fd,"Date: %s%c",gm_timestr_822(time(NULL)),LF);
|
||||
fprintf(fd,"Server: %s%c",SERVER_VERSION,LF);
|
||||
fprintf(fd,"MIME-version: 1.0%c",LF);
|
||||
}
|
||||
|
||||
void send_http_header(FILE *fd) {
|
||||
begin_http_header(fd,(location[0] ? "302 Found" : "200 OK"));
|
||||
if(content_type[0])
|
||||
fprintf(fd,"Content-type: %s%c",content_type,LF);
|
||||
if(last_modified[0])
|
||||
fprintf(fd,"Last-modified: %s%c",last_modified,LF);
|
||||
if(content_length >= 0)
|
||||
fprintf(fd,"Content-length: %d%c",content_length,LF);
|
||||
if(location[0])
|
||||
fprintf(fd,"Location: %s%c",location,LF);
|
||||
if(content_encoding[0])
|
||||
fprintf(fd,"Content-encoding: %s%c",content_encoding,LF,LF);
|
||||
|
||||
fprintf(fd,"%c",LF);
|
||||
}
|
29
src/http_put.c
Normal file
29
src/http_put.c
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* http_put.c: Handles PUT and POST
|
||||
*
|
||||
* Rob McCool
|
||||
*
|
||||
*/
|
||||
|
||||
#include "httpd.h"
|
||||
|
||||
|
||||
void get_node(char *name, char *args, int in, FILE *out) {
|
||||
struct stat finfo;
|
||||
int s;
|
||||
|
||||
s=translate_name(name,out);
|
||||
|
||||
switch(s) {
|
||||
case STD_DOCUMENT:
|
||||
die(NOT_IMPLEMENTED,
|
||||
"POST access to area not configured as script area",out);
|
||||
case REDIRECT_URL:
|
||||
die(REDIRECT,name,out);
|
||||
case SCRIPT_NCSA:
|
||||
exec_post_NCSA(name,args,in,out);
|
||||
return;
|
||||
case SCRIPT_CGI:
|
||||
exec_cgi_script("POST",name,args,in,out);
|
||||
}
|
||||
}
|
297
src/http_request.c
Normal file
297
src/http_request.c
Normal file
@ -0,0 +1,297 @@
|
||||
/*
|
||||
* http_request.c: functions to get and process requests
|
||||
*
|
||||
* Rob McCool 3/21/93
|
||||
*
|
||||
* Include code by Charles Henrich
|
||||
*/
|
||||
|
||||
|
||||
#include "httpd.h"
|
||||
|
||||
#define OUTBUFSIZE 1024
|
||||
|
||||
int assbackwards;
|
||||
char *remote_host;
|
||||
char *remote_ip;
|
||||
char *remote_name;
|
||||
|
||||
/* If RFC931 identity check is on, the remote user name */
|
||||
char *remote_logname;
|
||||
|
||||
/*
|
||||
* Thanks to Charles Henrich
|
||||
*/
|
||||
void process_include(FILE *f, FILE *fd, char *incstring, char *args)
|
||||
{
|
||||
FILE *ifp;
|
||||
char srcfile[HUGE_STRING_LEN];
|
||||
char command[HUGE_STRING_LEN];
|
||||
char errstr[MAX_STRING_LEN];
|
||||
char cmd[10];
|
||||
|
||||
if(sscanf(incstring,"%s \"%[^\"]", cmd, srcfile) != 2) {
|
||||
sprintf(errstr,"the include string %s was invalid",incstring);
|
||||
die(INCLUDE_ERROR,errstr,fd);
|
||||
}
|
||||
|
||||
if(strncasecmp(cmd,"srv",3) != 0) {
|
||||
fprintf(fd, "%s\r\n",cmd);
|
||||
return;
|
||||
}
|
||||
|
||||
if(srcfile[0] != '|') {
|
||||
if(num_includes > MAXINCLUDES) {
|
||||
die(INCLUDE_ERROR,
|
||||
"the maximum number of includes has been exceeded",fd);
|
||||
}
|
||||
|
||||
num_includes++;
|
||||
|
||||
if(translate_name(srcfile,fd) != 0)
|
||||
die(INCLUDE_ERROR,"non-standard file include",fd);
|
||||
ifp=fopen(srcfile,"r");
|
||||
|
||||
if(ifp != NULL) {
|
||||
send_fd(ifp, fd, "");
|
||||
fclose(ifp);
|
||||
}
|
||||
else {
|
||||
sprintf(errstr,"the include file %s was invalid",srcfile);
|
||||
die(INCLUDE_ERROR,errstr,fd);
|
||||
}
|
||||
}
|
||||
else {
|
||||
#ifndef PEM_AUTH
|
||||
escape_shell_cmd(&srcfile[1]);
|
||||
if(strncasecmp(cmd,"srvurl",6) == 0) {
|
||||
escape_shell_cmd(args);
|
||||
sprintf(command,"%s '%s'",&srcfile[1],args);
|
||||
}
|
||||
else {
|
||||
strcpy(command,&srcfile[1]);
|
||||
}
|
||||
|
||||
ifp=popen(command,"r");
|
||||
|
||||
if(ifp != NULL) {
|
||||
send_fd(ifp, fd, args);
|
||||
pclose(ifp);
|
||||
}
|
||||
else {
|
||||
sprintf(errstr,"the command %s is invalid",&srcfile[1]);
|
||||
die(INCLUDE_ERROR,errstr,fd);
|
||||
}
|
||||
#else
|
||||
int pid,p[2];
|
||||
|
||||
/* This is done because popen() seems to wait for the wrong */
|
||||
/* child process when encryption is being used. Suggestions */
|
||||
/* are welcome. */
|
||||
|
||||
if(pipe(p) == -1)
|
||||
die(SERVER_ERROR,"Could not create an IPC pipe",fd);
|
||||
if((pid = fork()) == -1)
|
||||
die(SERVER_ERROR,"Could not fork a new process",fd);
|
||||
if(!pid) {
|
||||
char *argv0;
|
||||
char *cmd;
|
||||
|
||||
cmd = &srcfile[1];
|
||||
if(!(argv0 = strrchr(cmd,'/')))
|
||||
argv0 = cmd;
|
||||
else
|
||||
argv0++;
|
||||
close(p[0]);
|
||||
if(p[1] != STDOUT_FILENO) {
|
||||
dup2(p[1],STDOUT_FILENO);
|
||||
close(p[1]);
|
||||
}
|
||||
if(strncasecmp(cmd,"srvurl",6) == 0) {
|
||||
escape_shell_cmd(args);
|
||||
if(execlp(cmd,argv0,args,(char *)0) == -1) {
|
||||
char errstr[MAX_STRING_LEN];
|
||||
sprintf(errstr,"could not execute included pgm %s",cmd);
|
||||
die(INCLUDE_ERROR,errstr,fd);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(execlp(cmd,argv0,(char *)0) == -1) {
|
||||
char errstr[MAX_STRING_LEN];
|
||||
sprintf(errstr,"could not execute included pgm %s",cmd);
|
||||
die(INCLUDE_ERROR,errstr,fd);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
close(p[1]);
|
||||
if(!(ifp = fdopen(p[0],"r")))
|
||||
die(INCLUDE_ERROR,"could not open stream to include pipe",fd);
|
||||
send_fd(ifp,fd,args);
|
||||
fclose(ifp);
|
||||
waitpid(pid,NULL,0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void send_fd_timed_out() {
|
||||
char errstr[MAX_STRING_LEN];
|
||||
|
||||
sprintf(errstr,"httpd: send timed out for %s",remote_host);
|
||||
log_error(errstr);
|
||||
fclose(stdin);
|
||||
fclose(stdout);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void send_fd(FILE *f, FILE *fd, char *args)
|
||||
{
|
||||
int num_chars=0;
|
||||
char c;
|
||||
struct stat finfo;
|
||||
|
||||
signal(SIGALRM,send_fd_timed_out);
|
||||
signal(SIGPIPE,send_fd_timed_out);
|
||||
|
||||
if((allow_options & OPT_INCLUDES) && is_content_type("text/html")) {
|
||||
char *find="<inc";
|
||||
char incstring[MAX_STRING_LEN];
|
||||
int x,p;
|
||||
|
||||
p=0;
|
||||
while(1) {
|
||||
alarm(timeout);
|
||||
c = fgetc(f);
|
||||
if(feof(f))
|
||||
return;
|
||||
if(tolower(c) == find[p]) {
|
||||
if((++p) == 4) {
|
||||
x=0;
|
||||
c=fgetc(f); /* get the space instead of the c */
|
||||
while(c != '>') {
|
||||
incstring[x++] = c;
|
||||
c = fgetc(f);
|
||||
if(feof(f)) {
|
||||
incstring[x] = '\0';
|
||||
fputs("<inc",fd);
|
||||
fputs(incstring,fd);
|
||||
return;
|
||||
}
|
||||
}
|
||||
incstring[x] = '\0';
|
||||
process_include(f,fd,incstring,args);
|
||||
p=0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(p) {
|
||||
for(x=0;x<p;x++)
|
||||
fputc(find[x],fd);
|
||||
p=0;
|
||||
}
|
||||
fputc(c,fd);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
char buf[OUTBUFSIZE];
|
||||
register int n,o,w;
|
||||
|
||||
while (1) {
|
||||
alarm(timeout);
|
||||
if((n=fread(buf,sizeof(char),OUTBUFSIZE,f)) < 1) {
|
||||
break;
|
||||
}
|
||||
o=0;
|
||||
while(n) {
|
||||
w=fwrite(&buf[o],sizeof(char),n,fd);
|
||||
n-=w;
|
||||
o+=w;
|
||||
}
|
||||
}
|
||||
}
|
||||
fflush(fd);
|
||||
}
|
||||
|
||||
void process_request(int in, FILE *out) {
|
||||
char m[HUGE_STRING_LEN];
|
||||
char w[HUGE_STRING_LEN];
|
||||
char l[HUGE_STRING_LEN];
|
||||
char url[HUGE_STRING_LEN];
|
||||
char args[HUGE_STRING_LEN];
|
||||
#ifdef HENRICHS_SILLY_HACK
|
||||
char tmpargs[HUGE_STRING_LEN];
|
||||
#endif
|
||||
int s,n;
|
||||
|
||||
get_remote_host(in);
|
||||
#ifdef PEM_AUTH
|
||||
doing_pem = -1;
|
||||
handle_request:
|
||||
#endif
|
||||
l[0] = '\0';
|
||||
if(getline(l,HUGE_STRING_LEN,in,timeout))
|
||||
return;
|
||||
if(!l[0])
|
||||
return;
|
||||
|
||||
#ifdef PEM_AUTH
|
||||
if(doing_pem == -1)
|
||||
#endif
|
||||
log_transaction(l);
|
||||
getword(m,l,' ');
|
||||
getword(args,l,' ');
|
||||
#ifdef HENRICHS_SILLY_HACK
|
||||
strcpy(tmpargs,args);
|
||||
getword(url,tmpargs,';');
|
||||
if(!tempargs[0])
|
||||
getword(url,args,'?');
|
||||
else
|
||||
strcpy(args,tmpargs);
|
||||
#else
|
||||
getword(url,args,'?');
|
||||
#endif
|
||||
plustospace(url);
|
||||
unescape_url(url);
|
||||
getword(w,l,'\0');
|
||||
if(w[0] != '\0') {
|
||||
assbackwards = 0;
|
||||
get_mime_headers(in);
|
||||
}
|
||||
else
|
||||
assbackwards = 1;
|
||||
|
||||
if(!strcmp(m,"HEAD")) {
|
||||
header_only=1;
|
||||
process_get(in,out,m,url,args);
|
||||
}
|
||||
else if(!strcmp(m,"GET")) {
|
||||
#ifdef PEM_AUTH
|
||||
if(!assbackwards) {
|
||||
if(doing_pem == -1) {
|
||||
int s2;
|
||||
s2 = pem_decrypt(in,url,&out);
|
||||
if(s2 != -1) {
|
||||
in = s2;
|
||||
content_type[0] = '\0';
|
||||
goto handle_request;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
header_only=0;
|
||||
process_get(in,out,m,url,args);
|
||||
}
|
||||
else if(!strcmp(m,"POST")) {
|
||||
header_only = 0;
|
||||
get_node(url,args,in,out);
|
||||
}
|
||||
else
|
||||
die(BAD_REQUEST,"Invalid or unsupported method.",out);
|
||||
|
||||
#ifdef PEM_AUTH
|
||||
if(doing_pem != -1) {
|
||||
close(in);
|
||||
htexit(0,out);
|
||||
}
|
||||
#endif
|
||||
}
|
418
src/http_script.c
Normal file
418
src/http_script.c
Normal file
@ -0,0 +1,418 @@
|
||||
/*
|
||||
* http_script: keeps all script-related ramblings together.
|
||||
*
|
||||
* Compliant to CGI/1.0 spec
|
||||
*
|
||||
* Rob McCool
|
||||
*
|
||||
*/
|
||||
|
||||
#include "httpd.h"
|
||||
|
||||
char **create_argv(char *av0, char *args, FILE *out) {
|
||||
register int x,n;
|
||||
char **av;
|
||||
char w[MAX_STRING_LEN];
|
||||
char l[MAX_STRING_LEN];
|
||||
|
||||
for(x=0,n=2;args[x];x++)
|
||||
if(args[x] == '+') ++n;
|
||||
|
||||
if(!(av = (char **)malloc((n+1)*sizeof(char *))))
|
||||
die(NO_MEMORY,"create_argv",out);
|
||||
av[0] = av0;
|
||||
strcpy(l,args);
|
||||
for(x=1;x<n;x++) {
|
||||
getword(w,l,'+');
|
||||
unescape_url(w);
|
||||
escape_shell_cmd(w);
|
||||
if(!(av[x] = strdup(w)))
|
||||
die(NO_MEMORY,"create_argv",out);
|
||||
}
|
||||
av[n] = NULL;
|
||||
return av;
|
||||
}
|
||||
|
||||
void get_path_info(char *path, char *path_args, FILE *out,
|
||||
struct stat *finfo)
|
||||
{
|
||||
register int x,max;
|
||||
char t[MAX_STRING_LEN];
|
||||
|
||||
path_args[0] = '\0';
|
||||
max=count_dirs(path);
|
||||
for(x=dirs_in_alias;x<=max;x++) {
|
||||
make_dirstr(path,x+1,t);
|
||||
if(!(stat(t,finfo))) {
|
||||
if(S_ISREG(finfo->st_mode)) {
|
||||
strcpy(path_args,&path[strlen(t)]);
|
||||
strcpy(path,t);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
for(x=dirs_in_alias - 1;x;--x) {
|
||||
make_dirstr(path,x+1,t);
|
||||
if(!(stat(t,finfo))) {
|
||||
if(S_ISREG(finfo->st_mode)) {
|
||||
strcpy(path_args,&path[strlen(t)]);
|
||||
strcpy(path,t);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
unmunge_name(path);
|
||||
die(NOT_FOUND,path,out);
|
||||
}
|
||||
|
||||
#define MAX_CGI_VARS 18
|
||||
|
||||
void exec_cgi_script(char *method, char *path, char *args, int in, FILE *out)
|
||||
{
|
||||
int pid, p[2];
|
||||
int content, nph;
|
||||
char cl[MAX_STRING_LEN],t[MAX_STRING_LEN],t2[MAX_STRING_LEN];
|
||||
char path_args[MAX_STRING_LEN];
|
||||
char *argv0,**env;
|
||||
FILE *psin;
|
||||
struct stat finfo;
|
||||
register int n,x;
|
||||
|
||||
get_path_info(path,path_args,out,&finfo);
|
||||
|
||||
if(!can_exec(&finfo)) {
|
||||
unmunge_name(path);
|
||||
die(FORBIDDEN,path,out);
|
||||
}
|
||||
|
||||
/* BAD -- method specific */
|
||||
evaluate_access(path,&finfo,((!strcmp(method,"POST")) ? M_POST : M_GET),
|
||||
&allow,&allow_options,out);
|
||||
if(!allow) {
|
||||
log_reason("client denied by server configuration",path);
|
||||
unmunge_name(path);
|
||||
die(FORBIDDEN,path,out);
|
||||
}
|
||||
|
||||
if(!(env = (char **)malloc((MAX_CGI_VARS + 2) * sizeof(char *))))
|
||||
die(NO_MEMORY,"exec_cgi_script",out);
|
||||
n = 0;
|
||||
env[n++] = make_env_str("PATH",getenv("PATH"),out);
|
||||
env[n++] = make_env_str("SERVER_SOFTWARE",SERVER_VERSION,out);
|
||||
env[n++] = make_env_str("SERVER_NAME",server_hostname,out);
|
||||
env[n++] = make_env_str("GATEWAY_INTERFACE","CGI/1.0",out);
|
||||
|
||||
sprintf(t,"%d",port);
|
||||
env[n++] = make_env_str("SERVER_PORT",t,out);
|
||||
|
||||
env[n++] = make_env_str("SERVER_PROTOCOL",
|
||||
(assbackwards ? "HTTP/0.9" : "HTTP/1.0"),out);
|
||||
env[n++] = make_env_str("REQUEST_METHOD",method,out);
|
||||
env[n++] = make_env_str("HTTP_ACCEPT",http_accept,out);
|
||||
if(path_args[0]) {
|
||||
env[n++] = make_env_str("PATH_INFO",path_args,out);
|
||||
strcpy(t2,path_args);
|
||||
translate_name(t2,out);
|
||||
env[n++] = make_env_str("PATH_TRANSLATED",t2,out);
|
||||
}
|
||||
strcpy(t,path);
|
||||
unmunge_name(t);
|
||||
env[n++] = make_env_str("SCRIPT_NAME",t,out);
|
||||
env[n++] = make_env_str("QUERY_STRING",args,out);
|
||||
env[n++] = make_env_str("REMOTE_HOST",remote_name,out);
|
||||
env[n++] = make_env_str("REMOTE_ADDR",remote_ip,out);
|
||||
if(user[0])
|
||||
env[n++] = make_env_str("REMOTE_USER",user,out);
|
||||
if(auth_type)
|
||||
env[n++] = make_env_str("AUTH_TYPE",auth_type,out);
|
||||
|
||||
if(do_rfc931)
|
||||
env[n++] = make_env_str("REMOTE_IDENT",remote_logname,out);
|
||||
content=0;
|
||||
if((!strcmp(method,"POST")) || (!strcmp(method,"PUT"))) {
|
||||
content=1;
|
||||
sprintf(cl,"%d",content_length);
|
||||
env[n++] = make_env_str("CONTENT_TYPE",content_type,out);
|
||||
env[n++] = make_env_str("CONTENT_LENGTH",cl,out);
|
||||
}
|
||||
env[n] = NULL;
|
||||
|
||||
if((argv0 = strrchr(path,'/')) != NULL)
|
||||
argv0++;
|
||||
else argv0 = path;
|
||||
|
||||
if(pipe(p) < 0)
|
||||
die(SERVER_ERROR,"httpd: could not create IPC pipe",out);
|
||||
if((pid = fork()) < 0)
|
||||
die(SERVER_ERROR,"httpd: could not fork new process",out);
|
||||
|
||||
nph = (strncmp(argv0,"nph-",4) ? 0 : 1);
|
||||
if(!pid) {
|
||||
if(content)
|
||||
if(in != STDIN_FILENO) {
|
||||
dup2(in,STDIN_FILENO);
|
||||
close(in);
|
||||
}
|
||||
if(nph) {
|
||||
if(fileno(out) != STDOUT_FILENO) {
|
||||
dup2(fileno(out),STDOUT_FILENO);
|
||||
fclose(out);
|
||||
}
|
||||
} else {
|
||||
if(p[1] != STDOUT_FILENO) {
|
||||
dup2(p[1],STDOUT_FILENO);
|
||||
close(p[1]);
|
||||
}
|
||||
}
|
||||
/* Only ISINDEX scripts get decoded arguments. */
|
||||
if((!args[0]) || (ind(args,'=') >= 0)) {
|
||||
if(execle(path,argv0,(char *)0,env) == -1) {
|
||||
fprintf(stderr,"httpd: exec of %s failed, errno is %d\n",
|
||||
path,errno);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(execve(path,create_argv(argv0,args,out),env) == -1) {
|
||||
fprintf(stderr,"httpd: exec of %s failed, errno is %d\n",
|
||||
path,errno);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for(x=0;x<n;x++)
|
||||
free(env[n]);
|
||||
free(env);
|
||||
close(p[1]);
|
||||
}
|
||||
|
||||
if(!nph) {
|
||||
if(!(psin = fdopen(p[0],"r")))
|
||||
die(SERVER_ERROR,"could not read from script",out);
|
||||
|
||||
if(scan_script_header(psin,out))
|
||||
die(REDIRECT,location,out);
|
||||
|
||||
if(location[0] == '/') {
|
||||
char t[MAX_STRING_LEN],a[MAX_STRING_LEN],*argp;
|
||||
|
||||
a[0] = '\0';
|
||||
fclose(psin);
|
||||
waitpid(pid,NULL,0);
|
||||
strcpy(t,location);
|
||||
location[0] = '\0';
|
||||
if(argp = strchr(t,'?')) {
|
||||
*argp++ = '\0';
|
||||
strcpy(a,argp);
|
||||
}
|
||||
process_get(in,out,method,t,a);
|
||||
return;
|
||||
}
|
||||
content_length = -1;
|
||||
if(!assbackwards)
|
||||
send_http_header(out);
|
||||
if(!header_only)
|
||||
send_fd(psin,out,args);
|
||||
/* This will cause SIGPIPE in child... it should terminate */
|
||||
fclose(psin);
|
||||
}
|
||||
waitpid(pid,NULL,0);
|
||||
}
|
||||
|
||||
char **set_env_NCSA(FILE *out) {
|
||||
char **env;
|
||||
int n;
|
||||
char t[MAX_STRING_LEN];
|
||||
|
||||
if(!(env = (char **) malloc ((4+2)*sizeof(char *))))
|
||||
die(NO_MEMORY,"set_env_NCSA",out);
|
||||
n=0;
|
||||
env[n++] = make_env_str("PATH",getenv("PATH"),out);
|
||||
|
||||
env[n++] = make_env_str("DOCUMENT_ROOT",document_root,out);
|
||||
env[n++] = make_env_str("SERVER_ROOT",server_root,out);
|
||||
env[n++] = make_env_str("REMOTE_HOST",remote_name,out);
|
||||
sprintf(t,"SERVER_NAME=%s:%d",server_hostname,port);
|
||||
if(!(env[n++] = strdup(t)))
|
||||
die(NO_MEMORY,"set_env_NCSA",out);
|
||||
env[n] = NULL;
|
||||
return env;
|
||||
}
|
||||
|
||||
void exec_get_NCSA(char *path, char *args, FILE *fd) {
|
||||
FILE *tfp;
|
||||
struct stat finfo;
|
||||
int pid,pfd[2];
|
||||
char path_args[MAX_STRING_LEN];
|
||||
char t[MAX_STRING_LEN];
|
||||
register int n,x;
|
||||
char **env;
|
||||
|
||||
env = set_env_NCSA(fd);
|
||||
|
||||
path_args[0] = '\0';
|
||||
/* check if it's really a script with extra args */
|
||||
n=count_dirs(path);
|
||||
for(x=0;x<=n;x++) {
|
||||
make_dirstr(path,x+1,t);
|
||||
if(!(stat(t,&finfo))) {
|
||||
if(S_ISREG(finfo.st_mode)) {
|
||||
strcpy(path_args,&path[strlen(t)]);
|
||||
strcpy(path,t);
|
||||
goto run_script;
|
||||
}
|
||||
}
|
||||
}
|
||||
log_reason("script not found or unable to stat",path);
|
||||
unmunge_name(path);
|
||||
die(NOT_FOUND,path,fd);
|
||||
run_script:
|
||||
if(!can_exec(&finfo)) {
|
||||
log_reason("file permissions deny server execution",path);
|
||||
unmunge_name(path);
|
||||
die(FORBIDDEN,path,fd);
|
||||
}
|
||||
evaluate_access(path,&finfo,M_GET,&allow,&allow_options,fd);
|
||||
if(!allow) {
|
||||
unmunge_name(path);
|
||||
die(FORBIDDEN,path,fd);
|
||||
}
|
||||
|
||||
if(pipe(pfd) < 0)
|
||||
die(SERVER_ERROR,"could not open pipe",fd);
|
||||
|
||||
signal(SIGALRM,send_fd_timed_out);
|
||||
signal(SIGPIPE,send_fd_timed_out);
|
||||
alarm(timeout);
|
||||
|
||||
if((pid = fork()) < 0)
|
||||
die(SERVER_ERROR,"could not fork",fd);
|
||||
else if(!pid) {
|
||||
char *argv0;
|
||||
|
||||
close(pfd[0]);
|
||||
if(pfd[1] != STDOUT_FILENO) {
|
||||
dup2(pfd[1],STDOUT_FILENO);
|
||||
close(pfd[1]);
|
||||
}
|
||||
if(argv0 = strrchr(path,'/'))
|
||||
argv0++;
|
||||
else
|
||||
argv0 = path;
|
||||
if(args[0] && path_args[0]) {
|
||||
if(execle(path,argv0,path_args,args,(char *)0,env) == -1)
|
||||
exit(1);
|
||||
}
|
||||
else if(args[0]) {
|
||||
if(execle(path,argv0,args,(char *)0,env) == -1)
|
||||
exit(1);
|
||||
}
|
||||
else if(path_args[0]) {
|
||||
if(execle(path,argv0,path_args,(char *)0,env) == -1)
|
||||
exit(1);
|
||||
}
|
||||
else
|
||||
if(execle(path,argv0,(char *)0,env) == -1)
|
||||
exit(1);
|
||||
}
|
||||
else
|
||||
close(pfd[1]);
|
||||
|
||||
tfp = fdopen(pfd[0],"r");
|
||||
|
||||
if(scan_script_header(tfp,fd))
|
||||
die(REDIRECT,location,fd);
|
||||
|
||||
if(location[0] == '/') {
|
||||
char *t;
|
||||
if(!(t = strdup(location)))
|
||||
die(NO_MEMORY,"exec_get_NCSA",fd);
|
||||
location[0] = '\0';
|
||||
send_node(t,"",fd);
|
||||
htexit(0,fd);
|
||||
}
|
||||
|
||||
if(!assbackwards)
|
||||
send_http_header(fd);
|
||||
|
||||
if(!header_only)
|
||||
send_fd(tfp,fd,args);
|
||||
fclose(tfp);
|
||||
waitpid(pid,NULL,0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void exec_post_NCSA(char *path, char *args, int in, FILE *out) {
|
||||
int pid, inpipe[2],outpipe[2], x;
|
||||
char cl[MAX_STRING_LEN];
|
||||
FILE *psin,*psout;
|
||||
struct stat finfo;
|
||||
char **env;
|
||||
|
||||
env = set_env_NCSA(out);
|
||||
|
||||
sprintf(cl,"%d",content_length);
|
||||
|
||||
if(stat(path,&finfo) == -1) {
|
||||
unmunge_name(path);
|
||||
if(errno == ENOENT) die(NOT_FOUND,path,out);
|
||||
die(FORBIDDEN,path,out);
|
||||
}
|
||||
evaluate_access(path,&finfo,M_POST,&allow,&allow_options,out);
|
||||
if(!allow)
|
||||
die(FORBIDDEN,path,out);
|
||||
|
||||
if(pipe(inpipe) < 0)
|
||||
die(SERVER_ERROR,"httpd: could not create IPC pipe",out);
|
||||
if(pipe(outpipe) < 0)
|
||||
die(SERVER_ERROR,"httpd: could not create IPC pipe",out);
|
||||
if((pid = fork()) < 0)
|
||||
die(SERVER_ERROR,"httpd: could not fork new process",out);
|
||||
|
||||
if(!pid) {
|
||||
char *argv0;
|
||||
|
||||
if(outpipe[1] != STDOUT_FILENO) {
|
||||
dup2(outpipe[1],STDOUT_FILENO);
|
||||
close(outpipe[1]);
|
||||
}
|
||||
if(in != STDIN_FILENO) {
|
||||
dup2(in,STDIN_FILENO);
|
||||
close(in);
|
||||
}
|
||||
if((argv0 = strrchr(path,'/')) != NULL)
|
||||
argv0++;
|
||||
else argv0 = path;
|
||||
if(execle(path,argv0,cl,args,(char *)0,env) == -1)
|
||||
exit(1);
|
||||
}
|
||||
else {
|
||||
close(outpipe[1]);
|
||||
close(inpipe[0]);
|
||||
}
|
||||
|
||||
if(!(psin = fdopen(outpipe[0],"r")))
|
||||
die(SERVER_ERROR,"could not read from script",out);
|
||||
|
||||
if(scan_script_header(psin,out))
|
||||
die(REDIRECT,location,out);
|
||||
|
||||
if(location[0] == '/') {
|
||||
char *t;
|
||||
if(!(t = strdup(location)))
|
||||
die(NO_MEMORY,"exec_post_NCSA",out);
|
||||
location[0] = '\0';
|
||||
send_node(t,"",out);
|
||||
htexit(0,out);
|
||||
}
|
||||
|
||||
content_length = -1;
|
||||
if(!assbackwards)
|
||||
send_http_header(out);
|
||||
|
||||
send_fd(psin,out,args);
|
||||
fclose(psin);
|
||||
waitpid(pid,NULL,0);
|
||||
}
|
265
src/httpd.c
Normal file
265
src/httpd.c
Normal file
@ -0,0 +1,265 @@
|
||||
/*
|
||||
* httpd.c: simple http daemon for answering WWW file requests
|
||||
*
|
||||
*
|
||||
* Rob McCool 3/21/93
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "httpd.h"
|
||||
|
||||
void usage(char *bin) {
|
||||
fprintf(stderr,"Usage: %s [-d directory] [-f file] [-v]\n",bin);
|
||||
fprintf(stderr,"-d directory : specify an alternate initial ServerRoot\n");
|
||||
fprintf(stderr,"-f file : specify an alternate ServerConfigFile\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void htexit(int status, FILE *out) {
|
||||
#ifdef PEM_AUTH
|
||||
pem_cleanup(status,out);
|
||||
#endif
|
||||
exit(status);
|
||||
}
|
||||
|
||||
int sd;
|
||||
pid_t pgrp;
|
||||
|
||||
void detach() {
|
||||
int x;
|
||||
|
||||
chdir("/");
|
||||
if((x = fork()) > 0)
|
||||
exit(0);
|
||||
else if(x == -1) {
|
||||
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");
|
||||
perror("setsid");
|
||||
exit(1);
|
||||
}
|
||||
#else
|
||||
if((pgrp=setpgrp(getpid(),0)) == -1) {
|
||||
fprintf(stderr,"httpd: setpgrp failed\n");
|
||||
perror("setpgrp");
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void sig_term() {
|
||||
log_error("httpd: caught SIGTERM, shutting down");
|
||||
#ifndef NO_KILLPG
|
||||
killpg(pgrp,SIGKILL);
|
||||
#else
|
||||
kill(-pgrp,SIGKILL);
|
||||
#endif
|
||||
shutdown(sd,2);
|
||||
close(sd);
|
||||
}
|
||||
|
||||
#ifdef BSD
|
||||
void ign() {
|
||||
#ifndef NEXT
|
||||
int status;
|
||||
#else
|
||||
union wait status;
|
||||
#endif
|
||||
pid_t pid;
|
||||
|
||||
while( (pid = wait3(&status, WNOHANG, NULL)) > 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
void bus_error() {
|
||||
log_error("httpd: caught SIGBUS, dumping core");
|
||||
chdir(server_root);
|
||||
abort();
|
||||
}
|
||||
|
||||
void seg_fault() {
|
||||
log_error("httpd: caught SIGSEGV, dumping core");
|
||||
chdir(server_root);
|
||||
abort();
|
||||
}
|
||||
|
||||
void set_signals();
|
||||
|
||||
void restart() {
|
||||
log_error("httpd: caught SIGHUP, restarting");
|
||||
kill_mime();
|
||||
kill_security();
|
||||
kill_indexing();
|
||||
if(server_hostname) {
|
||||
free(server_hostname);
|
||||
server_hostname = NULL;
|
||||
}
|
||||
read_config();
|
||||
close_logs();
|
||||
open_logs();
|
||||
log_error("httpd: successful restart");
|
||||
get_local_host();
|
||||
set_signals();
|
||||
}
|
||||
|
||||
void set_signals() {
|
||||
signal(SIGSEGV,(void (*)())seg_fault);
|
||||
signal(SIGBUS,(void (*)())bus_error);
|
||||
signal(SIGTERM,(void (*)())sig_term);
|
||||
signal(SIGHUP,(void (*)())restart);
|
||||
|
||||
#ifdef BSD
|
||||
signal(SIGCHLD,(void (*)())ign);
|
||||
#else
|
||||
signal(SIGCHLD,SIG_IGN);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void standalone_main() {
|
||||
int csd, clen,pid, one=1;
|
||||
#ifdef NEXT
|
||||
struct sockaddr_in sa_server;
|
||||
struct sockaddr sa_client;
|
||||
#else
|
||||
struct sockaddr_in sa_server,sa_client;
|
||||
#endif
|
||||
|
||||
detach();
|
||||
|
||||
if ((sd = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP)) == -1) {
|
||||
fprintf(stderr,"httpd: could not get socket\n");
|
||||
perror("socket");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if((setsockopt(sd,SOL_SOCKET,SO_REUSEADDR,&one,sizeof(one))) == -1) {
|
||||
fprintf(stderr,"httpd: could not set socket option\n");
|
||||
perror("setsockopt");
|
||||
exit(1);
|
||||
}
|
||||
bzero((char *) &sa_server, sizeof(sa_server));
|
||||
sa_server.sin_family=AF_INET;
|
||||
sa_server.sin_addr.s_addr=htonl(INADDR_ANY);
|
||||
sa_server.sin_port=htons(port);
|
||||
if(bind(sd,(struct sockaddr *) &sa_server,sizeof(sa_server)) == -1) {
|
||||
fprintf(stderr,"httpd: could not bind to port %d\n",port);
|
||||
perror("bind");
|
||||
exit(1);
|
||||
}
|
||||
listen(sd,5);
|
||||
|
||||
set_signals();
|
||||
log_pid();
|
||||
|
||||
while(1) {
|
||||
retry:
|
||||
clen=sizeof(sa_client);
|
||||
if((csd=accept(sd,&sa_client,&clen)) == -1) {
|
||||
if(errno == EINTR) {
|
||||
#ifdef BSD
|
||||
ign();
|
||||
#endif
|
||||
goto retry;
|
||||
}
|
||||
log_error("socket error: accept failed");
|
||||
goto retry;
|
||||
}
|
||||
remote_logname = (!do_rfc931 ? NULL :
|
||||
rfc931((struct sockaddr_in *)&sa_client,&sa_server));
|
||||
|
||||
/* we do this here so that logs can be opened as root */
|
||||
if((pid = fork()) == -1)
|
||||
log_error("unable to fork new process");
|
||||
else if(!pid) {
|
||||
struct passwd* pwent;
|
||||
struct linger sl;
|
||||
|
||||
sl.l_onoff = 1;
|
||||
sl.l_linger = 600; /* currently ignored anyway */
|
||||
/* this should check error status, but it's not crucial */
|
||||
setsockopt(csd,SOL_SOCKET,SO_LINGER,&sl,sizeof(sl));
|
||||
|
||||
close(0);
|
||||
close(1);
|
||||
dup2(csd,0);
|
||||
dup2(csd,1);
|
||||
close(sd);
|
||||
/* Only try to switch if we're running as root */
|
||||
if(!getuid()) {
|
||||
/* Now, make absolutely certain we don't have any privileges
|
||||
* except those mentioned in the configuration file. */
|
||||
if ((pwent = getpwuid(user_id)) == NULL)
|
||||
die(SERVER_ERROR,"couldn't determine user name from uid",
|
||||
stdout);
|
||||
/* Reset `groups' attribute. */
|
||||
if (initgroups(pwent->pw_name, group_id) == -1)
|
||||
die(SERVER_ERROR,"unable to setgroups",stdout);
|
||||
|
||||
/* Note the order, first setgid() and then setuid(), it
|
||||
* wouldn't work the other way around. */
|
||||
if (setgid(group_id) == -1)
|
||||
die(SERVER_ERROR,"unable to change gid",stdout);
|
||||
if (setuid(user_id) == -1)
|
||||
die(SERVER_ERROR,"unable to change uid",stdout);
|
||||
}
|
||||
process_request(0,stdout);
|
||||
fclose(stdin);
|
||||
fclose(stdout);
|
||||
shutdown(csd,2);
|
||||
close(csd);
|
||||
exit(0);
|
||||
}
|
||||
close(csd);
|
||||
}
|
||||
}
|
||||
|
||||
extern char *optarg;
|
||||
extern int optind;
|
||||
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int c;
|
||||
|
||||
strcpy(server_root,HTTPD_ROOT);
|
||||
make_full_path(server_root,SERVER_CONFIG_FILE,server_confname);
|
||||
|
||||
while((c = getopt(argc,argv,"d:f:v")) != -1) {
|
||||
switch(c) {
|
||||
case 'd':
|
||||
strcpy(server_root,optarg);
|
||||
make_full_path(server_root,SERVER_CONFIG_FILE,server_confname);
|
||||
break;
|
||||
case 'f':
|
||||
strcpy(server_confname,optarg);
|
||||
break;
|
||||
case 'v':
|
||||
printf("NCSA httpd version %s.\n",SERVER_VERSION);
|
||||
exit(1);
|
||||
case '?':
|
||||
usage(argv[0]);
|
||||
}
|
||||
}
|
||||
read_config();
|
||||
open_logs();
|
||||
get_local_host();
|
||||
|
||||
if(standalone)
|
||||
standalone_main();
|
||||
else {
|
||||
user_id = getuid();
|
||||
group_id = getgid();
|
||||
port = get_portnum(fileno(stdout),stdout);
|
||||
if(do_rfc931)
|
||||
remote_logname = get_remote_logname(stdout);
|
||||
process_request(0,stdout);
|
||||
}
|
||||
fclose(stdin);
|
||||
fclose(stdout);
|
||||
exit(0);
|
||||
}
|
525
src/httpd.h
Normal file
525
src/httpd.h
Normal file
@ -0,0 +1,525 @@
|
||||
/*
|
||||
* httpd.h: header for simple (ha! not anymore) http daemon
|
||||
*/
|
||||
|
||||
|
||||
/* Define one of these according to your system. */
|
||||
#if defined(SUNOS4)
|
||||
#define BSD
|
||||
#undef NO_KILLPG
|
||||
#undef NO_SETSID
|
||||
char *crypt(char *pw, char *salt);
|
||||
|
||||
#elif defined(SOLARIS2)
|
||||
#undef BSD
|
||||
#define NO_KILLPG
|
||||
#undef NO_SETSID
|
||||
#define bzero(a,b) memset(a,0,b)
|
||||
|
||||
#elif defined(IRIX)
|
||||
#undef BSD
|
||||
#undef NO_KILLPG
|
||||
#undef NO_SETSID
|
||||
|
||||
#elif defined(HPUX)
|
||||
#undef BSD
|
||||
#define NO_KILLPG
|
||||
#undef NO_SETSID
|
||||
#define _HPUX_SOURCE
|
||||
|
||||
#elif defined(AIX)
|
||||
#undef BSD
|
||||
#undef NO_KILLPG
|
||||
#undef NO_SETSID
|
||||
|
||||
#elif defined(ULTRIX)
|
||||
#define BSD
|
||||
#undef NO_KILLPG
|
||||
#undef NO_SETSID
|
||||
#define ULTRIX_BRAIN_DEATH
|
||||
#define NEED_STRDUP
|
||||
|
||||
#elif defined(OSF1)
|
||||
#define BSD
|
||||
#undef NO_KILLPG
|
||||
#undef NO_SETSID
|
||||
|
||||
#elif defined(SEQUENT)
|
||||
#define BSD
|
||||
#undef NO_KILLPG
|
||||
#define NO_SETSID
|
||||
#define NEED_STRDUP
|
||||
#define tolower(c) (isupper(c) ? tolower(c) : c)
|
||||
|
||||
#elif defined(NEXT)
|
||||
#define BSD
|
||||
#undef NO_KILLPG
|
||||
#define NO_SETSID
|
||||
#define NEED_STRDUP
|
||||
#undef _POSIX_SOURCE
|
||||
#ifndef S_ISDIR
|
||||
#define S_ISDIR(m) (((m)&(S_IFMT)) == (S_IFDIR))
|
||||
#endif
|
||||
#ifndef S_ISREG
|
||||
#define S_ISREG(m) (((m)&(S_IFMT)) == (S_IFREG))
|
||||
#endif
|
||||
#ifndef S_IXUSR
|
||||
#define S_IXUSR 00100
|
||||
#endif
|
||||
#ifndef S_IXGRP
|
||||
#define S_IXGRP 00010
|
||||
#endif
|
||||
#ifndef S_IXOTH
|
||||
#define S_IXOTH 00001
|
||||
#endif
|
||||
#ifndef S_IRUSR
|
||||
#define S_IRUSR S_IREAD
|
||||
#endif
|
||||
#ifndef S_IWUSR
|
||||
#define S_IWUSR S_IWRITE
|
||||
#endif
|
||||
#define STDIN_FILENO 0
|
||||
#define STDOUT_FILENO 1
|
||||
#define STDERR_FILENO 2
|
||||
#define waitpid(a,b,c) wait4(a,b,c,NULL)
|
||||
typedef int pid_t;
|
||||
|
||||
#elif defined(LINUX)
|
||||
#undef BSD
|
||||
#undef NO_KILLPG
|
||||
#undef NO_SETSID
|
||||
#undef NEED_STRDUP
|
||||
|
||||
#elif defined(SCO)
|
||||
#undef BSD
|
||||
#undef NO_KILLPG
|
||||
#undef NO_SETSID
|
||||
#define NEED_INITGROUPS
|
||||
|
||||
#elif defined(CONVEXOS)
|
||||
#define BSD
|
||||
#define NEED_STRDUP
|
||||
|
||||
#elif defined(AUX)
|
||||
#undef BSD
|
||||
#undef NO_KILLPG
|
||||
#undef NO_SETSID
|
||||
#define NEED_STRDUP
|
||||
#define _POSIX_SOURCE
|
||||
|
||||
#elif defined(SVR4)
|
||||
#define NO_KILLPG
|
||||
#undef NO_SETSID
|
||||
#undef NEED_STRDUP
|
||||
#define NEED_STRCASECMP
|
||||
#define NEED_STRNCASECMP
|
||||
#define bzero(a,b) memset(a,0,b)
|
||||
|
||||
/* Unknown system - Edit these to match */
|
||||
#else
|
||||
/* BSD is whether your system uses BSD calls or System V calls. */
|
||||
#define BSD
|
||||
/* NO_KILLPG is set on systems that don't have killpg */
|
||||
#undef NO_KILLPG
|
||||
/* NO_SETSID is set on systems that don't have setsid */
|
||||
#undef NO_SETSID
|
||||
/* NEED_STRDUP is set on stupid systems that don't have strdup. */
|
||||
#undef NEED_STRDUP
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The particular directory style your system supports. If you have dirent.h
|
||||
* in /usr/include (POSIX) or /usr/include/sys (SYSV), #include
|
||||
* that file and define DIR_TYPE to be dirent. Otherwise, if you have
|
||||
* /usr/include/sys/dir.h, define DIR_TYPE to be direct and include that
|
||||
* file. If you have neither, I'm confused.
|
||||
*/
|
||||
#if !defined(NEXT) && !defined(CONVEXOS)
|
||||
#include <dirent.h>
|
||||
#define DIR_TYPE dirent
|
||||
#else
|
||||
#include <sys/dir.h>
|
||||
#define DIR_TYPE direct
|
||||
#endif
|
||||
|
||||
/* ----------------------------- config dir ------------------------------ */
|
||||
|
||||
/* Define this to be the default server home dir. Anything later in this
|
||||
* file with a relative pathname will have this added.
|
||||
*/
|
||||
#define HTTPD_ROOT "/usr/local/etc/httpd"
|
||||
|
||||
/* Root of server */
|
||||
#define DOCUMENT_LOCATION "/usr/local/etc/httpd/htdocs"
|
||||
|
||||
/* Max. number of aliases */
|
||||
#define MAX_ALIASES 20
|
||||
|
||||
/* Max. number of security defines */
|
||||
#define MAX_SECURITY 50
|
||||
|
||||
/* Max. number of include files */
|
||||
#define MAXINCLUDES 20
|
||||
|
||||
/* Default administrator's address */
|
||||
#define DEFAULT_ADMIN "[no address given]"
|
||||
|
||||
/*
|
||||
* --------- You shouldn't have to edit anything below this line ----------
|
||||
*
|
||||
* Any modifications to any defaults not defined above should be done in the
|
||||
* respective config. file.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/* -------------- Port number for server running standalone --------------- */
|
||||
|
||||
#define DEFAULT_PORT 80
|
||||
|
||||
/* --------- Default user name and group name running standalone ---------- */
|
||||
/* --- These may be specified as numbers by placing a # before a number --- */
|
||||
|
||||
#define DEFAULT_USER "#-1"
|
||||
#define DEFAULT_GROUP "#-1"
|
||||
|
||||
/* The name of the log files */
|
||||
#define DEFAULT_XFERLOG "logs/access_log"
|
||||
#define DEFAULT_ERRORLOG "logs/error_log"
|
||||
#define DEFAULT_PIDLOG "logs/httpd.pid"
|
||||
|
||||
/* Define this to be what your HTML directory content files are called */
|
||||
#define DEFAULT_INDEX "index.html"
|
||||
|
||||
/* Define this to 1 if you want fancy indexing, 0 otherwise */
|
||||
#define DEFAULT_INDEXING 0
|
||||
|
||||
/* Define this to be what type you'd like returned for files with unknown */
|
||||
/* suffixes */
|
||||
#define DEFAULT_TYPE "text/html"
|
||||
|
||||
/* Define this to be what your per-directory security files are called */
|
||||
#define DEFAULT_ACCESS_FNAME ".htaccess"
|
||||
|
||||
/* The name of the server config file */
|
||||
#define SERVER_CONFIG_FILE "conf/httpd.conf"
|
||||
|
||||
/* The name of the document config file */
|
||||
#define RESOURCE_CONFIG_FILE "conf/srm.conf"
|
||||
|
||||
/* The name of the MIME types file */
|
||||
#define TYPES_CONFIG_FILE "conf/mime.types"
|
||||
|
||||
/* The name of the access file */
|
||||
#define ACCESS_CONFIG_FILE "conf/access.conf"
|
||||
|
||||
/* Whether we should enable rfc931 identity checking */
|
||||
#define DEFAULT_RFC931 0
|
||||
/* The default directory in user's home dir */
|
||||
#define DEFAULT_USER_DIR "public_html"
|
||||
|
||||
|
||||
/* The default string lengths */
|
||||
#define MAX_STRING_LEN 256
|
||||
#define HUGE_STRING_LEN 8192
|
||||
|
||||
/* The timeout for waiting for messages */
|
||||
#define DEFAULT_TIMEOUT 1200
|
||||
|
||||
|
||||
/* ------------------------------ error types ------------------------------ */
|
||||
|
||||
#define SERVER_VERSION "NCSA/1.1"
|
||||
#define SERVER_PROTOCOL "HTTP/1.0"
|
||||
#define SERVER_SUPPORT "httpd@ncsa.uiuc.edu"
|
||||
|
||||
#define DOCUMENT_FOLLOWS 200
|
||||
#define REDIRECT 302
|
||||
#define BAD_REQUEST 400
|
||||
#define AUTH_REQUIRED 401
|
||||
#define FORBIDDEN 403
|
||||
#define NOT_FOUND 404
|
||||
#define SERVER_ERROR 500
|
||||
#define NOT_IMPLEMENTED 501
|
||||
#define INCLUDE_ERROR 6991
|
||||
#define NO_MEMORY 6992
|
||||
|
||||
#define METHODS 3
|
||||
#define M_GET 0
|
||||
#define M_PUT 1
|
||||
#define M_POST 2
|
||||
|
||||
/* Object types */
|
||||
#define REDIRECT_URL -1
|
||||
#define STD_DOCUMENT 0
|
||||
#define SCRIPT_NCSA 1
|
||||
#define SCRIPT_CGI 2
|
||||
|
||||
#define OPT_NONE 0
|
||||
#define OPT_INDEXES 1
|
||||
#define OPT_INCLUDES 2
|
||||
#define OPT_SYM_LINKS 4
|
||||
#define OPT_UNSET 8
|
||||
#define OPT_ALL (OPT_INDEXES|OPT_INCLUDES|OPT_SYM_LINKS)
|
||||
|
||||
#define OR_NONE 0
|
||||
#define OR_LIMIT 1
|
||||
#define OR_OPTIONS 2
|
||||
#define OR_FILEINFO 4
|
||||
#define OR_AUTHCFG 16
|
||||
#define OR_ALL (OR_LIMIT|OR_OPTIONS|OR_FILEINFO|OR_AUTHCFG)
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/socket.h>
|
||||
#include <ctype.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <arpa/inet.h> /* for inet_ntoa */
|
||||
#include <time.h> /* for ctime */
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
#include <sys/wait.h>
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#ifndef NEXT
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef ultrix
|
||||
#define ULTRIX_BRAIN_DEATH
|
||||
#endif
|
||||
|
||||
/* Just in case your linefeed isn't the one the other end is expecting. */
|
||||
#define LF 10
|
||||
#define CR 13
|
||||
|
||||
/* For access control */
|
||||
#define DENY_THEN_ALLOW 0
|
||||
#define ALLOW_THEN_DENY 1
|
||||
|
||||
/* Struct shared by access and auth */
|
||||
typedef struct {
|
||||
char *d;
|
||||
char opts;
|
||||
char override;
|
||||
|
||||
int order[METHODS];
|
||||
|
||||
int num_allow[METHODS];
|
||||
char *allow[METHODS][MAX_SECURITY];
|
||||
int num_auth[METHODS];
|
||||
char *auth[METHODS][MAX_SECURITY];
|
||||
|
||||
char *auth_type;
|
||||
char *auth_name;
|
||||
char *auth_pwfile;
|
||||
char *auth_grpfile;
|
||||
|
||||
int num_deny[METHODS];
|
||||
char *deny[METHODS][MAX_SECURITY];
|
||||
} security_data;
|
||||
|
||||
/* Globals */
|
||||
|
||||
/* Server config */
|
||||
extern int standalone;
|
||||
extern int port;
|
||||
extern uid_t user_id;
|
||||
extern gid_t group_id;
|
||||
extern char server_root[MAX_STRING_LEN];
|
||||
extern char error_fname[MAX_STRING_LEN];
|
||||
extern char xfer_fname[MAX_STRING_LEN];
|
||||
extern char pid_fname[MAX_STRING_LEN];
|
||||
extern char server_admin[MAX_STRING_LEN];
|
||||
extern char *server_hostname;
|
||||
extern char server_confname[MAX_STRING_LEN];
|
||||
extern char srm_confname[MAX_STRING_LEN];
|
||||
extern char access_confname[MAX_STRING_LEN];
|
||||
extern char types_confname[MAX_STRING_LEN];
|
||||
extern int timeout;
|
||||
extern int do_rfc931;
|
||||
#ifdef PEM_AUTH
|
||||
extern char auth_pem_decrypt[MAX_STRING_LEN];
|
||||
extern char auth_pem_encrypt[MAX_STRING_LEN];
|
||||
extern char auth_pem_entity[MAX_STRING_LEN];
|
||||
extern char auth_pgp_decrypt[MAX_STRING_LEN];
|
||||
extern char auth_pgp_encrypt[MAX_STRING_LEN];
|
||||
extern char auth_pgp_entity[MAX_STRING_LEN];
|
||||
#endif
|
||||
|
||||
/* Document config */
|
||||
extern char user_dir[MAX_STRING_LEN];
|
||||
extern char index_name[MAX_STRING_LEN];
|
||||
extern char access_name[MAX_STRING_LEN];
|
||||
extern char document_root[MAX_STRING_LEN];
|
||||
extern char default_type[MAX_STRING_LEN];
|
||||
extern char default_icon[MAX_STRING_LEN];
|
||||
extern int fancy_indexing;
|
||||
extern char readme_fname[MAX_STRING_LEN];
|
||||
|
||||
/* Security config */
|
||||
extern int num_sec;
|
||||
extern security_data sec[MAX_SECURITY];
|
||||
|
||||
/* Auth config */
|
||||
extern char *auth_type;
|
||||
extern char *auth_name;
|
||||
extern char *auth_pwfile;
|
||||
extern char *auth_grpfile;
|
||||
extern char user[MAX_STRING_LEN];
|
||||
#ifdef PEM_AUTH
|
||||
extern int doing_pem;
|
||||
#endif
|
||||
|
||||
/* Request information */
|
||||
extern int assbackwards;
|
||||
extern int header_only;
|
||||
extern char *remote_host;
|
||||
extern char *remote_ip;
|
||||
extern char *remote_name;
|
||||
extern char *remote_logname;
|
||||
extern int allow;
|
||||
extern char allow_options;
|
||||
extern int num_includes;
|
||||
extern int dirs_in_alias;
|
||||
|
||||
/* MIME */
|
||||
extern char auth_line[MAX_STRING_LEN];
|
||||
extern int content_length;
|
||||
extern char content_type[MAX_STRING_LEN];
|
||||
extern char location[MAX_STRING_LEN];
|
||||
extern char http_accept[HUGE_STRING_LEN];
|
||||
/* Function prototypes. */
|
||||
|
||||
/* http_config */
|
||||
void read_config();
|
||||
void parse_htaccess(char *dir, char override, FILE *out);
|
||||
int get_pw(char *user, char *pw);
|
||||
int in_group(char *user, char *group);
|
||||
int init_group(char *grpfile, FILE *out);
|
||||
void kill_group();
|
||||
|
||||
/* http_alias */
|
||||
void reset_aliases();
|
||||
void dump_aliases();
|
||||
void add_alias(char *f, char *r, int is_script);
|
||||
void add_redirect(char *f, char *url);
|
||||
int translate_name(char *name,FILE *fd);
|
||||
void unmunge_name(char *name);
|
||||
|
||||
/* http_request */
|
||||
void process_request(int in, FILE *out);
|
||||
void send_fd(FILE *f, FILE *fd, char *args);
|
||||
void send_fd_timed_out();
|
||||
|
||||
/* http_get */
|
||||
void send_file(char *file,FILE *fd, char *args);
|
||||
void process_include(FILE *f, FILE *fd, char *incstring, char *args);
|
||||
void send_node(char *name, char *args, FILE *fd);
|
||||
void process_get(int in, FILE *out, char *m, char *url, char *args);
|
||||
|
||||
/* http_put */
|
||||
void get_node(char *name, char *args, int in, FILE *out);
|
||||
|
||||
/* http_script */
|
||||
void exec_cgi_script(char *method, char *path, char *args, int in, FILE *out);
|
||||
void exec_get_NCSA(char *path, char *args, FILE *fd);
|
||||
void exec_post_NCSA(char *path, char *args, int in, FILE *out);
|
||||
|
||||
/* http_dir */
|
||||
extern void index_directory(char *name, FILE *fd);
|
||||
extern void add_icon(char *icon, char *ext, FILE *out);
|
||||
extern void add_desc(char *desc, char *ext, FILE *out);
|
||||
extern void add_ignore(char *ext, FILE *out);
|
||||
extern void init_indexing();
|
||||
extern void kill_indexing();
|
||||
|
||||
/* http_log */
|
||||
void log_transaction(char *cmd_line);
|
||||
void log_error(char *err);
|
||||
void log_reason(char *reason, char *file);
|
||||
void die(int type, char *err_string, FILE *fd);
|
||||
void open_logs();
|
||||
void close_logs();
|
||||
void begin_http_header(FILE *fd, char *msg);
|
||||
|
||||
/* http_mime */
|
||||
void get_mime_headers(int fd);
|
||||
void send_http_header(FILE *fd);
|
||||
void set_content_type(char *fn);
|
||||
int scan_script_header(FILE *f, FILE *fd);
|
||||
void add_type(char *fn, char *t,FILE *out);
|
||||
void add_encoding(char *fn, char *t,FILE *out);
|
||||
void set_content_length(int l);
|
||||
void dump_types();
|
||||
void init_mime();
|
||||
void kill_mime();
|
||||
int is_content_type(char *type);
|
||||
void dump_default_header(FILE *fd);
|
||||
|
||||
/* http_access */
|
||||
void evaluate_access(char *path, struct stat *finfo,int m, int *allow,
|
||||
char *op, FILE *out);
|
||||
void kill_security();
|
||||
|
||||
/* http_auth */
|
||||
void check_auth(security_data *s, int m, FILE *out);
|
||||
#ifdef PEM_AUTH
|
||||
int pem_decrypt(int sfd, char *req, FILE **out);
|
||||
void htexit(int status, FILE *out);
|
||||
#endif
|
||||
|
||||
/* util */
|
||||
void strsubfirst(int start,char *dest, char *src);
|
||||
void make_full_path(char *src1,char *src2,char *dst);
|
||||
int is_directory(char *name);
|
||||
void getparents(char *name);
|
||||
uid_t uname2id(char *name);
|
||||
gid_t gname2id(char *name);
|
||||
int getline(char *s, int n, int f, unsigned int timeout);
|
||||
int cfg_getline(char *s, int n, FILE *f);
|
||||
void getword(char *word, char *line, char stop);
|
||||
void cfg_getword(char *word, char *line);
|
||||
void get_remote_host(int fd);
|
||||
char *get_time();
|
||||
char *gm_timestr_822(time_t t);
|
||||
void make_dirstr(char *s, int n, char *d);
|
||||
int count_dirs(char *path);
|
||||
void strcpy_dir(char *d, char *s);
|
||||
void unescape_url(char *url);
|
||||
void escape_url(char *url);
|
||||
void escape_shell_cmd(char *cmd);
|
||||
void plustospace(char *str);
|
||||
void spacetoplus(char *str);
|
||||
void str_tolower(char *str);
|
||||
void uudecode(char *s,unsigned char *d,int dl);
|
||||
#ifdef NEED_STRDUP
|
||||
char *strdup (char *str);
|
||||
#endif
|
||||
#ifdef NEED_STRCASECMP
|
||||
char *strcasecmp(const char *s1, const char *s2);
|
||||
#endif
|
||||
#ifdef NEED_STRNCASECMP
|
||||
char *strncasecmp(const char *s1, const char *s2, int n);
|
||||
#endif
|
||||
char *make_env_str(char *n, char *v, FILE *out);
|
||||
int ind(char *s, char c);
|
||||
int rind(char *s, char c);
|
||||
void construct_url(char *d, char *s);
|
||||
void get_local_host();
|
||||
int get_portnum(int sd,FILE *out);
|
||||
int can_exec(struct stat *finfo);
|
||||
#ifdef NEED_INITGROUPS
|
||||
int initgroups(const char *name, gid_t basegid);
|
||||
#endif
|
||||
char *get_remote_logname(FILE *fd);
|
||||
char *rfc931(struct sockaddr_in *rmt_sin,struct sockaddr_in *our_sin);
|
184
src/rfc931.c
Normal file
184
src/rfc931.c
Normal file
@ -0,0 +1,184 @@
|
||||
/*
|
||||
* rfc931() speaks a common subset of the RFC 931, AUTH, TAP and IDENT
|
||||
* protocols. The code queries an RFC 931 etc. compatible daemon on a remote
|
||||
* host to look up the owner of a connection. The information should not be
|
||||
* used for authentication purposes. This routine intercepts alarm signals.
|
||||
*
|
||||
* Diagnostics are reported through syslog(3).
|
||||
*
|
||||
* Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#) rfc931.c 1.8 93/12/13 22:23:20";
|
||||
#endif
|
||||
|
||||
/* System libraries. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <syslog.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <setjmp.h>
|
||||
#include <signal.h>
|
||||
|
||||
extern char *strchr();
|
||||
extern char *inet_ntoa();
|
||||
|
||||
/* Local stuff. */
|
||||
|
||||
/* #include "log_tcp.h" */
|
||||
|
||||
#define RFC931_TIMEOUT 500
|
||||
#define RFC931_PORT 113 /* Semi-well-known port */
|
||||
#define ANY_PORT 0 /* Any old port will do */
|
||||
#define FROM_UNKNOWN "unknown"
|
||||
|
||||
int rfc931_timeout = RFC931_TIMEOUT;/* Global so it can be changed */
|
||||
|
||||
static jmp_buf timebuf;
|
||||
|
||||
/* fsocket - open stdio stream on top of socket */
|
||||
|
||||
static FILE *fsocket(domain, type, protocol)
|
||||
int domain;
|
||||
int type;
|
||||
int protocol;
|
||||
{
|
||||
int s;
|
||||
FILE *fp;
|
||||
|
||||
if ((s = socket(domain, type, protocol)) < 0) {
|
||||
syslog(LOG_ERR, "socket: %m");
|
||||
return (0);
|
||||
} else {
|
||||
if ((fp = fdopen(s, "r+")) == 0) {
|
||||
syslog(LOG_ERR, "fdopen: %m");
|
||||
close(s);
|
||||
}
|
||||
return (fp);
|
||||
}
|
||||
}
|
||||
|
||||
/* bind_connect - bind both ends of a socket */
|
||||
|
||||
int bind_connect(s, local, remote, length)
|
||||
int s;
|
||||
struct sockaddr *local;
|
||||
struct sockaddr *remote;
|
||||
int length;
|
||||
{
|
||||
if (bind(s, local, length) < 0) {
|
||||
syslog(LOG_ERR, "bind: %m");
|
||||
return (-1);
|
||||
} else {
|
||||
return (connect(s, remote, length));
|
||||
}
|
||||
}
|
||||
|
||||
/* timeout - handle timeouts */
|
||||
|
||||
static void timeout(sig)
|
||||
int sig;
|
||||
{
|
||||
longjmp(timebuf, sig);
|
||||
}
|
||||
|
||||
/* rfc931 - return remote user name, given socket structures */
|
||||
|
||||
char *rfc931(rmt_sin, our_sin)
|
||||
struct sockaddr_in *rmt_sin;
|
||||
struct sockaddr_in *our_sin;
|
||||
{
|
||||
unsigned rmt_port;
|
||||
unsigned our_port;
|
||||
struct sockaddr_in rmt_query_sin;
|
||||
struct sockaddr_in our_query_sin;
|
||||
static char user[256]; /* XXX */
|
||||
char buffer[512]; /* XXX */
|
||||
char *cp;
|
||||
char *result = FROM_UNKNOWN; /* XXX */
|
||||
FILE *fp;
|
||||
|
||||
/*
|
||||
* Use one unbuffered stdio stream for writing to and for reading from
|
||||
* the RFC931 etc. server. This is done because of a bug in the SunOS
|
||||
* 4.1.x stdio library. The bug may live in other stdio implementations,
|
||||
* too. When we use a single, buffered, bidirectional stdio stream ("r+"
|
||||
* or "w+" mode) we read our own output. Such behaviour would make sense
|
||||
* with resources that support random-access operations, but not with
|
||||
* sockets.
|
||||
*/
|
||||
|
||||
if ((fp = fsocket(AF_INET, SOCK_STREAM, 0)) != 0) {
|
||||
setbuf(fp, (char *) 0);
|
||||
|
||||
/*
|
||||
* Set up a timer so we won't get stuck while waiting for the server.
|
||||
*/
|
||||
|
||||
if (setjmp(timebuf) == 0) {
|
||||
signal(SIGALRM, timeout);
|
||||
alarm(rfc931_timeout);
|
||||
|
||||
/*
|
||||
* Bind the local and remote ends of the query socket to the same
|
||||
* IP addresses as the connection under investigation. We go
|
||||
* through all this trouble because the local or remote system
|
||||
* might have more than one network address. The RFC931 etc.
|
||||
* client sends only port numbers; the server takes the IP
|
||||
* addresses from the query socket.
|
||||
*/
|
||||
|
||||
our_query_sin = *our_sin;
|
||||
our_query_sin.sin_port = htons(ANY_PORT);
|
||||
rmt_query_sin = *rmt_sin;
|
||||
rmt_query_sin.sin_port = htons(RFC931_PORT);
|
||||
|
||||
if (bind_connect(fileno(fp),
|
||||
(struct sockaddr *) & our_query_sin,
|
||||
(struct sockaddr *) & rmt_query_sin,
|
||||
sizeof(our_query_sin)) >= 0) {
|
||||
|
||||
/*
|
||||
* Send query to server. Neglect the risk that a 13-byte
|
||||
* write would have to be fragmented by the local system and
|
||||
* cause trouble with buggy System V stdio libraries.
|
||||
*/
|
||||
|
||||
fprintf(fp, "%u,%u\r\n",
|
||||
ntohs(rmt_sin->sin_port),
|
||||
ntohs(our_sin->sin_port));
|
||||
fflush(fp);
|
||||
|
||||
/*
|
||||
* Read response from server. Use fgets()/sscanf() so we can
|
||||
* work around System V stdio libraries that incorrectly
|
||||
* assume EOF when a read from a socket returns less than
|
||||
* requested.
|
||||
*/
|
||||
|
||||
if (fgets(buffer, sizeof(buffer), fp) != 0
|
||||
&& ferror(fp) == 0 && feof(fp) == 0
|
||||
&& sscanf(buffer, "%u , %u : USERID :%*[^:]:%255s",
|
||||
&rmt_port, &our_port, user) == 3
|
||||
&& ntohs(rmt_sin->sin_port) == rmt_port
|
||||
&& ntohs(our_sin->sin_port) == our_port) {
|
||||
|
||||
/*
|
||||
* Strip trailing carriage return. It is part of the
|
||||
* protocol, not part of the data.
|
||||
*/
|
||||
|
||||
if (cp = strchr(user, '\r'))
|
||||
*cp = 0;
|
||||
result = user;
|
||||
}
|
||||
}
|
||||
alarm(0);
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
return (result);
|
||||
}
|
590
src/util.c
Normal file
590
src/util.c
Normal file
@ -0,0 +1,590 @@
|
||||
/*
|
||||
* str.c: string utility things
|
||||
*
|
||||
* 3/21/93 Rob McCool
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "httpd.h"
|
||||
|
||||
char *get_time() {
|
||||
time_t t;
|
||||
char *time_string;
|
||||
|
||||
t=time(NULL);
|
||||
time_string = ctime(&t);
|
||||
time_string[strlen(time_string) - 1] = '\0';
|
||||
return (time_string);
|
||||
}
|
||||
|
||||
char *gm_timestr_822(time_t sec) {
|
||||
struct tm *t;
|
||||
static char ts[MAX_STRING_LEN];
|
||||
|
||||
t = gmtime(&sec);
|
||||
/* check return code? */
|
||||
strftime(ts,MAX_STRING_LEN,"%A, %d-%h-%y %T GMT",t);
|
||||
return ts;
|
||||
}
|
||||
|
||||
void strsubfirst(int start,char *dest, char *src)
|
||||
{
|
||||
char tmp[MAX_STRING_LEN];
|
||||
|
||||
strcpy(tmp,&dest[start]);
|
||||
strcpy(dest,src);
|
||||
strcpy(&dest[strlen(src)],tmp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse .. so we don't compromise security
|
||||
*/
|
||||
void getparents(char *name)
|
||||
{
|
||||
int l=0,w=0;
|
||||
const char *lookfor="..";
|
||||
|
||||
while(name[l]!='\0') {
|
||||
if(name[l]!=lookfor[w]) (w>0 ? (l-=(w-1),w=0) : l++);
|
||||
else {
|
||||
if(lookfor[++w]=='\0') {
|
||||
if((name[l+1]=='\0') || (name[l+1]=='/') &&
|
||||
(((l > 3) && (name[l-2] == '/')) || (l<=3))) {
|
||||
register int m=l+1,n;
|
||||
|
||||
l=l-3;
|
||||
if(l>=0) {
|
||||
while((l!=0) && (name[l]!='/')) --l;
|
||||
}
|
||||
else l=0;
|
||||
n=l;
|
||||
while(name[n]=name[m]) (++n,++m);
|
||||
w=0;
|
||||
}
|
||||
else w=0;
|
||||
}
|
||||
else ++l;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void make_dirstr(char *s, int n, char *d) {
|
||||
register int x,f;
|
||||
|
||||
for(x=0,f=0;s[x];x++) {
|
||||
if((d[x] = s[x]) == '/')
|
||||
if((++f) == n) {
|
||||
d[x] = '\0';
|
||||
return;
|
||||
}
|
||||
}
|
||||
d[x] = '\0';
|
||||
}
|
||||
|
||||
int count_dirs(char *path) {
|
||||
register int x,n;
|
||||
|
||||
for(x=0,n=0;path[x];x++)
|
||||
if(path[x] == '/') n++;
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
void strcpy_dir(char *d, char *s) {
|
||||
register int x;
|
||||
|
||||
for(x=0;s[x];x++)
|
||||
d[x] = s[x];
|
||||
|
||||
if(s[x-1] != '/') d[x++] = '/';
|
||||
d[x] = '\0';
|
||||
}
|
||||
|
||||
|
||||
void getline_timed_out() {
|
||||
char errstr[MAX_STRING_LEN];
|
||||
|
||||
sprintf(errstr,"timed out waiting for %s",remote_name);
|
||||
log_error(errstr);
|
||||
fclose(stdin);
|
||||
fclose(stdout);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
int getline(char *s, int n, int f, unsigned int timeout) {
|
||||
register int i=0;
|
||||
|
||||
signal(SIGALRM,getline_timed_out);
|
||||
alarm(timeout);
|
||||
while(1) {
|
||||
if(read(f,&s[i],1) <= 0) {
|
||||
s[i] = '\0';
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(s[i] == CR)
|
||||
read(f,&s[i],1);
|
||||
|
||||
if((s[i] == LF) || (i == (n-1))) {
|
||||
alarm(0);
|
||||
signal(SIGALRM,SIG_IGN);
|
||||
s[i] = '\0';
|
||||
return 0;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
void getword(char *word, char *line, char stop) {
|
||||
int x = 0,y;
|
||||
|
||||
for(x=0;((line[x]) && (line[x] != stop));x++)
|
||||
word[x] = line[x];
|
||||
|
||||
word[x] = '\0';
|
||||
if(line[x]) ++x;
|
||||
y=0;
|
||||
|
||||
while(line[y++] = line[x++]);
|
||||
}
|
||||
|
||||
void cfg_getword(char *word, char *line) {
|
||||
int x=0,y;
|
||||
|
||||
for(x=0;line[x] && isspace(line[x]);x++);
|
||||
y=0;
|
||||
while(1) {
|
||||
if(!(word[y] = line[x]))
|
||||
break;
|
||||
if(isspace(line[x]))
|
||||
if((!x) || (line[x-1] != '\\'))
|
||||
break;
|
||||
if(line[x] != '\\') ++y;
|
||||
++x;
|
||||
}
|
||||
word[y] = '\0';
|
||||
while(line[x] && isspace(line[x])) ++x;
|
||||
for(y=0;line[y] = line[x];++x,++y);
|
||||
}
|
||||
|
||||
int cfg_getline(char *s, int n, FILE *f) {
|
||||
register int i=0;
|
||||
register char c;
|
||||
|
||||
s[0] = '\0';
|
||||
/* skip leading whitespace */
|
||||
while(1) {
|
||||
c=(char)fgetc(f);
|
||||
if((c != '\t') && (c != ' '))
|
||||
break;
|
||||
}
|
||||
while(1) {
|
||||
if((c == '\t') || (c == ' ')) {
|
||||
s[i++] = ' ';
|
||||
while((c == '\t') || (c == ' '))
|
||||
c=(char)fgetc(f);
|
||||
}
|
||||
if(c == CR) {
|
||||
c = fgetc(f);
|
||||
}
|
||||
if((c == 0x4) || (c == LF) || (i == (n-1))) {
|
||||
/* blast trailing whitespace */
|
||||
while(i && (s[i-1] == ' ')) --i;
|
||||
s[i] = '\0';
|
||||
return (feof(f) ? 1 : 0);
|
||||
}
|
||||
s[i] = c;
|
||||
++i;
|
||||
c = (char)fgetc(f);
|
||||
}
|
||||
}
|
||||
|
||||
void escape_shell_cmd(char *cmd) {
|
||||
register int x,y,l;
|
||||
|
||||
l=strlen(cmd);
|
||||
for(x=0;cmd[x];x++) {
|
||||
if(ind("&;`'\"|*?~<>^()[]{}$\\",cmd[x]) != -1){
|
||||
for(y=l+1;y>x;y--)
|
||||
cmd[y] = cmd[y-1];
|
||||
l++; /* length has been increased */
|
||||
cmd[x] = '\\';
|
||||
x++; /* skip the character */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void plustospace(char *str) {
|
||||
register int x;
|
||||
|
||||
for(x=0;str[x];x++) if(str[x] == '+') str[x] = ' ';
|
||||
}
|
||||
|
||||
void spacetoplus(char *str) {
|
||||
register int x;
|
||||
|
||||
for(x=0;str[x];x++) if(str[x] == ' ') str[x] = '+';
|
||||
}
|
||||
|
||||
char x2c(char *what) {
|
||||
register char digit;
|
||||
|
||||
digit = ((what[0] >= 'A') ? ((what[0] & 0xdf) - 'A')+10 : (what[0] - '0'));
|
||||
digit *= 16;
|
||||
digit += (what[1] >= 'A' ? ((what[1] & 0xdf) - 'A')+10 : (what[1] - '0'));
|
||||
return(digit);
|
||||
}
|
||||
|
||||
void unescape_url(char *url) {
|
||||
register int x,y;
|
||||
|
||||
for(x=0,y=0;url[y];++x,++y) {
|
||||
if((url[x] = url[y]) == '%') {
|
||||
url[x] = x2c(&url[y+1]);
|
||||
y+=2;
|
||||
}
|
||||
}
|
||||
url[x] = '\0';
|
||||
}
|
||||
|
||||
#define c2x(what,where) sprintf(where,"%%%2x",what)
|
||||
|
||||
void escape_url(char *url) {
|
||||
register int x,y;
|
||||
register char digit;
|
||||
char *copy;
|
||||
|
||||
copy = strdup(url);
|
||||
|
||||
for(x=0,y=0;copy[x];x++,y++) {
|
||||
if(ind("% ?+&",url[y] = copy[x]) != -1) {
|
||||
c2x(copy[x],&url[y]);
|
||||
y+=2;
|
||||
}
|
||||
}
|
||||
url[y] = '\0';
|
||||
free(copy);
|
||||
}
|
||||
|
||||
void make_full_path(char *src1,char *src2,char *dst) {
|
||||
register int x,y;
|
||||
|
||||
for(x=0;dst[x] = src1[x];x++);
|
||||
|
||||
if(!x) dst[x++] = '/';
|
||||
else if((dst[x-1] != '/'))
|
||||
dst[x++] = '/';
|
||||
|
||||
for(y=0;dst[x] = src2[y];x++,y++);
|
||||
}
|
||||
|
||||
int is_directory(char *path) {
|
||||
struct stat finfo;
|
||||
|
||||
if(stat(path,&finfo) == -1)
|
||||
return 0; /* in error condition, just return no */
|
||||
|
||||
return(S_ISDIR(finfo.st_mode));
|
||||
}
|
||||
|
||||
int is_url(char *u) {
|
||||
register int x;
|
||||
|
||||
for(x=0;u[x] != ':';x++)
|
||||
if((!u[x]) || (!isalpha(u[x])))
|
||||
return 0;
|
||||
|
||||
if((u[x+1] == '/') && (u[x+2] == '/'))
|
||||
return 1;
|
||||
else return 0;
|
||||
}
|
||||
|
||||
char *make_env_str(char *name, char *value, FILE *out) {
|
||||
char *t,*tp;
|
||||
|
||||
if(!(t = (char *)malloc(strlen(name)+strlen(value)+2)))
|
||||
die(NO_MEMORY,"make_env_str",out);
|
||||
|
||||
for(tp=t;*tp = *name;tp++,name++);
|
||||
for(*tp++ = '=';*tp = *value;tp++,value++);
|
||||
return t;
|
||||
}
|
||||
|
||||
int can_exec(struct stat *finfo) {
|
||||
if(user_id == finfo->st_uid)
|
||||
if(finfo->st_mode & S_IXUSR)
|
||||
return 1;
|
||||
if(group_id == finfo->st_gid)
|
||||
if(finfo->st_mode & S_IXGRP)
|
||||
return 1;
|
||||
return (finfo->st_mode & S_IXOTH);
|
||||
}
|
||||
|
||||
#ifdef NEED_STRDUP
|
||||
char *strdup (char *str)
|
||||
{
|
||||
char *dup;
|
||||
|
||||
if(!(dup = (char *)malloc (strlen (str) + 1)))
|
||||
return NULL;
|
||||
dup = strcpy (dup, str);
|
||||
|
||||
return dup;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* The following two routines were donated for SVR4 by Andreas Vogel */
|
||||
#ifdef NEED_STRCASECMP
|
||||
int strcasecmp (const char *a, const char *b)
|
||||
{
|
||||
const char *p = a;
|
||||
const char *q = b;
|
||||
for (p = a, q = b; *p && *q; p++, q++)
|
||||
{
|
||||
int diff = tolower(*p) - tolower(*q);
|
||||
if (diff) return diff;
|
||||
}
|
||||
if (*p) return 1; /* p was longer than q */
|
||||
if (*q) return -1; /* p was shorter than q */
|
||||
return 0; /* Exact match */
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef NEED_STRNCASECMP
|
||||
int strncasecmp (const char *a, const char *b, int n)
|
||||
{
|
||||
const char *p = a;
|
||||
const char *q = b;
|
||||
|
||||
for (p = a, q = b; /*NOTHING*/; p++, q++)
|
||||
{
|
||||
int diff;
|
||||
if (p == a + n) return 0; /* Match up to n characters */
|
||||
if (!(*p && *q)) return *p - *q;
|
||||
diff = tolower(*p) - tolower(*q);
|
||||
if (diff) return diff;
|
||||
}
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifdef NEED_INITGROUPS
|
||||
int initgroups(const char *name, gid_t basegid)
|
||||
{
|
||||
gid_t groups[NGROUPS_MAX];
|
||||
struct group *g;
|
||||
int index = 0;
|
||||
|
||||
groups[index++] = basegid;
|
||||
|
||||
while (index < NGROUPS_MAX && ((g = getgrent()) != NULL))
|
||||
if (g->gr_gid != basegid)
|
||||
{
|
||||
char **names;
|
||||
|
||||
for (names = g->gr_mem; *names != NULL; ++names)
|
||||
if (!strcmp(*names, name))
|
||||
groups[index++] = g->gr_gid;
|
||||
}
|
||||
|
||||
return setgroups(index, groups);
|
||||
}
|
||||
#endif
|
||||
|
||||
int ind(char *s, char c) {
|
||||
register int x;
|
||||
|
||||
for(x=0;s[x];x++)
|
||||
if(s[x] == c) return x;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int rind(char *s, char c) {
|
||||
register int x;
|
||||
|
||||
for(x=strlen(s)-1;x != -1;x--)
|
||||
if(s[x] == c) return x;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void str_tolower(char *str) {
|
||||
while(*str) {
|
||||
*str = tolower(*str);
|
||||
++str;
|
||||
}
|
||||
}
|
||||
|
||||
uid_t uname2id(char *name) {
|
||||
struct passwd *ent;
|
||||
|
||||
if(name[0] == '#')
|
||||
return(atoi(&name[1]));
|
||||
|
||||
if(!(ent = getpwnam(name))) {
|
||||
fprintf(stderr,"httpd: bad user name %s\n",name);
|
||||
exit(1);
|
||||
}
|
||||
else return(ent->pw_uid);
|
||||
}
|
||||
|
||||
gid_t gname2id(char *name) {
|
||||
struct group *ent;
|
||||
|
||||
if(name[0] == '#')
|
||||
return(atoi(&name[1]));
|
||||
|
||||
if(!(ent = getgrnam(name))) {
|
||||
fprintf(stderr,"httpd: bad group name %s\n",name);
|
||||
exit(1);
|
||||
}
|
||||
else return(ent->gr_gid);
|
||||
}
|
||||
|
||||
int get_portnum(int sd,FILE *out) {
|
||||
struct sockaddr addr;
|
||||
int len;
|
||||
|
||||
len = sizeof(struct sockaddr);
|
||||
if(getsockname(sd,&addr,&len) < 0)
|
||||
die(SERVER_ERROR,"could not get port number",out);
|
||||
|
||||
return(((struct sockaddr_in *)&addr)->sin_port);
|
||||
}
|
||||
|
||||
void get_remote_host(int fd) {
|
||||
struct sockaddr addr;
|
||||
int len;
|
||||
struct in_addr *iaddr;
|
||||
struct hostent *hptr;
|
||||
|
||||
len = sizeof(struct sockaddr);
|
||||
|
||||
if ((getpeername(fd, &addr, &len)) < 0) {
|
||||
remote_host=NULL;
|
||||
remote_ip=NULL;
|
||||
remote_name="UNKNOWN_HOST";
|
||||
return;
|
||||
}
|
||||
iaddr = &(((struct sockaddr_in *)&addr)->sin_addr);
|
||||
hptr = gethostbyaddr((char *)iaddr, sizeof(struct in_addr), AF_INET);
|
||||
if(hptr) {
|
||||
remote_host = strdup(hptr->h_name);
|
||||
str_tolower(remote_host);
|
||||
remote_name = remote_host;
|
||||
}
|
||||
else remote_host = NULL;
|
||||
|
||||
remote_ip = inet_ntoa(*iaddr);
|
||||
if(!remote_host)
|
||||
remote_name = remote_ip;
|
||||
}
|
||||
|
||||
char *get_remote_logname(FILE *fd) {
|
||||
int len;
|
||||
char *result;
|
||||
#ifdef NEXT
|
||||
struct sockaddr_in sa_server;
|
||||
struct sockaddr sa_client;
|
||||
#else
|
||||
struct sockaddr_in sa_server,sa_client;
|
||||
#endif
|
||||
|
||||
len = sizeof(sa_client);
|
||||
if(getpeername(fileno(stdout),&sa_client,&len) != -1) {
|
||||
len = sizeof(sa_server);
|
||||
if(getsockname(fileno(stdout),&sa_server,&len) == -1)
|
||||
result = "unknown";
|
||||
else
|
||||
result = rfc931((struct sockaddr_in *) & sa_client,
|
||||
(struct sockaddr_in *) & sa_server);
|
||||
}
|
||||
else result = "unknown";
|
||||
}
|
||||
|
||||
void get_local_host()
|
||||
{
|
||||
char str[128];
|
||||
int len = 128;
|
||||
|
||||
if(!server_hostname) {
|
||||
struct hostent *p;
|
||||
gethostname(str, len);
|
||||
if(p=gethostbyname(str))
|
||||
server_hostname = strdup(p->h_name);
|
||||
else {
|
||||
fprintf(stderr,"httpd: cannot determine local host name.\n");
|
||||
fprintf(stderr,"Use ServerName to set it manually.\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void construct_url(char *d, char *s) {
|
||||
sprintf(d,"http://%s:%d%s",server_hostname,port,s);
|
||||
/* escape_url(d); */
|
||||
}
|
||||
|
||||
/* aaaack but it's fast and const should make it shared text page. */
|
||||
const int pr2six[256]={
|
||||
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
|
||||
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,62,64,64,64,63,
|
||||
52,53,54,55,56,57,58,59,60,61,64,64,64,64,64,64,64,0,1,2,3,4,5,6,7,8,9,
|
||||
10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,64,64,64,64,64,64,26,27,
|
||||
28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,
|
||||
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
|
||||
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
|
||||
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
|
||||
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
|
||||
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
|
||||
64,64,64,64,64,64,64,64,64,64,64,64,64
|
||||
};
|
||||
|
||||
void uudecode(char *bufcoded, unsigned char *bufplain, int outbufsize) {
|
||||
int nbytesdecoded, j;
|
||||
register char *bufin = bufcoded;
|
||||
register unsigned char *bufout = bufplain;
|
||||
register int nprbytes;
|
||||
|
||||
/* Strip leading whitespace. */
|
||||
|
||||
while(*bufcoded==' ' || *bufcoded == '\t') bufcoded++;
|
||||
|
||||
/* Figure out how many characters are in the input buffer.
|
||||
* If this would decode into more bytes than would fit into
|
||||
* the output buffer, adjust the number of input bytes downwards.
|
||||
*/
|
||||
bufin = bufcoded;
|
||||
while(pr2six[*(bufin++)] <= 63);
|
||||
nprbytes = bufin - bufcoded - 1;
|
||||
nbytesdecoded = ((nprbytes+3)/4) * 3;
|
||||
if(nbytesdecoded > outbufsize) {
|
||||
nprbytes = (outbufsize*4)/3;
|
||||
}
|
||||
|
||||
bufin = bufcoded;
|
||||
|
||||
while (nprbytes > 0) {
|
||||
*(bufout++) =
|
||||
(unsigned char) (pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4);
|
||||
*(bufout++) =
|
||||
(unsigned char) (pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2);
|
||||
*(bufout++) =
|
||||
(unsigned char) (pr2six[bufin[2]] << 6 | pr2six[bufin[3]]);
|
||||
bufin += 4;
|
||||
nprbytes -= 4;
|
||||
}
|
||||
|
||||
if(nprbytes & 03) {
|
||||
if(pr2six[bufin[-2]] > 63)
|
||||
nbytesdecoded -= 2;
|
||||
else
|
||||
nbytesdecoded -= 1;
|
||||
}
|
||||
bufplain[nbytesdecoded] = '\0';
|
||||
}
|
48
support/Makefile
Executable file
48
support/Makefile
Executable file
@ -0,0 +1,48 @@
|
||||
# For gcc
|
||||
CC= gcc
|
||||
# For ANSI compilers
|
||||
#CC= cc
|
||||
|
||||
#For Optimization
|
||||
#CFLAGS= -O2
|
||||
#For debugging
|
||||
CFLAGS= -g
|
||||
|
||||
RM= /bin/rm -f
|
||||
#--- You shouldn't have to edit anything else. ---
|
||||
|
||||
.c.o:
|
||||
$(CC) -c $(CFLAGS) $<
|
||||
|
||||
all: htpasswd unescape
|
||||
|
||||
ibm: $(OBJS)
|
||||
make all CC=gcc
|
||||
|
||||
sun: $(OBJS)
|
||||
make all CC=gcc
|
||||
|
||||
hp: $(OBJS)
|
||||
make all CC=gcc
|
||||
|
||||
sgi: $(OBJS)
|
||||
make all CC=cc
|
||||
|
||||
decmips: $(OBJS)
|
||||
make all CC=cc
|
||||
|
||||
decaxp: $(OBJS)
|
||||
make all CC=cc
|
||||
|
||||
tar: htpasswd unescape
|
||||
$(RM) htpasswd unescape
|
||||
|
||||
htpasswd: htpasswd.c
|
||||
$(CC) $(CFLAGS) htpasswd.c -o htpasswd
|
||||
|
||||
unescape: unescape.c
|
||||
$(CC) $(CFLAGS) unescape.c -o unescape
|
||||
|
||||
clean:
|
||||
rm -f htpasswd
|
||||
|
1060
support/WebReport2.2
Normal file
1060
support/WebReport2.2
Normal file
File diff suppressed because it is too large
Load Diff
40
support/auth/pgp-dec
Executable file
40
support/auth/pgp-dec
Executable file
@ -0,0 +1,40 @@
|
||||
#!/bin/sh
|
||||
# This script currently doesn't recover from errors too well.
|
||||
|
||||
# Set this to the password to your secret key
|
||||
PGPPASS=mypassword
|
||||
# Set this to the location of your keyrings and config files
|
||||
PGPPATH=/X11/robm/httpd/support/auth/pgp-keys
|
||||
# Set this to your user name, the name on your secret key
|
||||
PGPUSER=webmaster@hoohoo.ncsa.uiuc.edu
|
||||
# Set this to the full path to the PGP binary on your system
|
||||
PGPBIN=/usr/local/bin/pgp
|
||||
|
||||
|
||||
# You shouldn't need to look at the rest of this mess
|
||||
|
||||
export PGPPASS
|
||||
export PGPPATH
|
||||
|
||||
# Since PGP doesn't seem to have any options for using a specific public key
|
||||
# file, we'll trick it.
|
||||
|
||||
mkdir /tmp/pgp.$$
|
||||
|
||||
cat > /tmp/pgp.$$/request
|
||||
|
||||
for i in secring.pgp config.txt language.txt randseed.bin; do
|
||||
cp $PGPPATH/$i /tmp/pgp.$$
|
||||
done
|
||||
|
||||
$PGPBIN -kx $* /tmp/pgp.$$/pubring.pgp $PGPPATH/pubring.pgp > /dev/null 2>&1
|
||||
|
||||
PGPPATH=/tmp/pgp.$$
|
||||
export PGPPATH
|
||||
|
||||
# Make sure PGP doesn't try to make temp files in /
|
||||
cd /tmp
|
||||
|
||||
$PGPBIN -f -u $PGPUSER < /tmp/pgp.$$/request 2> /dev/null
|
||||
|
||||
/bin/rm -rf /tmp/pgp.$$
|
20
support/auth/pgp-enc
Executable file
20
support/auth/pgp-enc
Executable file
@ -0,0 +1,20 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Set this to your user name, the name on your secret key
|
||||
PGPUSER=webmaster@hoohoo.ncsa.uiuc.edu
|
||||
# Set this to the key to your secret key
|
||||
PGPPASS=mypassword
|
||||
# Set this to wherever you keep your secret and public keys
|
||||
PGPPATH=/X11/robm/httpd/support/auth/pgp-keys
|
||||
# Set this to the location of the PGP binary on your system
|
||||
PGPBIN=/usr/local/bin/pgp
|
||||
|
||||
# You shouldn't need to edit anything under this line
|
||||
|
||||
export PGPPASS
|
||||
export PGPPATH
|
||||
|
||||
# Make sure PGP doesn't try to make temp files in /
|
||||
cd /tmp
|
||||
exec $PGPBIN -fe $* -u $PGPUSER 2>/dev/null
|
||||
|
22
support/auth/ripem-dec
Executable file
22
support/auth/ripem-dec
Executable file
@ -0,0 +1,22 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Set this to wherever you installed my hacked uudecode
|
||||
HACKED_UUDECODE=/X11/robm/httpd/htauth/uudecode
|
||||
# Set this to the directory in which you will keep your users' keys.
|
||||
# You should keep each user's public key in a file in this directory, and the
|
||||
# filename should be that user's entity name.
|
||||
KEYS=/X11/robm/httpd/htauth/ripem-keys
|
||||
# Set this to your server's entity name
|
||||
# Be sure you place your server's public key into this user's .plan so that
|
||||
# the clients can find it.
|
||||
PEMUSER=webmaster@hoohoo.ncsa.uiuc.edu
|
||||
# Set this to the location of your secret key
|
||||
SECKEY=/X11/robm/httpd/htauth/.key-private
|
||||
# Set this to the password to your secret key
|
||||
KEYPASS=mypassword
|
||||
# Set this to the location of your RIPEM executable
|
||||
RIPEMBIN=/usr/local/bin/ripem
|
||||
|
||||
# That should be all you need to edit.
|
||||
|
||||
sed -e 's/Originator-Key-Asymmetric/Originator-Key-Disabled/g' | $RIPEMBIN -d -u $PEMUSER -Y f -p $KEYS/$1 -s $SECKEY -k $KEYPASS | $HACKED_UUDECODE
|
25
support/auth/ripem-enc
Executable file
25
support/auth/ripem-enc
Executable file
@ -0,0 +1,25 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Set this to the location of uuencode on your system. If your system doesn't
|
||||
# come with uuencode, use the one I have provided.
|
||||
UUENCODE=/bin/uuencode
|
||||
# Set this to the directory you are keeping your users' public keys in.
|
||||
# You should keep each user's public key in a file in this directory, and the
|
||||
# filename should be that user's entity name.
|
||||
KEYS=/X11/robm/httpd/support/auth/ripem-keys
|
||||
# Set this to your server's entity name
|
||||
# Be sure you place your server's public key into this user's .plan so that
|
||||
# the clients can find it.
|
||||
PEMUSER=webmaster@hoohoo.ncsa.uiuc.edu
|
||||
# Set this to the location of your secret key
|
||||
SECKEY=/X11/robm/httpd/htauth/.key-private
|
||||
# Set this to the password to your secret key
|
||||
KEYPASS=mypassword
|
||||
# Set this to the location of your RIPEM executable
|
||||
RIPEMBIN=/usr/local/bin/ripem
|
||||
|
||||
$UUENCODE foo | $RIPEMBIN -e -h i -Y f -p $KEYS/"$*" -u $PEMUSER -s $SECKEY -k $KEYPASS -r $*
|
||||
|
||||
|
||||
|
||||
|
184
support/auth/uudecode.c
Normal file
184
support/auth/uudecode.c
Normal file
@ -0,0 +1,184 @@
|
||||
/*
|
||||
* Copyright (c) 1983 Regents of the University of California.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)uudecode.c 5.10 (Berkeley) 6/1/90";
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
* uudecode [file ...]
|
||||
*
|
||||
* create the specified file, decoding as you go.
|
||||
* used with uuencode.
|
||||
*/
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
#include <pwd.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
char *filename;
|
||||
|
||||
/* ARGSUSED */
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
extern int errno;
|
||||
int rval;
|
||||
#if 0
|
||||
if (*++argv) {
|
||||
rval = 0;
|
||||
do {
|
||||
if (!freopen(filename = *argv, "r", stdin)) {
|
||||
(void)fprintf(stderr, "uudecode: %s: %s\n",
|
||||
*argv, strerror(errno));
|
||||
rval = 1;
|
||||
continue;
|
||||
}
|
||||
rval |= decode();
|
||||
} while (*++argv);
|
||||
} else {
|
||||
filename = "stdin";
|
||||
rval = decode();
|
||||
}
|
||||
#else
|
||||
filename = "stdin";
|
||||
rval = decode();
|
||||
#endif
|
||||
exit(rval);
|
||||
}
|
||||
|
||||
decode()
|
||||
{
|
||||
extern int errno;
|
||||
struct passwd *pw;
|
||||
register int n;
|
||||
register char ch, *p;
|
||||
int mode, n1;
|
||||
char buf[MAXPATHLEN];
|
||||
|
||||
/* search for header line */
|
||||
do {
|
||||
if (!fgets(buf, sizeof(buf), stdin)) {
|
||||
(void)fprintf(stderr,
|
||||
"uudecode: %s: no \"begin\" line\n", filename);
|
||||
return(1);
|
||||
}
|
||||
} while (strncmp(buf, "begin ", 6));
|
||||
(void)sscanf(buf, "begin %o %s", &mode, buf);
|
||||
|
||||
/* handle ~user/file format */
|
||||
if (buf[0] == '~') {
|
||||
if (!(p = index(buf, '/'))) {
|
||||
(void)fprintf(stderr, "uudecode: %s: illegal ~user.\n",
|
||||
filename);
|
||||
return(1);
|
||||
}
|
||||
*p++ = NULL;
|
||||
if (!(pw = getpwnam(buf + 1))) {
|
||||
(void)fprintf(stderr, "uudecode: %s: no user %s.\n",
|
||||
filename, buf);
|
||||
return(1);
|
||||
}
|
||||
n = strlen(pw->pw_dir);
|
||||
n1 = strlen(p);
|
||||
if (n + n1 + 2 > MAXPATHLEN) {
|
||||
(void)fprintf(stderr, "uudecode: %s: path too long.\n",
|
||||
filename);
|
||||
return(1);
|
||||
}
|
||||
bcopy(p, buf + n + 1, n1 + 1);
|
||||
bcopy(pw->pw_dir, buf, n);
|
||||
buf[n] = '/';
|
||||
}
|
||||
#if 0
|
||||
/* create output file, set mode */
|
||||
if (!freopen(buf, "w", stdout) ||
|
||||
fchmod(fileno(stdout), mode&0666)) {
|
||||
(void)fprintf(stderr, "uudecode: %s: %s: %s\n", buf,
|
||||
filename, strerror(errno));
|
||||
return(1);
|
||||
}
|
||||
#endif
|
||||
/* for each input line */
|
||||
for (;;) {
|
||||
if (!fgets(p = buf, sizeof(buf), stdin)) {
|
||||
(void)fprintf(stderr, "uudecode: %s: short file.\n",
|
||||
filename);
|
||||
return(1);
|
||||
}
|
||||
#define DEC(c) (((c) - ' ') & 077) /* single character decode */
|
||||
/*
|
||||
* `n' is used to avoid writing out all the characters
|
||||
* at the end of the file.
|
||||
*/
|
||||
if ((n = DEC(*p)) <= 0)
|
||||
break;
|
||||
for (++p; n > 0; p += 4, n -= 3)
|
||||
if (n >= 3) {
|
||||
ch = DEC(p[0]) << 2 | DEC(p[1]) >> 4;
|
||||
putchar(ch);
|
||||
ch = DEC(p[1]) << 4 | DEC(p[2]) >> 2;
|
||||
putchar(ch);
|
||||
ch = DEC(p[2]) << 6 | DEC(p[3]);
|
||||
putchar(ch);
|
||||
}
|
||||
else {
|
||||
if (n >= 1) {
|
||||
ch = DEC(p[0]) << 2 | DEC(p[1]) >> 4;
|
||||
putchar(ch);
|
||||
}
|
||||
if (n >= 2) {
|
||||
ch = DEC(p[1]) << 4 | DEC(p[2]) >> 2;
|
||||
putchar(ch);
|
||||
}
|
||||
if (n >= 3) {
|
||||
ch = DEC(p[2]) << 6 | DEC(p[3]);
|
||||
putchar(ch);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!fgets(buf, sizeof(buf), stdin) || strcmp(buf, "end\n")) {
|
||||
(void)fprintf(stderr, "uudecode: %s: no \"end\" line.\n",
|
||||
filename);
|
||||
return(1);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
usage()
|
||||
{
|
||||
(void)fprintf(stderr, "usage: uudecode [file ...]\n");
|
||||
exit(1);
|
||||
}
|
146
support/auth/uuencode.c
Normal file
146
support/auth/uuencode.c
Normal file
@ -0,0 +1,146 @@
|
||||
/*
|
||||
* Copyright (c) 1983 Regents of the University of California.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)uuencode.c 5.9 (Berkeley) 6/1/90";
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
* uuencode [input] output
|
||||
*
|
||||
* Encode a file so it can be mailed to a remote system.
|
||||
*/
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdio.h>
|
||||
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
extern int optind;
|
||||
extern int errno;
|
||||
struct stat sb;
|
||||
int mode;
|
||||
#if 0
|
||||
char *strerror();
|
||||
#else
|
||||
#define strerror(s) "strerror disabled"
|
||||
#endif
|
||||
|
||||
while (getopt(argc, argv, "") != EOF)
|
||||
usage();
|
||||
argv += optind;
|
||||
argc -= optind;
|
||||
|
||||
switch(argc) {
|
||||
case 2: /* optional first argument is input file */
|
||||
if (!freopen(*argv, "r", stdin) || fstat(fileno(stdin), &sb)) {
|
||||
(void)fprintf(stderr, "uuencode: %s: %s.\n",
|
||||
*argv, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
#define RWX (S_IRWXU|S_IRWXG|S_IRWXO)
|
||||
mode = sb.st_mode & RWX;
|
||||
++argv;
|
||||
break;
|
||||
case 1:
|
||||
#define RW (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)
|
||||
mode = RW & ~umask(RW);
|
||||
break;
|
||||
case 0:
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
|
||||
(void)printf("begin %o %s\n", mode, *argv);
|
||||
encode();
|
||||
(void)printf("end\n");
|
||||
if (ferror(stdout)) {
|
||||
(void)fprintf(stderr, "uuencode: write error.\n");
|
||||
exit(1);
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* ENC is the basic 1 character encoding function to make a char printing */
|
||||
#define ENC(c) ((c) ? ((c) & 077) + ' ': '`')
|
||||
|
||||
/*
|
||||
* copy from in to out, encoding as you go along.
|
||||
*/
|
||||
encode()
|
||||
{
|
||||
register int ch, n;
|
||||
register char *p;
|
||||
char buf[80];
|
||||
|
||||
while (n = fread(buf, 1, 45, stdin)) {
|
||||
ch = ENC(n);
|
||||
if (putchar(ch) == EOF)
|
||||
break;
|
||||
for (p = buf; n > 0; n -= 3, p += 3) {
|
||||
ch = *p >> 2;
|
||||
ch = ENC(ch);
|
||||
if (putchar(ch) == EOF)
|
||||
break;
|
||||
ch = (*p << 4) & 060 | (p[1] >> 4) & 017;
|
||||
ch = ENC(ch);
|
||||
if (putchar(ch) == EOF)
|
||||
break;
|
||||
ch = (p[1] << 2) & 074 | (p[2] >> 6) & 03;
|
||||
ch = ENC(ch);
|
||||
if (putchar(ch) == EOF)
|
||||
break;
|
||||
ch = p[2] & 077;
|
||||
ch = ENC(ch);
|
||||
if (putchar(ch) == EOF)
|
||||
break;
|
||||
}
|
||||
if (putchar('\n') == EOF)
|
||||
break;
|
||||
}
|
||||
if (ferror(stdin)) {
|
||||
(void)fprintf(stderr, "uuencode: read error.\n");
|
||||
exit(1);
|
||||
}
|
||||
ch = ENC('\0');
|
||||
(void)putchar(ch);
|
||||
(void)putchar('\n');
|
||||
}
|
||||
|
||||
usage()
|
||||
{
|
||||
(void)fprintf(stderr,"usage: uuencode [infile] remotefile\n");
|
||||
exit(1);
|
||||
}
|
89
support/change-passwd.readme
Normal file
89
support/change-passwd.readme
Normal file
@ -0,0 +1,89 @@
|
||||
Subject: The form for change-passwd
|
||||
Newsgroups: comp.infosystems.www
|
||||
Organization: NCSA
|
||||
Summary:
|
||||
Keywords:
|
||||
|
||||
|
||||
I've gotten a number of requests for the form that corresponds to the
|
||||
change-passwd program that accidentally found itself in the NCSA httpd 1.0
|
||||
distribution.
|
||||
|
||||
A brief introduction: change-passwd is a way for remote users to change
|
||||
their password for user authentication on your system without going through
|
||||
you.
|
||||
|
||||
To use this form, you must set up user authentication on your system
|
||||
(there's a short tutorial at
|
||||
http://wintermute.ncsa.uiuc.edu:8080/auth-tutorial/tutorial.html). You will
|
||||
want to leave the form unprotected, and the script protected with ``require
|
||||
valid-user'' so that any valid user may log in.
|
||||
|
||||
Compile change-passwd with USER_FILE set to the location of the
|
||||
AuthUserFile, and WIZARD set to the user id you would like to use to perform
|
||||
administration (as the wizard, you can change other people's passwords, and
|
||||
add new users).
|
||||
|
||||
To install the script, place the executable somewhere on your system,
|
||||
preferably not in DocumentRoot and not in cgi-bin. Let's say you put it in
|
||||
/foo/bar/change-passwd. Add a line to srm.conf which says:
|
||||
|
||||
ScriptAlias /change-passwd /foo/bar/change-passwd
|
||||
|
||||
A common setup would be to have the following as /foo/bar/.htaccess:
|
||||
|
||||
AuthType Basic
|
||||
AuthName PasswordAdmin
|
||||
AuthUserFile /usr/local/httpd/conf/.htpasswd
|
||||
|
||||
<Limit POST>
|
||||
require valid-user
|
||||
</Limit>
|
||||
|
||||
|
||||
At this point, you should try the form. If the change-passwd script core
|
||||
dumps, or Mosaic does not prompt you for a user name or password after you
|
||||
click on the submit button, you have not set up user authenitcation properly.
|
||||
|
||||
|
||||
--
|
||||
Rob McCool, robm@ncsa.uiuc.edu
|
||||
Software Development Group, National Center for Supercomputing Applications
|
||||
It was working ten minutes ago, I swear...
|
||||
<A HREF="http://hoohoo.ncsa.uiuc.edu/~robm/sg.html">A must see.</A>
|
||||
|
||||
|
||||
Here's the form:
|
||||
|
||||
|
||||
<TITLE>Change your password</TITLE>
|
||||
<H1>Change your password</H1>
|
||||
|
||||
<FORM ACTION="/change-passwd" METHOD="POST">
|
||||
|
||||
This is an HTML form used to change your password for HTTP user
|
||||
authentication on this system. <P>
|
||||
<HR>
|
||||
To use this form, you must know your user name on this system, and you must
|
||||
know your current password. <P>
|
||||
|
||||
First, enter your user name below. If you are defined to be the wizard on
|
||||
this server, and wish to change or add a user, enter their name below. <P>
|
||||
|
||||
User name: <P><INPUT TYPE="text" NAME="user"><P>
|
||||
|
||||
Now, enter what you want to change your password to. <P>
|
||||
|
||||
New password: <P><INPUT
|
||||
TYPE="password" NAME="newpasswd1"><P> Re-type new password: <P><INPUT
|
||||
TYPE="password" NAME="newpasswd2"><P>
|
||||
|
||||
When you click on the Change password button below, you will be asked to
|
||||
authenticate yourself. If you are changing your own password, use your user
|
||||
id and your <EM>old</EM> password to log on. If you are the wizard on this
|
||||
server, use your own user id and password to log in.<P>
|
||||
|
||||
<INPUT TYPE="submit" VALUE="Change password"><P>
|
||||
<INPUT TYPE="reset" VALUE="Reset these fields"><P>
|
||||
</FORM>
|
||||
|
179
support/htpasswd.c
Normal file
179
support/htpasswd.c
Normal file
@ -0,0 +1,179 @@
|
||||
/*
|
||||
* htpasswd.c: simple program for manipulating password file for NCSA httpd
|
||||
*
|
||||
* Rob McCool
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/signal.h>
|
||||
|
||||
#define LF 10
|
||||
#define CR 13
|
||||
|
||||
#define MAX_STRING_LEN 256
|
||||
|
||||
char *tn;
|
||||
|
||||
char *strd(char *s) {
|
||||
char *d;
|
||||
|
||||
d=(char *)malloc(strlen(s) + 1);
|
||||
strcpy(d,s);
|
||||
return(d);
|
||||
}
|
||||
|
||||
void getword(char *word, char *line, char stop) {
|
||||
int x = 0,y;
|
||||
|
||||
for(x=0;((line[x]) && (line[x] != stop));x++)
|
||||
word[x] = line[x];
|
||||
|
||||
word[x] = '\0';
|
||||
if(line[x]) ++x;
|
||||
y=0;
|
||||
|
||||
while(line[y++] = line[x++]);
|
||||
}
|
||||
|
||||
int getline(char *s, int n, FILE *f) {
|
||||
register int i=0;
|
||||
|
||||
while(1) {
|
||||
s[i] = (char)fgetc(f);
|
||||
|
||||
if(s[i] == CR)
|
||||
s[i] = fgetc(f);
|
||||
|
||||
if((s[i] == 0x4) || (s[i] == LF) || (i == (n-1))) {
|
||||
s[i] = '\0';
|
||||
return (feof(f) ? 1 : 0);
|
||||
}
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
void putline(FILE *f,char *l) {
|
||||
int x;
|
||||
|
||||
for(x=0;l[x];x++) fputc(l[x],f);
|
||||
fputc('\n',f);
|
||||
}
|
||||
|
||||
|
||||
/* From local_passwd.c (C) Regents of Univ. of California blah blah */
|
||||
static unsigned char itoa64[] = /* 0 ... 63 => ascii - 64 */
|
||||
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||
|
||||
to64(s, v, n)
|
||||
register char *s;
|
||||
register long v;
|
||||
register int n;
|
||||
{
|
||||
while (--n >= 0) {
|
||||
*s++ = itoa64[v&0x3f];
|
||||
v >>= 6;
|
||||
}
|
||||
}
|
||||
|
||||
char *getpass(char *prompt); /* ugh */
|
||||
char *crypt(char *pw, char *salt); /* why aren't these prototyped in include */
|
||||
|
||||
void add_password(char *user, FILE *f) {
|
||||
char *pw, *cpw, salt[3];
|
||||
|
||||
pw = strd(getpass("New password:"));
|
||||
if(strcmp(pw,getpass("Re-type new password:"))) {
|
||||
fprintf(stderr,"They don't match, sorry.\n");
|
||||
if(tn)
|
||||
unlink(tn);
|
||||
exit(1);
|
||||
}
|
||||
(void)srand((int)time((time_t *)NULL));
|
||||
to64(&salt[0],rand(),2);
|
||||
cpw = crypt(pw,salt);
|
||||
free(pw);
|
||||
fprintf(f,"%s:%s\n",user,cpw);
|
||||
}
|
||||
|
||||
void usage() {
|
||||
fprintf(stderr,"Usage: htpasswd [-c] passwordfile username\n");
|
||||
fprintf(stderr,"The -c flag creates a new file.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void interrupted() {
|
||||
fprintf(stderr,"Interrupted.\n");
|
||||
if(tn) unlink(tn);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
main(int argc, char *argv[]) {
|
||||
FILE *tfp,*f;
|
||||
char user[MAX_STRING_LEN];
|
||||
char line[MAX_STRING_LEN];
|
||||
char l[MAX_STRING_LEN];
|
||||
char w[MAX_STRING_LEN];
|
||||
char command[MAX_STRING_LEN];
|
||||
int found;
|
||||
|
||||
tn = NULL;
|
||||
signal(SIGINT,(void (*)())interrupted);
|
||||
if(argc == 4) {
|
||||
if(strcmp(argv[1],"-c"))
|
||||
usage();
|
||||
if(!(tfp = fopen(argv[2],"w"))) {
|
||||
fprintf(stderr,"Could not open passwd file %s for writing.\n",
|
||||
argv[2]);
|
||||
perror("fopen");
|
||||
exit(1);
|
||||
}
|
||||
printf("Adding password for %s.\n",argv[3]);
|
||||
add_password(argv[3],tfp);
|
||||
fclose(tfp);
|
||||
exit(0);
|
||||
} else if(argc != 3) usage();
|
||||
|
||||
tn = tmpnam(NULL);
|
||||
if(!(tfp = fopen(tn,"w"))) {
|
||||
fprintf(stderr,"Could not open temp file.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if(!(f = fopen(argv[1],"r"))) {
|
||||
fprintf(stderr,
|
||||
"Could not open passwd file %s for reading.\n",argv[1]);
|
||||
fprintf(stderr,"Use -c option to create new one.\n");
|
||||
exit(1);
|
||||
}
|
||||
strcpy(user,argv[2]);
|
||||
|
||||
found = 0;
|
||||
while(!(getline(line,MAX_STRING_LEN,f))) {
|
||||
if(found || (line[0] == '#') || (!line[0])) {
|
||||
putline(tfp,line);
|
||||
continue;
|
||||
}
|
||||
strcpy(l,line);
|
||||
getword(w,l,':');
|
||||
if(strcmp(user,w)) {
|
||||
putline(tfp,line);
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
printf("Changing password for user %s\n",user);
|
||||
add_password(user,tfp);
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
if(!found) {
|
||||
printf("Adding user %s\n",user);
|
||||
add_password(user,tfp);
|
||||
}
|
||||
fclose(f);
|
||||
fclose(tfp);
|
||||
sprintf(command,"cp %s %s",tn,argv[1]);
|
||||
system(command);
|
||||
unlink(tn);
|
||||
}
|
BIN
support/unescape
Executable file
BIN
support/unescape
Executable file
Binary file not shown.
91
support/unescape.c
Normal file
91
support/unescape.c
Normal file
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Short program to unescape a URL string
|
||||
*
|
||||
* Rob McCool
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
void plustospace(char *str) {
|
||||
register int x;
|
||||
|
||||
for(x=0;str[x];x++) if(str[x] == '+') str[x] = ' ';
|
||||
}
|
||||
|
||||
char x2c(char *what) {
|
||||
register char digit;
|
||||
|
||||
digit = ((what[0] >= 'A') ? ((what[0] & 0xdf) - 'A')+10 : (what[0] - '0'));
|
||||
digit *= 16;
|
||||
digit += (what[1] >= 'A' ? ((what[1] & 0xdf) - 'A')+10 : (what[1] - '0'));
|
||||
return(digit);
|
||||
}
|
||||
|
||||
void unescape_url(char *url) {
|
||||
register int x,y;
|
||||
|
||||
for(x=0;url[x];x++)
|
||||
if(url[x] == '%')
|
||||
url[x+1] = x2c(&url[x+1]);
|
||||
|
||||
for(x=0,y=0;url[y];++x,++y) {
|
||||
if((url[x] = url[y]) == '%') {
|
||||
url[x] = url[y+1];
|
||||
y+=2;
|
||||
}
|
||||
}
|
||||
url[x] = '\0';
|
||||
}
|
||||
|
||||
int ind(char *s, char c) {
|
||||
register int x;
|
||||
|
||||
for(x=0;s[x];x++)
|
||||
if(s[x] == c) return x;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void escape_shell_cmd(char *cmd) {
|
||||
register int x,y,l;
|
||||
|
||||
l=strlen(cmd);
|
||||
for(x=0;cmd[x];x++) {
|
||||
if(ind("&;`'|*?-~<>^()[]{}$\\",cmd[x]) != -1){
|
||||
for(y=l+1;y>x;y--)
|
||||
cmd[y] = cmd[y-1];
|
||||
l++; /* length has been increased */
|
||||
cmd[x] = '\\';
|
||||
x++; /* skip the character */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void usage(char *name) {
|
||||
fprintf(stderr,"Usage:\n%s [-e] url\n",name);
|
||||
fprintf(stderr,
|
||||
"The -e switch automatically escapes shell characters like ^ and &\n");
|
||||
fprintf(stderr,"and url is the encoded url string\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
main(int argc, char *argv[]) {
|
||||
|
||||
if((argc != 2) && (argc != 3))
|
||||
usage(argv[0]);
|
||||
else {
|
||||
char *t;
|
||||
|
||||
t = (char *) malloc(sizeof(char) * (strlen(argv[argc-1])+1));
|
||||
strcpy(t,argv[argc-1]);
|
||||
plustospace(t);
|
||||
unescape_url(t);
|
||||
if(argc == 3) {
|
||||
if(strcmp(argv[1],"-e"))
|
||||
usage(argv[0]);
|
||||
escape_shell_cmd(t);
|
||||
}
|
||||
printf("%s",t);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user