TechNet 홈 >  SharePoint Team Services 관리자 안내서 >  부록

FrontPage Apache 모듈 소스 코드

Apache 웹 서버와 함께 UNIX용 Microsoft® FrontPage Server Extensions 2002를 사용할 경우에는 Apache 웹 서버 패치를 설치하는 것이 좋습니다. Apache 웹 서버 패치에서는 다음 두 가지가 수정되었습니다.

  • FrontPage Apache 모듈, mod_frontpage.c - FrontPage® 클라이언트 프로그램에서 보낸 원격 요청을 중간에서 가로채고 보안을 확인한 다음 fpexe.c suid 루트 스텁 프로그램으로 요청을 리디렉션합니다.
  • fpexe.c 프로그램 - FrontPage Apache 모듈에서 보낸 제작 요청을 받아 들인 다음 추가 보안 확인을 수행하고 사용자 ID를 제작할 웹 사이트의 소유자로 변경한 다음 적절한 FrontPage Server ExtensionsCGI 실행 파일을 실행합니다.

다음 FrontPage Apache 모듈 소스 코드를 참고하십시오.

--- ./mod_frontpage.c.orig   Wed Dec 31 16:00:00 1969

+++ ./mod_frontpage.c   Mon Nov 20 11:38:29 2000

@@ -0,0 +1,852 @@

+/* ====================================================================

+ *

+ * Apache FrontPage module.

+ *

+ * Copyright (c) 1996-2001 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.

+ */

+

+

+/*

+ * 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>

+

+#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/version5.0";

+static const char* FPKEYDIR   =

+          "/usr/local/frontpage/version5.0/apache-fp";

+static const char* KEYFILEXOR =

+          "/usr/local/frontpage/version5.0/apache-fp/suidkey";

+static const char* KEYFILE    =

+          "/usr/local/frontpage/version5.0/apache-fp/suidkey.%d";

+static const char* FPSTUBDIR  =

+          "/usr/local/frontpage/version5.0/apache-fp/_vti_bin";

+static const char* FPSTUB     =

+          "/usr/local/frontpage/version5.0/apache-fp/_vti_bin/fpexe";

+static const char* IMAGESDIR  =

+          "/exes/_vti_bin/_vti_adm/images" ;

+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" ;

+static const char* ADMINCGI   =

+          "/_vti_bin/_vti_adm/fpadmcgi.exe" ;

+static const char* PASSWD     =

+          "/passwd.htm" ;

+static const char* VTIHELP    =

+          "/_vti_bin/_vti_adm/help/" ;

+static const char* VTI_ADM    =

+          "/_vti_bin/_vti_adm/" ;

+static const char* HELPDIR    =

+          "/help" ;

+static const char* ADMINDIR   =

+          "/admin" ;

+

+const int iVTI_LEN = sizeof(VTI_ADM)/sizeof(VTI_ADM[0]) - 1;

+const int iHELP    = sizeof(VTIHELP)/sizeof(VTIHELP[0]) - 1;

+

+

+/*

+ * 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 (lstat(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 (lstat(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 (stat(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 (stat(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/5.0.2.2314");

+}

+

+static int FrontPageCheckWebRoot(

+    request_rec* r,

+    char* szCgi,

+    struct stat *pWebroot)

+{

+    int iLen;

+    struct stat vti_pvt;

+    char szBuf[MAXPATHLEN];

+    char chSave;

+

+    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 (stat(szBuf, &vti_pvt) == -1       ||

+        vti_pvt.st_uid < LOWEST_VALID_UID ||

+        vti_pvt.st_gid < LOWEST_VALID_GID ||

+        stat(r->filename, pWebroot) != 0  ||

+        pWebroot->st_uid != vti_pvt.st_uid  || 

+        pWebroot->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;

+    }

+    

+    return OK;

+}

+

+

+/*

+ * 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)

+{

+    struct stat webroot;

+    struct stat stub;

+    char szBuf[MAXPATHLEN];

+

+    /*

+     * Decline if we cannot run the stub, or it is writable.

+     */

+    if (stat(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;

+    }

+

+    if (OK != FrontPageCheckWebRoot(r, szCgi, &webroot))

+        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;

+}

+

+static int FrontPageGetLcid(const char* szDir)

+{

+    int iLcid;

+    iLcid = atoi(szDir);

+    if (iLcid < 1 || iLcid > 9999)

+        iLcid = 1033;

+    return iLcid;

+}

+

+/*

+ * Look for a valid FrontPage extensions scenario and fake an alias if

+ * appropriate.  If there are any problems, we silently decline.

+ */

+static int FrontPageStaticAlias(

+    request_rec* r,

+    char* szCgi,

+    const char* szDir,

+    int iLcid)

+{

+    struct stat webroot;

+    char szBuf[8];

+    char* szBase;

+

+    if (OK != FrontPageCheckWebRoot(r, szCgi, &webroot))

+        return DECLINED;

+

+    szBase = strrchr(r->uri, '/');

+    if (!szBase)

+        return DECLINED;

+

+    szBuf[0] = 0;

+    if (iLcid > 0 && iLcid < 10000)

+        sprintf(szBuf, "/%04d", iLcid);

+

+    r->filename = ap_pstrcat(r->pool, FP, szDir, szBuf, szBase, NULL);

+

+    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 our 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...

+     * .../_vti_bin/_vti_adm/owsadm.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, ADMINCGI  ))

+        return FrontPageAlias(r, szCgi, ADMINCGI);

+    if (szCgi = strstr(szVti, FPCOUNT))

+        return FrontPageAlias(r, szCgi, FPCOUNT);

+

+    if (szCgi = strstr(szVti, VTIHELP))

+        return FrontPageStaticAlias(r, szVti, HELPDIR,

+                                    FrontPageGetLcid(szVti + iHELP));

+    

+    if ((szCgi = strrchr(szVti,'/')) && !strcmp(szCgi, PASSWD) &&

+        (iVTI_LEN < strlen(szVti)))

+        return FrontPageStaticAlias(r, szVti, ADMINDIR,

+                                    FrontPageGetLcid(szVti + iVTI_LEN));

+    if ((szCgi = strrchr(szVti,'.')) && !strcmp(szCgi, ".gif"))

+        return FrontPageStaticAlias(r, szVti, IMAGESDIR, 0);

+    if ((szCgi = strrchr(szVti,'.')) && !strcmp(szCgi, ".css") &&

+        (iVTI_LEN < strlen(szVti)))

+        return FrontPageStaticAlias(r, szVti, ADMINDIR,

+                                    FrontPageGetLcid(szVti + iVTI_LEN));

+    

+    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] URI-to-filename 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 */

+};

--- ./src/include/httpd.h.orig   Wed Feb 23 15:01:33 2000

+++ ./src/include/httpd.h   Wed Mar 22 20:42:45 2000

@@ -792,7 +792,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   Tue Jan 11 06:13:41 2000

+++ ./src/main/http_request.c   Wed Mar 22 20:42:46 2000

@@ -187,6 +187,8 @@

   return OK;

}

+    if (r->execfilename) path = r->execfilename;

+

#ifdef HAVE_DRIVE_LETTERS

/* If the directory is x:\, then we don't want to strip

* the trailing slash since x: is not a valid directory.

@@ -511,6 +513,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;

@@ -521,6 +524,7 @@

      r->per_dir_config = per_dir_defaults;

       }

}

+   if (r->execfilename) r->filename = r->execfilename;

}

/*

--- ./src/main/util.c.orig   Wed Feb 23 04:44:57 2000

+++ ./src/main/util.c   Wed Mar 22 20:42:46 2000

@@ -669,7 +669,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;

   }

 


 

최종 수정일 : 2001년 11월 5일