Use per connection peerid for control replies
authortobhe <tobhe@openbsd.org>
Wed, 24 Jan 2024 10:09:07 +0000 (10:09 +0000)
committertobhe <tobhe@openbsd.org>
Wed, 24 Jan 2024 10:09:07 +0000 (10:09 +0000)
instead of 'broadcasting' replies for 'ikectl show sa' and
similar control requests, we now assign a uniq peerid to each
request and pass this peerid between the processes so the reply
can be sent on the matching connection.

from markus@

sbin/iked/ca.c
sbin/iked/control.c
sbin/iked/iked.h
sbin/iked/ikev2.c

index 398a9ff..8c1cdd2 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ca.c,v 1.98 2024/01/15 15:29:00 tobhe Exp $   */
+/*     $OpenBSD: ca.c,v 1.99 2024/01/24 10:09:07 tobhe Exp $   */
 
 /*
  * Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org>
@@ -76,7 +76,7 @@ int    ca_x509_subjectaltname_get(X509 *cert, struct iked_id *);
 int     ca_dispatch_parent(int, struct privsep_proc *, struct imsg *);
 int     ca_dispatch_ikev2(int, struct privsep_proc *, struct imsg *);
 int     ca_dispatch_control(int, struct privsep_proc *, struct imsg *);
-void    ca_store_info(struct iked *, const char *, X509_STORE *);
+void    ca_store_info(struct iked *, struct imsg *, const char *, X509_STORE *);
 
 static struct privsep_proc procs[] = {
        { "parent",     PROC_PARENT,    ca_dispatch_parent },
@@ -391,11 +391,12 @@ ca_dispatch_control(int fd, struct privsep_proc *p, struct imsg *imsg)
 
        switch (imsg->hdr.type) {
        case IMSG_CTL_SHOW_CERTSTORE:
-               ca_store_info(env, "CA", store->ca_cas);
-               ca_store_info(env, "CERT", store->ca_certs);
+               ca_store_info(env, imsg, "CA", store->ca_cas);
+               ca_store_info(env, imsg, "CERT", store->ca_certs);
                /* Send empty reply to indicate end of information. */
-               proc_compose(&env->sc_ps, PROC_CONTROL, IMSG_CTL_SHOW_CERTSTORE,
-                   NULL, 0);
+               proc_compose_imsg(&env->sc_ps, PROC_CONTROL, -1,
+                   IMSG_CTL_SHOW_CERTSTORE, imsg->hdr.peerid,
+                   -1, NULL, 0);
                break;
        default:
                return (-1);
@@ -1333,7 +1334,7 @@ ca_subjectpubkey_digest(X509 *x509, uint8_t *md, unsigned int *size)
 }
 
 void
-ca_store_info(struct iked *env, const char *msg, X509_STORE *ctx)
+ca_store_info(struct iked *env, struct imsg *imsg, const char *msg, X509_STORE *ctx)
 {
        STACK_OF(X509_OBJECT)   *h;
        X509_OBJECT             *xo;
@@ -1357,8 +1358,9 @@ ca_store_info(struct iked *env, const char *msg, X509_STORE *ctx)
                OPENSSL_free(name);
                if (buflen == -1)
                        continue;
-               proc_compose(&env->sc_ps, PROC_CONTROL, IMSG_CTL_SHOW_CERTSTORE,
-                   buf, buflen + 1);
+               proc_compose_imsg(&env->sc_ps, PROC_CONTROL, -1,
+                   IMSG_CTL_SHOW_CERTSTORE, imsg->hdr.peerid,
+                   -1, buf, buflen + 1);
                free(buf);
        }
 }
