⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 unixd.c

📁 Apache官方在今天放出产品系列2.2的最新版本2.2.11的源码包 最流行的HTTP服务器软件之一
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements.  See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License.  You may obtain a copy of the License at * *     http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */#include "ap_config.h"#define CORE_PRIVATE#include "httpd.h"#include "http_config.h"#include "http_main.h"#include "http_log.h"#include "unixd.h"#include "mpm_common.h"#include "os.h"#include "ap_mpm.h"#include "apr_thread_proc.h"#include "apr_strings.h"#include "apr_portable.h"#ifdef HAVE_PWD_H#include <pwd.h>#endif#ifdef HAVE_SYS_RESOURCE_H#include <sys/resource.h>#endif/* XXX */#include <sys/stat.h>#ifdef HAVE_UNISTD_H#include <unistd.h>#endif#ifdef HAVE_GRP_H#include <grp.h>#endif#ifdef HAVE_STRINGS_H#include <strings.h>#endif#ifdef HAVE_SYS_SEM_H#include <sys/sem.h>#endif#ifdef HAVE_SYS_PRCTL_H#include <sys/prctl.h>#endifunixd_config_rec unixd_config;/* Set group privileges. * * Note that we use the username as set in the config files, rather than * the lookup of to uid --- the same uid may have multiple passwd entries, * with different sets of groups for each. */static int set_group_privs(void){    if (!geteuid()) {        const char *name;        /* Get username if passed as a uid */        if (unixd_config.user_name[0] == '#') {            struct passwd *ent;            uid_t uid = atoi(&unixd_config.user_name[1]);            if ((ent = getpwuid(uid)) == NULL) {                ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL,                         "getpwuid: couldn't determine user name from uid %u, "                         "you probably need to modify the User directive",                         (unsigned)uid);                return -1;            }            name = ent->pw_name;        }        else            name = unixd_config.user_name;#if !defined(OS2) && !defined(TPF)        /* OS/2 and TPF don't support groups. */        /*         * Set the GID before initgroups(), since on some platforms         * setgid() is known to zap the group list.         */        if (setgid(unixd_config.group_id) == -1) {            ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL,                        "setgid: unable to set group id to Group %u",                        (unsigned)unixd_config.group_id);            return -1;        }        /* Reset `groups' attributes. */        if (initgroups(name, unixd_config.group_id) == -1) {            ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL,                        "initgroups: unable to set groups for User %s "                        "and Group %u", name, (unsigned)unixd_config.group_id);            return -1;        }#endif /* !defined(OS2) && !defined(TPF) */    }    return 0;}AP_DECLARE(int) unixd_setup_child(void){    if (set_group_privs()) {        return -1;    }    if (NULL != unixd_config.chroot_dir) {        if (geteuid()) {            ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL,                         "Cannot chroot when not started as root");            return -1;        }        if (chdir(unixd_config.chroot_dir) != 0) {            ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL,                         "Can't chdir to %s", unixd_config.chroot_dir);            return -1;        }        if (chroot(unixd_config.chroot_dir) != 0) {            ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL,                         "Can't chroot to %s", unixd_config.chroot_dir);            return -1;        }        if (chdir("/") != 0) {            ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL,                         "Can't chdir to new root");            return -1;        }    }#ifdef MPE    /* Only try to switch if we're running as MANAGER.SYS */    if (geteuid() == 1 && unixd_config.user_id > 1) {        GETPRIVMODE();        if (setuid(unixd_config.user_id) == -1) {            GETUSERMODE();            ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL,                        "setuid: unable to change to uid: %ld",                        (long) unixd_config.user_id);            exit(1);        }        GETUSERMODE();    }#else    /* Only try to switch if we're running as root */    if (!geteuid() && (#ifdef _OSD_POSIX        os_init_job_environment(NULL, unixd_config.user_name, ap_exists_config_define("DEBUG")) != 0 ||#endif        setuid(unixd_config.user_id) == -1)) {        ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL,                    "setuid: unable to change to uid: %ld",                    (long) unixd_config.user_id);        return -1;    }#if defined(HAVE_PRCTL) && defined(PR_SET_DUMPABLE)    /* this applies to Linux 2.4+ */#ifdef AP_MPM_WANT_SET_COREDUMPDIR    if (ap_coredumpdir_configured) {        if (prctl(PR_SET_DUMPABLE, 1)) {            ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL,                         "set dumpable failed - this child will not coredump"                         " after software errors");        }    }#endif#endif#endif    return 0;}AP_DECLARE(const char *) unixd_set_user(cmd_parms *cmd, void *dummy,                                        const char *arg){    const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);    if (err != NULL) {        return err;    }    unixd_config.user_name = arg;    unixd_config.user_id = ap_uname2id(arg);#if !defined (BIG_SECURITY_HOLE) && !defined (OS2)    if (unixd_config.user_id == 0) {        return "Error:\tApache has not been designed to serve pages while\n"                "\trunning as root.  There are known race conditions that\n"                "\twill allow any local user to read any file on the system.\n"                "\tIf you still desire to serve pages as root then\n"                "\tadd -DBIG_SECURITY_HOLE to the CFLAGS env variable\n"                "\tand then rebuild the server.\n"                "\tIt is strongly suggested that you instead modify the User\n"                "\tdirective in your httpd.conf file to list a non-root\n"                "\tuser.\n";    }#endif    return NULL;}AP_DECLARE(const char *) unixd_set_group(cmd_parms *cmd, void *dummy,                                         const char *arg){    const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);    if (err != NULL) {        return err;    }    unixd_config.group_id = ap_gname2id(arg);    return NULL;}AP_DECLARE(const char *) unixd_set_chroot_dir(cmd_parms *cmd, void *dummy,                                              const char *arg){    const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);    if (err != NULL) {        return err;    }    if (!ap_is_directory(cmd->pool, arg)) {        return "ChrootDir must be a valid directory";    }    unixd_config.chroot_dir = arg;    return NULL;}AP_DECLARE(void) unixd_pre_config(apr_pool_t *ptemp){    apr_finfo_t wrapper;    unixd_config.user_name = DEFAULT_USER;    unixd_config.user_id = ap_uname2id(DEFAULT_USER);    unixd_config.group_id = ap_gname2id(DEFAULT_GROUP);        unixd_config.chroot_dir = NULL; /* none */    /* Check for suexec */    unixd_config.suexec_enabled = 0;    if ((apr_stat(&wrapper, SUEXEC_BIN,                  APR_FINFO_NORM, ptemp)) != APR_SUCCESS) {        return;    }    if ((wrapper.protection & APR_USETID) && wrapper.user == 0) {        unixd_config.suexec_enabled = 1;    }}AP_DECLARE(void) unixd_set_rlimit(cmd_parms *cmd, struct rlimit **plimit,                           const char *arg, const char * arg2, int type){#if (defined(RLIMIT_CPU) || defined(RLIMIT_DATA) || defined(RLIMIT_VMEM) || defined(RLIMIT_NPROC) || defined(RLIMIT_AS)) && APR_HAVE_STRUCT_RLIMIT && APR_HAVE_GETRLIMIT    char *str;    struct rlimit *limit;    /* If your platform doesn't define rlim_t then typedef it in ap_config.h */    rlim_t cur = 0;    rlim_t max = 0;    *plimit = (struct rlimit *)apr_pcalloc(cmd->pool, sizeof(**plimit));    limit = *plimit;    if ((getrlimit(type, limit)) != 0)  {        *plimit = NULL;        ap_log_error(APLOG_MARK, APLOG_ERR, errno, cmd->server,                     "%s: getrlimit failed", cmd->cmd->name);        return;    }    if ((str = ap_getword_conf(cmd->pool, &arg))) {        if (!strcasecmp(str, "max")) {            cur = limit->rlim_max;        }        else {            cur = atol(str);        }    }    else {        ap_log_error(APLOG_MARK, APLOG_ERR, 0, cmd->server,                     "Invalid parameters for %s", cmd->cmd->name);        return;    }    if (arg2 && (str = ap_getword_conf(cmd->pool, &arg2))) {        max = atol(str);    }    /* if we aren't running as root, cannot increase max */    if (geteuid()) {        limit->rlim_cur = cur;        if (max) {            ap_log_error(APLOG_MARK, APLOG_ERR, 0, cmd->server,                         "Must be uid 0 to raise maximum %s", cmd->cmd->name);        }    }    else {        if (cur) {            limit->rlim_cur = cur;        }        if (max) {            limit->rlim_max = max;        }    }#else    ap_log_error(APLOG_MARK, APLOG_ERR, 0, cmd->server,                 "Platform does not support rlimit for %s", cmd->cmd->name);#endif}APR_HOOK_STRUCT(               APR_HOOK_LINK(get_suexec_identity))AP_IMPLEMENT_HOOK_RUN_FIRST(ap_unix_identity_t *, get_suexec_identity,                         (const request_rec *r), (r), NULL)static apr_status_t ap_unix_create_privileged_process(                              apr_proc_t *newproc, const char *progname,                              const char * const *args,                              const char * const *env,                              apr_procattr_t *attr, ap_unix_identity_t *ugid,                              apr_pool_t *p){    int i = 0;    const char **newargs;    char *newprogname;    char *execuser, *execgroup;    const char *argv0;    if (!unixd_config.suexec_enabled) {        return apr_proc_create(newproc, progname, args, env, attr, p);    }    argv0 = ap_strrchr_c(progname, '/');    /* Allow suexec's "/" check to succeed */    if (argv0 != NULL) {        argv0++;    }    else {        argv0 = progname;    }    if (ugid->userdir) {        execuser = apr_psprintf(p, "~%ld", (long) ugid->uid);    }    else {        execuser = apr_psprintf(p, "%ld", (long) ugid->uid);    }    execgroup = apr_psprintf(p, "%ld", (long) ugid->gid);    if (!execuser || !execgroup) {        return APR_ENOMEM;    }    i = 0;    if (args) {        while (args[i]) {            i++;            }    }    /* allocate space for 4 new args, the input args, and a null terminator */    newargs = apr_palloc(p, sizeof(char *) * (i + 4));    newprogname = SUEXEC_BIN;    newargs[0] = SUEXEC_BIN;    newargs[1] = execuser;    newargs[2] = execgroup;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -