Tryag File Manager
Home
-
Turbo Force
Current Path :
/
usr
/
local
/
frontpage
/
version5.0
/
apache2
/
Upload File :
New :
File
Dir
//usr/local/frontpage/version5.0/apache2/mod_frontpage.c
/* ==================================================================== * * Apache FrontPage module, for Apache 2.0 * * Copyright (c) 1996-2003 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_request.h" #include "mod_frontpage.h" #include "mod_fpcgid.h" #include <stdio.h> #include <sys/time.h> #include <sys/stat.h> #include <fcntl.h> #include <dirent.h> #include <errno.h> #include <unistd.h> #include "apr_compat.h" #include "apr_strings.h" #include "http_log.h" #define DIR_TYPE dirent #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 gbEnabled; /* TRUE when SUID scheme is enabled */ 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* GLOBALADMINDIR = "/usr/local/frontpage/version5.0/admin-exes"; static const char* IMAGESDIR = "/exes/_vti_bin/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 VTI_AUT_PASSWD[] = { "/_vti_bin/_vti_aut/passwd.htm" }; static const char VTI_AUT_PASSWDALIAS[]= { "/_vti_bin/_vti_aut/passwa.htm" }; static const char VTI_BIN_PASSWD[] = { "/_vti_bin/passwd.htm" }; static const char VTI_BIN_PASSWDALIAS[]= { "/_vti_bin/passwb.htm" }; static const char VTI_ADM_HELP[] = { "/_vti_bin/_vti_adm/help/" }; static const char VTI_AUT[] = { "/_vti_bin/_vti_aut/" }; static const char VTI_ADM[] = { "/_vti_bin/_vti_adm/" }; static const char HELPDIR[] = "/help" ; static const char* ADMINDIR = "/admin" ; const int iVTI_ADM_LEN = sizeof(VTI_ADM); const int iVTI_AUT_LEN = sizeof(VTI_AUT); const int iVTI_BIN_LEN = sizeof(VTI_BIN); const int iVTI_AUT_PASSWD_LEN = sizeof(VTI_AUT_PASSWD); const int iVTI_BIN_PASSWD_LEN = sizeof(VTI_BIN_PASSWD); const int iVTI_ADM_HELP_LEN = sizeof(VTI_ADM_HELP); static int frontpage_init(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *main_server); /* * 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, int err) { 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(APLOG_MARK, APLOG_ERR, err, s, szBuf); } /* * 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, errno); 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, errno); } } } } 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, 0); 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, 0); 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, 0); 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, 0); return (FALSE); } return (TRUE); } /* * FrontPage-specific 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. */ int frontpage_validate_init(apr_pool_t *p, server_rec *s) { int fdPipe[2]; pid_t pid; struct stat fs; int fd; char szKeyFile[MAXPATHLEN]; int iRandom[5]; char* szRandom = (char*)iRandom; struct timeval tp; struct timezone tz; /* * Disable the suid scheme until everything falls perfectly into place. */ gbEnabled = FALSE; /* * Clean up old key files before we start */ FrontPageCleanup(s); if (!FrontPageCheckup(s)) return DECLINED; 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, errno); return DECLINED; } 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, errno); return DECLINED; } 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; int err; close(fdPipe[1]); if (waitpid(pid, &stat, 0) == -1 || (!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, 0); return DECLINED; } iCount = read(fdPipe[0], gszKeyVal, KEYLEN); err = errno; /* Save it now because close may change it */ 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, err); return DECLINED; } 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, 0); return DECLINED; } 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) { LogFrontPageError(s, "FrontPage daemon startup pipe failed %-.1024s", strerror(errno), "FrontPageInit()", TRUE, errno); exit(1); } 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 )) || defined(FREEBSD) #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, errno); return DECLINED; } 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, 0); return DECLINED; } 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, errno); return DECLINED; } 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, (iCount < 0 ? errno : 0)); close(fd); return DECLINED; } /* * 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, errno); return DECLINED; } if (write(fd, gszKeyVal, 128) != 128) { /* * This should be a rare occurrence. User recovery: check that you are * not out of disk space. */ LogFrontPageError(s, "Could not write to key file \"%-.1024s\"", szKeyFile, "FrontPageInit()", TRUE, errno); close(fd); unlink(szKeyFile); return DECLINED; } close(fd); /* * Everything looks OK enough to start the suid scheme. */ gbEnabled = TRUE; /* * Thanks to Scot Hetzel (hetzels@westbend.net) */ ap_add_version_component(p, "FrontPage/5.0.2.2635"); return OK; } /* * The caller is responsible for insuring that the pipe_info * structure is properly initialized, specifically the * isActive flag. */ int frontpage_makePipe(server_rec* main_server, request_rec* r, char** env, fpPipeInfo* pipe_info) { int i; /* * 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 (pipe_info->isActive) { close(pipe_info->fdKeyPipe[0]); pipe_info->isActive = 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(pipe_info->fdKeyPipe) == -1) { LogFrontPageError(r->server, "pipe() failed", 0, "frontpage_makePipe()", FALSE, errno); return TRUE; } if (write(pipe_info->fdKeyPipe[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, "frontpage_makePipe()", FALSE, errno); close(pipe_info->fdKeyPipe[0]); close(pipe_info->fdKeyPipe[1]); return TRUE; } i=0; while(env[i] != NULL) { if (strcmp(env[i],"FPFD=placeholder") == 0) { /* Allocate new space. A 64bit uint is 20 bytes decimal, so * 26 to allow for the FPFD= and null is fine. We don't * need to release the previous pointer, because the pool * gets cleared on each iteration in fpcgid_server. */ env[i] = apr_palloc(r->pool, 28*sizeof(char)); snprintf(env[i], 28, "FPFD=%d", pipe_info->fdKeyPipe[0]); } i++; } pipe_info->isActive = TRUE; return FALSE; } void frontpage_closePipeWrite(fpPipeInfo* pipe_info) { close(pipe_info->fdKeyPipe[1]); } int frontpage_checkForStub(char* filename) { /* If this request is for anything but the FPSTUB we decline it */ return (strcmp(filename, FPSTUB) == 0) ? 0 : DECLINED; } static int frontpage_init(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *main_server) { return fpcgid_init(p, plog, ptemp, main_server); } 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_run_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) != 0 || 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, 0); return DECLINED; } if ((!strcmp(r->filename,GLOBALADMINDIR)) ? vti_pvt.st_uid > 0 : (vti_pvt.st_uid < LOWEST_VALID_UID || vti_pvt.st_gid < LOWEST_VALID_GID)) { /* * 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, 0); 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, 0); return DECLINED; } if (OK != FrontPageCheckWebRoot(r, szCgi, &webroot)) 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)); ap_table_set(r->notes,"FPexecfilename", ap_pstrcat(r->pool, FPSTUB, NULL)); r->filename = ap_pstrcat(r->pool, r->filename, szCgi, NULL); 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; char* execFilename; 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); /* see the note in FrontPageAlias */ execFilename = ap_pstrcat(r->pool, FP, szDir, szBuf, szBase, NULL); ap_table_set(r->notes,"FPexecfilename", execFilename); /* We need to set the finfo field now. Otherwise Apache will set the path_info field automatically but incorrectly, which will result in the wrong file being checked. */ apr_stat(&r->finfo, execFilename, APR_FINFO_MIN, r->pool); 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, VTI_ADM_HELP))) return FrontPageStaticAlias(r, szVti, HELPDIR, FrontPageGetLcid(szVti + iVTI_ADM_HELP_LEN - 1)); if ((szCgi = strstr(szVti, VTI_AUT_PASSWD)) && (int)(szCgi-szVti)+iVTI_AUT_PASSWD_LEN == strlen(szVti)+1) { strncpy(szCgi, VTI_AUT_PASSWDALIAS, +iVTI_AUT_PASSWD_LEN); return FrontPageStaticAlias(r, szVti, ADMINDIR, FrontPageGetLcid(szVti + iVTI_AUT_LEN - 1)); } if ((szCgi = strstr(szVti, VTI_BIN_PASSWD)) && (int)(szCgi-szVti)+iVTI_BIN_PASSWD_LEN == strlen(szVti)+1) { strncpy(szCgi, VTI_BIN_PASSWDALIAS, +iVTI_BIN_PASSWD_LEN); return FrontPageStaticAlias(r, szVti, ADMINDIR, FrontPageGetLcid(szVti + iVTI_BIN_LEN - 1)); } if ((szCgi = strrchr(szVti,'.')) && !strcmp(szCgi, ".gif")) return FrontPageStaticAlias(r, szVti, IMAGESDIR, 0); if ((szCgi = strrchr(szVti,'.')) && !strcmp(szCgi, ".css") && (iVTI_ADM_LEN < strlen(szVti))) return FrontPageStaticAlias(r, szVti, ADMINDIR, FrontPageGetLcid(szVti + iVTI_ADM_LEN - 1)); return DECLINED; } /* This function handles setting the filename member of the request_rec * to be execfilename (at the appropriate time), so we don't have to patch * apache anymore. */ static int FrontPageFixup(request_rec *r) { if (!ap_table_get(r->notes, "FPexecfilename")) { FrontPageXlate(r); } if (ap_table_get(r->notes,"FPexecfilename")) { r->filename = (char*) ap_table_get(r->notes,"FPexecfilename"); apr_stat(&r->finfo, r->filename, APR_FINFO_MIN, r->pool); } return OK; } void frontpage_register_hook(apr_pool_t *p) { static const char* const aszPre[] = { "mod_include.c", NULL }; ap_log_perror(APLOG_MARK, APLOG_DEBUG, 0, p, "FrontPage register_hook"); ap_hook_post_config(frontpage_init, aszPre, NULL, APR_HOOK_MIDDLE); ap_hook_handler(fpcgid_handler, NULL, NULL, APR_HOOK_FIRST); ap_hook_translate_name(FrontPageXlate, NULL, NULL, APR_HOOK_FIRST); ap_hook_fixups(FrontPageFixup, NULL, NULL, APR_HOOK_LAST); }