index 5b73470..d690af9 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: control.c,v 1.37 2023/03/08 04:43:06 guenther Exp $   */
+/*     $OpenBSD: control.c,v 1.38 2024/01/24 10:09:07 tobhe Exp $      */
 
 /*
  * Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org>
@@ -36,6 +36,7 @@
 #define        CONTROL_BACKLOG 5
 
 struct ctl_connlist ctl_conns = TAILQ_HEAD_INITIALIZER(ctl_conns);
+uint32_t ctl_peerid;
 
 void
         control_accept(int, short, void *);
@@ -45,6 +46,7 @@ void   control_close(int, struct control_sock *);
 void    control_dispatch_imsg(int, short, void *);
 void    control_dispatch_parent(int, short, void *);
 void    control_imsg_forward(struct imsg *);
+void    control_imsg_forward_peerid(struct imsg *);
 void    control_run(struct privsep *, struct privsep_proc *, void *);
 int     control_dispatch_ikev2(int, struct privsep_proc *, struct imsg *);
 int     control_dispatch_ca(int, struct privsep_proc *, struct imsg *);
@@ -160,6 +162,7 @@ control_accept(int listenfd, short event, void *arg)
        socklen_t                len;
        struct sockaddr_un       s_un;
        struct ctl_conn         *c;
+       struct ctl_conn         *other;
 
        event_add(&cs->cs_ev, NULL);
        if ((event & EV_TIMEOUT))
@@ -197,6 +200,12 @@ control_accept(int listenfd, short event, void *arg)
            c->iev.handler, c->iev.data);
        event_add(&c->iev.ev, NULL);
 
+       /* O(n^2), but n is small */
+       c->peerid = ctl_peerid++;
+       TAILQ_FOREACH(other, &ctl_conns, entry)
+               if (c->peerid == other->peerid)
+                       c->peerid = ctl_peerid++;
+
        TAILQ_INSERT_TAIL(&ctl_conns, c, entry);
 }
 
@@ -277,6 +286,9 @@ control_dispatch_imsg(int fd, short event, void *arg)
 
                control_imsg_forward(&imsg);
 
