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

Fpexe.c 소스 코드

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 실행 파일을 실행합니다.

다음 fpexe.c 소스 코드를 참고하십시오.

/* ====================================================================

*

* FrontPage SUID Stub Executable

*

* Copyright (c) 1995-2000 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 5.0.0.0

*/

/*

* User configurable items.  We will not run the server extensions with any

* UID/GID less than LOWEST_VALID_UID/LOWEST_VALID_GID.

*/

#if defined(RS6000)

#define _ALL_SOURCE

#endif

#if defined(RS6000) | defined(UWARE7)

int initgroups (char *, int);

#endif

#if defined(MIPS_LINUX)

#define _GNU_SOURCE

#endif

#if defined(LINUX) || defined(MIPS_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, etc. */

#endif

#endif

#if defined(UWARE7)

#define Vstat stat32

#define Vlstat lstat32

int lstat32 (const char *, struct stat *);

int stat32 (const char *, struct stat *);

#else

#define Vstat stat

#define Vlstat lstat

#endif 

#define CLEAN_PATH "PATH=/usr/bin:/bin"

static struct SaveEnvVars

{

const char* szVar;

int         iLen;

} gSafeEnvVars[] =

{

{ "AUTH_TYPE=", 0 },

{ "CONTENT_LENGTH=", 0 },

{ "CONTENT_TYPE=", 0 },

{ "DATE_GMT=", 0 },

{ "DATE_LOCAL=", 0 },

{ "DOCUMENT_NAME=", 0 },

{ "DOCUMENT_PATH_INFO=", 0 },

{ "DOCUMENT_ROOT=", 0 },

{ "DOCUMENT_URI=", 0 },

{ "FILEPATH_INFO=", 0 },

#ifdef ALPHAOSF

{ "FP_USE_FLOCK=", 0 },

#endif

{ "FRONTPAGE_TEST_INSTALL=", 0 },

{ "GATEWAY_INTERFACE=", 0 },

{ "HTTP_", 0 },

{ "LAST_MODIFIED=", 0 },

{ "PATH_INFO=", 0 },

{ "PATH_trANSLATED=", 0 },

{ "QUERY_StrING=", 0 },

{ "QUERY_StrING_UNESCAPED=", 0 },

{ "REDIRECT_QUERY_StrING=", 0 },

{ "REDIRECT_STATUS=", 0 },

{ "REDIRECT_URL=", 0 },

{ "REMOTE_ADDR=", 0 },

{ "REMOTE_HOST=", 0 },

{ "REMOTE_IDENT=", 0 },

{ "REMOTE_PORT=", 0 },

{ "REMOTE_USER=", 0 },

{ "REQUEST_METHOD=", 0 },

{ "SCRIPT_FILENAME=", 0 },

{ "SCRIPT_NAME=", 0 },

{ "SCRIPT_URI=", 0 },

{ "SCRIPT_URL=", 0 },

{ "SERVER_ADMIN=", 0 },

{ "SERVER_NAME=", 0 },

{ "SERVER_PORT=", 0 },

{ "SERVER_PROTOCOL=", 0 },

{ "SERVER_SOFTWARE=", 0 },

{ "TZ=", 0 },

{ "USER_NAME=", 0 },

{ 0, 0 }

};

/*

* End of user configurable items

*/

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include <string.h>

#include <sys/stat.h>

#include <fcntl.h>

#include <ctype.h>

#include <time.h>

#include <pwd.h>

#include <grp.h>

#if !defined(bsdi) && !defined(hpux) && !defined(sun) && !defined(linux) && !defined(SCO5) && !defined(UWARE7) && !defined(FREEBSD)

#include <sys/mode.h>

#endif

#if defined(sun) || defined(bsdi) || defined(sgi) || defined(SCO5) || defined(UWARE7) || defined(FREEBSD) || defined(linux)

extern const char ** environ;

#endif

extern int errno;

#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) */

#define FPKEYDIR "/usr/local/frontpage/version5.0/apache-fp"

#define KEYFILE  "/usr/local/frontpage/version5.0/apache-fp/suidkey.%d"

#define FPDIR    "/usr/local/frontpage/version5.0/exes"

/* Legal modules */

#define SHTML    "/_vti_bin/shtml.exe"

#define FPCOUNT  "/_vti_bin/fpcount.exe"

#define AUTHOR   "/_vti_bin/_vti_aut/author.exe" 

#define ADMIN    "/_vti_bin/_vti_adm/admin.exe" 

