better chroot support, and also default chroot and userchange.

git-svn-id: file:///svn/unbound/trunk@723 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
Wouter Wijngaards 2007-10-31 10:56:31 +00:00
parent 75c30382ba
commit 2e9785cfb5
25 changed files with 63 additions and 43 deletions

View file

@ -32,8 +32,8 @@ staticexe=@staticexe@
YACC=@YACC@
LEX=@LEX@
CC=@CC@
CPPFLAGS=-I. @CPPFLAGS@ @DEFS@
CFLAGS=-I. @CFLAGS@
CPPFLAGS=-I$(srcdir) @CPPFLAGS@ @DEFS@
CFLAGS=@CFLAGS@
LDFLAGS=@LDFLAGS@
LIBS=@LIBS@
LIBOBJS=@LIBOBJS@
@ -59,7 +59,8 @@ COMMON_SRC=$(patsubst $(srcdir)/%,%, $(wildcard $(srcdir)/services/*.c \
util/configparser.c util/configlexer.c testcode/checklocks.c
COMMON_OBJ=$(addprefix $(BUILD),$(COMMON_SRC:.c=.o))
COMPAT_OBJ=$(addprefix $(BUILD)compat/,$(LIBOBJS))
UNITTEST_SRC=$(patsubst $(srcdir)/%,%, $(wildcard $(srcdir)/testcode/unit*.c)) \
UNITTEST_SRC=$(patsubst $(srcdir)/%,%, \
$(wildcard $(srcdir)/testcode/unit*.c)) \
testcode/readhex.c testcode/ldns-testpkts.c checkconf/worker_cb.c \
$(COMMON_SRC)
UNITTEST_OBJ=$(addprefix $(BUILD),$(UNITTEST_SRC:.c=.o)) $(COMPAT_OBJ)

View file

@ -172,7 +172,7 @@ int main(int argc, char* argv[])
{
int c;
log_ident_set("unbound-checkconf");
log_init(NULL, 0);
log_init(NULL, 0, NULL);
/* parse the options */
while( (c=getopt(argc, argv, "h")) != -1) {
switch(c) {

View file

@ -460,7 +460,6 @@ daemon_delete(struct daemon* daemon)
infra_delete(daemon->env->infra_cache);
}
alloc_clear(&daemon->superalloc);
free(daemon->cwd);
free(daemon->pidfile);
free(daemon->env);
free(daemon);

View file

@ -58,8 +58,6 @@ struct rrset_cache;
struct daemon {
/** The config settings */
struct config_file* cfg;
/** current working directory */
char* cwd;
/** pidfile that is used */
char* pidfile;
/** port number that has ports opened. */

View file

@ -110,25 +110,15 @@ checkrlimits(struct config_file* cfg)
}
}
/** to changedir, logfile */
/** set verbosity, check rlimits, cache settings */
static void
apply_dir(struct daemon* daemon, struct config_file* cfg, int cmdline_verbose)
apply_settings(struct daemon* daemon, struct config_file* cfg,
int cmdline_verbose)
{
/* apply if they have changed */
daemon->cfg = cfg;
verbosity = cmdline_verbose + cfg->verbosity;
config_apply(cfg);
if(cfg->directory && cfg->directory[0]) {
if(!daemon->cwd || strcmp(daemon->cwd, cfg->directory) != 0) {
if(chdir(cfg->directory)) {
log_err("Could not chdir to %s: %s",
cfg->directory, strerror(errno));
}
free(daemon->cwd);
if(!(daemon->cwd = strdup(cfg->directory)))
log_err("cwd: malloc failed");
}
}
if(!daemon->env->msg_cache ||
cfg->msg_cache_size != slabhash_get_size(daemon->env->msg_cache) ||
cfg->msg_cache_slabs != daemon->env->msg_cache->size) {
@ -223,7 +213,12 @@ static void
checkoldpid(struct config_file* cfg)
{
pid_t old;
if((old = readpid(cfg->pidfile)) != -1) {
char* file = cfg->pidfile;
if(cfg->chrootdir && cfg->chrootdir[0] &&
strncmp(file, cfg->chrootdir, strlen(cfg->chrootdir))==0) {
file += strlen(cfg->chrootdir);
}
if((old = readpid(file)) != -1) {
/* see if it is still alive */
if(kill(old, 0) == 0 || errno == EPERM)
log_warn("unbound is already running as pid %u.",
@ -268,9 +263,15 @@ do_chroot(struct daemon* daemon, struct config_file* cfg, int debug_mode)
log_assert(cfg);
/* daemonize last to be able to print error to user */
if(cfg->directory && cfg->directory[0])
if(chdir(cfg->directory)) {
fatal_exit("Could not chdir to %s: %s",
cfg->directory, strerror(errno));
}
if(cfg->chrootdir && cfg->chrootdir[0])
if(chroot(cfg->chrootdir))
fatal_exit("unable to chroot: %s", strerror(errno));
fatal_exit("unable to chroot to %s: %s",
cfg->chrootdir, strerror(errno));
if(cfg->username && cfg->username[0]) {
struct passwd *pwd;
if((pwd = getpwnam(cfg->username)) == NULL)
@ -287,13 +288,17 @@ do_chroot(struct daemon* daemon, struct config_file* cfg, int debug_mode)
}
/* init logfile just before fork */
log_init(cfg->logfile, cfg->use_syslog);
log_init(cfg->logfile, cfg->use_syslog, cfg->chrootdir);
if(!debug_mode && cfg->do_daemonize) {
detach(cfg);
}
if(cfg->pidfile && cfg->pidfile[0]) {
writepid(cfg->pidfile, getpid());
if(!(daemon->pidfile = strdup(cfg->pidfile)))
char* pf = cfg->pidfile;
if(cfg->chrootdir && cfg->chrootdir[0] &&
strncmp(pf, cfg->chrootdir, strlen(cfg->chrootdir))==0)
pf += strlen(cfg->chrootdir);
writepid(pf, getpid());
if(!(daemon->pidfile = strdup(pf)))
log_err("pidf: malloc failed");
}
}
@ -324,7 +329,7 @@ run_daemon(char* cfgfile, int cmdline_verbose, int debug_mode)
fatal_exit("Could not alloc config defaults");
if(!config_read(cfg, cfgfile))
fatal_exit("Could not read config file: %s", cfgfile);
apply_dir(daemon, cfg, cmdline_verbose);
apply_settings(daemon, cfg, cmdline_verbose);
/* prepare */
if(!daemon_open_shared_ports(daemon))
@ -332,7 +337,7 @@ run_daemon(char* cfgfile, int cmdline_verbose, int debug_mode)
if(!done_chroot) {
do_chroot(daemon, cfg, debug_mode);
done_chroot = 1;
} else log_init(cfg->logfile, cfg->use_syslog);
} else log_init(cfg->logfile, cfg->use_syslog, cfg->chrootdir);
/* work */
daemon_fork(daemon);
@ -369,7 +374,7 @@ main(int argc, char* argv[])
/* take debug snapshot of heap */
unbound_start_brk = sbrk(0);
log_init(NULL, 0);
log_init(NULL, 0, NULL);
/* parse the options */
while( (c=getopt(argc, argv, "c:dhv")) != -1) {
switch(c) {
@ -399,6 +404,6 @@ main(int argc, char* argv[])
}
run_daemon(cfgfile, cmdline_verbose, debug_mode);
log_init(NULL, 0); /* close logfile */
log_init(NULL, 0, NULL); /* close logfile */
return 0;
}

View file

@ -1,6 +1,10 @@
31 October 2007: Wouter
- cache-max-ttl config option.
- building outside sourcedir works again.
- defaults more secure:
username: "unbound"
chroot: "/etc/unbound"
The operator can override them to be less secure ("") if necessary.
30 October 2007: Wouter
- fixup assertion failure that relied on compressed names to be

View file

@ -52,3 +52,4 @@ o make timeout backoffs randomized (a couple percent random) to spread traffic.
o inspect date on executable, then warn user in log if its more than 1 year.
o proactively prime root, stubs and trust anchors, feature.
early failure, faster on first query, but more traffic.
o use privilege separation, to change privilege options during reload securely

View file

@ -114,10 +114,12 @@ server:
# if given, a chroot(2) is done to the given directory.
# i.e. you can chroot to the working directory, for example,
# for extra security, but make sure all files are in that directory.
# chroot: "/some/directory"
# If you give "" no chroot is performed.
# chroot: "/etc/unbound"
# if given, user privileges are dropped (after binding port),
# and the given username is assumed. Default is nothing "".
# and the given username is assumed. Default is user "unbound".
# If you give "" no priviliges are dropped.
# username: "unbound"
# the working directory.

View file

@ -155,10 +155,11 @@ Enable or disable whether UDP queries are answered. Default is yes.
.It \fBdo-tcp:\fR <yes or no>
Enable or disable whether TCP queries are answered. Default is yes.
.It \fBchroot:\fR <directory>
If given a chroot is done to the given directory. The default is none ("").
If given a chroot is done to the given directory. The default is
"/etc/unbound". If you give "" no chroot is performed.
.It \fBusername:\fR <name>
If given, after binding the port the user privileges are dropped. Default is
not to change user, username: "".
"unbound". If you give username: "" no user change is performed.
.Pp
If this user is not capable of binding the
port, reloads (by signal HUP) will still retain the opened ports.
@ -355,13 +356,16 @@ server:
.Sh FILES
.Bl -tag -width indent
.It Pa /etc/unbound
default unbound working directory
default unbound working directory and default
.Xr chroot 2
location.
.It Pa unbound.conf
unbound configuration file.
.It Pa unbound.pid
default unbound pidfile with process ID of the running daemon.
.It Pa unbound.log
unbound log file.
unbound log file. default is to log to
.Xr syslog 3 .
.El
.Sh SEE ALSO
.Xr unbound 8 ,

View file

@ -385,7 +385,7 @@ main(int argc, char* argv[])
usage();
return 1;
}
log_init(NULL, 0);
log_init(NULL, 0, NULL);
log_ident_set("lock-verify");
/* init */
all_locks = rbtree_create(order_lock_cmp);

View file

@ -236,7 +236,7 @@ process_nsec3(int argc, char* argv[])
/** main program */
int main(int argc, char* argv[])
{
log_init(NULL, 0);
log_init(NULL, 0, NULL);
if(argc != 6) {
usage();
}

View file

@ -138,6 +138,8 @@ setup_config(FILE* in, char* configfile, int* lineno,
/* some basic settings to not pollute the host system */
fprintf(cfg, "server: use-syslog: no\n");
fprintf(cfg, " directory: \"\"\n");
fprintf(cfg, " chroot: \"\"\n");
fprintf(cfg, " username: \"\"\n");
while(fgets(line, MAX_LINE_LEN-1, in)) {
parse = line;
(*lineno)++;
@ -207,7 +209,7 @@ main(int argc, char* argv[])
char* init_optarg = optarg;
struct replay_scenario* scen = NULL;
log_init(NULL, 0);
log_init(NULL, 0, NULL);
log_info("Start of %s testbound program.", PACKAGE_STRING);
/* determine commandline options for the daemon */
cfgfile[0] = 0;

View file

@ -228,7 +228,7 @@ rnd_test()
int
main(int argc, char* argv[])
{
log_init(NULL, 0);
log_init(NULL, 0, NULL);
if(argc != 1) {
printf("usage: %s\n", argv[0]);
printf("\tperforms unit tests.\n");

Binary file not shown.

Binary file not shown.

BIN
testdata/fwd_tcp.tpkg vendored

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
testdata/fwd_udp.tpkg vendored

Binary file not shown.

View file

@ -93,8 +93,8 @@ config_create()
cfg->infra_cache_slabs = 4;
cfg->infra_cache_numhosts = 10000;
cfg->infra_cache_lame_size = 10240; /* easily 40 or more entries */
if(!(cfg->username = strdup(""))) goto error_exit;
if(!(cfg->chrootdir = strdup(""))) goto error_exit;
if(!(cfg->username = strdup("unbound"))) goto error_exit;
if(!(cfg->chrootdir = strdup("/etc/unbound"))) goto error_exit;
if(!(cfg->directory = strdup("/etc/unbound"))) goto error_exit;
if(!(cfg->logfile = strdup(""))) goto error_exit;
if(!(cfg->pidfile = strdup("unbound.pid"))) goto error_exit;

View file

@ -71,7 +71,7 @@ static int log_to_syslog = 0;
#endif /* HAVE_SYSLOG_H */
void
log_init(const char* filename, int use_syslog)
log_init(const char* filename, int use_syslog, const char* chrootdir)
{
FILE *f;
if(!key_created) {
@ -103,6 +103,9 @@ log_init(const char* filename, int use_syslog)
return;
}
/* open the file for logging */
if(chrootdir && chrootdir[0] && strncmp(filename, chrootdir,
strlen(chrootdir)) == 0)
filename += strlen(chrootdir);
f = fopen(filename, "a");
if(!f) {
log_err("Could not open logfile %s: %s", filename,

View file

@ -78,8 +78,9 @@ void verbose(enum verbosity_value level,
* call this to initialize logging services.
* @param filename: if NULL stderr is used.
* @param use_syslog: set to true to ignore filename and use syslog(3).
* @param chrootdir: to which directory we have been chrooted, if any.
*/
void log_init(const char* filename, int use_syslog);
void log_init(const char* filename, int use_syslog, const char* chrootdir);
/**
* Init a thread (will print this number for the thread log entries).