|
--- ./src/include/httpd.h.orig Mon Sep 21 15:12:17 1998
+++ ./src/include/httpd.h Fri Sep 25 16:43:40 1998
@@ -719,7 +719,12 @@
char *unparsed_uri; /* the uri without any parsing performed */
char *uri; /* the path portion of the URI */
- char *filename;
+ char *execfilename; /* physical filename to exec */
+ char *filename; /* logical filename to exec -- always the same
+ * except for FrontPage CGI programs where we
+ * will execute the CGI program in
+ * /usr/local/frontpage....
+ */
char *path_info;
char *args; /* QUERY_ARGS, if any */
struct stat finfo; /* ST_MODE set to zero if no such file */
--- ./src/main/http_request.c.orig Mon Aug 10 20:09:46 1998
+++ ./src/main/http_request.c Fri Sep 25 16:43:43 1998
@@ -187,6 +187,8 @@
return OK;
}
+ if (r->execfilename) path = r->execfilename;
+
#ifdef WIN32
/* If the path is x:/, then convert it to x:/., coz that's what stat needs to work properly */
if(strlen(path) == 3 && path[1] == ':') {
@@ -459,6 +461,7 @@
res = ap_parse_htaccess(&htaccess_conf, r, overrides_here,
ap_pstrdup(r->pool, test_dirname),
sconf->access_name);
+ if (r->execfilename) r->filename = r->execfilename;
if (res)
return res;
--- ./src/main/util.c.orig Thu Sep 17 11:56:08 1998
+++ ./src/main/util.c Fri Sep 25 16:43:44 1998
@@ -582,7 +582,7 @@
char *res;
for (x = 0; (*line)[x]; x++) {
- if (ap_isspace((*line)[x])) {
+ if (ap_isspace((*line)[x]) && ((*line)[x] & 0x80)==0) {
pos = x;
break;
}
--- ./mod_frontpage.c.orig Fri Sep 25 16:43:44 1998
+++ ./mod_frontpage.c Fri Sep 25 16:43:45 1998
@@ -0,0 +1,777 @@
+/* ====================================================================
+ *
+ * Apache FrontPage module.
+ *
+ * Copyright (c) 1996-1998 Microsoft Corporation -- All Rights Reserved.
+ *
+ * NO WARRANTIES. Microsoft expressly disclaims any warranty for this code and
+ * information. This code and information and any related documentation is
+ * provided "as is" without warranty of any kind, either express or implied,
+ * including, without limitation, the implied warranties or merchantability,
+ * fitness for a particular purpose, or noninfringement. The entire risk
+ * arising out of use or performance of this code and information remains with
+ * you.
+ *
+ * NO LIABILITY FOR DAMAGES. In no event shall Microsoft or its suppliers be
+ * liable for any damages whatsoever (including, without limitation, damages
+ * for loss of business profits, business interruption, loss of business
+ * information, or any other pecuniary loss) arising out of the use of or
+ * inability to use this Microsoft product, even if Microsoft has been advised
+ * of the possibility of such damages. Because some states/jurisdictions do not
+ * allow the exclusion or limitation of liability for consequential or
+ * incidental damages, the above limitation may not apply to you.
+ *
+ * Version 4.0.4.3
+ *
+ */
+
+
+/*
+ * User configurable items. We will not run the server extensions with any
+ * UID/GID less than LOWEST_VALID_UID/LOWEST_VALID_GID.
+ */
+
+#if defined(LINUX)
+#define LOWEST_VALID_UID 15
+#else
+#define LOWEST_VALID_UID 11
+#endif
+
+#if defined(HPUX) || defined(IRIX) || defined(SUNOS4)
+#define LOWEST_VALID_GID 20
+#else
+#if defined(SCO)
+#define LOWEST_VALID_GID 24
+#else
+#define LOWEST_VALID_GID 21 /* Solaris, AIX, Alpha, Bsdi, *BSD, etc. */
+#endif
+#endif
+
+/*
+ * End of user configurable items
+ */
+
+
+#include "httpd.h"
+#include "http_config.h"
+#include "http_conf_globals.h"
+
+#include <stdio.h>
+#include <sys/time.h>
+
+#if defined(UWARE7) || UW==700
+#define Vstat stat32
+#define Vlstat lstat32
+#else
+#define Vstat stat
+#define Vlstat lstat
+#endif
+
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef MAXPATHLEN
+#define MAXPATHLEN 1024
+#endif
+#if (MAXPATHLEN < 1024)
+#undef MAXPATHLEN
+#define MAXPATHLEN 1024
+#endif
+
+#define KEYLEN 128 /* Should be a multiple of sizeof(int) */
+
+static char gszKeyVal[KEYLEN+1]; /* SUID key value used by this module */
+static int gfdKeyPipe[2]; /* Pipe to fpexe stub CGI */
+static int gbKeyPipeActive; /* Pipe to fpexe stub CGI is active */
+static int gbEnabled; /* TRUE when SUID scheme is enabled */
+static int giInitializeCount; /* FrontPageInit called previously */
+
+static const char* FP =
+ "/usr/local/frontpage/version4.0";
+static const char* FPKEYDIR =
+ "/usr/local/frontpage/version4.0/apache-fp";
+static const char* KEYFILEXOR =
+ "/usr/local/frontpage/version4.0/apache-fp/suidkey";
+static const char* KEYFILE =
+ "/usr/local/frontpage/version4.0/apache-fp/suidkey.%d";
+static const char* FPSTUBDIR =
+ "/usr/local/frontpage/version4.0/apache-fp/_vti_bin";
+static const char* FPSTUB =
+ "/usr/local/frontpage/version4.0/apache-fp/_vti_bin/fpexe";
+static const char* SHTML =
+ "/_vti_bin/shtml.exe";
+static const char* SHTML2 =
+ "/_vti_bin/shtml.dll";
+static const char* VTI_BIN =
+ "/_vti_bin";
+static const char* FPCOUNT =
+ "/_vti_bin/fpcount.exe";
+static const char* AUTHOR =
+ "/_vti_bin/_vti_aut/author.exe" ;
+static const char* ADMIN =
+ "/_vti_bin/_vti_adm/admin.exe" ;
+
+
+/*
+ * Print a descriptive error in the httpd's error_log. The format string
+ * should be length limited so that it is no longer than 1800 bytes.
+ */
+static void LogFrontPageError(
+ server_rec* s,
+ const char* szFormat,
+ const char* szFile,
+ const char* szRoutine,
+ int bIsDisabled)
+{
+ char szBuf[MAXPATHLEN * 2];
+ sprintf(szBuf, szFormat, szFile);
+ strcat(szBuf, " in ");
+ strcat(szBuf, szRoutine);
+ strcat(szBuf, ".");
+ if (bIsDisabled)
+ {
+ strcat(szBuf, " Until this problem is fixed, the FrontPage security patch is disabled and the FrontPage extensions may not work correctly.");
+ gbEnabled = FALSE; /* Make double sure we're not enabled */
+ }
+ ap_log_error_old(szBuf, s);
+}
+
+
+/*
+ * Clean up stale keyfiles. Failure to clean up stale keyfiles does not
+ * stop the FrontPage SUID scheme.
+ */
+static void FrontPageCleanup(server_rec *s)
+{
+ DIR *d;
+ struct DIR_TYPE *dstruct;
+ int myPid = getpid();
+
+ if (!(d = opendir(FPKEYDIR)))
+ {
+ /*
+ * This should be a rare occurrence, because we're running as root and
+ * should have access to the directory. Stale key files can be
+ * exploited. User recovery: Check that the directory exists and is
+ * properly protected (owned by root, permissions rwx--x--x), and that
+ * there are no stale key files in it (suidkey.*, where * is a
+ * non-existant PID).
+ */
+ LogFrontPageError(s, "Can't clean stale key files from directory \"%-.1024s\"",
+ FPKEYDIR, "FrontPageCleanup()", FALSE);
+ return;
+ }
+
+ while ((dstruct = readdir(d)))
+ {
+ if (strncmp("suidkey.", dstruct->d_name, 8) == 0)
+ {
+ /*
+ * Make sure the key file contains a pid number - otherwise
+ * it is harmless and you can ignore it.
+ */
+ char* pEnd = 0;
+ int pid = strtol(dstruct->d_name + 8, &pEnd, 10);
+ if (!pEnd || *pEnd)
+ continue;
+
+ /*
+ * Make sure there isn't some other server using this key file.
+ * If the process group isn't alive, then the file is stale
+ * and we want to remove it.
+ */
+ if (pid == myPid || kill(pid, 0) == -1)
+ {
+ char szBuf[MAXPATHLEN];
+ sprintf(szBuf, "%-.500s/%-.500s", FPKEYDIR, dstruct->d_name);
+ if (unlink(szBuf) == -1)
+ {
+ /*
+ * This should be a rare occurrence, because we're running
+ * as root and should always have permission to delete the
+ * file. Stale key files can be exploited. User recovery:
+ * delete the offending file.
+ */
+ LogFrontPageError(s, "Can't unlink stale key file \"%-.1024s\"",
+ szBuf, "FrontPageCleanup()", FALSE);
+ }
+ }
+ }
+ }
+
+ closedir(d);
+}
+
+/*
+ * Checks that all the permissions are currently correct for the FrontPage
+ * fpexe SUID stub to run correctly. If not, it logs an error and aborts
+ * initialization, effectively disabling the FrontPage SUID scheme.
+ * It checks both the file permissions (owned by root and not writable to
+ * group, other) and that the directory is not writable.
+ */
+static int FrontPageCheckup(server_rec *s)
+{
+ struct stat fs;
+
+ if (geteuid() != 0)
+ {
+ /*
+ * We need to be root to have the security scheme work correctly.
+ * User recovery: run the server as root.
+ */
+ LogFrontPageError(s, "Not running as root",
+ 0, "FrontPageCheckup()", TRUE);
+ return (FALSE);
+ }
+
+ if (Vlstat(FPKEYDIR, &fs) == -1 || /* We can't stat the key dir */
+ fs.st_uid || /* key dir not owned by root */
+ (fs.st_mode & (S_IRGRP | S_IROTH)) || /* key dir is readable */
+ (fs.st_mode & (S_IWGRP | S_IWOTH)) || /* key dir is writable */
+ !(fs.st_mode & (S_IXGRP | S_IXOTH)) || /* key dir is not executable */
+ !(S_ISDIR(fs.st_mode)))
+ {
+ /*
+ * User recovery: set directory to be owned by by root with permissions
+ * rwx--x--x. Note you need the execute bit for group and other so
+ * that non-root programs can run apache-fp/_vti_bin/fpexe (even though
+ * non-root cannot list the directory).
+ */
+ LogFrontPageError(s, "Incorrect permissions on key directory \"%-.1024s\"",
+ FPKEYDIR, "FrontPageCheckup()", TRUE);
+ return (FALSE);
+ }
+
+ if (Vlstat(FPSTUBDIR, &fs) == -1 || /* We can't stat the stub dir */
+ fs.st_uid || /* stub dir not owned by root */
+ (fs.st_mode & (S_IWGRP | S_IWOTH)) || /* stub dir is writable */
+ (!S_ISDIR(fs.st_mode)))
+ {
+ /*
+ * User recovery: set directory to be owned by by root with permissions
+ * r*x*-x*-x.
+ */
+ LogFrontPageError(s, "Incorrect permissions on stub directory \"%-.1024s\"",
+ FPSTUBDIR, "FrontPageCheckup()", TRUE);
+ return (FALSE);
+ }
+
+ if (Vstat(FPSTUB, &fs) == -1 || /* We can't stat the stub */
+ fs.st_uid || /* stub not owned by root */
+ !(fs.st_mode & S_ISUID) || /* stub is not set-uid */
+ (fs.st_mode & S_ISGID) || /* stub is set-gid */
+ (fs.st_mode & (S_IWGRP | S_IWOTH)) || /* stub is writable */
+ !(fs.st_mode & (S_IXGRP | S_IXOTH))) /* stub is not executable */
+ {
+ /*
+ * User recovery: set stub to be owned by by root with permissions
+ * r*s*-x*-x.
+ */
+ LogFrontPageError(s, "Incorrect permissions on stub \"%-.1024s\"",
+ FPSTUB, "FrontPageCheckup()", TRUE);
+ return (FALSE);
+ }
+
+ return (TRUE);
+}
+
+
+/*
+ * Module-initializer: Create the suidkey file and local value.
+ * Everything needs to be just right, or we don't create the key file, and
+ * therefore, the fpexe SUID stub refuses to run.
+ */
+static void FrontPageInit(server_rec *s, pool *p)
+{
+ int fdPipe[2];
+ pid_t pid;
+ FILE *f;
+ struct stat fs;
+ int fd;
+ char szKeyFile[MAXPATHLEN];
+ int iRandom[5];
+ char* szRandom = (char*)iRandom;
+ struct timeval tp;
+ struct timezone tz;
+
+ (void)p; /* p is unused */
+
+ /*
+ * Standalone servers call initialization twice: once in main() and again
+ * in standalone_main(). The fully initializing on the the first call is a
+ * waste of time, and a race condition can leave a stale suidkey.pgrpid
+ * file around.
+ */
+ if (ap_standalone && !giInitializeCount++)
+ return;
+
+ /*
+ * Disable the suid scheme until everything falls perfectly into place.
+ */
+ gbEnabled = FALSE;
+ gbKeyPipeActive = FALSE;
+
+ /*
+ * Clean up old key files before we start
+ */
+ FrontPageCleanup(s);
+ if (!FrontPageCheckup(s))
+ return;
+
+ if (pipe(fdPipe) == -1)
+ {
+ /*
+ * This should be a rare occurrence. User recovery: check to see why
+ * the system cannot allocate a pipe (is the file table full from
+ * run-away processes?), and fix the problem or reboot, then try again.
+ */
+ LogFrontPageError(s, "pipe() failed", 0, "FrontPageInit()", TRUE);
+ return;
+ }
+
+ gettimeofday(&tp, &tz);
+ iRandom[0] = tp.tv_sec;
+ iRandom[1] = tp.tv_usec | tp.tv_usec << 20;
+
+ pid = fork();
+ if (pid == -1)
+ {
+ /*
+ * This should be a rare occurrence. User recovery: check to see why
+ * the system cannot allocate a process (is the process table full from
+ * run-away processes?), and fix the problem or reboot, then try again.
+ */
+ LogFrontPageError(s, "fork() failed", 0, "FrontPageInit()", TRUE);
+ return;
+ }
+
+ if (pid)
+ {
+ /*
+ * I am the parent process. Try to read a random number from the
+ * child process.
+ */
+
+ unsigned int npos = (unsigned int)-1;
+ unsigned int v1 = npos, v2 = npos, v3 = npos, v4 = npos;
+ int stat;
+ int iCount;
+
+ close(fdPipe[1]);
+ if (waitpid(pid, &stat, 0) == -1 ||
+ (!WIFEXITED(stat) || WIFEXITED(stat) && WEXITSTATUS(stat)))
+ {
+ /*
+ * This should be a rare occurrence. User recovery: Make sure you
+ * have a /bin/sh, or change the shell location in the execl
+ * command below. Try the commands defined in RAND_CMD in a
+ * /bin/sh session to make sure they work properly. Rebuild this
+ * module and your httpd with the proper commands.
+ */
+ LogFrontPageError(s, "Random number generator exited abnormally", 0,
+ "FrontPageInit()", TRUE);
+ return;
+ }
+
+ iCount = read(fdPipe[0], gszKeyVal, KEYLEN);
+ close(fdPipe[0]);
+ if (iCount < 0)
+ {
+ /*
+ * This should be a rare occurrence. See the above comment under
+ * the waitpid failure condition for user recovery steps.
+ */
+ LogFrontPageError(s, "Could not read random numbers", 0,
+ "FrontPageInit()", TRUE);
+ return;
+ }
+ gszKeyVal[iCount] = 0;
+
+ sscanf(gszKeyVal, "%u %u %u %u", &v2, &v1, &v4, &v3);
+ if (v1 == npos || v2 == npos || v3 == npos || v4 == npos)
+ {
+ /*
+ * This should be a rare occurrence. See the above comment under
+ * the waitpid failure condition for user recovery steps.
+ */
+ LogFrontPageError(s, "Could not scan random numbers", 0,
+ "FrontPageInit()", TRUE);
+ return;
+ }
+
+ iRandom[2] = (v1 << 16) + v2 + (v4 << 12) + v3;
+ }
+ else
+ {
+ /*
+ * I am the child process. Create a random number which shouldn't
+ * be easily duplicated.
+ */
+
+ if (dup2(fdPipe[1], 1) == -1)
+ exit(1); /* Parent picks up the error */
+
+ close(fdPipe[0]);
+
+#ifdef LINUX
+#define RAND_CMD "/bin/ps laxww | /usr/bin/sum ; /bin/ps laxww | /usr/bin/sum"
+#else
+#if defined ( bsdi ) || ( defined ( BSD ) && ( BSD >= 199103 ))
+#define RAND_CMD "/bin/ps laxww | /usr/bin/cksum -o 1 ; /bin/ps laxww | /usr/bin/cksum -o 1"
+#else
+#define RAND_CMD "/bin/ps -ea | /bin/sum ; /bin/ps -ea | /bin/sum"
+#endif
+#endif
+ execl("/bin/sh", "/bin/sh", "-c", RAND_CMD, NULL);
+ exit(1);
+ }
+
+ gettimeofday(&tp, &tz);
+ iRandom[3] = tp.tv_sec;
+ iRandom[4] = tp.tv_usec | tp.tv_usec << 20;
+
+ /*
+ * See if there is an 'suidkey' file to merge into our key.
+ */
+ if (Vstat(KEYFILEXOR, &fs) == -1)
+ {
+ /*
+ * It's a security violation if the key file is not present. User
+ * recovery: Make sure the key file is present and properly protected
+ * (owned by root, permissions r**------).
+ */
+ LogFrontPageError(s, "The key file \"%-.1024s\" does not exist",
+ KEYFILEXOR, "FrontPageInit()", TRUE);
+ return;
+ }
+ else
+ {
+ int i, iCount;
+ char szBuf[KEYLEN];
+
+ if ((fs.st_mode & (S_IRWXG | S_IRWXO)) || fs.st_uid)
+ {
+ /*
+ * It's a security violation if the key file is not owned by root,
+ * and is not protected from all other group. User recovery: Make
+ * sure the key file is properly protected (owned by root,
+ * permissions r**------).
+ */
+ LogFrontPageError(s, "The key file \"%-.1024s\" must not be accessible except by root",
+ KEYFILEXOR, "FrontPageInit()", TRUE);
+ return;
+ }
+
+ if ((fd = open(KEYFILEXOR, O_RDONLY)) == -1)
+ {
+ /*
+ * This should be a rare occurrence. User recovery: Make sure
+ * the key file exists, is properly owned and protected, and is
+ * readable.
+ */
+ LogFrontPageError(s, "Cannot open key file \"%-.1024s\"",
+ KEYFILEXOR, "FrontPageInit()", TRUE);
+ return;
+ }
+
+ iCount = read(fd, szBuf, KEYLEN);
+ if (iCount < 8)
+ {
+ /*
+ * The keyfile must be at least 8 bytes. If it longer than 128
+ * bytes, only the first 128 bytes will be used. Any character
+ * value from 0-255 is fine. User recovery: Make sure the key file
+ * is at least 8 bytes long.
+ */
+ LogFrontPageError(s, "Key file \"%-.1024s\" is unreadable or is too short",
+ KEYFILEXOR, "FrontPageInit()", TRUE);
+ close(fd);
+ return;
+ }
+
+ /*
+ * Now generate the effective key we'll be using by XORing your key
+ * with 5 "random" 32-bit integers. The primary security of this
+ * scheme is your key; properly setting it and changing it often keeps
+ * the FrontPage SUID scheme secure. All this work above to generate 5
+ * random 32-bit integers is soley to make your key somewhat harder to
+ * crack (assuming the key files are properly protected). If you don't
+ * like the algorithm used to generate the 5 random integers, feel free
+ * to substitute as appropriate (check out SGI's Lavarand (TM) at
+ * lavarand.sgi.com).
+ */
+ for (i = 0; i < KEYLEN; i++)
+ gszKeyVal[i] = szBuf[i % iCount] ^ szRandom[i % sizeof(iRandom)];
+
+ /*
+ * Thanks to A.Mayrhofer@Austria.EU.net 980130
+ */
+ close(fd);
+ }
+
+#if defined(SUNOS4)
+ pid = getpgrp(0);
+#else
+ pid = getpgrp();
+#endif
+ sprintf(szKeyFile, KEYFILE, (int)pid);
+
+ fd = creat(szKeyFile, 0600);
+ if (fd < 0)
+ {
+ /*
+ * This should be a rare occurrence, because we're running as root and
+ * should always have permission to create the file. User recovery:
+ * check that you are not out of disk space, or that the file is not
+ * NFS-mounted on a share where you do not have permissions.
+ */
+ LogFrontPageError(s, "Could not create key file \"%-.1024s\"",
+ szKeyFile, "FrontPageInit()", TRUE);
+ return;
+ }
+
+ if (write(fd, gszKeyVal, 128) != 128)
+ {
+ /*
+ * This should be a rare occurrence. User recovery: check that you are
+ * not out of disk space.
+ */
+ close(fd);
+ unlink(szKeyFile);
+ LogFrontPageError(s, "Could not write to key file \"%-.1024s\"",
+ szKeyFile, "FrontPageInit()", TRUE);
+ return;
+ }
+
+ close(fd);
+
+ /*
+ * Everything looks OK enough to start the suid scheme.
+ */
+ gbEnabled = TRUE;
+
+ /*
+ * Thanks to Scot Hetzel (hetzels@westbend.net)
+ */
+ ap_add_version_component("FrontPage/4.0.4.3");
+}
+
+
+/*
+ * Look for a valid FrontPage extensions scenario and fake a scriptalias if
+ * appropriate. If there are any problems, we silently decline.
+ */
+static int FrontPageAlias(
+ request_rec* r,
+ char* szCgi,
+ const char* szFpexe)
+{
+ int iLen;
+ struct stat webroot;
+ struct stat vti_pvt;
+ struct stat stub;
+ char szBuf[MAXPATHLEN];
+ char chSave;
+
+ /*
+ * Decline if we cannot run the stub, or it is writable.
+ */
+ if (Vstat(FPSTUB, &stub) == -1 || !(stub.st_mode & S_IXOTH) ||
+ stub.st_mode & (S_IWGRP | S_IWOTH))
+ {
+ /*
+ * The stub used to be correctly permissioned; what happened? User
+ * recovery: set stub to be owned by by root with permissions
+ * r*s*-x*-x.
+ */
+ LogFrontPageError(r->server, "Incorrect permissions on stub \"%-.1024s\"",
+ FPSTUB, "FrontPageAlias()", FALSE);
+ return DECLINED;
+ }
+
+ chSave = szCgi[1];
+ szCgi[1] = '\0';
+ ap_translate_name(r);
+ szCgi[1] = chSave;
+
+ /*
+ * Zap trailing slash that confuses some OSes.
+ */
+ iLen = strlen(r->filename);
+ r->filename[--iLen] = 0;
+
+ if (iLen > MAXPATHLEN - 10)
+ return DECLINED;
+ sprintf(szBuf, "%s/_vti_pvt", r->filename);
+
+ /*
+ * Decline if webroot and webroot/_vti_pvt don't have the same
+ * user and group or uid < LOWEST_VALID_UID or gid < LOWEST_VALID_GID.
+ */
+ if (Vstat(szBuf, &vti_pvt) == -1 ||
+ vti_pvt.st_uid < LOWEST_VALID_UID ||
+ vti_pvt.st_gid < LOWEST_VALID_GID ||
+ Vstat(r->filename, &webroot) != 0 ||
+ webroot.st_uid != vti_pvt.st_uid ||
+ webroot.st_gid != vti_pvt.st_gid)
+ {
+ /*
+ * The webroot and webroot/_vti_pvt don't match. User recovery: fix
+ * the owners and groups of both directories to match, and have both a
+ * uid and gid in the allowable range.
+ */
+ LogFrontPageError(r->server, "Incorrect permissions on webroot \"%-.0124s\" and webroot's _vti_pvt directory",
+ szBuf, "FrontPageAlias()", FALSE);
+ return DECLINED;
+ }
+
+ /*
+ * If the pipe is active, it was because we previously executed a CGI.
+ * That CGI must have finished by now (otherwise we wouldn't be processing
+ * this next request), so we can and should close the pipe to avoid a
+ * resource leak.
+ */
+ if (gbKeyPipeActive)
+ {
+ close(gfdKeyPipe[0]);
+ gbKeyPipeActive = FALSE;
+ }
+
+ /*
+ * If we can't get a pipe, that's really bad. We'll log an error, and
+ * decline. This should be a rare occurrence. User recovery: check to see
+ * why the system cannot allocate a pipe (is the file table full from
+ * run-away processes?), and fix the problem or reboot, then try again.
+ */
+ if (pipe(gfdKeyPipe) == -1)
+ {
+ LogFrontPageError(r->server, "pipe() failed", 0,
+ "FrontPageAlias()", FALSE);
+ return DECLINED;
+ }
+
+ /*
+ * Note: ap_pstrdup allocates memory, but it checks for out of memory
+ * conditions - it will not return if out of memory.
+ */
+ r->handler = ap_pstrdup(r->pool, "cgi-script");
+ ap_table_set(r->notes, "alias-forced-type", r->handler);
+
+ ap_table_set(r->subprocess_env, "FPEXE", ap_pstrdup(r->pool, szFpexe));
+ sprintf(szBuf, "%d", webroot.st_uid );
+ ap_table_set(r->subprocess_env, "FPUID", ap_pstrdup(r->pool, szBuf));
+ sprintf(szBuf, "%d", webroot.st_gid );
+ ap_table_set(r->subprocess_env, "FPGID", ap_pstrdup(r->pool, szBuf));
+ sprintf(szBuf, "%d", gfdKeyPipe[0]);
+ ap_table_set(r->subprocess_env, "FPFD", ap_pstrdup(r->pool, szBuf));
+
+ r->execfilename = ap_pstrcat(r->pool, FPSTUB, szCgi+strlen(szFpexe), NULL);
+ r->filename = ap_pstrcat(r->pool, r->filename, szCgi, NULL);
+
+ if (write(gfdKeyPipe[1], gszKeyVal, 128) != 128)
+ {
+ /*
+ * If we can't write to the pipe, that's really bad. We'll log an
+ * error, and decline. This should be a rare occurrence. User
+ * recovery: check to see why the system cannot write to the pipe (is
+ * the system being choked with too much load?), and fix the problem or
+ * reboot, then try again.
+ */
+ LogFrontPageError(r->server, "Write to pipe failed", 0,
+ "FrontPageAlias()", FALSE);
+ close (gfdKeyPipe[0]);
+ close (gfdKeyPipe[1]);
+ return DECLINED;
+ }
+ close(gfdKeyPipe[1]);
+
+ gbKeyPipeActive = TRUE;
+ return OK;
+}
+
+
+/*
+ * This routine looks for shtml.exe, fpcount.exe, author.exe and admin.exe
+ * in a URI, and if found we call FrontPageAlias() to check for a valid
+ * FrontPage scenario.
+ *
+ * The return value is OK or DECLINED.
+ */
+static int FrontPageXlate(
+ request_rec *r)
+{
+ char *szVti;
+ char *szCgi;
+
+ /*
+ * Decline if we're improperly initialized.
+ */
+ if (!gbEnabled)
+ return DECLINED;
+
+ /*
+ * Check once for anything with _vti_bin. This is much faster than
+ * checking all four paths, because anything without this is definitely
+ * not a FrontPage scenario.
+ */
+ if (!(szVti = strstr(r->uri, VTI_BIN)))
+ return DECLINED;
+
+ /*
+ * Test for FrontPage server extenders:
+ * .../_vti_bin/shtml.exe...
+ * .../_vti_bin/shtml.dll...
+ * .../_vti_bin/fpcount.exe...
+ * .../_vti_bin/_vti_aut/author.exe...
+ * .../_vti_bin/_vti_adm/admin.exe...
+ */
+ if (szCgi = strstr(szVti, AUTHOR ))
+ return FrontPageAlias(r, szCgi, AUTHOR);
+ /*
+ * Convert inadvertent shtml.dll to shtml.exe
+ * Thanks for the idea to Scot Hetzel (hetzels@westbend.net)
+ */
+ if (szCgi = strstr(szVti, SHTML2 ))
+ {
+ int iShtmlExtPos = strlen(SHTML2) - 3;
+ strncpy(szCgi + iShtmlExtPos, SHTML + iShtmlExtPos, 3);
+ }
+ if (szCgi = strstr(szVti, SHTML ))
+ return FrontPageAlias(r, szCgi, SHTML);
+ if (szCgi = strstr(szVti, ADMIN ))
+ return FrontPageAlias(r, szCgi, ADMIN);
+ if (szCgi = strstr(szVti, FPCOUNT))
+ return FrontPageAlias(r, szCgi, FPCOUNT);
+
+ return DECLINED;
+}
+
+
+/*
+ * Declare ourselves so the configuration routines can find us.
+ */
+module frontpage_module =
+{
+ STANDARD_MODULE_STUFF,
+ FrontPageInit, /* initializer */
+ NULL, /* per-directory config creater */
+ NULL, /* dir config merger - default is to override */
+ NULL, /* server config creator */
+ NULL, /* server config merger */
+ NULL, /* command table */
+ NULL, /* [6] list of handlers */
+ FrontPageXlate, /* [1] filename-to-URI translation */
+ NULL, /* [4] check/validate HTTP user_id */
+ NULL, /* [5] check HTTP user_id is valid *here* */
+ NULL, /* [3] check access by host address, etc. */
+ NULL, /* [6] MIME type checker/setter */
+ NULL, /* [7] fixups */
+ NULL, /* [9] logger */
+ NULL, /* [2] header parser */
+};
|