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

📄 suexec.c

📁 Apache HTTP Server 是一个功能强大的灵活的与HTTP/1.1相兼容的web服务器.这里给出的是Apache HTTP服务器的源码。
💻 C
📖 第 1 页 / 共 2 页
字号:
        exit(101);    }    target_uname = argv[1];    target_gname = argv[2];    cmd = argv[3];    /*     * Check to see if the user running this program     * is the user allowed to do so as defined in     * suexec.h.  If not the allowed user, error out.     */#ifdef _OSD_POSIX    /* User name comparisons are case insensitive on BS2000/OSD */    if (strcasecmp(AP_HTTPD_USER, pw->pw_name)) {        log_err("user mismatch (%s instead of %s)\n", pw->pw_name, AP_HTTPD_USER);        exit(103);    }#else  /*_OSD_POSIX*/    if (strcmp(AP_HTTPD_USER, pw->pw_name)) {        log_err("user mismatch (%s instead of %s)\n", pw->pw_name, AP_HTTPD_USER);        exit(103);    }#endif /*_OSD_POSIX*/    /*     * Check for a leading '/' (absolute path) in the command to be executed,     * or attempts to back up out of the current directory,     * to protect against attacks.  If any are     * found, error out.  Naughty naughty crackers.     */    if ((cmd[0] == '/') || (!strncmp(cmd, "../", 3))        || (strstr(cmd, "/../") != NULL)) {        log_err("invalid command (%s)\n", cmd);        exit(104);    }    /*     * Check to see if this is a ~userdir request.  If     * so, set the flag, and remove the '~' from the     * target username.     */    if (!strncmp("~", target_uname, 1)) {        target_uname++;        userdir = 1;    }    /*     * Error out if the target username is invalid.     */    if (strspn(target_uname, "1234567890") != strlen(target_uname)) {        if ((pw = getpwnam(target_uname)) == NULL) {            log_err("invalid target user name: (%s)\n", target_uname);            exit(105);        }    }    else {        if ((pw = getpwuid(atoi(target_uname))) == NULL) {            log_err("invalid target user id: (%s)\n", target_uname);            exit(121);        }    }    /*     * Error out if the target group name is invalid.     */    if (strspn(target_gname, "1234567890") != strlen(target_gname)) {        if ((gr = getgrnam(target_gname)) == NULL) {            log_err("invalid target group name: (%s)\n", target_gname);            exit(106);        }        gid = gr->gr_gid;        actual_gname = strdup(gr->gr_name);    }    else {        gid = atoi(target_gname);        actual_gname = strdup(target_gname);    }#ifdef _OSD_POSIX    /*     * Initialize BS2000 user environment     */    {        pid_t pid;        int status;        switch (pid = ufork(target_uname)) {        case -1:    /* Error */            log_err("failed to setup bs2000 environment for user %s: %s\n",                    target_uname, strerror(errno));            exit(150);        case 0:     /* Child */            break;        default:    /* Father */            while (pid != waitpid(pid, &status, 0))                ;            /* @@@ FIXME: should we deal with STOP signals as well? */            if (WIFSIGNALED(status)) {                kill (getpid(), WTERMSIG(status));            }            exit(WEXITSTATUS(status));        }    }#endif /*_OSD_POSIX*/        /*     * Save these for later since initgroups will hose the struct     */    uid = pw->pw_uid;    actual_uname = strdup(pw->pw_name);    target_homedir = strdup(pw->pw_dir);    /*     * Log the transaction here to be sure we have an open log      * before we setuid().     */    log_err("uid: (%s/%s) gid: (%s/%s) cmd: %s\n",            target_uname, actual_uname,            target_gname, actual_gname,            cmd);    /*     * 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)) {        log_err("cannot run as forbidden uid (%d/%s)\n", uid, cmd);        exit(107);    }    /*     * Error out if attempt is made to execute as root group     * or as a GID less than AP_GID_MIN.  Tsk tsk.     */    if ((gid == 0) || (gid < AP_GID_MIN)) {        log_err("cannot run as forbidden gid (%d/%s)\n", gid, cmd);        exit(108);    }    /*     * Change UID/GID here so that the following tests work over NFS.     *     * Initialize the group access list for the target user,     * and setgid() to the target group. If unsuccessful, error out.     */    if (((setgid(gid)) != 0) || (initgroups(actual_uname, gid) != 0)) {        log_err("failed to setgid (%ld: %s)\n", gid, cmd);        exit(109);    }    /*     * setuid() to the target user.  Error out on fail.     */    if ((setuid(uid)) != 0) {        log_err("failed to setuid (%ld: %s)\n", uid, cmd);        exit(110);    }    /*     * Get the current working directory, as well as the proper     * document root (dependant upon whether or not it is a     * ~userdir request).  Error out if we cannot get either one,     * or if the current working directory is not in the docroot.     * Use chdir()s and getcwd()s to avoid problems with symlinked     * directories.  Yuck.     */    if (getcwd(cwd, AP_MAXPATH) == NULL) {        log_err("cannot get current working directory\n");        exit(111);    }    if (userdir) {        if (((chdir(target_homedir)) != 0) ||            ((chdir(AP_USERDIR_SUFFIX)) != 0) ||            ((getcwd(dwd, AP_MAXPATH)) == NULL) ||            ((chdir(cwd)) != 0)) {            log_err("cannot get docroot information (%s)\n", target_homedir);            exit(112);        }    }    else {        if (((chdir(AP_DOC_ROOT)) != 0) ||            ((getcwd(dwd, AP_MAXPATH)) == NULL) ||            ((chdir(cwd)) != 0)) {            log_err("cannot get docroot information (%s)\n", AP_DOC_ROOT);            exit(113);        }    }    if ((strncmp(cwd, dwd, strlen(dwd))) != 0) {        log_err("command not in docroot (%s/%s)\n", cwd, cmd);        exit(114);    }    /*     * Stat the cwd and verify it is a directory, or error out.     */    if (((lstat(cwd, &dir_info)) != 0) || !(S_ISDIR(dir_info.st_mode))) {        log_err("cannot stat directory: (%s)\n", cwd);        exit(115);    }    /*     * Error out if cwd is writable by others.     */    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);    }    /*     * Error out if we cannot stat the program.     */    if (((lstat(cmd, &prg_info)) != 0) || (S_ISLNK(prg_info.st_mode))) {        log_err("cannot stat program: (%s)\n", cmd);        exit(117);    }    /*     * Error out if the program is writable by others.     */    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);    }    /*     * Error out if the file is setuid or setgid.     */    if ((prg_info.st_mode & S_ISUID) || (prg_info.st_mode & S_ISGID)) {        log_err("file is either setuid or setgid: (%s/%s)\n", cwd, cmd);        exit(119);    }    /*     * Error out if the target name/group is different from     * the name/group of the cwd or the program.     */    if ((uid != dir_info.st_uid) ||        (gid != dir_info.st_gid) ||        (uid != prg_info.st_uid) ||        (gid != prg_info.st_gid)) {        log_err("target uid/gid (%ld/%ld) mismatch "                "with directory (%ld/%ld) or program (%ld/%ld)\n",                uid, gid,                dir_info.st_uid, dir_info.st_gid,                prg_info.st_uid, prg_info.st_gid);        exit(120);    }    /*     * Error out if the program is not executable for the user.     * Otherwise, she won't find any error in the logs except for     * "[error] Premature end of script headers: ..."     */    if (!(prg_info.st_mode & S_IXUSR)) {        log_err("file has no execute permission: (%s/%s)\n", cwd, cmd);        exit(121);    }#ifdef AP_SUEXEC_UMASK    /*     * umask() uses inverse logic; bits are CLEAR for allowed access.     */    if ((~AP_SUEXEC_UMASK) & 0022) {        log_err("notice: AP_SUEXEC_UMASK of %03o allows "                "write permission to group and/or other\n", AP_SUEXEC_UMASK);    }    umask(AP_SUEXEC_UMASK);#endif /* AP_SUEXEC_UMASK */    /*      * Be sure to close the log file so the CGI can't     * mess with it.  If the exec fails, it will be reopened      * automatically when log_err is called.  Note that the log     * might not actually be open if AP_LOG_EXEC isn't defined.     * However, the "log" cell isn't ifdef'd so let's be defensive     * and assume someone might have done something with it     * outside an ifdef'd AP_LOG_EXEC block.     */    if (log != NULL) {        fclose(log);        log = NULL;    }    /*     * Execute the command, replacing our image with its own.     */#ifdef NEED_HASHBANG_EMUL    /* We need the #! emulation when we want to execute scripts */    {        extern char **environ;        ap_execve(cmd, &argv[3], environ);    }#else /*NEED_HASHBANG_EMUL*/    execv(cmd, &argv[3]);#endif /*NEED_HASHBANG_EMUL*/    /*     * (I can't help myself...sorry.)     *     * Uh oh.  Still here.  Where's the kaboom?  There was supposed to be an     * EARTH-shattering kaboom!     *     * Oh well, log the failure and error out.     */    log_err("(%d)%s: exec failed (%s)\n", errno, strerror(errno), cmd);    exit(255);}

⌨️ 快捷键说明

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