From ce95017bf16f7937013134fc5188900d3e2cd9c7 Mon Sep 17 00:00:00 2001 From: Reyk Floeter Date: Wed, 16 Aug 2017 09:27:36 +0200 Subject: sync --- httpd/httpd.c | 150 ++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 82 insertions(+), 68 deletions(-) (limited to 'httpd/httpd.c') diff --git a/httpd/httpd.c b/httpd/httpd.c index fae7c53..6d1d1ff 100644 --- a/httpd/httpd.c +++ b/httpd/httpd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: httpd.c,v 1.56 2016/06/10 12:09:48 florian Exp $ */ +/* $OpenBSD: httpd.c,v 1.67 2017/05/28 10:37:26 benno Exp $ */ /* * Copyright (c) 2014 Reyk Floeter @@ -16,12 +16,10 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include /* nitems */ #include #include #include #include -#include #include #include @@ -59,6 +57,8 @@ int parent_dispatch_server(int, struct privsep_proc *, struct imsg *); int parent_dispatch_logger(int, struct privsep_proc *, struct imsg *); +void parent_tls_ticket_rekey_start(struct server *); +void parent_tls_ticket_rekey(int, short, void *); struct httpd *httpd_env; @@ -71,56 +71,11 @@ void parent_sig_handler(int sig, short event, void *arg) { struct privsep *ps = arg; - int die = 0, status, fail, id; - pid_t pid; - char *cause; switch (sig) { case SIGTERM: case SIGINT: - die = 1; - /* FALLTHROUGH */ - case SIGCHLD: - do { - int len; - - pid = waitpid(WAIT_ANY, &status, WNOHANG); - if (pid <= 0) - continue; - - fail = 0; - if (WIFSIGNALED(status)) { - fail = 1; - len = asprintf(&cause, "terminated; signal %d", - WTERMSIG(status)); - } else if (WIFEXITED(status)) { - if (WEXITSTATUS(status) != 0) { - fail = 1; - len = asprintf(&cause, - "exited abnormally"); - } else - len = asprintf(&cause, "exited okay"); - } else - fatalx("unexpected cause of SIGCHLD"); - - if (len == -1) - fatal("asprintf"); - - die = 1; - - for (id = 0; id < PROC_MAX; id++) - if (pid == ps->ps_pid[id]) { - if (fail) - log_warnx("lost child: %s %s", - ps->ps_title[id], cause); - break; - } - - free(cause); - } while (pid > 0 || (pid == -1 && errno == EINTR)); - - if (die) - parent_shutdown(ps->ps_env); + parent_shutdown(ps->ps_env); break; case SIGHUP: log_info("%s: reload requested with SIGHUP", __func__); @@ -164,8 +119,12 @@ main(int argc, char *argv[]) struct httpd *env; struct privsep *ps; const char *conffile = CONF_FILE; + enum privsep_procid proc_id = PROC_PARENT; + int proc_instance = 0; + const char *errp, *title = NULL; + int argc0 = argc; - while ((c = getopt(argc, argv, "dD:nf:v")) != -1) { + while ((c = getopt(argc, argv, "dD:nf:I:P:v")) != -1) { switch (c) { case 'd': debug = 2; @@ -186,6 +145,18 @@ main(int argc, char *argv[]) verbose++; opts |= HTTPD_OPT_VERBOSE; break; + case 'P': + title = optarg; + proc_id = proc_getid(procs, nitems(procs), title); + if (proc_id == PROC_MAX) + fatalx("invalid process name"); + break; + case 'I': + proc_instance = strtonum(optarg, 0, + PROC_MAX_INSTANCES, &errp); + if (errp) + fatalx("invalid process instance"); + break; default: usage(); } @@ -222,18 +193,15 @@ main(int argc, char *argv[]) ps->ps_csock.cs_name = NULL; log_init(debug, LOG_DAEMON); - log_verbose(verbose); - - if (!debug && daemon(1, 0) == -1) - err(1, "failed to daemonize"); + log_setverbose(verbose); if (env->sc_opts & HTTPD_OPT_NOACTION) ps->ps_noaction = 1; - else - log_info("startup"); ps->ps_instances[PROC_SERVER] = env->sc_prefork_server; - ps->ps_ninstances = env->sc_prefork_server; + ps->ps_instance = proc_instance; + if (title != NULL) + ps->ps_title[proc_id] = title; if (env->sc_chroot == NULL) env->sc_chroot = ps->ps_pw->pw_dir; @@ -246,30 +214,34 @@ main(int argc, char *argv[]) errx(1, "malloc failed"); } - proc_init(ps, procs, nitems(procs)); + /* only the parent returns */ + proc_init(ps, procs, nitems(procs), argc0, argv, proc_id); + log_procinit("parent"); + if (!debug && daemon(1, 0) == -1) + err(1, "failed to daemonize"); - if (pledge("stdio rpath wpath cpath inet dns proc ioctl sendfd", - NULL) == -1) + if (ps->ps_noaction == 0) + log_info("startup"); + + if (pledge("stdio rpath wpath cpath inet dns sendfd", NULL) == -1) fatal("pledge"); event_init(); signal_set(&ps->ps_evsigint, SIGINT, parent_sig_handler, ps); signal_set(&ps->ps_evsigterm, SIGTERM, parent_sig_handler, ps); - signal_set(&ps->ps_evsigchld, SIGCHLD, parent_sig_handler, ps); signal_set(&ps->ps_evsighup, SIGHUP, parent_sig_handler, ps); signal_set(&ps->ps_evsigpipe, SIGPIPE, parent_sig_handler, ps); signal_set(&ps->ps_evsigusr1, SIGUSR1, parent_sig_handler, ps); signal_add(&ps->ps_evsigint, NULL); signal_add(&ps->ps_evsigterm, NULL); - signal_add(&ps->ps_evsigchld, NULL); signal_add(&ps->ps_evsighup, NULL); signal_add(&ps->ps_evsigpipe, NULL); signal_add(&ps->ps_evsigusr1, NULL); - proc_listen(ps, procs, nitems(procs)); + proc_connect(ps); if (load_config(env->sc_conffile, env) == -1) { proc_kill(env->sc_ps); @@ -282,6 +254,9 @@ main(int argc, char *argv[]) exit(0); } + /* initialize the TLS session id to a random key for all procs */ + arc4random_buf(env->sc_tls_sid, sizeof(env->sc_tls_sid)); + if (parent_configure(env) == -1) fatalx("configuration failed"); @@ -317,6 +292,10 @@ parent_configure(struct httpd *env) TAILQ_FOREACH(srv, env->sc_servers, srv_entry) { if (srv->srv_conf.flags & SRVFLAG_LOCATION) continue; + /* start the rekey of the tls ticket keys */ + if (srv->srv_conf.flags & SRVFLAG_TLS && + srv->srv_conf.tls_ticket_lifetime) + parent_tls_ticket_rekey_start(srv); if (config_setserver(env, srv) == -1) fatal("send server"); } @@ -336,13 +315,14 @@ parent_configure(struct httpd *env) continue; cf.cf_opts = env->sc_opts; cf.cf_flags = env->sc_flags; + memcpy(cf.cf_tls_sid, env->sc_tls_sid, sizeof(cf.cf_tls_sid)); proc_compose(env->sc_ps, id, IMSG_CFG_DONE, &cf, sizeof(cf)); } ret = 0; - config_purge(env, CONFIG_ALL); + config_purge(env, CONFIG_ALL & ~CONFIG_SERVERS); return (ret); } @@ -427,7 +407,8 @@ parent_shutdown(struct httpd *env) int parent_dispatch_server(int fd, struct privsep_proc *p, struct imsg *imsg) { - struct httpd *env = p->p_env; + struct privsep *ps = p->p_ps; + struct httpd *env = ps->ps_env; switch (imsg->hdr.type) { case IMSG_CFG_DONE: @@ -443,7 +424,8 @@ parent_dispatch_server(int fd, struct privsep_proc *p, struct imsg *imsg) int parent_dispatch_logger(int fd, struct privsep_proc *p, struct imsg *imsg) { - struct httpd *env = p->p_env; + struct privsep *ps = p->p_ps; + struct httpd *env = ps->ps_env; unsigned int v; char *str = NULL; @@ -479,6 +461,38 @@ parent_dispatch_logger(int fd, struct privsep_proc *p, struct imsg *imsg) return (0); } +void +parent_tls_ticket_rekey_start(struct server *srv) +{ + struct timeval tv; + + server_generate_ticket_key(&srv->srv_conf); + + evtimer_set(&srv->srv_evt, parent_tls_ticket_rekey, srv); + timerclear(&tv); + tv.tv_sec = srv->srv_conf.tls_ticket_lifetime / 4; + evtimer_add(&srv->srv_evt, &tv); +} + +void +parent_tls_ticket_rekey(int fd, short events, void *arg) +{ + struct server *srv = arg; + struct timeval tv; + + server_generate_ticket_key(&srv->srv_conf); + proc_compose_imsg(httpd_env->sc_ps, PROC_SERVER, -1, + IMSG_TLSTICKET_REKEY, -1, -1, &srv->srv_conf.tls_ticket_key, + sizeof(srv->srv_conf.tls_ticket_key)); + explicit_bzero(&srv->srv_conf.tls_ticket_key, + sizeof(srv->srv_conf.tls_ticket_key)); + + evtimer_set(&srv->srv_evt, parent_tls_ticket_rekey, srv); + timerclear(&tv); + tv.tv_sec = srv->srv_conf.tls_ticket_lifetime / 4; + evtimer_add(&srv->srv_evt, &tv); +} + /* * Utility functions */ @@ -777,7 +791,7 @@ socket_rlimit(int maxfd) struct rlimit rl; if (getrlimit(RLIMIT_NOFILE, &rl) == -1) - fatal("socket_rlimit: failed to get resource limit"); + fatal("%s: failed to get resource limit", __func__); log_debug("%s: max open files %llu", __func__, rl.rlim_max); /* @@ -789,7 +803,7 @@ socket_rlimit(int maxfd) else rl.rlim_cur = MAXIMUM(rl.rlim_max, (rlim_t)maxfd); if (setrlimit(RLIMIT_NOFILE, &rl) == -1) - fatal("socket_rlimit: failed to set resource limit"); + fatal("%s: failed to set resource limit", __func__); } char * -- cgit v1.2.3-54-g00ecf