diff options
author | Henning Brauer <henning@cvs.openbsd.org> | 2002-07-09 17:28:48 +0000 |
---|---|---|
committer | Henning Brauer <henning@cvs.openbsd.org> | 2002-07-09 17:28:48 +0000 |
commit | 72e0abdf851ab032aee6617e08e532de96025792 (patch) | |
tree | ffc08ea56d682fe7e19320360acab08b96280e78 | |
parent | a747849505003806ab3b78d76dacce7aba6b7c7d (diff) |
apache chroot and privilege drop.
httpd will chroot itself into ServerRoot (/var/www) and drop root privileges
now. This is enabled by default. Make sure to read httpd(8).
help deraadt@
ssl mutex fixes beck@
"commit" deraadt@
-rw-r--r-- | usr.sbin/httpd/conf/httpd.conf | 2 | ||||
-rw-r--r-- | usr.sbin/httpd/src/include/ap_config.h | 4 | ||||
-rw-r--r-- | usr.sbin/httpd/src/main/http_core.c | 10 | ||||
-rw-r--r-- | usr.sbin/httpd/src/main/http_main.c | 58 | ||||
-rw-r--r-- | usr.sbin/httpd/src/modules/ssl/mod_ssl.h | 1 | ||||
-rw-r--r-- | usr.sbin/httpd/src/modules/ssl/ssl_engine_mutex.c | 13 | ||||
-rw-r--r-- | usr.sbin/httpd/src/modules/ssl/ssl_scache_dbm.c | 6 | ||||
-rw-r--r-- | usr.sbin/httpd/src/modules/standard/mod_alias.c | 2 |
8 files changed, 89 insertions, 7 deletions
diff --git a/usr.sbin/httpd/conf/httpd.conf b/usr.sbin/httpd/conf/httpd.conf index 254907e0d2f..9409196e1b4 100644 --- a/usr.sbin/httpd/conf/httpd.conf +++ b/usr.sbin/httpd/conf/httpd.conf @@ -891,7 +891,7 @@ SSLSessionCacheTimeout 300 # Semaphore: # Configure the path to the mutual exclusion semaphore the # SSL engine uses internally for inter-process synchronization. -SSLMutex file:logs/ssl_mutex +SSLMutex sem # Pseudo Random Number Generator (PRNG): # Configure one or more sources to seed the PRNG of the diff --git a/usr.sbin/httpd/src/include/ap_config.h b/usr.sbin/httpd/src/include/ap_config.h index 47ed5199611..4132f91ccdc 100644 --- a/usr.sbin/httpd/src/include/ap_config.h +++ b/usr.sbin/httpd/src/include/ap_config.h @@ -687,7 +687,11 @@ extern char *crypt(); #define HAVE_MMAP 1 #define USE_MMAP_SCOREBOARD #define USE_MMAP_FILES +#if defined __OpenBSD__ +#define HAVE_SYSVSEM_SERIALIZED_ACCEPT +#else #define HAVE_FLOCK_SERIALIZED_ACCEPT +#endif #define SINGLE_LISTEN_UNSERIALIZED_ACCEPT #elif defined(UTS21) diff --git a/usr.sbin/httpd/src/main/http_core.c b/usr.sbin/httpd/src/main/http_core.c index d37b04bd83b..5397eff2316 100644 --- a/usr.sbin/httpd/src/main/http_core.c +++ b/usr.sbin/httpd/src/main/http_core.c @@ -349,6 +349,7 @@ static void *merge_core_dir_configs(pool *a, void *basev, void *newv) if (new->cgi_command_args != AP_FLAG_UNSET) { conf->cgi_command_args = new->cgi_command_args; } + ap_server_strip_chroot(conf->d, 0); return (void*)conf; } @@ -1205,7 +1206,7 @@ static const char *set_document_root(cmd_parms *cmd, void *dummy, char *arg) return "DocumentRoot must be a directory"; } } - + ap_server_strip_chroot(arg, 1); conf->ap_document_root = arg; return NULL; } @@ -1216,6 +1217,7 @@ API_EXPORT(void) ap_custom_response(request_rec *r, int status, char *string) ap_get_module_config(r->per_dir_config, &core_module); int idx; + ap_server_strip_chroot(conf->d, 0); if(conf->response_code_strings == NULL) { conf->response_code_strings = ap_pcalloc(r->pool, @@ -1558,6 +1560,7 @@ static const char *dirsection(cmd_parms *cmd, void *dummy, const char *arg) *endp = '\0'; cmd->path = ap_getword_conf(cmd->pool, &arg); + ap_server_strip_chroot(cmd->path, 1); cmd->override = OR_ALL|ACCESS_CONF; if (thiscmd->cmd_data) { /* <DirectoryMatch> */ @@ -1565,6 +1568,7 @@ static const char *dirsection(cmd_parms *cmd, void *dummy, const char *arg) } else if (!strcmp(cmd->path, "~")) { cmd->path = ap_getword_conf(cmd->pool, &arg); + ap_server_strip_chroot(cmd->path, 1); r = ap_pregcomp(cmd->pool, cmd->path, REG_EXTENDED|USE_ICASE); } #if defined(HAVE_DRIVE_LETTERS) || defined(NETWARE) @@ -1639,6 +1643,7 @@ static const char *urlsection(cmd_parms *cmd, void *dummy, const char *arg) *endp = '\0'; cmd->path = ap_getword_conf(cmd->pool, &arg); + ap_server_strip_chroot(cmd->path, 0); cmd->override = OR_ALL|ACCESS_CONF; if (thiscmd->cmd_data) { /* <LocationMatch> */ @@ -1646,6 +1651,7 @@ static const char *urlsection(cmd_parms *cmd, void *dummy, const char *arg) } else if (!strcmp(cmd->path, "~")) { cmd->path = ap_getword_conf(cmd->pool, &arg); + ap_server_strip_chroot(cmd->path, 0); r = ap_pregcomp(cmd->pool, cmd->path, REG_EXTENDED); } @@ -1707,6 +1713,7 @@ static const char *filesection(cmd_parms *cmd, core_dir_config *c, *endp = '\0'; cmd->path = ap_getword_conf(cmd->pool, &arg); + ap_server_strip_chroot(cmd->path, 1); /* Only if not an .htaccess file */ if (!old_path) { cmd->override = OR_ALL|ACCESS_CONF; @@ -1717,6 +1724,7 @@ static const char *filesection(cmd_parms *cmd, core_dir_config *c, } else if (!strcmp(cmd->path, "~")) { cmd->path = ap_getword_conf(cmd->pool, &arg); + ap_server_strip_chroot(cmd->path, 1); r = ap_pregcomp(cmd->pool, cmd->path, REG_EXTENDED|USE_ICASE); } else { diff --git a/usr.sbin/httpd/src/main/http_main.c b/usr.sbin/httpd/src/main/http_main.c index 29be0125a4c..a754d7cf25e 100644 --- a/usr.sbin/httpd/src/main/http_main.c +++ b/usr.sbin/httpd/src/main/http_main.c @@ -318,6 +318,9 @@ API_VAR_EXPORT array_header *ap_server_pre_read_config=NULL; API_VAR_EXPORT array_header *ap_server_post_read_config=NULL; API_VAR_EXPORT array_header *ap_server_config_defines=NULL; +API_VAR_EXPORT int ap_server_chroot=1; +API_VAR_EXPORT int is_chrooted=0; + /* *Non*-shared http_main globals... */ static server_rec *server_conf; @@ -978,6 +981,7 @@ static void accept_mutex_child_init_flock(pool *p) static void accept_mutex_init_flock(pool *p) { expand_lock_fname(p); + ap_server_strip_chroot(ap_lock_fname, 0); unlink(ap_lock_fname); flock_fd = ap_popenf(p, ap_lock_fname, O_CREAT | O_WRONLY | O_EXCL, 0600); if (flock_fd == -1) { @@ -1384,7 +1388,7 @@ static void usage(char *bin) fprintf(stderr, "Usage: %s [-D name] [-d directory] [-f file]\n", bin); #endif fprintf(stderr, " %s [-C \"directive\"] [-c \"directive\"]\n", pad); - fprintf(stderr, " %s [-v] [-V] [-h] [-l] [-L] [-S] [-t] [-T]\n", pad); + fprintf(stderr, " %s [-v] [-V] [-h] [-l] [-L] [-S] [-t] [-T] [-u]\n", pad); fprintf(stderr, "Options:\n"); #ifdef SHARED_CORE fprintf(stderr, " -R directory : specify an alternate location for shared object files\n"); @@ -4285,6 +4289,8 @@ static void child_main(int child_num_arg) my_child_num = child_num_arg; requests_this_child = 0; + setproctitle("child"); + /* Get a sub pool for global allocations in this child, so that * we can have cleanups occur when the child exits. */ @@ -5139,6 +5145,38 @@ static void standalone_main(int argc, char **argv) ap_set_version(); /* create our server_version string */ ap_init_modules(pconf, server_conf); version_locked++; /* no more changes to server_version */ + + if(!is_graceful && ap_server_chroot) { + if (geteuid()) { + ap_log_error(APLOG_MARK, APLOG_ALERT, server_conf, + "can't run in secure mode if not started with root privs."); + exit(1); + } + + if(chroot(ap_server_root) < 0) { + ap_log_error(APLOG_MARK, APLOG_CRIT, server_conf, + "unable to chroot into %s!", ap_server_root); + exit(1); + } + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, server_conf, + "chrooted in %s", ap_server_root); + chdir("/"); + is_chrooted = 1; + setproctitle("parent [chroot %s]", ap_server_root); + + if ( setgroups(1, &ap_group_id) || setegid(ap_group_id) || + setgid(ap_group_id) || seteuid(ap_user_id) || + setuid(ap_user_id) ) { + ap_log_error(APLOG_MARK, APLOG_CRIT, server_conf, + "can't drop priviliges!"); + exit(1); + } else + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, + server_conf, "changed to uid %ld, gid %ld", + (long)ap_user_id, (long)ap_group_id); + } else + setproctitle("parent"); + SAFE_ACCEPT(accept_mutex_init(pconf)); if (!is_graceful) { reinit_scoreboard(pconf); @@ -5279,6 +5317,7 @@ static void standalone_main(int argc, char **argv) { const char *pidfile = NULL; pidfile = ap_server_root_relative (pconf, ap_pid_fname); + ap_server_strip_chroot(pidfile, 0); if ( pidfile != NULL && unlink(pidfile) == 0) ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, server_conf, @@ -5407,7 +5446,7 @@ int REALMAIN(int argc, char *argv[]) ap_setup_prelinked_modules(); while ((c = getopt(argc, argv, - "D:C:c:xXd:f:vVlLR:StTh" + "D:C:c:xXd:f:vVlLR:StThu" #ifdef DEBUG_SIGSTOP "Z:" #endif @@ -5484,6 +5523,9 @@ int REALMAIN(int argc, char *argv[]) break; case 'h': usage(argv[0]); + case 'u': + ap_server_chroot = 0; + break; case '?': usage(argv[0]); } @@ -7967,3 +8009,15 @@ const XML_LChar *suck_in_expat(void) } #endif /* USE_EXPAT */ +API_EXPORT(int) ap_server_strip_chroot(char *src, int force) +{ + char buf[MAX_STRING_LEN]; + + if(src != NULL && ap_server_chroot && (is_chrooted || force)) { + if (strncmp(ap_server_root, src, strlen(ap_server_root)) == 0) { + strlcpy(buf, src+strlen(ap_server_root), MAX_STRING_LEN); + strlcpy(src, buf, strlen(src)); + } + } +} + diff --git a/usr.sbin/httpd/src/modules/ssl/mod_ssl.h b/usr.sbin/httpd/src/modules/ssl/mod_ssl.h index afc1e0dfbe7..8d881940d48 100644 --- a/usr.sbin/httpd/src/modules/ssl/mod_ssl.h +++ b/usr.sbin/httpd/src/modules/ssl/mod_ssl.h @@ -284,6 +284,7 @@ #define SSL_MUTEX_LOCK_MODE (_S_IREAD|_S_IWRITE ) #endif #if defined(USE_SYSVSEM_SERIALIZED_ACCEPT) ||\ + defined(__OpenBSD__) ||\ (defined(__FreeBSD__) && defined(__FreeBSD_version) &&\ __FreeBSD_version >= 300000) ||\ (defined(LINUX) && defined(__GLIBC__) && defined(__GLIBC_MINOR__) &&\ diff --git a/usr.sbin/httpd/src/modules/ssl/ssl_engine_mutex.c b/usr.sbin/httpd/src/modules/ssl/ssl_engine_mutex.c index 146f9ce4d90..720854d9e53 100644 --- a/usr.sbin/httpd/src/modules/ssl/ssl_engine_mutex.c +++ b/usr.sbin/httpd/src/modules/ssl/ssl_engine_mutex.c @@ -177,13 +177,17 @@ void ssl_mutex_file_open(server_rec *s, pool *p) { #ifndef WIN32 SSLModConfigRec *mc = myModConfig(); + char mutexfile[MAXPATHLEN]; + + strlcpy(mutexfile, mc->szMutexFile, sizeof(mutexfile)); + ap_server_strip_chroot(mutexfile, 0); /* open the lockfile (once per child) to get a unique fd */ - if ((mc->nMutexFD = ap_popenf(p, mc->szMutexFile, + if ((mc->nMutexFD = ap_popenf(p, mutexfile, O_WRONLY, SSL_MUTEX_LOCK_MODE)) < 0) { ssl_log(s, SSL_LOG_ERROR|SSL_ADD_ERRNO, "Child could not open SSLMutex lockfile %s", - mc->szMutexFile); + mutexfile); ssl_die(); } #endif @@ -194,9 +198,12 @@ void ssl_mutex_file_remove(void *data) { #ifndef WIN32 SSLModConfigRec *mc = myModConfig(); + char mutexfile[MAXPATHLEN]; + strlcpy(mutexfile, mc->szMutexFile, sizeof(mutexfile)); + ap_server_strip_chroot(mutexfile, 0); /* remove the mutex lockfile */ - unlink(mc->szMutexFile); + unlink(mutexfile); #endif return; } diff --git a/usr.sbin/httpd/src/modules/ssl/ssl_scache_dbm.c b/usr.sbin/httpd/src/modules/ssl/ssl_scache_dbm.c index 669658f84ba..26f4e297e40 100644 --- a/usr.sbin/httpd/src/modules/ssl/ssl_scache_dbm.c +++ b/usr.sbin/httpd/src/modules/ssl/ssl_scache_dbm.c @@ -120,6 +120,7 @@ void ssl_scache_dbm_kill(server_rec *s) if ((p = ap_make_sub_pool(NULL)) != NULL) { /* the correct way */ + ap_server_strip_chroot(mc->szSessionCacheDataFile, 0); unlink(ap_pstrcat(p, mc->szSessionCacheDataFile, SSL_DBM_FILE_SUFFIX_DIR, NULL)); unlink(ap_pstrcat(p, mc->szSessionCacheDataFile, SSL_DBM_FILE_SUFFIX_PAG, NULL)); /* the additional ways to be sure */ @@ -171,6 +172,7 @@ BOOL ssl_scache_dbm_store(server_rec *s, UCHAR *id, int idlen, time_t expiry, SS /* and store it to the DBM file */ ssl_mutex_on(s); + ap_server_strip_chroot(mc->szSessionCacheDataFile, 0); if ((dbm = ssl_dbm_open(mc->szSessionCacheDataFile, O_RDWR, SSL_DBM_FILE_MODE)) == NULL) { ssl_log(s, SSL_LOG_ERROR|SSL_ADD_ERRNO, @@ -222,6 +224,7 @@ SSL_SESSION *ssl_scache_dbm_retrieve(server_rec *s, UCHAR *id, int idlen) /* and fetch it from the DBM file */ ssl_mutex_on(s); + ap_server_strip_chroot(mc->szSessionCacheDataFile); if ((dbm = ssl_dbm_open(mc->szSessionCacheDataFile, O_RDONLY, SSL_DBM_FILE_MODE)) == NULL) { ssl_log(s, SSL_LOG_ERROR|SSL_ADD_ERRNO, @@ -271,6 +274,7 @@ void ssl_scache_dbm_remove(server_rec *s, UCHAR *id, int idlen) /* and delete it from the DBM file */ ssl_mutex_on(s); + ap_server_strip_chroot(mc->szSessionCacheDataFile, 0); if ((dbm = ssl_dbm_open(mc->szSessionCacheDataFile, O_RDWR, SSL_DBM_FILE_MODE)) == NULL) { ssl_log(s, SSL_LOG_ERROR|SSL_ADD_ERRNO, @@ -338,6 +342,7 @@ void ssl_scache_dbm_expire(server_rec *s) /* pass 1: scan DBM database */ keyidx = 0; + ap_server_strip_chroot(mc->szSessionCacheDataFile, 0); if ((dbm = ssl_dbm_open(mc->szSessionCacheDataFile, O_RDWR, SSL_DBM_FILE_MODE)) == NULL) { ssl_log(s, SSL_LOG_ERROR|SSL_ADD_ERRNO, @@ -412,6 +417,7 @@ void ssl_scache_dbm_status(server_rec *s, pool *p, void (*func)(char *, void *), nElem = 0; nSize = 0; ssl_mutex_on(s); + ap_server_strip_chroot(mc->szSessionCacheDataFile, 0); if ((dbm = ssl_dbm_open(mc->szSessionCacheDataFile, O_RDONLY, SSL_DBM_FILE_MODE)) == NULL) { ssl_log(s, SSL_LOG_ERROR|SSL_ADD_ERRNO, diff --git a/usr.sbin/httpd/src/modules/standard/mod_alias.c b/usr.sbin/httpd/src/modules/standard/mod_alias.c index 69afa7f967e..333ec157952 100644 --- a/usr.sbin/httpd/src/modules/standard/mod_alias.c +++ b/usr.sbin/httpd/src/modules/standard/mod_alias.c @@ -136,6 +136,8 @@ static const char *add_alias_internal(cmd_parms *cmd, void *dummy, char *f, char /* XX r can NOT be relative to DocumentRoot here... compat bug. */ + ap_server_strip_chroot(r, 0); + if (use_regex) { new->regexp = ap_pregcomp(cmd->pool, f, REG_EXTENDED); if (new->regexp == NULL) |