You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by Randy Terbush <ra...@zyzzyva.com> on 1997/01/11 00:29:09 UTC

suexec.patch (again?)

Not sure why this did not show up on my first attempt to send
it. 


------- Forwarded Message

To: new-httpd@apache.org
Subject: suexec patch
X-uri: http://www.zyzzyva.com/
Mime-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Date: Fri, 10 Jan 1997 16:41:05 -0600
From: Randy Terbush <ra...@sierra>

I have the following patch which includes Jason Dour's changes
along with my addition to control environment variables passed
by the suexec wrapper. I'd appreciate comments regarding how I
handled the enviro thing if there is an easier way. 

Would appreciate those on the list using suexec giving this a
spin before we unleash it on the public.

Index: suexec.c
===================================================================
RCS file: /export/home/cvs/apache/support/suexec.c,v
retrieving revision 1.10
diff -c -r1.10 suexec.c
*** suexec.c	1997/01/01 18:26:17	1.10
- --- suexec.c	1997/01/10 22:33:03
***************
*** 81,89 ****
- --- 81,121 ----
  #include <time.h>
  #include <sys/stat.h>
  
+ #define CLEAN_ENV_BUF 64
  
+ extern char **environ;
  static FILE *log;
  
+ char *safe_env_lst[] =
+ {
+     "CONTENT_TYPE",
+     "CONTENT_LENGTH",
+     "SERVER_SOFTWARE",
+     "SERVER_NAME",
+     "SERVER_PORT",
+     "REMOTE_HOST",
+     "REMOTE_ADDR",
+     "DOCUMENT_ROOT",
+     "SERVER_ADMIN",
+     "SCRIPT_FILENAME",
+     "REMOTE_USER",
+     "AUTH_TYPE",
+     "REMOTE_IDENT",
+     "REMOTE_PORT",
+     "REDIRECT_QUERY_STRING",
+     "REDIRECT_URL",
+     "GATEWAY_INTERFACE",
+     "SERVER_PROTOCOL",
+     "REQUEST_METHOD",
+     "QUERY_STRING",
+     "SCRIPT_NAME",
+     "PATH_INFO",
+     "FILEPATH_INFO",
+     "PATH_TRANSLATED",
+     NULL
+ };
+ 
+ 
  static void err_output(const char *fmt, va_list ap)
  {
      time_t timevar;
***************
*** 120,128 ****
      return;
  }
  
! int main(int argc, char *argv[], char **env)
  {
- -     int doclen;             /* length of the docroot     */
      int userdir = 0;        /* ~userdir flag             */
      uid_t uid;              /* user information          */
      gid_t gid;              /* target group placeholder  */
- --- 152,197 ----
      return;
  }
  
! void clean_env() 
! {
!     char pathbuf[512];
!     char **cleanenv;
!     char **ep;
!     int cidx = 0;
!     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++;
! 	}
! 	else {
! 	    for (idx = 0; safe_env_lst[idx]; idx++) {
! 		if (!strncmp(*ep, safe_env_lst[idx], strlen(safe_env_lst[idx]))) {
! 		    cleanenv[cidx] = *ep;
! 		    cidx++;
! 		    break;
! 		}
! 	    }
! 	}
!     }
! 
!     sprintf(pathbuf, "PATH=%s", SAFE_PATH);
!     cleanenv[cidx] = pathbuf;
!     cleanenv[++cidx] = NULL;
! 	    
!     environ = cleanenv;
!     free(cleanenv);
! }
! 
! int main(int argc, char *argv[])
  {
      int userdir = 0;        /* ~userdir flag             */
      uid_t uid;              /* user information          */
      gid_t gid;              /* target group placeholder  */
***************
*** 211,217 ****
      /*
       * 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,
       * or if the current working directory is not in the docroot.
       * Use chdir()s and getcwd()s to avoid problems with symlinked
       * directories.  Yuck.
- --- 280,286 ----
      /*
       * 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,
       * or if the current working directory is not in the docroot.
       * Use chdir()s and getcwd()s to avoid problems with symlinked
       * directories.  Yuck.
***************
*** 223,228 ****
- --- 292,298 ----
      
      if (userdir) {
          if (((chdir(pw->pw_dir)) != 0) ||
+             ((chdir(USERDIR_SUFFIX)) != 0) ||
  	    ((getcwd(dwd, MAXPATHLEN)) == NULL) ||
              ((chdir(cwd)) != 0))
          {
***************
*** 239,247 ****
              exit(108);
          }
      }
!     
!     doclen = strlen(dwd);
!     if ((strncmp(cwd, dwd, doclen)) != 0) {
          log_err("command not in docroot (%s/%s)\n", cwd, cmd);
          exit(109);
      }
- --- 309,316 ----
              exit(108);
          }
      }
! 
!     if ((strncmp(cwd, dwd, strlen(dwd))) != 0) {
          log_err("command not in docroot (%s/%s)\n", cwd, cmd);
          exit(109);
      }
***************
*** 303,320 ****
      }
  
      /*
!      * Error out if attempt is made to execute as root.  Tsk tsk.
       */
!     if (pw->pw_uid == 0) {
! 	log_err("cannot run as uid 0 (%s)\n", cmd);
  	exit(116);
      }
  
      /*
!      * Error out if attempt is made to execute as root group.  Tsk tsk.
       */
!     if (gr->gr_gid == 0) {
! 	log_err("cannot run as gid 0 (%s)\n", cmd);
  	exit(117);
      }
  
- --- 372,393 ----
      }
  
      /*
!      * 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);
      }
  
***************
*** 333,339 ****
       */
      uid = pw->pw_uid;
      gid = gr->gr_gid;
