summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHenning Brauer <henning@cvs.openbsd.org>2002-07-09 17:28:48 +0000
committerHenning Brauer <henning@cvs.openbsd.org>2002-07-09 17:28:48 +0000
commit72e0abdf851ab032aee6617e08e532de96025792 (patch)
treeffc08ea56d682fe7e19320360acab08b96280e78
parenta747849505003806ab3b78d76dacce7aba6b7c7d (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.conf2
-rw-r--r--usr.sbin/httpd/src/include/ap_config.h4
-rw-r--r--usr.sbin/httpd/src/main/http_core.c10
-rw-r--r--usr.sbin/httpd/src/main/http_main.c58
-rw-r--r--usr.sbin/httpd/src/modules/ssl/mod_ssl.h1
-rw-r--r--usr.sbin/httpd/src/modules/ssl/ssl_engine_mutex.c13
-rw-r--r--usr.sbin/httpd/src/modules/ssl/ssl_scache_dbm.c6
-rw-r--r--usr.sbin/httpd/src/modules/standard/mod_alias.c2
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)