#define ADMINCGI "/_vti_bin/_vti_adm/fpadmcgi.exe" 

/*

* Something is not quite right - give up

*/

void die(const char *msg)

{

char timebuf[26];

time_t t = time(0);

strcpy(timebuf, ctime(&t));

timebuf[24] = '\0';

fprintf(stderr, "[%s] %s\n", timebuf, msg);

printf("Content-Type: text/html\n\n<HTML>*-*-* :-| :^| :-/ :-( 8-( *-*-*\n<ul>\n<li>status=1\n<li
>osstatus=0\n<li>msg=FrontPage security violation.\n<li>osmsg=\n</ul>\n");

exit(0);

}

/*

* Remove any variable that is not known to be a standard CGI or OS

* environment variable.  Also, sanitizes the PATH.

*/

static void CleanEnvironment() 

{

const char** pp;

const char** ppi;

struct SaveEnvVars* pOkEnv;

for (ppi = pp = environ;  *pp;  pp++)

{

/*

* Inefficient linear lookup; could be improved with binary search.

*/

for (pOkEnv = gSafeEnvVars;  pOkEnv->szVar;  pOkEnv++)

{

int iLen = pOkEnv->iLen;

if (!iLen)

pOkEnv->iLen = iLen = strlen(pOkEnv->szVar);

if (strncmp(pOkEnv->szVar, *pp, iLen) == 0)

break;

}

if (!strncmp(*pp, "PATH=", 5))

*ppi++ = CLEAN_PATH;

else if (pOkEnv->szVar)

*ppi++ = *pp;

}

*ppi = 0;

}

int main(int argc, char **argv)

{

struct passwd* pw = 0;

const char* szFpUserName;

const char* szFpExe = getenv("FPEXE");

const char* szFpUid = getenv("FPUID");

const char* szFpGid = getenv("FPGID");

const char* szFpFd  = getenv("FPFD");

const char* szFpDir = getenv("FPEXEDIR");

char* pEnd;

char* pDir;

uid_t iFpUid;

uid_t iFpGid;

uid_t iBinUid;

int iFpFd;

int iKeyFd;

int iCount;

char szKeyFile[MAXPATHLEN];

char szWork[MAXPATHLEN];

char inpKey[KEYLEN];

char refKey[KEYLEN];

struct stat fs;

/*

* Fall back to default location for the real FrontPage executables.

* if FPEXEDIR is not set in the environment.

*/

if (!szFpDir)

szFpDir = FPDIR;

/*

* Assure that this program was actually SUID'd to root

*/

if (geteuid())

/*

* User recovery:  Make sure fpexe is setuid to root

*/

die("FrontPage SUID Error: not running as root");

/*

* Assure that the user the web server runs as is a valid user

*/

if (!getpwuid(getuid()))

/*

* User recovery:  Make sure that the web server user is in /etc/passwd

*/

die("FrontPage SUID Error: invalid uid");

/*

* Assure that we have the proper arguments (passed in the environment)

*/

if (!szFpExe || !szFpUid || !szFpGid || !szFpFd || !szFpDir)

/*

* User recovery:  Make sure fpexe is run from patched Apache server

*/

die("FrontPage SUID Error: invalid environment arguments");

/*

* Validate the arguments

*/

if (strcmp(szFpExe, SHTML) != 0   &&

strcmp(szFpExe, FPCOUNT) != 0 &&

strcmp(szFpExe, AUTHOR) != 0  &&

strcmp(szFpExe, ADMIN) != 0  &&

strcmp(szFpExe, ADMINCGI) != 0)

/*

* User recovery:  Make sure fpexe is only invoked to run FrontPage

* server extension programs.

*/

die("FrontPage SUID Error: target program violation");

if (strlen(szFpExe) + strlen(szFpDir) + 1 > MAXPATHLEN)

die("FrontPage SUID Error: path too long");

strcpy(szWork, szFpDir);

strcat(szWork, szFpExe);

iFpUid = strtol(szFpUid, &pEnd, 10);

if (!pEnd || *pEnd)

iFpUid = 0;

if (iFpUid < LOWEST_VALID_UID || !(pw = getpwuid(iFpUid)))

/*

* User recovery:  Make sure FrontPage user ids are above minimum

*/

die("FrontPage SUID Error: invalid target uid");

szFpUserName = strdup(pw->pw_name);

iFpGid = strtol(szFpGid, &pEnd, 10);

if (!pEnd || *pEnd)

iFpGid = 0;

if (iFpGid < LOWEST_VALID_GID || !getgrgid(iFpGid))

/*

* User recovery:  Make sure FrontPage group ids are above minimum

*/

die("FrontPage SUID Error: invalid target gid");

iFpFd = strtol(szFpFd, &pEnd, 10);

if (!pEnd || *pEnd)

iFpFd = -1;

if (iFpFd < 0)

/*

* User recovery:  Make sure fpexe is run from patched Apache server

*/

die("FrontPage SUID Error: invalid key file descriptor");

/*

* Read the key from our server.  And, while we're still root and have

* access, read the key from the master key file.  Verify the key matches.

*/

if (Vlstat(FPKEYDIR, &fs) == -1 ||

(fs.st_mode & (S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)) || fs.st_uid ||

!(S_ISDIR(fs.st_mode)))

/*

* User recovery is: set directory to be owned by by root with

* permissions rwx--x--x.

*/

die("FrontPage SUID Error: key file directory is insecure");

#if defined(sun) && !defined(__SVR4)

sprintf(szKeyFile, KEYFILE, (int)getpgrp(0));

#else

sprintf(szKeyFile, KEYFILE, (int)getpgrp());

#endif

if (Vstat(szKeyFile, &fs) == -1 ||

(fs.st_mode & (S_IRWXG | S_IRWXO)) || fs.st_uid)

/*

* User recovery is:  Make sure the key file is properly protected

* (owned by root, permissions r**------), restart patched Apache

* server.

*/

die("FrontPage SUID Error: key file security violation");

iKeyFd = open(szKeyFile, O_RDONLY);

if (iKeyFd < 0)

/*

* User recovery is:  Make sure fpexe is run from patched Apache

* server, restart the patched Apache server.

*/

die("FrontPage SUID Error: could not open key file" );

iCount = read(iKeyFd, refKey, sizeof(refKey));

close(iKeyFd);

if (iCount != sizeof(refKey))

/*

* User recovery is:  Make sure fpexe is run from patched Apache

* server, restart the patched Apache server.

*/

die("FrontPage SUID Error: could not read valid key from key file");

iCount = read(iFpFd, inpKey, sizeof(inpKey));

close(iFpFd);

if (iCount != sizeof(inpKey))

/*

* User recovery is:  Make sure fpexe is run from patched Apache server

*/

die("FrontPage SUID Error: could not read valid input key");

if (memcmp(inpKey, refKey, sizeof(refKey)) != 0)

/*

* User recovery is:  Make sure fpexe is run from patched Apache server

*/

die("FrontPage SUID Error: key security violation");

/*

* Change user and group IDs to be the indicated user

*/

if (setgid(iFpGid) == -1 || initgroups(szFpUserName, iFpGid) == -1)

/*

* User recovery:  Make sure user is properly registered in 

* /etc/passwd and /etc/group.

*/

die("FrontPage SUID Error: setgid() failed");

if (setuid(iFpUid) == -1)

/*

* User recovery:  Make sure user is properly registered in

* /etc/passwd.

*/

die("FrontPage SUID Error: setuid() failed");

/*

* Validate the target directory.

*/

iBinUid = 0;

if (pw = getpwnam("bin"))

iBinUid = pw->pw_uid;

pDir = strrchr(szWork, '/');

*pDir = 0;

if (Vlstat(szWork, &fs) == -1 || (fs.st_mode & (S_IWGRP | S_IWOTH)) ||

(fs.st_uid != iBinUid && fs.st_uid != 0) ||

!(S_ISDIR(fs.st_mode)))

/*

* User recovery is: make sure FrontPage exe programs are available,

* set directory to be owned by bin or root and have permissions

* rwx*-x*-x.

*/

die("FrontPage SUID Error: target directory not found or insecure");

*pDir = '/';

/*

* Validate the target program

*/

if (Vstat(szWork, &fs) == -1 || ((fs.st_mode & (S_IWGRP | S_IWOTH)) ||

(fs.st_mode & (S_ISUID | S_ISGID)) ||

(fs.st_uid != iBinUid && fs.st_uid != 0)))

/*

* User recovery is: make sure FrontPage exe programs are available,

* set programs to be owned by bin or root and have permissions

* rwx*-x*-x.

*/

die("FrontPage SUID Error: target program not found or insecure");

*pDir = '/';

/*

* Make sure the environment contains no unsafe values.

*/

CleanEnvironment();

/*

* Run the specified program.

*/

argv[0] = szWork;

umask(022);

execv(argv[0], argv);

/*

* We should never get here.  Exit with error.

*/

return (1);

}

 


 

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