aboutsummaryrefslogtreecommitdiff
path: root/contrib/unbound/daemon/unbound.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/unbound/daemon/unbound.c')
-rw-r--r--contrib/unbound/daemon/unbound.c136
1 files changed, 85 insertions, 51 deletions
diff --git a/contrib/unbound/daemon/unbound.c b/contrib/unbound/daemon/unbound.c
index 457a08032857..164d0fb89509 100644
--- a/contrib/unbound/daemon/unbound.c
+++ b/contrib/unbound/daemon/unbound.c
@@ -174,7 +174,7 @@ static void
checkrlimits(struct config_file* cfg)
{
#ifndef S_SPLINT_S
-#ifdef HAVE_GETRLIMIT
+#if defined(HAVE_GETRLIMIT) && !defined(unbound_testbound)
/* list has number of ports to listen to, ifs number addresses */
int list = ((cfg->do_udp?1:0) + (cfg->do_tcp?1 +
(int)cfg->incoming_num_tcp:0));
@@ -366,9 +366,8 @@ readpid (const char* file)
/** write pid to file.
* @param pidfile: file name of pid file.
* @param pid: pid to write to file.
- * @return false on failure
*/
-static int
+static void
writepid (const char* pidfile, pid_t pid)
{
int fd;
@@ -383,7 +382,7 @@ writepid (const char* pidfile, pid_t pid)
, 0644)) == -1) {
log_err("cannot open pidfile %s: %s",
pidfile, strerror(errno));
- return 0;
+ return;
}
while(count < strlen(pidbuf)) {
ssize_t r = write(fd, pidbuf+count, strlen(pidbuf)-count);
@@ -393,17 +392,16 @@ writepid (const char* pidfile, pid_t pid)
log_err("cannot write to pidfile %s: %s",
pidfile, strerror(errno));
close(fd);
- return 0;
+ return;
} else if(r == 0) {
log_err("cannot write any bytes to pidfile %s: "
"write returns 0 bytes written", pidfile);
close(fd);
- return 0;
+ return;
}
count += r;
}
close(fd);
- return 1;
}
/**
@@ -465,6 +463,62 @@ detach(void)
#endif /* HAVE_DAEMON */
}
+#ifdef HAVE_SSL
+/* setup a listening ssl context, fatal_exit() on any failure */
+static void
+setup_listen_sslctx(void** ctx, int is_dot, int is_doh, struct config_file* cfg)
+{
+ if(!(*ctx = listen_sslctx_create(
+ cfg->ssl_service_key, cfg->ssl_service_pem, NULL,
+ cfg->tls_ciphers, cfg->tls_ciphersuites,
+ (cfg->tls_session_ticket_keys.first &&
+ cfg->tls_session_ticket_keys.first->str[0] != 0),
+ is_dot, is_doh))) {
+ fatal_exit("could not set up listen SSL_CTX");
+ }
+}
+#endif /* HAVE_SSL */
+
+/* setups the needed ssl contexts, fatal_exit() on any failure */
+static void
+setup_sslctxs(struct daemon* daemon, struct config_file* cfg)
+{
+#ifdef HAVE_SSL
+ if(!(daemon->rc = daemon_remote_create(cfg)))
+ fatal_exit("could not set up remote-control");
+ if(cfg->ssl_service_key && cfg->ssl_service_key[0]) {
+ /* setup the session keys; the callback to use them will be
+ * attached to each sslctx separately */
+ if(cfg->tls_session_ticket_keys.first &&
+ cfg->tls_session_ticket_keys.first->str[0] != 0) {
+ if(!listen_sslctx_setup_ticket_keys(
+ cfg->tls_session_ticket_keys.first)) {
+ fatal_exit("could not set session ticket SSL_CTX");
+ }
+ }
+ (void)setup_listen_sslctx(&daemon->listen_dot_sslctx, 1, 0, cfg);
+#ifdef HAVE_NGHTTP2_NGHTTP2_H
+ if(cfg_has_https(cfg)) {
+ (void)setup_listen_sslctx(&daemon->listen_doh_sslctx, 0, 1, cfg);
+ }
+#endif
+#ifdef HAVE_NGTCP2
+ if(cfg_has_quic(cfg)) {
+ if(!(daemon->listen_quic_sslctx = quic_sslctx_create(
+ cfg->ssl_service_key, cfg->ssl_service_pem, NULL))) {
+ fatal_exit("could not set up quic SSL_CTX");
+ }
+ }
+#endif /* HAVE_NGTCP2 */
+ }
+ if(!(daemon->connect_dot_sslctx = connect_sslctx_create(NULL, NULL,
+ cfg->tls_cert_bundle, cfg->tls_win_cert)))
+ fatal_exit("could not set up connect SSL_CTX");
+#else /* HAVE_SSL */
+ (void)daemon;(void)cfg;
+#endif /* HAVE_SSL */
+}
+
/** daemonize, drop user privileges and chroot if needed */
static void
perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
@@ -475,7 +529,11 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
#endif
#ifdef HAVE_GETPWNAM
struct passwd *pwd = NULL;
+#endif
+ if(!daemon_privileged(daemon))
+ fatal_exit("could not do privileged setup");
+#ifdef HAVE_GETPWNAM
if(cfg->username && cfg->username[0]) {
if((pwd = getpwnam(cfg->username)) == NULL)
fatal_exit("user '%s' does not exist.", cfg->username);
@@ -487,36 +545,7 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
#endif
/* read ssl keys while superuser and outside chroot */
-#ifdef HAVE_SSL
- if(!(daemon->rc = daemon_remote_create(cfg)))
- fatal_exit("could not set up remote-control");
- if(cfg->ssl_service_key && cfg->ssl_service_key[0]) {
- if(!(daemon->listen_sslctx = listen_sslctx_create(
- cfg->ssl_service_key, cfg->ssl_service_pem, NULL)))
- fatal_exit("could not set up listen SSL_CTX");
- if(cfg->tls_ciphers && cfg->tls_ciphers[0]) {
- if (!SSL_CTX_set_cipher_list(daemon->listen_sslctx, cfg->tls_ciphers)) {
- fatal_exit("failed to set tls-cipher %s", cfg->tls_ciphers);
- }
- }
-#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
- if(cfg->tls_ciphersuites && cfg->tls_ciphersuites[0]) {
- if (!SSL_CTX_set_ciphersuites(daemon->listen_sslctx, cfg->tls_ciphersuites)) {
- fatal_exit("failed to set tls-ciphersuites %s", cfg->tls_ciphersuites);
- }
- }
-#endif
- if(cfg->tls_session_ticket_keys.first &&
- cfg->tls_session_ticket_keys.first->str[0] != 0) {
- if(!listen_sslctx_setup_ticket_keys(daemon->listen_sslctx, cfg->tls_session_ticket_keys.first)) {
- fatal_exit("could not set session ticket SSL_CTX");
- }
- }
- }
- if(!(daemon->connect_sslctx = connect_sslctx_create(NULL, NULL,
- cfg->tls_cert_bundle, cfg->tls_win_cert)))
- fatal_exit("could not set up connect SSL_CTX");
-#endif
+ (void)setup_sslctxs(daemon, cfg);
/* init syslog (as root) if needed, before daemonize, otherwise
* a fork error could not be printed since daemonize closed stderr.*/
@@ -545,7 +574,15 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
cfg, 1);
if(!daemon->pidfile)
fatal_exit("pidfile alloc: out of memory");
- checkoldpid(daemon->pidfile, pidinchroot);
+ /* Check old pid if there is no username configured.
+ * With a username, the assumption is that the privilege
+ * drop makes a pidfile not removed when the server stopped
+ * last time. The server does not chown the pidfile for it,
+ * because that creates privilege escape problems, with the
+ * pidfile writable by unprivileged users, but used by
+ * privileged users. */
+ if(!(cfg->username && cfg->username[0]))
+ checkoldpid(daemon->pidfile, pidinchroot);
}
#endif
@@ -557,18 +594,7 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
/* write new pidfile (while still root, so can be outside chroot) */
#ifdef HAVE_KILL
if(cfg->pidfile && cfg->pidfile[0] && need_pidfile) {
- if(writepid(daemon->pidfile, getpid())) {
- if(cfg->username && cfg->username[0] && cfg_uid != (uid_t)-1 &&
- pidinchroot) {
-# ifdef HAVE_CHOWN
- if(chown(daemon->pidfile, cfg_uid, cfg_gid) == -1) {
- verbose(VERB_QUERY, "cannot chown %u.%u %s: %s",
- (unsigned)cfg_uid, (unsigned)cfg_gid,
- daemon->pidfile, strerror(errno));
- }
-# endif /* HAVE_CHOWN */
- }
- }
+ writepid(daemon->pidfile, getpid());
}
#else
(void)daemon;
@@ -682,6 +708,9 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
* it would succeed on SIGHUP as well */
if(!cfg->use_syslog)
log_init(cfg->logfile, cfg->use_syslog, cfg->chrootdir);
+ daemon->cfgfile = strdup(*cfgfile);
+ if(!daemon->cfgfile)
+ fatal_exit("out of memory in daemon cfgfile strdup");
}
/**
@@ -716,6 +745,7 @@ run_daemon(const char* cfgfile, int cmdline_verbose, int debug_mode, int need_pi
"the commandline to see more errors, "
"or unbound-checkconf", cfgfile);
log_warn("Continuing with default config settings");
+ config_auto_slab_values(cfg);
}
apply_settings(daemon, cfg, cmdline_verbose, debug_mode);
if(!done_setup)
@@ -746,7 +776,11 @@ run_daemon(const char* cfgfile, int cmdline_verbose, int debug_mode, int need_pi
if(daemon->pidfile) {
int fd;
/* truncate pidfile */
- fd = open(daemon->pidfile, O_WRONLY | O_TRUNC, 0644);
+ fd = open(daemon->pidfile, O_WRONLY | O_TRUNC
+#ifdef O_NOFOLLOW
+ | O_NOFOLLOW
+#endif
+ , 0644);
if(fd != -1)
close(fd);
/* delete pidfile */