monster patch for consideration...
Forwarded message:
> From leitner@prz.tu-berlin.de Wed Sep 13 13:30:23 1995
> From: leitner@prz.tu-berlin.de
> Message-Id: <199509132029.WAA00729@tubkom.prz.tu-berlin.de>
> Subject: Apache secure CGI bin patch
> To: apache-bugs@mail.apache.org
> Date: Wed, 13 Sep 1995 22:29:21 +0100 (MESZ)
> Mime-Version: 1.0
> Content-Type: text/plain; charset=ISO-8859-1
> Content-Transfer-Encoding: 8bit
> Content-Length: 12694
>
> Hi folks,
>
> I wanted to patch some server for quite a while, and now I finally found
> a worthy server, Apache ;)
>
> This is my patch. Go into the apache_0.8.11 directory and run "patch -s
> -p1 < apache.diff" where apache.diff is included here. Please read the
> file README.SETUID in the src/ directory to see what this patch does.
>
> I hope I'll get on the Apache credits list now ;))
>
> Felix
>
>
> diff -u --recursive --new-file apache_0.8.11/src/Configuration apache_0.8.11.setuid/src/Configuration
> --- apache_0.8.11/src/Configuration Tue Aug 8 18:56:04 1995
> +++ apache_0.8.11.setuid/src/Configuration Tue Sep 5 23:16:42 1995
> @@ -34,11 +34,11 @@
> # defaults in. Note that this config file does not include DBM auth by
> # default --- configure it in below if you need it].
>
> -CFLAGS= -O2
> +CFLAGS= -O2 -DSETUID
>
> # Place here any flags you may need upon linking, such as a flag to
> # prevent dynamic linking (if desired)
> -LFLAGS=
> +LFLAGS= -s
>
> # Place here any extra libraries you may need to link to.
> # -lndbm is commonly required for DBM auth, if that is configured in.
> diff -u --recursive --new-file apache_0.8.11/src/README.SETUID apache_0.8.11.setuid/src/README.SETUID
> --- apache_0.8.11/src/README.SETUID
> +++ apache_0.8.11.setuid/src/README.SETUID Wed Sep 13 21:55:52 1995
> @@ -0,0 +1,80 @@
> +This README describes my SETUID patch to the wonderful Apache HTTP
> +server. It tries to fix Apache so that sysadmins have fewer reasons to
> +disable CGI binaries in user's directories. Normally, a sysadmin with
> +security in mind cannot allow CGI binaries in user's directories, since
> +user can kill each other's CGI bins, and they run under another UID, so
> +users can install backdoors to allow remote login under the UID of their
> +CGI bins. Besides, if users want to do some logging with their CGI
> +binaries, they have to chmod u+X them or make the log file world
> +writable. Both is unsatisfactory.
> +
> +Another thing that causes much grief to me is the .htaccess file. Now
> +users can password-protect their files, but every local user can just
> +copy the files from their account, since they have to be world readable
> +so that the HTTP daemon can read them.
> +
> +My patch changes the Apache daemon in the following ways :
> +
> + * When run standalone, the daemon does not setuid(wanted), but it
> + does seteuid(wanted). This makes it possible that the daemon can
> + later seteuid to some other uid. The daemon still does all the dirty
> + work (like writing log files, etc) under the EUID you set up.
> + * When run from inetd, it must be run as root and I changed the code
> + that it changes UID just like the standalone server.
> + * Files in home directories are now read under the EUID of the owner
> + of the home directory. That means they no longer need to be world
> + readable. Nor does the public_html directory need to be world
> + executable !
> + * CGI-bins in home directories are now run under the UID of the owner
> + of the home. That means, if a user does a "kill -9 -1", it just his
> + processes that die. And if you have a fascist Unix with process,
> + CPU and memory quota, you can keep users from killing your HTTP
> + server this way.
> + Note that before CGI-bins are executed, the real UID is changed to
> + the effective UID, so no CGI-bin can setuid(getuid) and be root !
> + * Server Parsed HTML files can include both files and program outputs.
> + Now this is a little tricky, because a malevolent user could use a
> + server parsed HTML file to read any file in another user's
> + public_html hierarchy. For this reason, no UID swapping takes place
> + when including files. The same is true for foreign CGI-bins ! They
> + have to be executable to the user to be includable.
> + * CGI-bins can only be executed if they belong to the owner of
> + the home directory. An exception are server parsed HTML included
> + CGI-bins, otherwise one could not include foreign CGI bins.
> + This is important, because otherwise people would compromise their
> + accounts if they accidentally left one directory in their
> + public_html hierarchy group or world writable by accident. Then any
> + local malevolent user could create a CGI-bin that would modify that
> + user's .rhosts file.
> + * CGI-bins can not be executed if they are group or world
> + writable. If someone had group or world writable CGI-bins, anyone
> + could modify that CGI-bin and then compromise that user's account by
> + modifying .rhosts.
> +
> +Please note that my code is ugly. It does not do error checking.
> +If seteuid fails, you'll not get the error you'll expected, but you'll
> +get an error that some files could not be read.
> +
> +To make the decision to integrate my patches easier, the changes are
> +only effective if you #define SETUID.
> +
> +If you do not understand what the heck I am talking about, I suggest
> +that you do not run a web server until you have consulted a security
> +specialist.
> +
> +Since I am but a humble admin and C/C++/Perl hacker, I can't guarantee
> +that this code works, does anything at all, and does not open new holes.
> +I advise you to think before enabling SETUID blindly.
> +
> +If you find a bug, add error handling, find a security hole, or just
> +want to tell me something, feel free to e-mail me as
> +leitner@prz.tu-berlin.de. Alternatively, you could try to e-mail me as
> +leitner@inf.fu-berlin.de. If that does not work, too, you can still
> +send me snail mail (I just *love* postcards) :
> +
> + Felix von Leitner
> + Gervinusstraße 22 [Foreigners without ISO umlauts do s/ß/ss/]
> + 10629 Berlin
> + Germany
> +
> +Felix
> diff -u --recursive --new-file apache_0.8.11/src/http_core.c apache_0.8.11.setuid/src/http_core.c
> --- apache_0.8.11/src/http_core.c Wed Aug 23 03:16:07 1995
> +++ apache_0.8.11.setuid/src/http_core.c Wed Sep 13 20:39:23 1995
> @@ -670,7 +670,15 @@
> || (errstatus = set_last_modified (r, r->finfo.st_mtime)))
> return errstatus;
>
> +#ifdef SETUID
> + seteuid(0); /* First become root again so we can */
> + seteuid(destuid); /* seteuid again */
> +#endif
> f = fopen (r->filename, "r");
> +#ifdef SETUID
> + seteuid(0); /* First become root again so we can */
> + seteuid(user_id); /* seteuid again */
> +#endif
>
> if (f == NULL) {
> log_reason("file permissions deny server access", r->filename, r);
> diff -u --recursive --new-file apache_0.8.11/src/http_main.c apache_0.8.11.setuid/src/http_main.c
> --- apache_0.8.11/src/http_main.c Wed Aug 23 03:16:10 1995
> +++ apache_0.8.11.setuid/src/http_main.c Wed Sep 13 20:38:53 1995
> @@ -102,6 +102,10 @@
>
> int standalone;
> uid_t user_id;
> +#ifdef SETUID
> +uid_t destuid;
> +char ininclude=0;
> +#endif
> char *user_name;
> gid_t group_id;
> int max_requests_per_child;
> @@ -711,7 +715,11 @@
> reopen_scoreboard (pconf);
>
> /* Only try to switch if we're running as root */
> +#ifdef SETUID
> + if(!getuid() && seteuid(user_id) == -1) {
> +#else
> if(!getuid() && setuid(user_id) == -1) {
> +#endif
> log_error ("unable to change uid", server_conf);
> exit (1);
> }
> @@ -987,8 +995,10 @@
> if (!server_conf->server_hostname)
> server_conf->server_hostname = get_local_host(pconf);
>
> +#ifndef SETUID
> user_id = getuid();
> group_id = getgid();
> +#endif
>
> server_conf->port = get_portnum(fileno(stdout));
> conn = new_connection (ptrans, server_conf, stdin, stdout);
> diff -u --recursive --new-file apache_0.8.11/src/httpd.h apache_0.8.11.setuid/src/httpd.h
> --- apache_0.8.11/src/httpd.h Thu Aug 24 02:09:47 1995
> +++ apache_0.8.11.setuid/src/httpd.h Wed Sep 13 20:45:06 1995
> @@ -101,6 +101,11 @@
> #define DEFAULT_USER "#-1"
> #define DEFAULT_GROUP "#-1"
>
> +#ifdef SETUID
> +extern uid_t destuid;
> +extern char ininclude;
> +#endif
> +
> /* The name of the log files */
> #define DEFAULT_XFERLOG "logs/access_log"
> #define DEFAULT_ERRORLOG "logs/error_log"
> diff -u --recursive --new-file apache_0.8.11/src/mod_asis.c apache_0.8.11.setuid/src/mod_asis.c
> --- apache_0.8.11/src/mod_asis.c Wed Aug 23 03:16:18 1995
> +++ apache_0.8.11.setuid/src/mod_asis.c Wed Sep 13 19:56:20 1995
> @@ -64,6 +64,8 @@
> #include "util_script.h"
> #include "http_main.h"
>
> +extern uid_t user_id;
> +
> int asis_handler (request_rec *r)
> {
> FILE *f;
> @@ -73,8 +75,15 @@
> log_reason("File does not exist", r->filename, r);
> return NOT_FOUND;
> }
> -
> +#ifdef SETUID
> + seteuid(0); /* First become root again so we can */
> + seteuid(destuid); /* seteuid again */
> +#endif
> f = fopen (r->filename, "r");
> +#ifdef SETUID
> + seteuid(0); /* First become root again so we can */
> + seteuid(user_id); /* seteuid again */
> +#endif
>
> if (f == NULL) {
> log_reason("file permissions deny server access", r->filename, r);
> diff -u --recursive --new-file apache_0.8.11/src/mod_cgi.c apache_0.8.11.setuid/src/mod_cgi.c
> --- apache_0.8.11/src/mod_cgi.c Wed Aug 23 03:16:20 1995
> +++ apache_0.8.11.setuid/src/mod_cgi.c Wed Sep 13 21:39:50 1995
> @@ -195,6 +195,9 @@
>
> cleanup_for_exec();
>
> +#ifdef SETUID
> + setuid(destuid);
> +#endif
> if((!r->args) || (!r->args[0]) || (ind(r->args,'=') >= 0))
> execle(r->filename, argv0, NULL, env);
> else
> diff -u --recursive --new-file apache_0.8.11/src/mod_include.c apache_0.8.11.setuid/src/mod_include.c
> --- apache_0.8.11/src/mod_include.c Wed Aug 23 03:16:23 1995
> +++ apache_0.8.11.setuid/src/mod_include.c Wed Sep 13 20:37:27 1995
> @@ -687,6 +687,10 @@
>
> /* This is a stub which parses a file descriptor. */
>
> +#ifdef SETUID
> +extern char ininclude;
> +#endif
> +
> void send_parsed_content(FILE *f, request_rec *r)
> {
> char directive[MAX_STRING_LEN], error[MAX_STRING_LEN];
> @@ -712,12 +716,25 @@
> rprintf(r,"%s",error);
> ret = find_string(f,ENDING_SEQUENCE,NULL);
> } else
> +#ifdef SETUID
> + { ininclude++;
> +#endif
> ret=handle_exec(f, r, error);
> +#ifdef SETUID
> + ininclude--; }
> +#endif
> }
> else if(!strcmp(directive,"config"))
> ret=handle_config(f, r, error, timefmt, &sizefmt);
> else if(!strcmp(directive,"include"))
> +#ifdef SETUID
> + { ininclude++;
> +#endif
> ret=handle_include(f, r, error, noexec);
> +#ifdef SETUID
> + ininclude--;
> + }
> +#endif
> else if(!strcmp(directive,"echo"))
> ret=handle_echo(f, r, error);
> else if(!strcmp(directive,"fsize"))
> diff -u --recursive --new-file apache_0.8.11/src/mod_userdir.c apache_0.8.11.setuid/src/mod_userdir.c
> --- apache_0.8.11/src/mod_userdir.c Wed Aug 23 03:16:28 1995
> +++ apache_0.8.11.setuid/src/mod_userdir.c Wed Sep 13 20:31:22 1995
> @@ -69,6 +69,7 @@
>
> #include "httpd.h"
> #include "http_config.h"
> +#include "http_conf_globals.h"
>
> module userdir_module;
>
> @@ -97,12 +98,19 @@
> { NULL }
> };
>
> +#ifdef SETUID
> +extern char ininclude;
> +#endif
> +
> int translate_userdir (request_rec *r)
> {
> void *server_conf = r->server->module_config;
> char *userdir = (char *)get_module_config(server_conf, &userdir_module);
> char *name = r->uri;
>
> +#ifdef SETUID
> + destuid=user_id;
> +#endif
> if (userdir && (name[0] == '/') && (name[1] == '~'))
> {
> struct passwd *pw;
> @@ -112,6 +120,10 @@
> w = getword(r->pool, &dname, '/');
> if(!(pw=getpwnam(w)))
> return NOT_FOUND;
> +#ifdef SETUID
> + if (ininclude==0)
> + destuid=pw->pw_uid;
> +#endif
>
> /* The 'dname' funny business involves backing it up to capture
> * the '/' delimiting the "/~user" part from the rest of the URL,
> diff -u --recursive --new-file apache_0.8.11/src/util.c apache_0.8.11.setuid/src/util.c
> --- apache_0.8.11/src/util.c Wed Aug 23 03:16:31 1995
> +++ apache_0.8.11.setuid/src/util.c Wed Sep 13 21:36:59 1995
> @@ -532,6 +532,25 @@
> }
>
> int can_exec(struct stat *finfo) {
> +#ifdef SETUID /* hack by Felix von Leitner <leitner@prz.tu-berlin.de> */
> + if (finfo->st_mode & (S_IWGRP+S_IWOTH)) {
> + fprintf(stderr,"group or world writable\n");
> + return 0; /* Never allow to execute group or world writable CGIs */
> + }
> + if (ininclude==0)
> + if (finfo->st_uid != destuid) {
> + fprintf(stderr,"CGI uid=%d, home uid=%d\n",finfo->st_uid,destuid);
> + return 0; /* Do not allow to execute CGIs not belonging
> + to the owner of the home */
> + }
> + if(destuid == finfo->st_uid)
> + if(finfo->st_mode & S_IXUSR)
> + return 1;
> + if(group_id == finfo->st_gid)
> + if(finfo->st_mode & S_IXGRP)
> + return 1;
> + return (finfo->st_mode & S_IXOTH);
> +#else
> if(user_id == finfo->st_uid)
> if(finfo->st_mode & S_IXUSR)
> return 1;
> @@ -539,6 +558,7 @@
> if(finfo->st_mode & S_IXGRP)
> return 1;
> return (finfo->st_mode & S_IXOTH);
> +#endif
> }
>
> #ifdef NEED_STRDUP
>
Forwarded message:
> From leitner@prz.tu-berlin.de Wed Sep 13 13:30:23 1995
> From: leitner@prz.tu-berlin.de
> Message-Id: <199509132029.WAA00729@tubkom.prz.tu-berlin.de>
> Subject: Apache secure CGI bin patch
> To: apache-bugs@mail.apache.org
> Date: Wed, 13 Sep 1995 22:29:21 +0100 (MESZ)
> Mime-Version: 1.0
> Content-Type: text/plain; charset=ISO-8859-1
> Content-Transfer-Encoding: 8bit
> Content-Length: 12694
>
> Hi folks,
>
> I wanted to patch some server for quite a while, and now I finally found
> a worthy server, Apache ;)
>
> This is my patch. Go into the apache_0.8.11 directory and run "patch -s
> -p1 < apache.diff" where apache.diff is included here. Please read the
> file README.SETUID in the src/ directory to see what this patch does.
>
> I hope I'll get on the Apache credits list now ;))
>
> Felix
>
>
> diff -u --recursive --new-file apache_0.8.11/src/Configuration apache_0.8.11.setuid/src/Configuration
> --- apache_0.8.11/src/Configuration Tue Aug 8 18:56:04 1995
> +++ apache_0.8.11.setuid/src/Configuration Tue Sep 5 23:16:42 1995
> @@ -34,11 +34,11 @@
> # defaults in. Note that this config file does not include DBM auth by
> # default --- configure it in below if you need it].
>
> -CFLAGS= -O2
> +CFLAGS= -O2 -DSETUID
>
> # Place here any flags you may need upon linking, such as a flag to
> # prevent dynamic linking (if desired)
> -LFLAGS=
> +LFLAGS= -s
>
> # Place here any extra libraries you may need to link to.
> # -lndbm is commonly required for DBM auth, if that is configured in.
> diff -u --recursive --new-file apache_0.8.11/src/README.SETUID apache_0.8.11.setuid/src/README.SETUID
> --- apache_0.8.11/src/README.SETUID
> +++ apache_0.8.11.setuid/src/README.SETUID Wed Sep 13 21:55:52 1995
> @@ -0,0 +1,80 @@
> +This README describes my SETUID patch to the wonderful Apache HTTP
> +server. It tries to fix Apache so that sysadmins have fewer reasons to
> +disable CGI binaries in user's directories. Normally, a sysadmin with
> +security in mind cannot allow CGI binaries in user's directories, since
> +user can kill each other's CGI bins, and they run under another UID, so
> +users can install backdoors to allow remote login under the UID of their
> +CGI bins. Besides, if users want to do some logging with their CGI
> +binaries, they have to chmod u+X them or make the log file world
> +writable. Both is unsatisfactory.
> +
> +Another thing that causes much grief to me is the .htaccess file. Now
> +users can password-protect their files, but every local user can just
> +copy the files from their account, since they have to be world readable
> +so that the HTTP daemon can read them.
> +
> +My patch changes the Apache daemon in the following ways :
> +
> + * When run standalone, the daemon does not setuid(wanted), but it
> + does seteuid(wanted). This makes it possible that the daemon can
> + later seteuid to some other uid. The daemon still does all the dirty
> + work (like writing log files, etc) under the EUID you set up.
> + * When run from inetd, it must be run as root and I changed the code
> + that it changes UID just like the standalone server.
> + * Files in home directories are now read under the EUID of the owner
> + of the home directory. That means they no longer need to be world
> + readable. Nor does the public_html directory need to be world
> + executable !
> + * CGI-bins in home directories are now run under the UID of the owner
> + of the home. That means, if a user does a "kill -9 -1", it just his
> + processes that die. And if you have a fascist Unix with process,
> + CPU and memory quota, you can keep users from killing your HTTP
> + server this way.
> + Note that before CGI-bins are executed, the real UID is changed to
> + the effective UID, so no CGI-bin can setuid(getuid) and be root !
> + * Server Parsed HTML files can include both files and program outputs.
> + Now this is a little tricky, because a malevolent user could use a
> + server parsed HTML file to read any file in another user's
> + public_html hierarchy. For this reason, no UID swapping takes place
> + when including files. The same is true for foreign CGI-bins ! They
> + have to be executable to the user to be includable.
> + * CGI-bins can only be executed if they belong to the owner of
> + the home directory. An exception are server parsed HTML included
> + CGI-bins, otherwise one could not include foreign CGI bins.
> + This is important, because otherwise people would compromise their
> + accounts if they accidentally left one directory in their
> + public_html hierarchy group or world writable by accident. Then any
> + local malevolent user could create a CGI-bin that would modify that
> + user's .rhosts file.
> + * CGI-bins can not be executed if they are group or world
> + writable. If someone had group or world writable CGI-bins, anyone
> + could modify that CGI-bin and then compromise that user's account by
> + modifying .rhosts.
> +
> +Please note that my code is ugly. It does not do error checking.
> +If seteuid fails, you'll not get the error you'll expected, but you'll
> +get an error that some files could not be read.
> +
> +To make the decision to integrate my patches easier, the changes are
> +only effective if you #define SETUID.
> +
> +If you do not understand what the heck I am talking about, I suggest
> +that you do not run a web server until you have consulted a security
> +specialist.
> +
> +Since I am but a humble admin and C/C++/Perl hacker, I can't guarantee
> +that this code works, does anything at all, and does not open new holes.
> +I advise you to think before enabling SETUID blindly.
> +
> +If you find a bug, add error handling, find a security hole, or just
> +want to tell me something, feel free to e-mail me as
> +leitner@prz.tu-berlin.de. Alternatively, you could try to e-mail me as
> +leitner@inf.fu-berlin.de. If that does not work, too, you can still
> +send me snail mail (I just *love* postcards) :
> +
> + Felix von Leitner
> + Gervinusstraße 22 [Foreigners without ISO umlauts do s/ß/ss/]
> + 10629 Berlin
> + Germany
> +
> +Felix
> diff -u --recursive --new-file apache_0.8.11/src/http_core.c apache_0.8.11.setuid/src/http_core.c
> --- apache_0.8.11/src/http_core.c Wed Aug 23 03:16:07 1995
> +++ apache_0.8.11.setuid/src/http_core.c Wed Sep 13 20:39:23 1995
> @@ -670,7 +670,15 @@
> || (errstatus = set_last_modified (r, r->finfo.st_mtime)))
> return errstatus;
>
> +#ifdef SETUID
> + seteuid(0); /* First become root again so we can */
> + seteuid(destuid); /* seteuid again */
> +#endif
> f = fopen (r->filename, "r");
> +#ifdef SETUID
> + seteuid(0); /* First become root again so we can */
> + seteuid(user_id); /* seteuid again */
> +#endif
>
> if (f == NULL) {
> log_reason("file permissions deny server access", r->filename, r);
> diff -u --recursive --new-file apache_0.8.11/src/http_main.c apache_0.8.11.setuid/src/http_main.c
> --- apache_0.8.11/src/http_main.c Wed Aug 23 03:16:10 1995
> +++ apache_0.8.11.setuid/src/http_main.c Wed Sep 13 20:38:53 1995
> @@ -102,6 +102,10 @@
>
> int standalone;
> uid_t user_id;
> +#ifdef SETUID
> +uid_t destuid;
> +char ininclude=0;
> +#endif
> char *user_name;
> gid_t group_id;
> int max_requests_per_child;
> @@ -711,7 +715,11 @@
> reopen_scoreboard (pconf);
>
> /* Only try to switch if we're running as root */
> +#ifdef SETUID
> + if(!getuid() && seteuid(user_id) == -1) {
> +#else
> if(!getuid() && setuid(user_id) == -1) {
> +#endif
> log_error ("unable to change uid", server_conf);
> exit (1);
> }
> @@ -987,8 +995,10 @@
> if (!server_conf->server_hostname)
> server_conf->server_hostname = get_local_host(pconf);
>
> +#ifndef SETUID
> user_id = getuid();
> group_id = getgid();
> +#endif
>
> server_conf->port = get_portnum(fileno(stdout));
> conn = new_connection (ptrans, server_conf, stdin, stdout);
> diff -u --recursive --new-file apache_0.8.11/src/httpd.h apache_0.8.11.setuid/src/httpd.h
> --- apache_0.8.11/src/httpd.h Thu Aug 24 02:09:47 1995
> +++ apache_0.8.11.setuid/src/httpd.h Wed Sep 13 20:45:06 1995
> @@ -101,6 +101,11 @@
> #define DEFAULT_USER "#-1"
> #define DEFAULT_GROUP "#-1"
>
> +#ifdef SETUID
> +extern uid_t destuid;
> +extern char ininclude;
> +#endif
> +
> /* The name of the log files */
> #define DEFAULT_XFERLOG "logs/access_log"
> #define DEFAULT_ERRORLOG "logs/error_log"
> diff -u --recursive --new-file apache_0.8.11/src/mod_asis.c apache_0.8.11.setuid/src/mod_asis.c
> --- apache_0.8.11/src/mod_asis.c Wed Aug 23 03:16:18 1995
> +++ apache_0.8.11.setuid/src/mod_asis.c Wed Sep 13 19:56:20 1995
> @@ -64,6 +64,8 @@
> #include "util_script.h"
> #include "http_main.h"
>
> +extern uid_t user_id;
> +
> int asis_handler (request_rec *r)
> {
> FILE *f;
> @@ -73,8 +75,15 @@
> log_reason("File does not exist", r->filename, r);
> return NOT_FOUND;
> }
> -
> +#ifdef SETUID
> + seteuid(0); /* First become root again so we can */
> + seteuid(destuid); /* seteuid again */
> +#endif
> f = fopen (r->filename, "r");
> +#ifdef SETUID
> + seteuid(0); /* First become root again so we can */
> + seteuid(user_id); /* seteuid again */
> +#endif
>
> if (f == NULL) {
> log_reason("file permissions deny server access", r->filename, r);
> diff -u --recursive --new-file apache_0.8.11/src/mod_cgi.c apache_0.8.11.setuid/src/mod_cgi.c
> --- apache_0.8.11/src/mod_cgi.c Wed Aug 23 03:16:20 1995
> +++ apache_0.8.11.setuid/src/mod_cgi.c Wed Sep 13 21:39:50 1995
> @@ -195,6 +195,9 @@
>
> cleanup_for_exec();
>
> +#ifdef SETUID
> + setuid(destuid);
> +#endif
> if((!r->args) || (!r->args[0]) || (ind(r->args,'=') >= 0))
> execle(r->filename, argv0, NULL, env);
> else
> diff -u --recursive --new-file apache_0.8.11/src/mod_include.c apache_0.8.11.setuid/src/mod_include.c
> --- apache_0.8.11/src/mod_include.c Wed Aug 23 03:16:23 1995
> +++ apache_0.8.11.setuid/src/mod_include.c Wed Sep 13 20:37:27 1995
> @@ -687,6 +687,10 @@
>
> /* This is a stub which parses a file descriptor. */
>
> +#ifdef SETUID
> +extern char ininclude;
> +#endif
> +
> void send_parsed_content(FILE *f, request_rec *r)
> {
> char directive[MAX_STRING_LEN], error[MAX_STRING_LEN];
> @@ -712,12 +716,25 @@
> rprintf(r,"%s",error);
> ret = find_string(f,ENDING_SEQUENCE,NULL);
> } else
> +#ifdef SETUID
> + { ininclude++;
> +#endif
> ret=handle_exec(f, r, error);
> +#ifdef SETUID
> + ininclude--; }
> +#endif
> }
> else if(!strcmp(directive,"config"))
> ret=handle_config(f, r, error, timefmt, &sizefmt);
> else if(!strcmp(directive,"include"))
> +#ifdef SETUID
> + { ininclude++;
> +#endif
> ret=handle_include(f, r, error, noexec);
> +#ifdef SETUID
> + ininclude--;
> + }
> +#endif
> else if(!strcmp(directive,"echo"))
> ret=handle_echo(f, r, error);
> else if(!strcmp(directive,"fsize"))
> diff -u --recursive --new-file apache_0.8.11/src/mod_userdir.c apache_0.8.11.setuid/src/mod_userdir.c
> --- apache_0.8.11/src/mod_userdir.c Wed Aug 23 03:16:28 1995
> +++ apache_0.8.11.setuid/src/mod_userdir.c Wed Sep 13 20:31:22 1995
> @@ -69,6 +69,7 @@
>
> #include "httpd.h"
> #include "http_config.h"
> +#include "http_conf_globals.h"
>
> module userdir_module;
>
> @@ -97,12 +98,19 @@
> { NULL }
> };
>
> +#ifdef SETUID
> +extern char ininclude;
> +#endif
> +
> int translate_userdir (request_rec *r)
> {
> void *server_conf = r->server->module_config;
> char *userdir = (char *)get_module_config(server_conf, &userdir_module);
> char *name = r->uri;
>
> +#ifdef SETUID
> + destuid=user_id;
> +#endif
> if (userdir && (name[0] == '/') && (name[1] == '~'))
> {
> struct passwd *pw;
> @@ -112,6 +120,10 @@
> w = getword(r->pool, &dname, '/');
> if(!(pw=getpwnam(w)))
> return NOT_FOUND;
> +#ifdef SETUID
> + if (ininclude==0)
> + destuid=pw->pw_uid;
> +#endif
>
> /* The 'dname' funny business involves backing it up to capture
> * the '/' delimiting the "/~user" part from the rest of the URL,
> diff -u --recursive --new-file apache_0.8.11/src/util.c apache_0.8.11.setuid/src/util.c
> --- apache_0.8.11/src/util.c Wed Aug 23 03:16:31 1995
> +++ apache_0.8.11.setuid/src/util.c Wed Sep 13 21:36:59 1995
> @@ -532,6 +532,25 @@
> }
>
> int can_exec(struct stat *finfo) {
> +#ifdef SETUID /* hack by Felix von Leitner <leitner@prz.tu-berlin.de> */
> + if (finfo->st_mode & (S_IWGRP+S_IWOTH)) {
> + fprintf(stderr,"group or world writable\n");
> + return 0; /* Never allow to execute group or world writable CGIs */
> + }
> + if (ininclude==0)
> + if (finfo->st_uid != destuid) {
> + fprintf(stderr,"CGI uid=%d, home uid=%d\n",finfo->st_uid,destuid);
> + return 0; /* Do not allow to execute CGIs not belonging
> + to the owner of the home */
> + }
> + if(destuid == finfo->st_uid)
> + if(finfo->st_mode & S_IXUSR)
> + return 1;
> + if(group_id == finfo->st_gid)
> + if(finfo->st_mode & S_IXGRP)
> + return 1;
> + return (finfo->st_mode & S_IXOTH);
> +#else
> if(user_id == finfo->st_uid)
> if(finfo->st_mode & S_IXUSR)
> return 1;
> @@ -539,6 +558,7 @@
> if(finfo->st_mode & S_IXGRP)
> return 1;
> return (finfo->st_mode & S_IXOTH);
> +#endif
> }
>
> #ifdef NEED_STRDUP
>