!     if ((initgroups(target_uname,gid) != 0) || ((setgid(gid)) != 0)) {
          log_err("failed to setgid (%ld: %s/%s)\n", gid, cwd, cmd);
          exit(118);
      }
- --- 406,412 ----
       */
      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);
      }
***************
*** 346,360 ****
  	exit(119);
      }
  
!     if ((setenv("PATH", SAFE_PATH, 1)) != 0) {
! 	log_err("cannot reset environment PATH\n");
! 	exit(120);
!     }
      
      /*
       * Execute the command, replacing our image with its own.
       */
!     execve(cmd, &argv[3], env);
  
      /*
       * (I can't help myself...sorry.)
- --- 419,430 ----
  	exit(119);
      }
  
!     clean_env();
      
      /*
       * Execute the command, replacing our image with its own.
       */
!     execv(cmd, argv);
  
      /*
       * (I can't help myself...sorry.)
Index: suexec.h
===================================================================
RCS file: /export/home/cvs/apache/support/suexec.h,v
retrieving revision 1.6
diff -c -r1.6 suexec.h
*** suexec.h	1997/01/01 18:26:18	1.6
- --- suexec.h	1997/01/10 22:33:05
***************
*** 68,73 ****
- --- 68,103 ----
  #endif
  
  /*
+  * UID_MIN -- Define this as the lowest UID allowed to be a target user
+  *            for suEXEC.  For most systems, 500 or 100 is common.
+  */
+ #ifndef UID_MIN
+ #define UID_MIN 500
+ #endif
+ 
+ /*
+  * GID_MIN -- Define this as the lowest GID allowed to be a target group
+  *            for suEXEC.  For most systems, 100 is common.
+  */
+ #ifndef GID_MIN
+ #define GID_MIN 100
+ #endif
+ 
+ /*
+  * USERDIR_SUFFIX -- Define to be the same as the UserDir in the conf
+  *                   file.  If you have VirtualHosts with a different
+  *                   UserDir for each, you will need to define them to
+  *                   all reside in one parent directory; then name that
+  *                   parent directory here.  IF THIS IS NOT DEFINED
+  *                   PROPERLY, ~USERDIR CGI REQUESTS WILL NOT WORK!
+  *                   See the suEXEC documentation for more detailed
+  *                   information.
+  */
+ #ifndef USERDIR_SUFFIX
+ #define USERDIR_SUFFIX "public_html"
+ #endif
+ 
+ /*
   * LOG_EXEC -- Define this as a filename if you want all suEXEC
   *             transactions and errors logged for auditing and
   *             debugging purposes.




------- End of Forwarded Message




Re: suexec.patch (again?)

Posted by Marc Slemko <ma...@znep.com>.
On Fri, 10 Jan 1997, Randy Terbush wrote:

> + char *safe_env_lst[] =
> + {
> +     "CONTENT_TYPE",
> +     "CONTENT_LENGTH",
> +     "SERVER_SOFTWARE",
> +     "SERVER_NAME",
> +     "SERVER_PORT",
> +     "REMOTE_HOST",
> +     "REMOTE_ADDR",
> +     "DOCUMENT_ROOT",
> +     "SERVER_ADMIN",
> +     "SCRIPT_FILENAME",
> +     "REMOTE_USER",
> +     "AUTH_TYPE",
> +     "REMOTE_IDENT",
> +     "REMOTE_PORT",
> +     "REDIRECT_QUERY_STRING",
> +     "REDIRECT_URL",
> +     "GATEWAY_INTERFACE",
> +     "SERVER_PROTOCOL",
> +     "REQUEST_METHOD",
> +     "QUERY_STRING",
> +     "SCRIPT_NAME",
> +     "PATH_INFO",
> +     "FILEPATH_INFO",
> +     "PATH_TRANSLATED",
> +     NULL
> + };

What about REDIRECT_STATUS, SCRIPT_URL, SCRIPT_URI, DATE_LOCAL, DATE_GMT
and LAST_MODIFED?

The rest of it looks cool, but I don't run it anywhere right now, so...