# scripts.mit.edu httpd suexec patch # Copyright (C) 2006, 2007 Jeff Arnold , Joe Presbrey , Anders Kaseorg # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA # # See /COPYRIGHT in this repository for more information. # --- httpd-2.2.2/support/Makefile.in.old 2005-07-06 19:15:34.000000000 -0400 +++ httpd-2.2.2/support/Makefile.in 2007-01-20 17:12:51.000000000 -0500 @@ -60,7 +60,7 @@ suexec_OBJECTS = suexec.lo suexec: $(suexec_OBJECTS) - $(LINK) $(suexec_OBJECTS) + $(LINK) -lselinux $(suexec_OBJECTS) htcacheclean_OBJECTS = htcacheclean.lo htcacheclean: $(htcacheclean_OBJECTS) --- httpd-2.2.2/support/suexec.c.old 2006-04-21 21:53:06.000000000 -0400 +++ httpd-2.2.2/support/suexec.c 2007-05-22 10:32:04.000000000 -0400 @@ -30,6 +30,8 @@ * */ +#define STATIC_CAT_PATH "/usr/local/bin/static-cat" + #include "apr.h" #include "ap_config.h" #include "suexec.h" @@ -46,6 +48,7 @@ #include #include #include +#include #ifdef HAVE_PWD_H #include @@ -95,6 +98,7 @@ { /* variable name starts with */ "HTTP_", + "HTTPS_", "SSL_", /* variable name is */ @@ -140,6 +144,7 @@ "UNIQUE_ID=", "USER_NAME=", "TZ=", + "PHPRC=", NULL }; @@ -245,6 +250,53 @@ environ = cleanenv; } +static const char *static_extensions[] = { + "html", + "css", + "gif", + "jpg", + "png", + "htm", + "jpeg", + "js", + "ico", + "xml", + "xsl", + "tiff", + "tif", + "tgz", + "tar", + "jar", + "zip", + "pdf", + "ps", + "doc", + "xls", + "ppt", + "swf", + "mp3", + "mov", + "wmv", + "mpg", + "mpeg", + "avi", + "il", + "JPG", + "xhtml", + NULL +}; + +static int is_static_extension(const char *file) +{ + const char *extension = strrchr(file, '.'); + const char **p; + if (extension == NULL) return 0; + for (p = static_extensions; *p; ++p) { + if (strcmp(extension + 1, *p) == 0) return 1; + } + return 0; +} + int main(int argc, char *argv[]) { int userdir = 0; /* ~userdir flag */ @@ -450,7 +501,7 @@ * Error out if attempt is made to execute as root or as * a UID less than AP_UID_MIN. Tsk tsk. */ - if ((uid == 0) || (uid < AP_UID_MIN)) { + if ((uid == 0) || (uid < AP_UID_MIN && uid != 102)) { log_err("cannot run as forbidden uid (%d/%s)\n", uid, cmd); exit(107); } @@ -482,6 +533,19 @@ log_err("failed to setuid (%ld: %s)\n", uid, cmd); exit(110); } + if (is_selinux_enabled()) { + if (uid == 102) { + if (setexeccon("system_u:system_r:signup_t:s0") == -1) { + log_err("failed to setexeccon (%ld: %s) to signup_t\n", uid, cmd); + exit(201); + } + } else { + if (setexeccon("user_u:user_r:user_t:s0") == -1) { + log_err("failed to setexeccon (%ld: %s) to user_t\n", uid, cmd); + exit(202); + } + } + } /* * Get the current working directory, as well as the proper @@ -513,6 +575,13 @@ exit(113); } } + size_t expected_len = strlen(target_homedir)+1+strlen(AP_USERDIR_SUFFIX)+1; + char *expected = malloc(expected_len); + snprintf(expected, expected_len, "%s/%s", target_homedir, AP_USERDIR_SUFFIX); + if (strncmp(cwd, expected, expected_len-1) != 0) { + log_err("error: file's directory not a subdirectory of user's home directory (%s, %s)\n", cwd, expected); + exit(114); + } if ((strncmp(cwd, dwd, strlen(dwd))) != 0) { log_err("command not in docroot (%s/%s)\n", cwd, cmd); @@ -530,15 +598,17 @@ /* * Error out if cwd is writable by others. */ +#if 0 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); } +#endif /* * Error out if we cannot stat the program. */ - if (((lstat(cmd, &prg_info)) != 0) || (S_ISLNK(prg_info.st_mode))) { + if (((lstat(cmd, &prg_info)) != 0) /*|| (S_ISLNK(prg_info.st_mode))*/) { log_err("cannot stat program: (%s)\n", cmd); exit(117); } @@ -546,10 +616,12 @@ /* * Error out if the program is writable by others. */ +#if 0 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); } +#endif /* * Error out if the file is setuid or setgid. @@ -563,6 +635,7 @@ * Error out if the target name/group is different from * the name/group of the cwd or the program. */ +#if 0 if ((uid != dir_info.st_uid) || (gid != dir_info.st_gid) || (uid != prg_info.st_uid) || @@ -574,6 +647,7 @@ prg_info.st_uid, prg_info.st_gid); exit(120); } +#endif /* * Error out if the program is not executable for the user. * Otherwise, she won't find any error in the logs except for @@ -609,6 +683,13 @@ log = NULL; } + if (is_static_extension(cmd)) { + argv[2] = STATIC_CAT_PATH; + execv(STATIC_CAT_PATH, &argv[2]); + log_err("(%d)%s: static_cat exec failed (%s)\n", errno, strerror(errno), argv[2]); + exit(255); + } + /* * Execute the command, replacing our image with its own. */