From 76eb97c5f13448c259d6d1f244dd7233affc4f25 Mon Sep 17 00:00:00 2001 From: reyk Date: Thu, 1 May 2014 15:50:20 +0000 Subject: [PATCH] Move RSA keys from "lka" to a new dedicated "ca" process because lka is handling some async requests and shouldn't be busy with sync RSA. ok gilles@ --- usr.sbin/smtpd/ca.c | 212 +++++++++++++++++++++++++++++++--------- usr.sbin/smtpd/config.c | 5 +- usr.sbin/smtpd/lka.c | 9 +- usr.sbin/smtpd/pony.c | 3 +- usr.sbin/smtpd/smtpd.c | 33 ++++++- usr.sbin/smtpd/smtpd.h | 7 +- 6 files changed, 208 insertions(+), 61 deletions(-) diff --git a/usr.sbin/smtpd/ca.c b/usr.sbin/smtpd/ca.c index 6a4e771feb1..719c7579f02 100644 --- a/usr.sbin/smtpd/ca.c +++ b/usr.sbin/smtpd/ca.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ca.c,v 1.5 2014/04/30 08:23:42 reyk Exp $ */ +/* $OpenBSD: ca.c,v 1.6 2014/05/01 15:50:20 reyk Exp $ */ /* * Copyright (c) 2014 Reyk Floeter @@ -23,7 +23,10 @@ #include #include +#include #include +#include +#include #include #include @@ -55,6 +58,85 @@ static int rsae_keygen(RSA *, int, BIGNUM *, BN_GENCB *); static uint64_t rsae_reqid = 0; +static void +ca_shutdown(void) +{ + log_info("info: ca agent exiting"); + _exit(0); +} + +static void +ca_sig_handler(int sig, short event, void *p) +{ + switch (sig) { + case SIGINT: + case SIGTERM: + ca_shutdown(); + break; + default: + fatalx("ca_sig_handler: unexpected signal"); + } +} + +pid_t +ca(void) +{ + pid_t pid; + struct passwd *pw; + struct event ev_sigint; + struct event ev_sigterm; + + switch (pid = fork()) { + case -1: + fatal("ca: cannot fork"); + case 0: + post_fork(PROC_CA); + break; + default: + return (pid); + } + + purge_config(PURGE_LISTENERS|PURGE_TABLES|PURGE_RULES); + + if ((pw = getpwnam(SMTPD_USER)) == NULL) + fatalx("unknown user " SMTPD_USER); + + if (chroot(PATH_CHROOT) == -1) + fatal("ca: chroot"); + if (chdir("/") == -1) + fatal("ca: chdir(\"/\")"); + + config_process(PROC_CA); + + if (setgroups(1, &pw->pw_gid) || + setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || + setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) + fatal("ca: cannot drop privileges"); + + imsg_callback = ca_imsg; + event_init(); + + signal_set(&ev_sigint, SIGINT, ca_sig_handler, NULL); + signal_set(&ev_sigterm, SIGTERM, ca_sig_handler, NULL); + signal_add(&ev_sigint, NULL); + signal_add(&ev_sigterm, NULL); + signal(SIGPIPE, SIG_IGN); + signal(SIGHUP, SIG_IGN); + + config_peer(PROC_PARENT); + config_peer(PROC_PONY); + config_done(); + + /* Ignore them until we get our config */ + mproc_disable(p_pony); + + if (event_dispatch() < 0) + fatal("event_dispatch"); + ca_shutdown(); + + return (0); +} + void ca_init(void) { @@ -167,43 +249,81 @@ ca_imsg(struct mproc *p, struct imsg *imsg) struct pki *pki; int ret = 0; uint64_t id; - - m_msg(&m, imsg); - m_get_id(&m, &id); - m_get_string(&m, &pkiname); - m_get_data(&m, &from, &flen); - m_get_size(&m, &tlen); - m_get_size(&m, &padding); - m_end(&m); - - pki = dict_get(env->sc_pki_dict, pkiname); - if (pki == NULL || pki->pki_pkey == NULL || - (rsa = EVP_PKEY_get1_RSA(pki->pki_pkey)) == NULL) - fatalx("ca_imsg: invalid pki"); - - if ((to = calloc(1, tlen)) == NULL) - fatalx("ca_imsg: calloc"); - - switch (imsg->hdr.type) { - case IMSG_CA_PRIVENC: - ret = RSA_private_encrypt(flen, from, to, rsa, - padding); - break; - case IMSG_CA_PRIVDEC: - ret = RSA_private_decrypt(flen, from, to, rsa, - padding); - break; + int v; + + log_imsg(smtpd_process, p->proc, imsg); + + if (p->proc == PROC_PARENT) { + switch (imsg->hdr.type) { + case IMSG_CONF_START: + return; + case IMSG_CONF_END: + ca_init(); + + /* Start fulfilling requests */ + mproc_enable(p_pony); + return; + case IMSG_CTL_VERBOSE: + m_msg(&m, imsg); + m_get_int(&m, &v); + m_end(&m); + log_verbose(v); + return; + case IMSG_CTL_PROFILE: + m_msg(&m, imsg); + m_get_int(&m, &v); + m_end(&m); + profiling = v; + return; + } } - m_create(p, imsg->hdr.type, 0, 0, -1); - m_add_id(p, id); - m_add_int(p, ret); - if (ret > 0) - m_add_data(p, to, (size_t)ret); - m_close(p); + if (p->proc == PROC_PONY) { + switch (imsg->hdr.type) { + case IMSG_CA_PRIVENC: + case IMSG_CA_PRIVDEC: + m_msg(&m, imsg); + m_get_id(&m, &id); + m_get_string(&m, &pkiname); + m_get_data(&m, &from, &flen); + m_get_size(&m, &tlen); + m_get_size(&m, &padding); + m_end(&m); + + pki = dict_get(env->sc_pki_dict, pkiname); + if (pki == NULL || pki->pki_pkey == NULL || + (rsa = EVP_PKEY_get1_RSA(pki->pki_pkey)) == NULL) + fatalx("ca_imsg: invalid pki"); + + if ((to = calloc(1, tlen)) == NULL) + fatalx("ca_imsg: calloc"); + + switch (imsg->hdr.type) { + case IMSG_CA_PRIVENC: + ret = RSA_private_encrypt(flen, from, to, rsa, + padding); + break; + case IMSG_CA_PRIVDEC: + ret = RSA_private_decrypt(flen, from, to, rsa, + padding); + break; + } + + m_create(p, imsg->hdr.type, 0, 0, -1); + m_add_id(p, id); + m_add_int(p, ret); + if (ret > 0) + m_add_data(p, to, (size_t)ret); + m_close(p); + + free(to); + RSA_free(rsa); + + return; + } + } - free(to); - RSA_free(rsa); + errx(1, "ca_imsg: unexpected %s imsg", imsg_to_str(imsg->hdr.type)); } /* @@ -250,16 +370,16 @@ rsae_send_imsg(int flen, const u_char *from, u_char *to, RSA *rsa, * Send a synchronous imsg because we cannot defer the RSA * operation in OpenSSL's engine layer. */ - m_create(p_lka, cmd, 0, 0, -1); + m_create(p_ca, cmd, 0, 0, -1); rsae_reqid++; - m_add_id(p_lka, rsae_reqid); - m_add_string(p_lka, pkiname); - m_add_data(p_lka, (const void *)from, (size_t)flen); - m_add_size(p_lka, (size_t)RSA_size(rsa)); - m_add_size(p_lka, (size_t)padding); - m_flush(p_lka); + m_add_id(p_ca, rsae_reqid); + m_add_string(p_ca, pkiname); + m_add_data(p_ca, (const void *)from, (size_t)flen); + m_add_size(p_ca, (size_t)RSA_size(rsa)); + m_add_size(p_ca, (size_t)padding); + m_flush(p_ca); - ibuf = &p_lka->imsgbuf; + ibuf = &p_ca->imsgbuf; while (!done) { if ((n = imsg_read(ibuf)) == -1) @@ -273,7 +393,7 @@ rsae_send_imsg(int flen, const u_char *from, u_char *to, RSA *rsa, if (n == 0) break; - log_imsg(PROC_PONY, PROC_LKA, &imsg); + log_imsg(PROC_PONY, PROC_CA, &imsg); switch (imsg.hdr.type) { case IMSG_CA_PRIVENC: @@ -281,7 +401,7 @@ rsae_send_imsg(int flen, const u_char *from, u_char *to, RSA *rsa, break; default: /* Another imsg is queued up in the buffer */ - pony_imsg(p_lka, &imsg); + pony_imsg(p_ca, &imsg); imsg_free(&imsg); continue; } @@ -302,7 +422,7 @@ rsae_send_imsg(int flen, const u_char *from, u_char *to, RSA *rsa, imsg_free(&imsg); } } - mproc_event_add(p_lka); + mproc_event_add(p_ca); return (ret); } diff --git a/usr.sbin/smtpd/config.c b/usr.sbin/smtpd/config.c index 10843ef56f7..6443e4506c6 100644 --- a/usr.sbin/smtpd/config.c +++ b/usr.sbin/smtpd/config.c @@ -1,4 +1,4 @@ -/* $OpenBSD: config.c,v 1.30 2014/04/29 19:13:13 reyk Exp $ */ +/* $OpenBSD: config.c,v 1.31 2014/05/01 15:50:20 reyk Exp $ */ /* * Copyright (c) 2008 Pierre-Yves Ritschard @@ -165,6 +165,8 @@ config_peer(enum smtp_proc_type proc) p_scheduler = p; else if (proc == PROC_PONY) p_pony = p; + else if (proc == PROC_CA) + p_ca = p; else fatalx("bad peer"); } @@ -229,6 +231,7 @@ process_stat_event(int fd, short ev, void *arg) process_stat(p_queue); process_stat(p_scheduler); process_stat(p_pony); + process_stat(p_ca); tv.tv_sec = 1; tv.tv_usec = 0; diff --git a/usr.sbin/smtpd/lka.c b/usr.sbin/smtpd/lka.c index dc7f7852924..226614f2629 100644 --- a/usr.sbin/smtpd/lka.c +++ b/usr.sbin/smtpd/lka.c @@ -1,4 +1,4 @@ -/* $OpenBSD: lka.c,v 1.168 2014/04/29 19:13:13 reyk Exp $ */ +/* $OpenBSD: lka.c,v 1.169 2014/05/01 15:50:20 reyk Exp $ */ /* * Copyright (c) 2008 Pierre-Yves Ritschard @@ -91,12 +91,6 @@ lka_imsg(struct mproc *p, struct imsg *imsg) return; } - if (imsg->hdr.type == IMSG_CA_PRIVENC || - imsg->hdr.type == IMSG_CA_PRIVDEC) { - ca_imsg(p, imsg); - return; - } - if (p->proc == PROC_PONY) { switch (imsg->hdr.type) { case IMSG_SMTP_EXPAND_RCPT: @@ -389,7 +383,6 @@ lka_imsg(struct mproc *p, struct imsg *imsg) if (verbose & TRACE_TABLES) table_dump_all(); table_open_all(); - ca_init(); /* Start fulfilling requests */ mproc_enable(p_pony); diff --git a/usr.sbin/smtpd/pony.c b/usr.sbin/smtpd/pony.c index 754480a27d6..b61d29720fe 100644 --- a/usr.sbin/smtpd/pony.c +++ b/usr.sbin/smtpd/pony.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pony.c,v 1.4 2014/04/30 08:23:42 reyk Exp $ */ +/* $OpenBSD: pony.c,v 1.5 2014/05/01 15:50:20 reyk Exp $ */ /* * Copyright (c) 2014 Gilles Chehade @@ -210,6 +210,7 @@ pony(void) config_peer(PROC_QUEUE); config_peer(PROC_LKA); config_peer(PROC_CONTROL); + config_peer(PROC_CA); config_done(); ca_engine_init(); diff --git a/usr.sbin/smtpd/smtpd.c b/usr.sbin/smtpd/smtpd.c index bdfbed4b15c..8844bedd945 100644 --- a/usr.sbin/smtpd/smtpd.c +++ b/usr.sbin/smtpd/smtpd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: smtpd.c,v 1.225 2014/04/30 08:23:42 reyk Exp $ */ +/* $OpenBSD: smtpd.c,v 1.226 2014/05/01 15:50:20 reyk Exp $ */ /* * Copyright (c) 2008 Gilles Chehade @@ -59,6 +59,7 @@ static void parent_shutdown(int); static void parent_send_config(int, short, void *); static void parent_send_config_lka(void); static void parent_send_config_pony(void); +static void parent_send_config_ca(void); static void parent_sig_handler(int, short, void *); static void forkmda(struct mproc *, uint64_t, struct deliver *); static int parent_forward_open(char *, char *, uid_t, gid_t); @@ -122,6 +123,7 @@ struct mproc *p_parent = NULL; struct mproc *p_queue = NULL; struct mproc *p_scheduler = NULL; struct mproc *p_pony = NULL; +struct mproc *p_ca = NULL; const char *backend_queue = "fs"; const char *backend_scheduler = "ramqueue"; @@ -236,6 +238,7 @@ parent_imsg(struct mproc *p, struct imsg *imsg) m_forward(p_lka, imsg); m_forward(p_queue, imsg); m_forward(p_pony, imsg); + m_forward(p_ca, imsg); return; case IMSG_CTL_TRACE_ENABLE: @@ -278,7 +281,8 @@ parent_imsg(struct mproc *p, struct imsg *imsg) } } - errx(1, "parent_imsg: unexpected %s imsg", imsg_to_str(imsg->hdr.type)); + errx(1, "parent_imsg: unexpected %s imsg from %s", + imsg_to_str(imsg->hdr.type), proc_title(p->proc)); } static void @@ -318,6 +322,7 @@ parent_send_config(int fd, short event, void *p) { parent_send_config_lka(); parent_send_config_pony(); + parent_send_config_ca(); purge_config(PURGE_PKI); } @@ -337,6 +342,14 @@ parent_send_config_lka() m_compose(p_lka, IMSG_CONF_END, 0, 0, -1, NULL, 0); } +static void +parent_send_config_ca(void) +{ + log_debug("debug: parent_send_config: configuring ca process"); + m_compose(p_ca, IMSG_CONF_START, 0, 0, -1, NULL, 0); + m_compose(p_ca, IMSG_CONF_END, 0, 0, -1, NULL, 0); +} + static void parent_sig_handler(int sig, short event, void *p) { @@ -650,6 +663,7 @@ main(int argc, char *argv[]) config_peer(PROC_CONTROL); config_peer(PROC_LKA); config_peer(PROC_QUEUE); + config_peer(PROC_CA); config_peer(PROC_PONY); config_done(); @@ -731,6 +745,7 @@ fork_peers(void) child_add(lka(), CHILD_DAEMON, proc_title(PROC_LKA)); child_add(scheduler(), CHILD_DAEMON, proc_title(PROC_SCHEDULER)); child_add(pony(), CHILD_DAEMON, proc_title(PROC_PONY)); + child_add(ca(), CHILD_DAEMON, proc_title(PROC_CA)); post_fork(PROC_PARENT); } @@ -745,7 +760,7 @@ post_fork(int proc) control_socket = -1; } - if (proc == PROC_LKA) { + if (proc == PROC_CA) { load_pki_keys(); } } @@ -1229,6 +1244,8 @@ proc_title(enum smtp_proc_type proc) return "scheduler"; case PROC_PONY: return "pony express"; + case PROC_CA: + return "klondike"; default: return "unknown"; } @@ -1250,6 +1267,8 @@ proc_name(enum smtp_proc_type proc) return "scheduler"; case PROC_PONY: return "pony"; + case PROC_CA: + return "ca"; case PROC_FILTER: return "filter-proc"; case PROC_CLIENT: @@ -1439,6 +1458,10 @@ parent_broadcast_verbose(uint32_t v) m_create(p_queue, IMSG_CTL_VERBOSE, 0, 0, -1); m_add_int(p_queue, v); m_close(p_queue); + + m_create(p_ca, IMSG_CTL_VERBOSE, 0, 0, -1); + m_add_int(p_ca, v); + m_close(p_ca); } static void @@ -1455,4 +1478,8 @@ parent_broadcast_profile(uint32_t v) m_create(p_queue, IMSG_CTL_PROFILE, 0, 0, -1); m_add_int(p_queue, v); m_close(p_queue); + + m_create(p_ca, IMSG_CTL_VERBOSE, 0, 0, -1); + m_add_int(p_ca, v); + m_close(p_ca); } diff --git a/usr.sbin/smtpd/smtpd.h b/usr.sbin/smtpd/smtpd.h index 606f62a0f4d..c1db503ef63 100644 --- a/usr.sbin/smtpd/smtpd.h +++ b/usr.sbin/smtpd/smtpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: smtpd.h,v 1.459 2014/04/30 09:17:29 gilles Exp $ */ +/* $OpenBSD: smtpd.h,v 1.460 2014/05/01 15:50:20 reyk Exp $ */ /* * Copyright (c) 2008 Gilles Chehade @@ -31,7 +31,7 @@ #define MAILNAME_FILE "/etc/mail/mailname" #define CA_FILE "/etc/ssl/cert.pem" -#define PROC_COUNT 6 +#define PROC_COUNT 7 #define MAX_HOPS_COUNT 100 #define DEFAULT_MAX_BODY_SIZE (35*1024*1024) @@ -301,6 +301,7 @@ enum smtp_proc_type { PROC_CONTROL, PROC_SCHEDULER, PROC_PONY, + PROC_CA, PROC_FILTER, PROC_CLIENT, @@ -979,6 +980,7 @@ extern struct mproc *p_lka; extern struct mproc *p_queue; extern struct mproc *p_scheduler; extern struct mproc *p_pony; +extern struct mproc *p_ca; extern struct smtpd *env; extern void (*imsg_callback)(struct mproc *, struct imsg *); @@ -1072,6 +1074,7 @@ void bounce_fd(int); /* ca.c */ +pid_t ca(void); int ca_X509_verify(void *, void *, const char *, const char *, const char **); void ca_imsg(struct mproc *, struct imsg *); void ca_init(void); -- 2.20.1