+               /* record peerid of connection for reply */
+               imsg.hdr.peerid = c->peerid;
+
                switch (imsg.hdr.type) {
                case IMSG_CTL_NOTIFY:
                        if (c->flags & CTL_CONN_NOTIFY) {
@@ -311,11 +323,9 @@ control_dispatch_imsg(int fd, short event, void *arg)
                case IMSG_CTL_SHOW_SA:
                case IMSG_CTL_SHOW_STATS:
                        proc_forward_imsg(&env->sc_ps, &imsg, PROC_IKEV2, -1);
-                       c->flags |= CTL_CONN_NOTIFY;
                        break;
                case IMSG_CTL_SHOW_CERTSTORE:
                        proc_forward_imsg(&env->sc_ps, &imsg, PROC_CERT, -1);
-                       c->flags |= CTL_CONN_NOTIFY;
                        break;
                default:
                        log_debug("%s: error handling imsg %d",
@@ -340,13 +350,25 @@ control_imsg_forward(struct imsg *imsg)
                            imsg->hdr.len - IMSG_HEADER_SIZE);
 }
 
+void
+control_imsg_forward_peerid(struct imsg *imsg)
+{
+       struct ctl_conn *c;
+
+       TAILQ_FOREACH(c, &ctl_conns, entry)
+               if (c->peerid == imsg->hdr.peerid)
+                       imsg_compose_event(&c->iev, imsg->hdr.type,
+                           0, imsg->hdr.pid, -1, imsg->data,
+                           imsg->hdr.len - IMSG_HEADER_SIZE);
+}
+
 int
 control_dispatch_ikev2(int fd, struct privsep_proc *p, struct imsg *imsg)
 {
        switch (imsg->hdr.type) {
        case IMSG_CTL_SHOW_SA:
        case IMSG_CTL_SHOW_STATS:
-               control_imsg_forward(imsg);
+               control_imsg_forward_peerid(imsg);
                return (0);
        default:
                break;
@@ -360,7 +382,7 @@ control_dispatch_ca(int fd, struct privsep_proc *p, struct imsg *imsg)
 {
        switch (imsg->hdr.type) {
        case IMSG_CTL_SHOW_CERTSTORE:
-               control_imsg_forward(imsg);
+               control_imsg_forward_peerid(imsg);
                return (0);
        default:
                break;
index 89d491a..9717489 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: iked.h,v 1.225 2024/01/15 15:29:00 tobhe Exp $        */
+/*     $OpenBSD: iked.h,v 1.226 2024/01/24 10:09:07 tobhe Exp $        */
 
 /*
  * Copyright (c) 2019 Tobias Heider <tobias.heider@stusta.de>
@@ -99,6 +99,7 @@ struct ctl_conn {
        uint8_t                  flags;
 #define CTL_CONN_NOTIFY                 0x01
        struct imsgev            iev;
+       uint32_t                 peerid;
 };
 TAILQ_HEAD(ctl_connlist, ctl_conn);
 
index 27f246c..0f7a966 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ikev2.c,v 1.382 2024/01/15 21:37:58 jan Exp $ */
+/*     $OpenBSD: ikev2.c,v 1.383 2024/01/24 10:09:07 tobhe Exp $       */
 
 /*
  * Copyright (c) 2019 Tobias Heider <tobias.heider@stusta.de>
 #include "chap_ms.h"
 #include "version.h"
 
-void    ikev2_info(struct iked *, int);
-void    ikev2_info_sa(struct iked *, int, const char *, struct iked_sa *);
-void    ikev2_info_csa(struct iked *, int, const char *, struct iked_childsa *);
-void    ikev2_info_flow(struct iked *, int, const char *, struct iked_flow *);
+void    ikev2_info(struct iked *, struct imsg *, int);
+void    ikev2_info_sa(struct iked *, struct imsg *, int, const char *,
+           struct iked_sa *);
+void    ikev2_info_csa(struct iked *, struct imsg *, int, const char *,
+           struct iked_childsa *);
+void    ikev2_info_flow(struct iked *, struct imsg *, int, const char *,
+           struct iked_flow *);
 void    ikev2_log_established(struct iked_sa *);
 void    ikev2_log_proposal(struct iked_sa *, struct iked_proposals *);
 void    ikev2_log_cert_info(const char *, struct iked_id *);
@@ -188,8 +191,8 @@ int  ikev2_resp_informational(struct iked *, struct iked_sa *,
            struct iked_message *);
 
 void   ikev2_ctl_reset_id(struct iked *, struct imsg *, unsigned int);
-void   ikev2_ctl_show_sa(struct iked *);
-void   ikev2_ctl_show_stats(struct iked *);
+void   ikev2_ctl_show_sa(struct iked *, struct imsg *);
+void   ikev2_ctl_show_stats(struct iked *, struct imsg *);
 
 static struct privsep_proc procs[] = {
        { "parent",     PROC_PARENT,    ikev2_dispatch_parent },
@@ -512,10 +515,10 @@ ikev2_dispatch_control(int fd, struct privsep_proc *p, struct imsg *imsg)
                ikev2_ctl_reset_id(env, imsg, imsg->hdr.type);
                break;
        case IMSG_CTL_SHOW_SA:
-               ikev2_ctl_show_sa(env);
+               ikev2_ctl_show_sa(env, imsg);
                break;
        case IMSG_CTL_SHOW_STATS:
-               ikev2_ctl_show_stats(env);
+               ikev2_ctl_show_stats(env, imsg);
                break;
        default:
                return (-1);
@@ -572,15 +575,16 @@ ikev2_ctl_reset_id(struct iked *env, struct imsg *imsg, unsigned int type)
 }
 
 void
-ikev2_ctl_show_sa(struct iked *env)
+ikev2_ctl_show_sa(struct iked *env, struct imsg *imsg)
 {
-       ikev2_info(env, 0);
+       ikev2_info(env, imsg, 0);
 }
 
 void
-ikev2_ctl_show_stats(struct iked *env)
+ikev2_ctl_show_stats(struct iked *env, struct imsg *imsg)
 {
-       proc_compose(&env->sc_ps, PROC_CONTROL, IMSG_CTL_SHOW_STATS,
+       proc_compose_imsg(&env->sc_ps, PROC_CONTROL, -1,
+           IMSG_CTL_SHOW_STATS, imsg->hdr.peerid, -1,
            &env->sc_stats, sizeof(env->sc_stats));
 }
 
@@ -7444,7 +7448,8 @@ ikev2_update_sa_addresses(struct iked *env, struct iked_sa *sa)
 }
 
 void
-ikev2_info_sa(struct iked *env, int dolog, const char *msg, struct iked_sa *sa)
+ikev2_info_sa(struct iked *env, struct imsg *imsg, int dolog, const char *msg,
+    struct iked_sa *sa)
 {
        char             idstr[IKED_ID_SIZE];
        char            *buf;
@@ -7476,13 +7481,15 @@ ikev2_info_sa(struct iked *env, int dolog, const char *msg, struct iked_sa *sa)
                        buf[buflen - 1] = '\0';
                log_debug("%s", buf);
        } else
-               proc_compose(&env->sc_ps, PROC_CONTROL, IMSG_CTL_SHOW_SA,
+               proc_compose_imsg(&env->sc_ps, PROC_CONTROL, -1,
+                   IMSG_CTL_SHOW_SA, imsg->hdr.peerid, -1,
                    buf, buflen + 1);
        free(buf);
 }
 
 void
-ikev2_info_csa(struct iked *env, int dolog, const char *msg, struct iked_childsa *csa)
+ikev2_info_csa(struct iked *env, struct imsg *imsg, int dolog, const char *msg,
+    struct iked_childsa *csa)
 {
        char            *buf;
        int              buflen;
@@ -7510,13 +7517,15 @@ ikev2_info_csa(struct iked *env, int dolog, const char *msg, struct iked_childsa
                        buf[buflen - 1] = '\0';
                log_debug("%s", buf);
        } else
-               proc_compose(&env->sc_ps, PROC_CONTROL, IMSG_CTL_SHOW_SA,
+               proc_compose_imsg(&env->sc_ps, PROC_CONTROL, -1,
+                   IMSG_CTL_SHOW_SA, imsg->hdr.peerid, -1,
                    buf, buflen + 1);
        free(buf);
 }
 
 void
-ikev2_info_flow(struct iked *env, int dolog, const char *msg, struct iked_flow *flow)
+ikev2_info_flow(struct iked *env, struct imsg *imsg, int dolog, const char *msg,
+    struct iked_flow *flow)
 {
        char            prenat_mask[10];
        char            *buf;
@@ -7555,13 +7564,14 @@ ikev2_info_flow(struct iked *env, int dolog, const char *msg, struct iked_flow *
                        buf[buflen - 1] = '\0';
                log_debug("%s", buf);
        } else
-               proc_compose(&env->sc_ps, PROC_CONTROL, IMSG_CTL_SHOW_SA,
+               proc_compose_imsg(&env->sc_ps, PROC_CONTROL, -1,
+                   IMSG_CTL_SHOW_SA, imsg->hdr.peerid, -1,
                    buf, buflen + 1);
        free(buf);
 }
 
 void
-ikev2_info(struct iked *env, int dolog)
+ikev2_info(struct iked *env, struct imsg *imsg, int dolog)
 {
        struct iked_sa                  *sa;
        struct iked_childsa             *csa, *ipcomp;
@@ -7570,32 +7580,33 @@ ikev2_info(struct iked *env, int dolog)
        log_debug("%s: called", __func__);
 
        RB_FOREACH(sa, iked_sas, &env->sc_sas) {
-               ikev2_info_sa(env, dolog, "iked_sas", sa);
+               ikev2_info_sa(env, imsg, dolog, "iked_sas", sa);
                TAILQ_FOREACH(csa, &sa->sa_childsas, csa_entry) {
-                       ikev2_info_csa(env, dolog, "  sa_childsas", csa);
+                       ikev2_info_csa(env, imsg, dolog, "  sa_childsas", csa);
                        if ((ipcomp = csa->csa_bundled) != NULL)
-                               ikev2_info_csa(env, dolog, "             ",
+                               ikev2_info_csa(env, imsg, dolog, "             ",
                                    ipcomp);
                }
                TAILQ_FOREACH(flow, &sa->sa_flows, flow_entry) {
-                       ikev2_info_flow(env, dolog, "  sa_flows", flow);
+                       ikev2_info_flow(env, imsg, dolog, "  sa_flows", flow);
                }
        }
        RB_FOREACH(csa, iked_activesas, &env->sc_activesas) {
-               ikev2_info_csa(env, dolog, "iked_activesas", csa);
+               ikev2_info_csa(env, imsg, dolog, "iked_activesas", csa);
                if ((ipcomp = csa->csa_bundled) != NULL)
-                       ikev2_info_csa(env, dolog, "              ", ipcomp);
+                       ikev2_info_csa(env, imsg, dolog, "              ", ipcomp);
        }
        RB_FOREACH(flow, iked_flows, &env->sc_activeflows) {
-               ikev2_info_flow(env, dolog, "iked_flows", flow);
+               ikev2_info_flow(env, imsg, dolog, "iked_flows", flow);
        }
        RB_FOREACH(sa, iked_dstid_sas, &env->sc_dstid_sas) {
-               ikev2_info_sa(env, dolog, "iked_dstid_sas", sa);
+               ikev2_info_sa(env, imsg, dolog, "iked_dstid_sas", sa);
        }
        if (dolog)
                return;
        /* Send empty reply to indicate end of information. */
-       proc_compose(&env->sc_ps, PROC_CONTROL, IMSG_CTL_SHOW_SA, NULL, 0);
+       proc_compose_imsg(&env->sc_ps, PROC_CONTROL, -1, IMSG_CTL_SHOW_SA,
+           imsg->hdr.peerid, -1, NULL, 0);
 }
 
 const char *