summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorReyk Floeter <reyk@cvs.openbsd.org>2014-05-01 15:50:21 +0000
committerReyk Floeter <reyk@cvs.openbsd.org>2014-05-01 15:50:21 +0000
commitb9d5b385896620a2eb15f204eab14e505b832482 (patch)
tree718b35029409ee72de57b12375e145a9a23ed533
parent5777f40cae0c30958be1374dead4ddae1efc2046 (diff)
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@
-rw-r--r--usr.sbin/smtpd/ca.c212
-rw-r--r--usr.sbin/smtpd/config.c5
-rw-r--r--usr.sbin/smtpd/lka.c9
-rw-r--r--usr.sbin/smtpd/pony.c3
-rw-r--r--usr.sbin/smtpd/smtpd.c33
-rw-r--r--usr.sbin/smtpd/smtpd.h7
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 <reyk@openbsd.org>
@@ -23,7 +23,10 @@
#include <string.h>
#include <stdlib.h>
+#include <unistd.h>
#include <imsg.h>
+#include <pwd.h>
+#include <err.h>
#include <openssl/pem.h>
#include <openssl/evp.h>
@@ -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 <pyr@openbsd.org>
@@ -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 <pyr@openbsd.org>
@@ -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 <gilles@poolp.org>
@@ -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 <gilles@poolp.org>
@@ -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);
}
@@ -338,6 +343,14 @@ parent_send_config_lka()
}
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)
{
struct child *child;
@@ -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 <gilles@poolp.org>
@@ -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);