mirror of
https://github.com/NLnetLabs/unbound.git
synced 2026-05-28 04:02:33 -04:00
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:
parent
75c30382ba
commit
2e9785cfb5
25 changed files with 63 additions and 43 deletions
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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. */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
1
doc/TODO
1
doc/TODO
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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 ,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
BIN
testdata/fwd_compress_c00c.tpkg
vendored
BIN
testdata/fwd_compress_c00c.tpkg
vendored
Binary file not shown.
BIN
testdata/fwd_no_edns.tpkg
vendored
BIN
testdata/fwd_no_edns.tpkg
vendored
Binary file not shown.
BIN
testdata/fwd_tcp.tpkg
vendored
BIN
testdata/fwd_tcp.tpkg
vendored
Binary file not shown.
BIN
testdata/fwd_tcp_tc.tpkg
vendored
BIN
testdata/fwd_tcp_tc.tpkg
vendored
Binary file not shown.
BIN
testdata/fwd_tcp_tc6.tpkg
vendored
BIN
testdata/fwd_tcp_tc6.tpkg
vendored
Binary file not shown.
BIN
testdata/fwd_three.tpkg
vendored
BIN
testdata/fwd_three.tpkg
vendored
Binary file not shown.
BIN
testdata/fwd_three_service.tpkg
vendored
BIN
testdata/fwd_three_service.tpkg
vendored
Binary file not shown.
BIN
testdata/fwd_ttlexpire.tpkg
vendored
BIN
testdata/fwd_ttlexpire.tpkg
vendored
Binary file not shown.
BIN
testdata/fwd_udp.tpkg
vendored
BIN
testdata/fwd_udp.tpkg
vendored
Binary file not shown.
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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).
|
||||
|
|
|
|||
Loading…
Reference in a new issue