Move RSA keys from "lka" to a new dedicated "ca" process because lka
authorreyk <reyk@openbsd.org>
Thu, 1 May 2014 15:50:20 +0000 (15:50 +0000)
committerreyk <reyk@openbsd.org>
Thu, 1 May 2014 15:50:20 +0000 (15:50 +0000)
is handling some async requests and shouldn't be busy with sync RSA.

ok gilles@

usr.sbin/smtpd/ca.c
usr.sbin/smtpd/config.c
usr.sbin/smtpd/lka.c
usr.sbin/smtpd/pony.c
usr.sbin/smtpd/smtpd.c
usr.sbin/smtpd/smtpd.h

index 6a4e771..719c757 100644 (file)
@@ -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>
 
 #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);
 }
index 10843ef..6443e45 100644 (file)
@@ -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;
index dc7f785..226614f 100644 (file)
@@ -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);
index 754480a..b61d297 100644 (file)
@@ -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();
index bdfbed4..8844bed 100644 (file)
@@ -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);
 }
 
@@ -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);
 }
index 606f62a..c1db503 100644 (file)
@@ -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);