NCSA HTTPd 1.1

This commit is contained in:
I am not me 2013-03-13 02:25:16 -04:00
parent 4e19b9e4a0
commit 9572b626b7
64 changed files with 8722 additions and 0 deletions

27
cgi-bin/archie Executable file
View 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
View 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
View 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
View 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
View 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

Binary file not shown.

29
cgi-bin/nph-test-cgi Executable file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

40
support/auth/pgp-dec Executable file
View 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
View 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
View 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
View 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
View 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
View 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);
}

View 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
View 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

Binary file not shown.

91
support/unescape.c Normal file
View 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);
}
}