📄 suexec.c
字号:
/* Copyright 1999-2005 The Apache Software Foundation or its licensors, as * applicable. * * Licensed 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. *//* * suexec.c -- "Wrapper" support program for suEXEC behaviour for Apache * *********************************************************************** * * NOTE! : DO NOT edit this code!!! Unless you know what you are doing, * editing this code might open up your system in unexpected * ways to would-be crackers. Every precaution has been taken * to make this code as safe as possible; alter it at your own * risk. * *********************************************************************** * * */#include "apr.h"#include "ap_config.h"#include "suexec.h"#include <sys/param.h>#include <sys/stat.h>#include <sys/types.h>#include <string.h>#include <time.h>#if APR_HAVE_UNISTD_H#include <unistd.h>#endif#include <stdio.h>#include <stdarg.h>#include <stdlib.h>#ifdef HAVE_PWD_H#include <pwd.h>#endif#ifdef HAVE_GRP_H#include <grp.h>#endif/* *********************************************************************** * There is no initgroups() in QNX, so I believe this is safe :-) * Use cc -osuexec -3 -O -mf -DQNX suexec.c to compile. * * May 17, 1997. * Igor N. Kovalenko -- infoh@mail.wplus.net *********************************************************************** */#if defined(NEED_INITGROUPS)int initgroups(const char *name, gid_t basegid){ /* QNX and MPE do not appear to support supplementary groups. */ return 0;}#endif#if defined(SUNOS4)extern char *sys_errlist[];#define strerror(x) sys_errlist[(x)]#endif#if defined(PATH_MAX)#define AP_MAXPATH PATH_MAX#elif defined(MAXPATHLEN)#define AP_MAXPATH MAXPATHLEN#else#define AP_MAXPATH 8192#endif#define AP_ENVBUF 256extern char **environ;static FILE *log = NULL;char *safe_env_lst[] ={ /* variable name starts with */ "HTTP_", "SSL_", /* variable name is */ "AUTH_TYPE=", "CONTENT_LENGTH=", "CONTENT_TYPE=", "DATE_GMT=", "DATE_LOCAL=", "DOCUMENT_NAME=", "DOCUMENT_PATH_INFO=", "DOCUMENT_ROOT=", "DOCUMENT_URI=", "FILEPATH_INFO=", "GATEWAY_INTERFACE=", "HTTPS=", "LAST_MODIFIED=", "PATH_INFO=", "PATH_TRANSLATED=", "QUERY_STRING=", "QUERY_STRING_UNESCAPED=", "REMOTE_ADDR=", "REMOTE_HOST=", "REMOTE_IDENT=", "REMOTE_PORT=", "REMOTE_USER=", "REDIRECT_QUERY_STRING=", "REDIRECT_REMOTE_USER=", "REDIRECT_STATUS=", "REDIRECT_URL=", "REQUEST_METHOD=", "REQUEST_URI=", "SCRIPT_FILENAME=", "SCRIPT_NAME=", "SCRIPT_URI=", "SCRIPT_URL=", "SERVER_ADMIN=", "SERVER_NAME=", "SERVER_ADDR=", "SERVER_PORT=", "SERVER_PROTOCOL=", "SERVER_SIGNATURE=", "SERVER_SOFTWARE=", "UNIQUE_ID=", "USER_NAME=", "TZ=", NULL};static void err_output(const char *fmt, va_list ap){#ifdef AP_LOG_EXEC time_t timevar; struct tm *lt; if (!log) { if ((log = fopen(AP_LOG_EXEC, "a")) == NULL) { fprintf(stderr, "failed to open log file\n"); perror("fopen"); exit(1); } } time(&timevar); lt = localtime(&timevar); fprintf(log, "[%d-%.2d-%.2d %.2d:%.2d:%.2d]: ", lt->tm_year + 1900, lt->tm_mon + 1, lt->tm_mday, lt->tm_hour, lt->tm_min, lt->tm_sec); vfprintf(log, fmt, ap); fflush(log);#endif /* AP_LOG_EXEC */ return;}static void log_err(const char *fmt,...){#ifdef AP_LOG_EXEC va_list ap; va_start(ap, fmt); err_output(fmt, ap); va_end(ap);#endif /* AP_LOG_EXEC */ return;}static void clean_env(void){ char pathbuf[512]; char **cleanenv; char **ep; int cidx = 0; int idx; /* While cleaning the environment, the environment should be clean. * (e.g. malloc() may get the name of a file for writing debugging info. * Bad news if MALLOC_DEBUG_FILE is set to /etc/passwd. Sprintf() may be * susceptible to bad locale settings....) * (from PR 2790) */ char **envp = environ; char *empty_ptr = NULL; environ = &empty_ptr; /* VERY safe environment */ if ((cleanenv = (char **) calloc(AP_ENVBUF, sizeof(char *))) == NULL) { log_err("failed to malloc memory for environment\n"); exit(120); } sprintf(pathbuf, "PATH=%s", AP_SAFE_PATH); cleanenv[cidx] = strdup(pathbuf); cidx++; for (ep = envp; *ep && cidx < AP_ENVBUF-1; ep++) { for (idx = 0; safe_env_lst[idx]; idx++) { if (!strncmp(*ep, safe_env_lst[idx], strlen(safe_env_lst[idx]))) { cleanenv[cidx] = *ep; cidx++; break; } } } cleanenv[cidx] = NULL; environ = cleanenv;}int main(int argc, char *argv[]){ int userdir = 0; /* ~userdir flag */ uid_t uid; /* user information */ gid_t gid; /* target group placeholder */ char *target_uname; /* target user name */ char *target_gname; /* target group name */ char *target_homedir; /* target home directory */ char *actual_uname; /* actual user name */ char *actual_gname; /* actual group name */ char *prog; /* name of this program */ char *cmd; /* command to be executed */ char cwd[AP_MAXPATH]; /* current working directory */ char dwd[AP_MAXPATH]; /* docroot working directory */ struct passwd *pw; /* password entry holder */ struct group *gr; /* group entry holder */ struct stat dir_info; /* directory info holder */ struct stat prg_info; /* program info holder */ /* * Start with a "clean" environment */ clean_env(); prog = argv[0]; /* * Check existence/validity of the UID of the user * running this program. Error out if invalid. */ uid = getuid(); if ((pw = getpwuid(uid)) == NULL) { log_err("crit: invalid uid: (%ld)\n", uid); exit(102); } /* * See if this is a 'how were you compiled' request, and * comply if so. */ if ((argc > 1) && (! strcmp(argv[1], "-V")) && ((uid == 0)#ifdef _OSD_POSIX /* User name comparisons are case insensitive on BS2000/OSD */ || (! strcasecmp(AP_HTTPD_USER, pw->pw_name)))#else /* _OSD_POSIX */ || (! strcmp(AP_HTTPD_USER, pw->pw_name)))#endif /* _OSD_POSIX */ ) {#ifdef AP_DOC_ROOT fprintf(stderr, " -D AP_DOC_ROOT=\"%s\"\n", AP_DOC_ROOT);#endif#ifdef AP_GID_MIN fprintf(stderr, " -D AP_GID_MIN=%d\n", AP_GID_MIN);#endif#ifdef AP_HTTPD_USER fprintf(stderr, " -D AP_HTTPD_USER=\"%s\"\n", AP_HTTPD_USER);#endif#ifdef AP_LOG_EXEC fprintf(stderr, " -D AP_LOG_EXEC=\"%s\"\n", AP_LOG_EXEC);#endif#ifdef AP_SAFE_PATH fprintf(stderr, " -D AP_SAFE_PATH=\"%s\"\n", AP_SAFE_PATH);#endif#ifdef AP_SUEXEC_UMASK fprintf(stderr, " -D AP_SUEXEC_UMASK=%03o\n", AP_SUEXEC_UMASK);#endif#ifdef AP_UID_MIN fprintf(stderr, " -D AP_UID_MIN=%d\n", AP_UID_MIN);#endif#ifdef AP_USERDIR_SUFFIX fprintf(stderr, " -D AP_USERDIR_SUFFIX=\"%s\"\n", AP_USERDIR_SUFFIX);#endif exit(0); } /* * If there are a proper number of arguments, set * all of them to variables. Otherwise, error out. */ if (argc < 4) { log_err("too few arguments\n");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -