httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Randy Terbush <ra...@zyzzyva.com>
Subject [PATCH] suexec changes
Date Sat, 08 Feb 1997 16:46:02 GMT

Since I have not gotten a response from the testers I have mailed
these changes to, I think I had better get this in front of the 
group for other scrutiny.

Changes below fix the following problems:
* array overrun in clean_env if more than AP_ENVBUF variables
* portability of MAXPATHLEN addressed
* PR#70 make directory checks work on NFS mounted filesystems

The size of this patch is misleading. The changes to accomodate
the fix for PR#70 are simply reordering changes where we move
the setuid/setgid calls before directory checks. I don't have
this scenario to test on, so it would be much appreciated if 
someone who does could verify that the changes work.


------- Forwarded Message

===================================================================
RCS file: /export/home/cvs/apache/support/suexec.c,v
retrieving revision 1.14
diff -c -r1.14 suexec.c
*** suexec.c	1997/02/06 21:46:08	1.14
--- suexec.c	1997/02/08 16:32:25
***************
*** 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();

------- End of Forwarded Message




Mime
View raw message