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@
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)
{
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) {
infra_delete(daemon->env->infra_cache);
}
alloc_clear(&daemon->superalloc);
- free(daemon->cwd);
free(daemon->pidfile);
free(daemon->env);
free(daemon);
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. */
}
}
-/** 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) {
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.",
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)
}
/* 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");
}
}
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))
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);
/* 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) {
}
run_daemon(cfgfile, cmdline_verbose, debug_mode);
- log_init(NULL, 0); /* close logfile */
+ log_init(NULL, 0, NULL); /* close logfile */
return 0;
}
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
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
# 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.
.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.
.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 ,
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);
/** main program */
int main(int argc, char* argv[])
{
- log_init(NULL, 0);
+ log_init(NULL, 0, NULL);
if(argc != 6) {
usage();
}
/* 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)++;
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;
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");
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;
#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) {
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,
* 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).