randy 97/02/10 06:05:35
Modified: src CHANGES
Log:
Update changes for suexec fixes.
Revision Changes Path
1.155 +5 -0 apache/src/CHANGES
Index: CHANGES
===================================================================
RCS file: /export/home/cvs/apache/src/CHANGES,v
retrieving revision 1.154
retrieving revision 1.155
diff -C3 -r1.154 -r1.155
*** CHANGES 1997/02/10 12:07:20 1.154
--- CHANGES 1997/02/10 14:03:48 1.155
***************
*** 1,5 ****
--- 1,10 ----
Changes with Apache 1.2b7
+ *) Several fixes for suexec wrapper. [Randy Terbush]
+ - Make wrapper work for files on NFS filesystem.
+ - Fix portability problem of MAXPATHLEN.
+ - Fix array overrun problem in clean_env().
+
*) Removed extraneous blank line is description of mod_status chars.
[Kurt Kohler]
Modified: support suexec.c
Log:
*) Several fixes for suexec wrapper. [Randy Terbush]
- Make wrapper work for files on NFS filesystem.
- Fix portability problem of MAXPATHLEN.
- Fix array overrun problem in clean_env().
Reviewed by: Michael Zucchi ([EMAIL PROTECTED])
Revision Changes Path
1.15 +76 -66 apache/support/suexec.c
Index: suexec.c
===================================================================
RCS file: /export/home/cvs/apache/support/suexec.c,v
retrieving revision 1.14
retrieving revision 1.15
diff -C3 -r1.14 -r1.15
*** suexec.c 1997/02/06 21:46:08 1.14
--- suexec.c 1997/02/10 14:05:34 1.15
***************
*** 81,87 ****
#include <time.h>
#include <sys/stat.h>
! #define CLEAN_ENV_BUF 256
extern char **environ;
static FILE *log;
--- 81,95 ----
#include <time.h>
#include <sys/stat.h>
! #if defined(PATH_MAX)
! #define AP_MAXPATH PATH_MAX
! #elif defined(MAXPATHLEN)
! #define AP_MAXPATH MAXPATHLEN
! #else
! #define AP_MAXPATH 256
! #endif
!
! #define AP_ENVBUF 256
extern char **environ;
static FILE *log;
***************
*** 173,184 ****
int idx;
! if ((cleanenv = (char **)malloc(CLEAN_ENV_BUF * (sizeof(char *)))) ==
NULL) {
log_err("failed to malloc env mem\n");
exit(120);
}
! for (ep = environ; *ep; ep++) {
if (!strncmp(*ep, "HTTP_", 5)) {
cleanenv[cidx] = *ep;
cidx++;
--- 181,192 ----
int idx;
! if ((cleanenv = (char **)calloc(AP_ENVBUF, AP_ENVBUF * (sizeof(char
*)))) == NULL) {
log_err("failed to malloc env mem\n");
exit(120);
}
! for (ep = environ; *ep && cidx < AP_ENVBUF; ep++) {
if (!strncmp(*ep, "HTTP_", 5)) {
cleanenv[cidx] = *ep;
cidx++;
***************
*** 210,217 ****
char *target_gname; /* target group name */
char *prog; /* name of this program */
char *cmd; /* command to be executed */
! char cwd[MAXPATHLEN]; /* current working directory */
! char dwd[MAXPATHLEN]; /* docroot working directory */
struct passwd *pw; /* password entry holder */
struct group *gr; /* group entry holder */
struct stat dir_info; /* directory info holder */
--- 218,225 ----
char *target_gname; /* target group name */
char *prog; /* name of this program */
char *cmd; /* command to be executed */
! char cwd[AP_MAXPATH]; /* current working directory */
! char dwd[AP_MAXPATH]; /* docroot working directory */
struct passwd *pw; /* password entry holder */
struct group *gr; /* group entry holder */
struct stat dir_info; /* directory info holder */
***************
*** 289,294 ****
--- 297,352 ----
}
/*
+ * Log the transaction here to be sure we have an open log
+ * before we setuid().
+ */
+ log_err("uid: (%s/%s) gid: (%s/%s) %s\n",
+ target_uname, pw->pw_name,
+ target_gname, gr->gr_name,
+ cmd);
+
+ /*
+ * Error out if attempt is made to execute as root or as
+ * a UID less than UID_MIN. Tsk tsk.
+ */
+ if ((pw->pw_uid == 0) ||
+ (pw->pw_uid < UID_MIN)) {
+ log_err("cannot run as forbidden uid (%d/%s)\n", pw->pw_uid, cmd);
+ exit(107);
+ }
+
+ /*
+ * Error out if attempt is made to execute as root group
+ * or as a GID less than GID_MIN. Tsk tsk.
+ */
+ if ((gr->gr_gid == 0) ||
+ (gr->gr_gid < GID_MIN)) {
+ log_err("cannot run as forbidden gid (%d/%s)\n", gr->gr_gid, cmd);
+ exit(108);
+ }
+
+ /*
+ * Change UID/GID here so that the following tests work over NFS.
+ *
+ * Initialize the group access list for the target user,
+ * and setgid() to the target group. If unsuccessful, error out.
+ */
+ uid = pw->pw_uid;
+ gid = gr->gr_gid;
+ if (((setgid(gid)) != 0) || (initgroups(pw->pw_name,gid) != 0)) {
+ log_err("failed to setgid (%ld: %s/%s)\n", gid, cwd, cmd);
+ exit(109);
+ }
+
+ /*
+ * setuid() to the target user. Error out on fail.
+ */
+ if ((setuid(uid)) != 0) {
+ log_err("failed to setuid (%ld: %s/%s)\n", uid, cwd, cmd);
+ exit(110);
+ }
+
+ /*
* Get the current working directory, as well as the proper
* document root (dependant upon whether or not it is a
* ~userdir request). Error out if we cannot get either one,
***************
*** 296,329 ****
* Use chdir()s and getcwd()s to avoid problems with symlinked
* directories. Yuck.
*/
! if (getcwd(cwd, MAXPATHLEN) == NULL) {
log_err("cannot get current working directory\n");
! exit(107);
}
if (userdir) {
if (((chdir(pw->pw_dir)) != 0) ||
((chdir(USERDIR_SUFFIX)) != 0) ||
! ((getcwd(dwd, MAXPATHLEN)) == NULL) ||
((chdir(cwd)) != 0))
{
log_err("cannot get docroot information (%s)\n", pw->pw_dir);
! exit(108);
}
}
else {
if (((chdir(DOC_ROOT)) != 0) ||
! ((getcwd(dwd, MAXPATHLEN)) == NULL) ||
((chdir(cwd)) != 0))
{
log_err("cannot get docroot information (%s)\n", DOC_ROOT);
! exit(108);
}
}
if ((strncmp(cwd, dwd, strlen(dwd))) != 0) {
log_err("command not in docroot (%s/%s)\n", cwd, cmd);
! exit(109);
}
/*
--- 354,387 ----
* Use chdir()s and getcwd()s to avoid problems with symlinked
* directories. Yuck.
*/
! if (getcwd(cwd, AP_MAXPATH) == NULL) {
log_err("cannot get current working directory\n");
! exit(111);
}
if (userdir) {
if (((chdir(pw->pw_dir)) != 0) ||
((chdir(USERDIR_SUFFIX)) != 0) ||
! ((getcwd(dwd, AP_MAXPATH)) == NULL) ||
((chdir(cwd)) != 0))
{
log_err("cannot get docroot information (%s)\n", pw->pw_dir);
! exit(112);
}
}
else {
if (((chdir(DOC_ROOT)) != 0) ||
! ((getcwd(dwd, AP_MAXPATH)) == NULL) ||
((chdir(cwd)) != 0))
{
log_err("cannot get docroot information (%s)\n", DOC_ROOT);
! exit(113);
}
}
if ((strncmp(cwd, dwd, strlen(dwd))) != 0) {
log_err("command not in docroot (%s/%s)\n", cwd, cmd);
! exit(114);
}
/*
***************
*** 331,337 ****
*/
if (((lstat(cwd, &dir_info)) != 0) || !(S_ISDIR(dir_info.st_mode))) {
log_err("cannot stat directory: (%s)\n", cwd);
! exit(110);
}
/*
--- 389,395 ----
*/
if (((lstat(cwd, &dir_info)) != 0) || !(S_ISDIR(dir_info.st_mode))) {
log_err("cannot stat directory: (%s)\n", cwd);
! exit(115);
}
/*
***************
*** 339,345 ****
*/
if ((dir_info.st_mode & S_IWOTH) || (dir_info.st_mode & S_IWGRP)) {
log_err("directory is writable by others: (%s)\n", cwd);
! exit(111);
}
/*
--- 397,403 ----
*/
if ((dir_info.st_mode & S_IWOTH) || (dir_info.st_mode & S_IWGRP)) {
log_err("directory is writable by others: (%s)\n", cwd);
! exit(116);
}
/*
***************
*** 347,353 ****
*/
if (((lstat(cmd, &prg_info)) != 0) || (S_ISLNK(prg_info.st_mode))) {
log_err("cannot stat program: (%s)\n", cmd);
! exit(112);
}
/*
--- 405,411 ----
*/
if (((lstat(cmd, &prg_info)) != 0) || (S_ISLNK(prg_info.st_mode))) {
log_err("cannot stat program: (%s)\n", cmd);
! exit(117);
}
/*
***************
*** 355,361 ****
*/
if ((prg_info.st_mode & S_IWOTH) || (prg_info.st_mode & S_IWGRP)) {
log_err("file is writable by others: (%s/%s)\n", cwd, cmd);
! exit(113);
}
/*
--- 413,419 ----
*/
if ((prg_info.st_mode & S_IWOTH) || (prg_info.st_mode & S_IWGRP)) {
log_err("file is writable by others: (%s/%s)\n", cwd, cmd);
! exit(118);
}
/*
***************
*** 363,369 ****
*/
if ((prg_info.st_mode & S_ISUID) || (prg_info.st_mode & S_ISGID)) {
log_err("file is either setuid or setgid: (%s/%s)\n",cwd,cmd);
! exit(114);
}
/*
--- 421,427 ----
*/
if ((prg_info.st_mode & S_ISUID) || (prg_info.st_mode & S_ISGID)) {
log_err("file is either setuid or setgid: (%s/%s)\n",cwd,cmd);
! exit(119);
}
/*
***************
*** 379,433 ****
pw->pw_uid, gr->gr_gid,
dir_info.st_uid, dir_info.st_gid,
prg_info.st_uid, prg_info.st_gid);
! exit(115);
! }
!
! /*
! * Error out if attempt is made to execute as root or as
! * a UID less than UID_MIN. Tsk tsk.
! */
! if ((pw->pw_uid == 0) ||
! (pw->pw_uid < UID_MIN)) {
! log_err("cannot run as forbidden uid (%d/%s)\n", pw->pw_uid, cmd);
! exit(116);
! }
!
! /*
! * Error out if attempt is made to execute as root group
! * or as a GID less than GID_MIN. Tsk tsk.
! */
! if ((gr->gr_gid == 0) ||
! (gr->gr_gid < GID_MIN)) {
! log_err("cannot run as forbidden gid (%d/%s)\n", gr->gr_gid, cmd);
! exit(117);
! }
!
! /*
! * Log the transaction here to be sure we have an open log
! * before we setuid().
! */
! log_err("uid: (%s/%s) gid: (%s/%s) %s\n",
! target_uname, pw->pw_name,
! target_gname, gr->gr_name,
! cmd);
!
! /*
! * Initialize the group access list for the target user,
! * and setgid() to the target group. If unsuccessful, error out.
! */
! uid = pw->pw_uid;
! gid = gr->gr_gid;
! if (((setgid(gid)) != 0) || (initgroups(pw->pw_name,gid) != 0)) {
! log_err("failed to setgid (%ld: %s/%s)\n", gid, cwd, cmd);
! exit(118);
! }
!
! /*
! * setuid() to the target user. Error out on fail.
! */
! if ((setuid(uid)) != 0) {
! log_err("failed to setuid (%ld: %s/%s)\n", uid, cwd, cmd);
! exit(119);
}
clean_env();
--- 437,443 ----
pw->pw_uid, gr->gr_gid,
dir_info.st_uid, dir_info.st_gid,
prg_info.st_uid, prg_info.st_gid);
! exit(120);
}
clean_env();