Microsoft 主页 Microsoft 主页

附录


FrontPage Apache 模块的源代码

当在 Apache 站点服务器上使用用于 UNIX 系统的 FrontPage 2000 服务器扩展时,修补 Apache 站点服务器是推荐的做法。Apache 站点服务器的补丁由两项修改所组成:

  • FrontPage Apache 模块 mod_frontpage.c ,它会截取来自 FrontPage 客户端程序的远程要求、确认安全性以及将要求重新导向至 fpexe.c suid root 根程序。
  • fpexe.c 程序会从 FrontPage Apache 模块接受创作要求、执行额外的安全性确认、将用户 ID 更改为被创作的 Web 站点的所有者以及运行适当的 FrontPage 服务器扩展 CGI 可执行程序。

 

此处列出 FrontPage Apache 模块的源代码以供查看。此源代码也包含在用于 UNIX 的 FrontPage 2000 服务器扩展下载包中,可用于和 Apache 站点服务器的自定义 build 一同编译。

--- ./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 */
+};

后退  回到页首

最近更新时间 1999 年 6 月
©1999 Microsoft Corporation。保留所有权利。使用规定。 声明