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

Last change on this file since 873 was 873, checked in by andersk, 15 years ago
No more x bit hack.
File size: 8.9 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.2/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"
     
    4648#include <stdio.h>
    4749#include <stdarg.h>
    4850#include <stdlib.h>
     51#include <selinux/selinux.h>
    4952
    5053#ifdef HAVE_PWD_H
    5154#include <pwd.h>
     
    9598{
    9699    /* variable name starts with */
    97100    "HTTP_",
     101    "HTTPS_",
    98102    "SSL_",
    99103
    100104    /* 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    NULL
     288};
     289
     290static int is_static_extension(const char *file)
     291{
     292    const char *extension = strrchr(file, '.');
     293    const char **p;
     294    if (extension == NULL) return 0;
     295    for (p = static_extensions; *p; ++p) {
     296        if (strcmp(extension + 1, *p) == 0) return 1;
     297    }
     298    return 0;
     299}
     300
     301static int is_php_extension(const char *file)
     302{
     303    const char *extension = strrchr(file, '.');
     304    if (extension == NULL) return 0;
     305    return strcmp(extension + 1, "php") == 0;
     306}
     307
    248308int main(int argc, char *argv[])
    249309{
    250310    int userdir = 0;        /* ~userdir flag             */
     311    int trusteddir = 0;     /* TRUSTED_DIRECTORY flag    */
    251312    uid_t uid;              /* user information          */
    252313    gid_t gid;              /* target group placeholder  */
    253314    char *target_uname;     /* target user name          */
     
    350404#endif /*_OSD_POSIX*/
    351405
    352406    /*
     407     * First check if this is an absolute path to the directory
     408     * of trusted executables. These are supposed to be security
     409     * audited to check parameters and validity on their own...
     410     */
     411    if (strstr(cmd, AP_TRUSTED_DIRECTORY) == cmd) {
     412        if (strstr(cmd, "/../") != NULL) {
     413            log_err("invalid command (%s)\n", cmd);
     414            exit(104);
     415        }
     416        trusteddir = 1;
     417        goto TRUSTED_DIRECTORY;
     418    }
     419
     420    /*
    353421     * Check for a leading '/' (absolute path) in the command to be executed,
    354422     * or attempts to back up out of the current directory,
    355423     * to protect against attacks.  If any are
     
    371439        userdir = 1;
    372440    }
    373441
     442TRUSTED_DIRECTORY:
    374443    /*
    375444     * Error out if the target username is invalid.
    376445     */
     
    450519     * Error out if attempt is made to execute as root or as
    451520     * a UID less than AP_UID_MIN.  Tsk tsk.
    452521     */
    453     if ((uid == 0) || (uid < AP_UID_MIN)) {
     522    if ((uid == 0) || (uid < AP_UID_MIN && uid != 102)) {
    454523        log_err("cannot run as forbidden uid (%d/%s)\n", uid, cmd);
    455524        exit(107);
    456525    }
     
    482551        log_err("failed to setuid (%ld: %s)\n", uid, cmd);
    483552        exit(110);
    484553    }
     554    if (is_selinux_enabled()) {
     555        if (uid == 102) {
     556            if (setexeccon("system_u:system_r:signup_t:s0") == -1) {
     557                log_err("failed to setexeccon (%ld: %s) to signup_t\n", uid, cmd);
     558                exit(201);
     559            }
     560        } else {
     561            if (setexeccon("user_u:user_r:user_t:s0") == -1) {
     562                log_err("failed to setexeccon (%ld: %s) to user_t\n", uid, cmd);
     563                exit(202);
     564            }
     565        }
     566    }
    485567
    486568    /*
    487569     * Get the current working directory, as well as the proper
     
    504586            log_err("cannot get docroot information (%s)\n", target_homedir);
    505587            exit(112);
    506588        }
     589        size_t expected_len = strlen(target_homedir)+1+strlen(AP_USERDIR_SUFFIX)+1;
     590        char *expected = malloc(expected_len);
     591        snprintf(expected, expected_len, "%s/%s", target_homedir, AP_USERDIR_SUFFIX);
     592        if (strncmp(cwd, expected, expected_len-1) != 0) {
     593            log_err("error: file's directory not a subdirectory of user's home directory (%s, %s)\n", cwd, expected);
     594            exit(114);
     595        }
     596    }
     597    else if (trusteddir) {
     598        if (((chdir(AP_TRUSTED_DIRECTORY)) != 0) ||
     599            ((getcwd(dwd, AP_MAXPATH)) == NULL) |
     600            ((chdir(cwd)) != 0)) {
     601            log_err("cannot get docroot information (%s)\n", AP_TRUSTED_DIRECTORY);
     602            exit(112);
     603        }
    507604    }
    508605    else {
    509606        if (((chdir(AP_DOC_ROOT)) != 0) ||
     
    530627    /*
    531628     * Error out if cwd is writable by others.
    532629     */
     630#if 0
    533631    if ((dir_info.st_mode & S_IWOTH) || (dir_info.st_mode & S_IWGRP)) {
    534632        log_err("directory is writable by others: (%s)\n", cwd);
    535633        exit(116);
    536634    }
     635#endif
    537636
    538637    /*
    539638     * Error out if we cannot stat the program.
    540639     */
    541     if (((lstat(cmd, &prg_info)) != 0) || (S_ISLNK(prg_info.st_mode))) {
     640    if (((lstat(cmd, &prg_info)) != 0) /*|| (S_ISLNK(prg_info.st_mode))*/) {
    542641        log_err("cannot stat program: (%s)\n", cmd);
    543642        exit(117);
    544643    }
     
    546645    /*
    547646     * Error out if the program is writable by others.
    548647     */
     648#if 0
    549649    if ((prg_info.st_mode & S_IWOTH) || (prg_info.st_mode & S_IWGRP)) {
    550650        log_err("file is writable by others: (%s/%s)\n", cwd, cmd);
    551651        exit(118);
    552652    }
     653#endif
    553654
    554655    /*
    555656     * Error out if the file is setuid or setgid.
     
    563664     * Error out if the target name/group is different from
    564665     * the name/group of the cwd or the program.
    565666     */
     667#if 0
    566668    if ((uid != dir_info.st_uid) ||
    567669        (gid != dir_info.st_gid) ||
    568670        (uid != prg_info.st_uid) ||
     
    574676                prg_info.st_uid, prg_info.st_gid);
    575677        exit(120);
    576678    }
     679#endif
    577680    /*
    578681     * Error out if the program is not executable for the user.
    579682     * Otherwise, she won't find any error in the logs except for
    580683     * "[error] Premature end of script headers: ..."
    581684     */
    582     if (!(prg_info.st_mode & S_IXUSR)) {
     685    if (!is_static_extension(cmd) && !is_php_extension(cmd) &&
     686        !(prg_info.st_mode & S_IXUSR)) {
    583687        log_err("file has no execute permission: (%s/%s)\n", cwd, cmd);
    584688        exit(121);
    585689    }
     
    606709      exit(122);
    607710    }
    608711
     712    if (is_static_extension(cmd)) {
     713        argv[2] = STATIC_CAT_PATH;
     714        execv(STATIC_CAT_PATH, &argv[2]);
     715        log_err("(%d)%s: static_cat exec failed (%s)\n", errno, strerror(errno), argv[2]);
     716        exit(255);
     717    }
     718    if (is_php_extension(cmd)) {
     719        setenv("PHPRC", ".", 1);
     720        argv[1] = PHP_PATH;
     721        argv[2] = "-f";
     722        execv(PHP_PATH, &argv[1]);
     723        log_err("(%d)%s: php exec failed (%s)\n", errno, strerror(errno), argv[2]);
     724        exit(255);
     725    }
     726
    609727    /*
    610728     * Execute the command, replacing our image with its own.
    611729     */
Note: See TracBrowser for help on using the repository browser.