source: trunk/server/common/patches/httpd-suexec-scripts.patch @ 1453

Last change on this file since 1453 was 1355, checked in by andersk, 14 years ago
suexec: Exec static-cat or php-cgi after closing the suexec log.
File size: 9.3 KB
  • httpd-2.2.2/support/Makefile.in

    # scripts.mit.edu httpd suexec patch
    # Copyright (C) 2006, 2007, 2008  Jeff Arnold <jbarnold@mit.edu>,
    #                                 Joe Presbrey <presbrey@mit.edu>,
    #                                 Anders Kaseorg <andersk@mit.edu>,
    #                                 Geoffrey Thomas <geofft@mit.edu>
    #
    # 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.
    #
    old new  
    6060
    6161suexec_OBJECTS = suexec.lo
    6262suexec: $(suexec_OBJECTS)
    63         $(LINK) $(suexec_OBJECTS)
     63        $(LINK) -lselinux $(suexec_OBJECTS)
    6464
    6565htcacheclean_OBJECTS = htcacheclean.lo
    6666htcacheclean: $(htcacheclean_OBJECTS)
  • httpd-2.2.2/configure.in

    old new  
    559559APACHE_HELP_STRING(--with-suexec-userdir,User subdirectory),[
    560560  AC_DEFINE_UNQUOTED(AP_USERDIR_SUFFIX, "$withval", [User subdirectory] ) ] )
    561561
     562AC_ARG_WITH(suexec-trusteddir,
     563APACHE_HELP_STRING(--with-suexec-trusteddir,Trusted SuExec directory),[
     564  AC_DEFINE_UNQUOTED(AP_TRUSTED_DIRECTORY, "$withval", [Trusted SuExec directory] ) ] )
     565
    562566AC_ARG_WITH(suexec-docroot,
    563567APACHE_HELP_STRING(--with-suexec-docroot,SuExec root directory),[
    564568  AC_DEFINE_UNQUOTED(AP_DOC_ROOT, "$withval", [SuExec root directory] ) ] )
  • httpd-2.2.11/support/suexec.c

    old new  
    3030 *
    3131 */
    3232
     33#define STATIC_CAT_PATH "/usr/local/bin/static-cat"
     34#define PHP_PATH "/usr/bin/php-cgi"
     35
    3336#include "apr.h"
    3437#include "ap_config.h"
    3538#include "suexec.h"
     
    4649#include <stdio.h>
    4750#include <stdarg.h>
    4851#include <stdlib.h>
     52#include <selinux/selinux.h>
    4953
    5054#ifdef HAVE_PWD_H
    5155#include <pwd.h>
     
    9599{
    96100    /* variable name starts with */
    97101    "HTTP_",
     102    "HTTPS_",
    98103    "SSL_",
    99104
    100105    /* variable name is */
     
    245250    environ = cleanenv;
    246251}
    247252
     253static const char *static_extensions[] = {
     254    "html",
     255    "css",
     256    "gif",
     257    "jpg",
     258    "png",
     259    "htm",
     260    "jpeg",
     261    "js",
     262    "ico",
     263    "xml",
     264    "xsl",
     265    "tiff",
     266    "tif",
     267    "tgz",
     268    "tar",
     269    "jar",
     270    "zip",
     271    "pdf",
     272    "ps",
     273    "doc",
     274    "xls",
     275    "ppt",
     276    "swf",
     277    "mp3",
     278    "mov",
     279    "wmv",
     280    "mpg",
     281    "mpeg",
     282    "avi",
     283    "il",
     284    "JPG",
     285    "xhtml",
     286    "svg",
     287    "xaml",
     288    "xap",
     289    NULL
     290};
     291
     292static int is_static_extension(const char *file)
     293{
     294    const char *extension = strrchr(file, '.');
     295    const char **p;
     296    if (extension == NULL) return 0;
     297    for (p = static_extensions; *p; ++p) {
     298        if (strcmp(extension + 1, *p) == 0) return 1;
     299    }
     300    return 0;
     301}
     302
     303static int is_php_extension(const char *file)
     304{
     305    const char *extension = strrchr(file, '.');
     306    if (extension == NULL) return 0;
     307    return strcmp(extension + 1, "php") == 0;
     308}
     309
    248310int main(int argc, char *argv[])
    249311{
    250312    int userdir = 0;        /* ~userdir flag             */
     313    int trusteddir = 0;     /* TRUSTED_DIRECTORY flag    */
    251314    uid_t uid;              /* user information          */
    252315    gid_t gid;              /* target group placeholder  */
    253316    char *target_uname;     /* target user name          */
     
    268331     * Start with a "clean" environment
    269332     */
    270333    clean_env();
     334    setenv("JAVA_TOOL_OPTIONS", "-Xmx128M", 1); /* scripts.mit.edu local hack */
    271335
    272336    prog = argv[0];
    273337    /*
     
    350414#endif /*_OSD_POSIX*/
    351415
    352416    /*
     417     * First check if this is an absolute path to the directory
     418     * of trusted executables. These are supposed to be security
     419     * audited to check parameters and validity on their own...
     420     */
     421    if (strstr(cmd, AP_TRUSTED_DIRECTORY) == cmd) {
     422        if (strstr(cmd, "/../") != NULL) {
     423            log_err("invalid command (%s)\n", cmd);
     424            exit(104);
     425        }
     426        trusteddir = 1;
     427        goto TRUSTED_DIRECTORY;
     428    }
     429
     430    /*
    353431     * Check for a leading '/' (absolute path) in the command to be executed,
    354432     * or attempts to back up out of the current directory,
    355433     * to protect against attacks.  If any are
     
    371449        userdir = 1;
    372450    }
    373451
     452TRUSTED_DIRECTORY:
    374453    /*
    375454     * Error out if the target username is invalid.
    376455     */
     
    452531     * Error out if attempt is made to execute as root or as
    453532     * a UID less than AP_UID_MIN.  Tsk tsk.
    454533     */
    455     if ((uid == 0) || (uid < AP_UID_MIN)) {
     534    if ((uid == 0) || (uid < AP_UID_MIN && uid != 102)) {
    456535        log_err("cannot run as forbidden uid (%d/%s)\n", uid, cmd);
    457536        exit(107);
    458537    }
     
    484563        log_err("failed to setuid (%ld: %s)\n", uid, cmd);
    485564        exit(110);
    486565    }
     566    if (is_selinux_enabled()) {
     567        if (uid == 102) {
     568            if (setexeccon("system_u:system_r:signup_t:s0") == -1) {
     569                log_err("failed to setexeccon (%ld: %s) to signup_t\n", uid, cmd);
     570                exit(201);
     571            }
     572        } else {
     573            if (setexeccon("user_u:user_r:user_t:s0") == -1) {
     574                log_err("failed to setexeccon (%ld: %s) to user_t\n", uid, cmd);
     575                exit(202);
     576            }
     577        }
     578    }
     579
     580    setenv("HOME", target_homedir, 1);
    487581
    488582    /*
    489583     * Get the current working directory, as well as the proper
     
    506600            log_err("cannot get docroot information (%s)\n", target_homedir);
    507601            exit(112);
    508602        }
     603        size_t expected_len = strlen(target_homedir)+1+strlen(AP_USERDIR_SUFFIX)+1;
     604        char *expected = malloc(expected_len);
     605        snprintf(expected, expected_len, "%s/%s", target_homedir, AP_USERDIR_SUFFIX);
     606        if (strncmp(cwd, expected, expected_len-1) != 0) {
     607            log_err("error: file's directory not a subdirectory of user's home directory (%s, %s)\n", cwd, expected);
     608            exit(114);
     609        }
     610    }
     611    else if (trusteddir) {
     612        if (((chdir(AP_TRUSTED_DIRECTORY)) != 0) ||
     613            ((getcwd(dwd, AP_MAXPATH)) == NULL) |
     614            ((chdir(cwd)) != 0)) {
     615            log_err("cannot get docroot information (%s)\n", AP_TRUSTED_DIRECTORY);
     616            exit(112);
     617        }
    509618    }
    510619    else {
    511620        if (((chdir(AP_DOC_ROOT)) != 0) ||
     
    532641    /*
    533642     * Error out if cwd is writable by others.
    534643     */
     644#if 0
    535645    if ((dir_info.st_mode & S_IWOTH) || (dir_info.st_mode & S_IWGRP)) {
    536646        log_err("directory is writable by others: (%s)\n", cwd);
    537647        exit(116);
    538648    }
     649#endif
    539650
    540651    /*
    541652     * Error out if we cannot stat the program.
    542653     */
    543     if (((lstat(cmd, &prg_info)) != 0) || (S_ISLNK(prg_info.st_mode))) {
     654    if (((lstat(cmd, &prg_info)) != 0) /*|| (S_ISLNK(prg_info.st_mode))*/) {
    544655        log_err("cannot stat program: (%s)\n", cmd);
    545656        exit(117);
    546657    }
     
    548659    /*
    549660     * Error out if the program is writable by others.
    550661     */
     662#if 0
    551663    if ((prg_info.st_mode & S_IWOTH) || (prg_info.st_mode & S_IWGRP)) {
    552664        log_err("file is writable by others: (%s/%s)\n", cwd, cmd);
    553665        exit(118);
    554666    }
     667#endif
    555668
    556669    /*
    557670     * Error out if the file is setuid or setgid.
     
    565678     * Error out if the target name/group is different from
    566679     * the name/group of the cwd or the program.
    567680     */
     681#if 0
    568682    if ((uid != dir_info.st_uid) ||
    569683        (gid != dir_info.st_gid) ||
    570684        (uid != prg_info.st_uid) ||
     
    576690                prg_info.st_uid, prg_info.st_gid);
    577691        exit(120);
    578692    }
     693#endif
    579694    /*
    580695     * Error out if the program is not executable for the user.
    581696     * Otherwise, she won't find any error in the logs except for
    582697     * "[error] Premature end of script headers: ..."
    583698     */
    584     if (!(prg_info.st_mode & S_IXUSR)) {
     699    if (!is_static_extension(cmd) && !is_php_extension(cmd) &&
     700        !(prg_info.st_mode & S_IXUSR)) {
    585701        log_err("file has no execute permission: (%s/%s)\n", cwd, cmd);
    586702        exit(121);
    587703    }
     
    614730    /*
    615731     * Execute the command, replacing our image with its own.
    616732     */
     733    if (is_static_extension(cmd)) {
     734        argv[2] = STATIC_CAT_PATH;
     735        execv(STATIC_CAT_PATH, &argv[2]);
     736        log_err("(%d)%s: static_cat exec failed (%s)\n", errno, strerror(errno), argv[2]);
     737        exit(255);
     738    }
     739    if (is_php_extension(cmd)) {
     740        setenv("PHPRC", ".", 1);
     741        argv[1] = PHP_PATH;
     742        argv[2] = "-f";
     743        execv(PHP_PATH, &argv[1]);
     744        log_err("(%d)%s: php exec failed (%s)\n", errno, strerror(errno), argv[1]);
     745        exit(255);
     746    }
    617747#ifdef NEED_HASHBANG_EMUL
    618748    /* We need the #! emulation when we want to execute scripts */
    619749    {
Note: See TracBrowser for help on using the repository browser.