|
Packit |
90a5c9 |
/* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
Packit |
90a5c9 |
* contributor license agreements. See the NOTICE file distributed with
|
|
Packit |
90a5c9 |
* this work for additional information regarding copyright ownership.
|
|
Packit |
90a5c9 |
* The ASF licenses this file to You under the Apache License, Version 2.0
|
|
Packit |
90a5c9 |
* (the "License"); you may not use this file except in compliance with
|
|
Packit |
90a5c9 |
* the License. You may obtain a copy of the License at
|
|
Packit |
90a5c9 |
*
|
|
Packit |
90a5c9 |
* http://www.apache.org/licenses/LICENSE-2.0
|
|
Packit |
90a5c9 |
*
|
|
Packit |
90a5c9 |
* Unless required by applicable law or agreed to in writing, software
|
|
Packit |
90a5c9 |
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
Packit |
90a5c9 |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
Packit |
90a5c9 |
* See the License for the specific language governing permissions and
|
|
Packit |
90a5c9 |
* limitations under the License.
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
#include "ap_config.h"
|
|
Packit |
90a5c9 |
#include "httpd.h"
|
|
Packit |
90a5c9 |
#include "http_config.h"
|
|
Packit |
90a5c9 |
#include "http_main.h"
|
|
Packit |
90a5c9 |
#include "http_log.h"
|
|
Packit |
90a5c9 |
#include "http_core.h"
|
|
Packit |
90a5c9 |
#include "mpm_common.h"
|
|
Packit |
90a5c9 |
#include "os.h"
|
|
Packit |
90a5c9 |
#include "ap_mpm.h"
|
|
Packit |
90a5c9 |
#include "mod_unixd.h"
|
|
Packit |
90a5c9 |
#include "apr_thread_proc.h"
|
|
Packit |
90a5c9 |
#include "apr_strings.h"
|
|
Packit |
90a5c9 |
#include "apr_portable.h"
|
|
Packit |
90a5c9 |
#ifdef HAVE_PWD_H
|
|
Packit |
90a5c9 |
#include <pwd.h>
|
|
Packit |
90a5c9 |
#endif
|
|
Packit |
90a5c9 |
#ifdef HAVE_SYS_RESOURCE_H
|
|
Packit |
90a5c9 |
#include <sys/resource.h>
|
|
Packit |
90a5c9 |
#endif
|
|
Packit |
90a5c9 |
/* XXX */
|
|
Packit |
90a5c9 |
#include <sys/stat.h>
|
|
Packit |
90a5c9 |
#ifdef HAVE_UNISTD_H
|
|
Packit |
90a5c9 |
#include <unistd.h>
|
|
Packit |
90a5c9 |
#endif
|
|
Packit |
90a5c9 |
#ifdef HAVE_GRP_H
|
|
Packit |
90a5c9 |
#include <grp.h>
|
|
Packit |
90a5c9 |
#endif
|
|
Packit |
90a5c9 |
#ifdef HAVE_STRINGS_H
|
|
Packit |
90a5c9 |
#include <strings.h>
|
|
Packit |
90a5c9 |
#endif
|
|
Packit |
90a5c9 |
#ifdef HAVE_SYS_SEM_H
|
|
Packit |
90a5c9 |
#include <sys/sem.h>
|
|
Packit |
90a5c9 |
#endif
|
|
Packit |
90a5c9 |
#ifdef HAVE_SYS_PRCTL_H
|
|
Packit |
90a5c9 |
#include <sys/prctl.h>
|
|
Packit |
90a5c9 |
#endif
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
#ifndef DEFAULT_USER
|
|
Packit |
90a5c9 |
#define DEFAULT_USER "#-1"
|
|
Packit |
90a5c9 |
#endif
|
|
Packit |
90a5c9 |
#ifndef DEFAULT_GROUP
|
|
Packit |
90a5c9 |
#define DEFAULT_GROUP "#-1"
|
|
Packit |
90a5c9 |
#endif
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
#if 0
|
|
Packit |
90a5c9 |
typedef struct {
|
|
Packit |
90a5c9 |
const char *user_name;
|
|
Packit |
90a5c9 |
uid_t user_id;
|
|
Packit |
90a5c9 |
gid_t group_id;
|
|
Packit |
90a5c9 |
const char *chroot_dir;
|
|
Packit |
90a5c9 |
} unixd_config_t;
|
|
Packit |
90a5c9 |
#else
|
|
Packit |
90a5c9 |
/*
|
|
Packit |
90a5c9 |
* TODO: clean up the separation between this code
|
|
Packit |
90a5c9 |
* and its data structures and unixd.c, as shown
|
|
Packit |
90a5c9 |
* by the fact that we include unixd.h. Create
|
|
Packit |
90a5c9 |
* mod_unixd.h which does what we need and
|
|
Packit |
90a5c9 |
* clean up unixd.h for what it no longer needs
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
#include "unixd.h"
|
|
Packit |
90a5c9 |
#endif
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/* Set group privileges.
|
|
Packit |
90a5c9 |
*
|
|
Packit |
90a5c9 |
* Note that we use the username as set in the config files, rather than
|
|
Packit |
90a5c9 |
* the lookup of to uid --- the same uid may have multiple passwd entries,
|
|
Packit |
90a5c9 |
* with different sets of groups for each.
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
static int set_group_privs(void)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
if (!geteuid()) {
|
|
Packit |
90a5c9 |
const char *name;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/* Get username if passed as a uid */
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (ap_unixd_config.user_name[0] == '#') {
|
|
Packit |
90a5c9 |
struct passwd *ent;
|
|
Packit |
90a5c9 |
uid_t uid = atol(&ap_unixd_config.user_name[1]);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if ((ent = getpwuid(uid)) == NULL) {
|
|
Packit |
90a5c9 |
ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL, APLOGNO(02155)
|
|
Packit |
90a5c9 |
"getpwuid: couldn't determine user name from uid %ld, "
|
|
Packit |
90a5c9 |
"you probably need to modify the User directive",
|
|
Packit |
90a5c9 |
(long)uid);
|
|
Packit |
90a5c9 |
return -1;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
name = ent->pw_name;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else
|
|
Packit |
90a5c9 |
name = ap_unixd_config.user_name;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
#if !defined(OS2)
|
|
Packit |
90a5c9 |
/* OS/2 doesn't support groups. */
|
|
Packit |
90a5c9 |
/*
|
|
Packit |
90a5c9 |
* Set the GID before initgroups(), since on some platforms
|
|
Packit |
90a5c9 |
* setgid() is known to zap the group list.
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
if (setgid(ap_unixd_config.group_id) == -1) {
|
|
Packit |
90a5c9 |
ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL, APLOGNO(02156)
|
|
Packit |
90a5c9 |
"setgid: unable to set group id to Group %ld",
|
|
Packit |
90a5c9 |
(long)ap_unixd_config.group_id);
|
|
Packit |
90a5c9 |
return -1;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/* Reset `groups' attributes. */
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (initgroups(name, ap_unixd_config.group_id) == -1) {
|
|
Packit |
90a5c9 |
ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL, APLOGNO(02157)
|
|
Packit |
90a5c9 |
"initgroups: unable to set groups for User %s "
|
|
Packit |
90a5c9 |
"and Group %ld", name, (long)ap_unixd_config.group_id);
|
|
Packit |
90a5c9 |
return -1;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
#endif /* !defined(OS2) */
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
return 0;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
static int
|
|
Packit |
90a5c9 |
unixd_drop_privileges(apr_pool_t *pool, server_rec *s)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
int rv = set_group_privs();
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (rv) {
|
|
Packit |
90a5c9 |
return rv;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (NULL != ap_unixd_config.chroot_dir) {
|
|
Packit |
90a5c9 |
if (geteuid()) {
|
|
Packit |
90a5c9 |
rv = errno;
|
|
Packit |
90a5c9 |
ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL, APLOGNO(02158)
|
|
Packit |
90a5c9 |
"Cannot chroot when not started as root");
|
|
Packit |
90a5c9 |
return rv;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (chdir(ap_unixd_config.chroot_dir) != 0) {
|
|
Packit |
90a5c9 |
rv = errno;
|
|
Packit |
90a5c9 |
ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL, APLOGNO(02159)
|
|
Packit |
90a5c9 |
"Can't chdir to %s", ap_unixd_config.chroot_dir);
|
|
Packit |
90a5c9 |
return rv;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (chroot(ap_unixd_config.chroot_dir) != 0) {
|
|
Packit |
90a5c9 |
rv = errno;
|
|
Packit |
90a5c9 |
ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL, APLOGNO(02160)
|
|
Packit |
90a5c9 |
"Can't chroot to %s", ap_unixd_config.chroot_dir);
|
|
Packit |
90a5c9 |
return rv;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (chdir("/") != 0) {
|
|
Packit |
90a5c9 |
rv = errno;
|
|
Packit |
90a5c9 |
ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL, APLOGNO(02161)
|
|
Packit |
90a5c9 |
"Can't chdir to new root");
|
|
Packit |
90a5c9 |
return rv;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/* Only try to switch if we're running as root */
|
|
Packit |
90a5c9 |
if (!geteuid() && (
|
|
Packit |
90a5c9 |
#ifdef _OSD_POSIX
|
|
Packit |
90a5c9 |
os_init_job_environment(NULL, ap_unixd_config.user_name, ap_exists_config_define("DEBUG")) != 0 ||
|
|
Packit |
90a5c9 |
#endif
|
|
Packit |
90a5c9 |
setuid(ap_unixd_config.user_id) == -1)) {
|
|
Packit |
90a5c9 |
rv = errno;
|
|
Packit |
90a5c9 |
ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL, APLOGNO(02162)
|
|
Packit |
90a5c9 |
"setuid: unable to change to uid: %ld",
|
|
Packit |
90a5c9 |
(long) ap_unixd_config.user_id);
|
|
Packit |
90a5c9 |
return rv;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
#if defined(HAVE_PRCTL) && defined(PR_SET_DUMPABLE)
|
|
Packit |
90a5c9 |
/* this applies to Linux 2.4+ */
|
|
Packit |
90a5c9 |
if (ap_coredumpdir_configured) {
|
|
Packit |
90a5c9 |
if (prctl(PR_SET_DUMPABLE, 1)) {
|
|
Packit |
90a5c9 |
rv = errno;
|
|
Packit |
90a5c9 |
ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL, APLOGNO(02163)
|
|
Packit |
90a5c9 |
"set dumpable failed - this child will not coredump"
|
|
Packit |
90a5c9 |
" after software errors");
|
|
Packit |
90a5c9 |
return rv;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
#endif
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
return OK;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
static const char *
|
|
Packit |
90a5c9 |
unixd_set_user(cmd_parms *cmd, void *dummy,
|
|
Packit |
90a5c9 |
const char *arg)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
|
|
Packit |
90a5c9 |
if (err != NULL) {
|
|
Packit |
90a5c9 |
return err;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
ap_unixd_config.user_name = arg;
|
|
Packit |
90a5c9 |
ap_unixd_config.user_id = ap_uname2id(arg);
|
|
Packit |
90a5c9 |
#if !defined (BIG_SECURITY_HOLE) && !defined (OS2)
|
|
Packit |
90a5c9 |
if (ap_unixd_config.user_id == 0) {
|
|
Packit |
90a5c9 |
return "Error:\tApache has not been designed to serve pages while\n"
|
|
Packit |
90a5c9 |
"\trunning as root. There are known race conditions that\n"
|
|
Packit |
90a5c9 |
"\twill allow any local user to read any file on the system.\n"
|
|
Packit |
90a5c9 |
"\tIf you still desire to serve pages as root then\n"
|
|
Packit |
90a5c9 |
"\tadd -DBIG_SECURITY_HOLE to the CFLAGS env variable\n"
|
|
Packit |
90a5c9 |
"\tand then rebuild the server.\n"
|
|
Packit |
90a5c9 |
"\tIt is strongly suggested that you instead modify the User\n"
|
|
Packit |
90a5c9 |
"\tdirective in your httpd.conf file to list a non-root\n"
|
|
Packit |
90a5c9 |
"\tuser.\n";
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
#endif
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
return NULL;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
static const char*
|
|
Packit |
90a5c9 |
unixd_set_group(cmd_parms *cmd, void *dummy,
|
|
Packit |
90a5c9 |
const char *arg)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
|
|
Packit |
90a5c9 |
if (err != NULL) {
|
|
Packit |
90a5c9 |
return err;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
ap_unixd_config.group_name = arg;
|
|
Packit |
90a5c9 |
ap_unixd_config.group_id = ap_gname2id(arg);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
return NULL;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
static const char*
|
|
Packit |
90a5c9 |
unixd_set_chroot_dir(cmd_parms *cmd, void *dummy,
|
|
Packit |
90a5c9 |
const char *arg)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
|
|
Packit |
90a5c9 |
if (err != NULL) {
|
|
Packit |
90a5c9 |
return err;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if (!ap_is_directory(cmd->pool, arg)) {
|
|
Packit |
90a5c9 |
return "ChrootDir must be a valid directory";
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
ap_unixd_config.chroot_dir = arg;
|
|
Packit |
90a5c9 |
return NULL;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
static const char *
|
|
Packit |
90a5c9 |
unixd_set_suexec(cmd_parms *cmd, void *dummy, int arg)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (err != NULL) {
|
|
Packit |
90a5c9 |
return err;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (!ap_unixd_config.suexec_enabled && arg) {
|
|
Packit |
90a5c9 |
return apr_pstrcat(cmd->pool, "suEXEC isn't supported: ",
|
|
Packit |
90a5c9 |
ap_unixd_config.suexec_disabled_reason, NULL);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (!arg) {
|
|
Packit |
90a5c9 |
ap_unixd_config.suexec_disabled_reason = "Suexec directive is Off";
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
ap_unixd_config.suexec_enabled = arg;
|
|
Packit |
90a5c9 |
return NULL;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
#ifdef AP_SUEXEC_CAPABILITIES
|
|
Packit |
90a5c9 |
/* If suexec is using capabilities, don't test for the setuid bit. */
|
|
Packit |
90a5c9 |
#define SETUID_TEST(finfo) (1)
|
|
Packit |
90a5c9 |
#else
|
|
Packit |
90a5c9 |
#define SETUID_TEST(finfo) (finfo.protection & APR_USETID)
|
|
Packit |
90a5c9 |
#endif
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
static int
|
|
Packit |
90a5c9 |
unixd_pre_config(apr_pool_t *pconf, apr_pool_t *plog,
|
|
Packit |
90a5c9 |
apr_pool_t *ptemp)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
apr_finfo_t wrapper;
|
|
Packit |
90a5c9 |
ap_unixd_config.user_name = DEFAULT_USER;
|
|
Packit |
90a5c9 |
ap_unixd_config.user_id = ap_uname2id(DEFAULT_USER);
|
|
Packit |
90a5c9 |
ap_unixd_config.group_name = DEFAULT_GROUP;
|
|
Packit |
90a5c9 |
ap_unixd_config.group_id = ap_gname2id(DEFAULT_GROUP);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
ap_unixd_config.chroot_dir = NULL; /* none */
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/* Check for suexec */
|
|
Packit |
90a5c9 |
ap_unixd_config.suexec_enabled = 0;
|
|
Packit |
90a5c9 |
if ((apr_stat(&wrapper, SUEXEC_BIN, APR_FINFO_NORM, ptemp))
|
|
Packit |
90a5c9 |
== APR_SUCCESS) {
|
|
Packit |
90a5c9 |
if (SETUID_TEST(wrapper) && wrapper.user == 0
|
|
Packit |
90a5c9 |
&& (access(SUEXEC_BIN, R_OK|X_OK) == 0)) {
|
|
Packit |
90a5c9 |
ap_unixd_config.suexec_enabled = 1;
|
|
Packit |
90a5c9 |
ap_unixd_config.suexec_disabled_reason = "";
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else {
|
|
Packit |
90a5c9 |
ap_unixd_config.suexec_disabled_reason =
|
|
Packit |
90a5c9 |
"Invalid owner or file mode for " SUEXEC_BIN;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else {
|
|
Packit |
90a5c9 |
ap_unixd_config.suexec_disabled_reason =
|
|
Packit |
90a5c9 |
"Missing suexec binary " SUEXEC_BIN;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
ap_sys_privileges_handlers(1);
|
|
Packit |
90a5c9 |
return OK;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
AP_DECLARE(int) ap_unixd_setup_child(void)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
if (set_group_privs()) {
|
|
Packit |
90a5c9 |
return -1;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (NULL != ap_unixd_config.chroot_dir) {
|
|
Packit |
90a5c9 |
if (geteuid()) {
|
|
Packit |
90a5c9 |
ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL, APLOGNO(02164)
|
|
Packit |
90a5c9 |
"Cannot chroot when not started as root");
|
|
Packit |
90a5c9 |
return -1;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if (chdir(ap_unixd_config.chroot_dir) != 0) {
|
|
Packit |
90a5c9 |
ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL, APLOGNO(02165)
|
|
Packit |
90a5c9 |
"Can't chdir to %s", ap_unixd_config.chroot_dir);
|
|
Packit |
90a5c9 |
return -1;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if (chroot(ap_unixd_config.chroot_dir) != 0) {
|
|
Packit |
90a5c9 |
ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL, APLOGNO(02166)
|
|
Packit |
90a5c9 |
"Can't chroot to %s", ap_unixd_config.chroot_dir);
|
|
Packit |
90a5c9 |
return -1;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if (chdir("/") != 0) {
|
|
Packit |
90a5c9 |
ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL, APLOGNO(02167)
|
|
Packit |
90a5c9 |
"Can't chdir to new root");
|
|
Packit |
90a5c9 |
return -1;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/* Only try to switch if we're running as root */
|
|
Packit |
90a5c9 |
if (!geteuid() && (
|
|
Packit |
90a5c9 |
#ifdef _OSD_POSIX
|
|
Packit |
90a5c9 |
os_init_job_environment(NULL, ap_unixd_config.user_name, ap_exists_config_define("DEBUG")) != 0 ||
|
|
Packit |
90a5c9 |
#endif
|
|
Packit |
90a5c9 |
setuid(ap_unixd_config.user_id) == -1)) {
|
|
Packit |
90a5c9 |
ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL, APLOGNO(02168)
|
|
Packit |
90a5c9 |
"setuid: unable to change to uid: %ld",
|
|
Packit |
90a5c9 |
(long) ap_unixd_config.user_id);
|
|
Packit |
90a5c9 |
return -1;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
#if defined(HAVE_PRCTL) && defined(PR_SET_DUMPABLE)
|
|
Packit |
90a5c9 |
/* this applies to Linux 2.4+ */
|
|
Packit |
90a5c9 |
if (ap_coredumpdir_configured) {
|
|
Packit |
90a5c9 |
if (prctl(PR_SET_DUMPABLE, 1)) {
|
|
Packit |
90a5c9 |
ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL, APLOGNO(02169)
|
|
Packit |
90a5c9 |
"set dumpable failed - this child will not coredump"
|
|
Packit |
90a5c9 |
" after software errors");
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
#endif
|
|
Packit |
90a5c9 |
return 0;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
static void unixd_dump_config(apr_pool_t *p, server_rec *s)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
apr_file_t *out = NULL;
|
|
Packit |
90a5c9 |
apr_uid_t uid = ap_unixd_config.user_id;
|
|
Packit |
90a5c9 |
apr_gid_t gid = ap_unixd_config.group_id;
|
|
Packit |
90a5c9 |
char *no_root = "";
|
|
Packit |
90a5c9 |
if (!ap_exists_config_define("DUMP_RUN_CFG"))
|
|
Packit |
90a5c9 |
return;
|
|
Packit |
90a5c9 |
if (geteuid() != 0)
|
|
Packit |
90a5c9 |
no_root = " not_used";
|
|
Packit |
90a5c9 |
apr_file_open_stdout(&out, p);
|
|
Packit |
90a5c9 |
apr_file_printf(out, "User: name=\"%s\" id=%lu%s\n",
|
|
Packit |
90a5c9 |
ap_unixd_config.user_name, (unsigned long)uid, no_root);
|
|
Packit |
90a5c9 |
apr_file_printf(out, "Group: name=\"%s\" id=%lu%s\n",
|
|
Packit |
90a5c9 |
ap_unixd_config.group_name, (unsigned long)gid, no_root);
|
|
Packit |
90a5c9 |
if (ap_unixd_config.chroot_dir)
|
|
Packit |
90a5c9 |
apr_file_printf(out, "ChrootDir: \"%s\"%s\n",
|
|
Packit |
90a5c9 |
ap_unixd_config.chroot_dir, no_root);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
static void unixd_hooks(apr_pool_t *pool)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
ap_hook_pre_config(unixd_pre_config,
|
|
Packit |
90a5c9 |
NULL, NULL, APR_HOOK_FIRST);
|
|
Packit |
90a5c9 |
ap_hook_test_config(unixd_dump_config,
|
|
Packit |
90a5c9 |
NULL, NULL, APR_HOOK_FIRST);
|
|
Packit |
90a5c9 |
ap_hook_drop_privileges(unixd_drop_privileges,
|
|
Packit |
90a5c9 |
NULL, NULL, APR_HOOK_MIDDLE);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
static const command_rec unixd_cmds[] = {
|
|
Packit |
90a5c9 |
AP_INIT_TAKE1("User", unixd_set_user, NULL, RSRC_CONF,
|
|
Packit |
90a5c9 |
"Effective user id for this server"),
|
|
Packit |
90a5c9 |
AP_INIT_TAKE1("Group", unixd_set_group, NULL, RSRC_CONF,
|
|
Packit |
90a5c9 |
"Effective group id for this server"),
|
|
Packit |
90a5c9 |
AP_INIT_TAKE1("ChrootDir", unixd_set_chroot_dir, NULL, RSRC_CONF,
|
|
Packit |
90a5c9 |
"The directory to chroot(2) into"),
|
|
Packit |
90a5c9 |
AP_INIT_FLAG("Suexec", unixd_set_suexec, NULL, RSRC_CONF,
|
|
Packit |
90a5c9 |
"Enable or disable suEXEC support"),
|
|
Packit |
90a5c9 |
{NULL}
|
|
Packit |
90a5c9 |
};
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
AP_DECLARE_MODULE(unixd) = {
|
|
Packit |
90a5c9 |
STANDARD20_MODULE_STUFF,
|
|
Packit |
90a5c9 |
NULL,
|
|
Packit |
90a5c9 |
NULL,
|
|
Packit |
90a5c9 |
NULL,
|
|
Packit |
90a5c9 |
NULL,
|
|
Packit |
90a5c9 |
unixd_cmds,
|
|
Packit |
90a5c9 |
unixd_hooks
|
|
Packit |
90a5c9 |
};
|
|
Packit |
90a5c9 |
|