From patchwork Sun Nov 27 09:07:42 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arne Schwabe X-Patchwork-Id: 2861 Return-Path: Delivered-To: patchwork@openvpn.net Delivered-To: patchwork@openvpn.net Received: from director9.mail.ord1d.rsapps.net ([172.30.191.6]) by backend30.mail.ord1d.rsapps.net with LMTP id HpL9HjYpg2PACAAAIUCqbw (envelope-from ) for ; Sun, 27 Nov 2022 04:09:10 -0500 Received: from proxy15.mail.ord1d.rsapps.net ([172.30.191.6]) by director9.mail.ord1d.rsapps.net with LMTP id wN5vHjYpg2P/aAAAalYnBA (envelope-from ) for ; Sun, 27 Nov 2022 04:09:10 -0500 Received: from smtp26.gate.ord1c ([172.30.191.6]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) by proxy15.mail.ord1d.rsapps.net with LMTPS id IELFHjYpg2MFGQAAAY1PeQ (envelope-from ) for ; Sun, 27 Nov 2022 04:09:10 -0500 X-Spam-Threshold: 95 X-Spam-Score: 0 X-Spam-Flag: NO X-Virus-Scanned: OK X-Orig-To: openvpnslackdevel@openvpn.net X-Originating-Ip: [216.105.38.7] Authentication-Results: smtp26.gate.ord1c.rsapps.net; iprev=pass policy.iprev="216.105.38.7"; spf=pass smtp.mailfrom="openvpn-devel-bounces@lists.sourceforge.net" smtp.helo="lists.sourceforge.net"; dkim=fail (signature verification failed) header.d=sourceforge.net; dkim=fail (signature verification failed) header.d=sf.net; dmarc=none (p=nil; dis=none) header.from=rfc2549.org X-Suspicious-Flag: YES X-Classification-ID: 26e2b47a-6e33-11ed-8c99-b8ca3a5bd12c-1-1 Received: from [216.105.38.7] ([216.105.38.7:39910] helo=lists.sourceforge.net) by smtp26.gate.ord1c.rsapps.net (envelope-from ) (ecelerity 4.2.38.62370 r(:)) with ESMTPS (cipher=DHE-RSA-AES256-GCM-SHA384) id 33/76-11957-53923836; Sun, 27 Nov 2022 04:09:10 -0500 Received: from [127.0.0.1] (helo=sfs-ml-2.v29.lw.sourceforge.com) by sfs-ml-2.v29.lw.sourceforge.com with esmtp (Exim 4.95) (envelope-from ) id 1ozDe5-0008Lx-Ta; Sun, 27 Nov 2022 09:08:17 +0000 Received: from [172.30.20.202] (helo=mx.sourceforge.net) by sfs-ml-2.v29.lw.sourceforge.com with esmtps (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.95) (envelope-from ) id 1ozDdi-0008LW-HR for openvpn-devel@lists.sourceforge.net; Sun, 27 Nov 2022 09:07:54 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sourceforge.net; s=x; h=Content-Transfer-Encoding:MIME-Version:References: In-Reply-To:Message-Id:Date:Subject:To:From:Sender:Reply-To:Cc:Content-Type: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=oZQBMRUuIut4e+48HS/24qjWNWKZ3NGGhutWCd+n8Gk=; b=JFPGEPX4V7jJwTHZWZGAyoWo4y NwsfXalvEzaTH3WsguZF/cuw+IIlkNa4mi42FtXjqQzam93Y0aUuB2uZ2VXz4go3gaOuVYMaCz70D 0YV2sKNr3+Fmh4poZzQPlUROqJOo6/112jeIdo3Chcm/2zEttxaERU363Q7XmqBPLKcA=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-Id: Date:Subject:To:From:Sender:Reply-To:Cc:Content-Type:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=oZQBMRUuIut4e+48HS/24qjWNWKZ3NGGhutWCd+n8Gk=; b=F6fkupd3VO6PFpwO6GwRABh0y3 Kz7PymaPUUD5tixw+vzFN9HHNwbnHljyEu2UsQaZuZO0zjG2EoSpAfmFEME4afnCsuHuVQtW3OPQP VusrdV521vnkF8FAGROVu8sZdqhhPdoSIpxfNIVRZHk97yv7aacPs2mJjh0ltqZ66ZvE=; Received: from mail.blinkt.de ([192.26.174.232]) by sfi-mx-1.v28.lw.sourceforge.com with esmtps (TLS1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.95) id 1ozDdh-00FLsg-KD for openvpn-devel@lists.sourceforge.net; Sun, 27 Nov 2022 09:07:54 +0000 Received: from kamera.blinkt.de ([2001:638:502:390:20c:29ff:fec8:535c]) by mail.blinkt.de with smtp (Exim 4.95 (FreeBSD)) (envelope-from ) id 1ozDdW-000IAQ-KO for openvpn-devel@lists.sourceforge.net; Sun, 27 Nov 2022 10:07:42 +0100 Received: (nullmailer pid 3488043 invoked by uid 10006); Sun, 27 Nov 2022 09:07:42 -0000 From: Arne Schwabe To: openvpn-devel@lists.sourceforge.net Date: Sun, 27 Nov 2022 10:07:42 +0100 Message-Id: <20221127090742.3487997-1-arne@rfc2549.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20221012133457.1927871-1-arne@rfc2549.org> References: <20221012133457.1927871-1-arne@rfc2549.org> MIME-Version: 1.0 X-Spam-Report: Spam detection software, running on the system "util-spamd-2.v13.lw.sourceforge.com", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: The lifetime and state machine of multi->peer_id does not exactly the lifetime/state of DCO. This is especially for p2p NCP where a reconnection can change the peer id. Also use this new field with va [...] Content analysis details: (0.3 points, 6.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.0 SPF_NONE SPF: sender does not publish an SPF Record 0.2 HEADER_FROM_DIFFERENT_DOMAINS From and EnvelopeFrom 2nd level mail domains are different X-Headers-End: 1ozDdh-00FLsg-KD Subject: [Openvpn-devel] [PATCH v3 1/3] Use dedicated multi->dco_peer_id for DCO instead of multi->peer_id X-BeenThere: openvpn-devel@lists.sourceforge.net X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: openvpn-devel-bounces@lists.sourceforge.net X-getmail-retrieved-from-mailbox: Inbox The lifetime and state machine of multi->peer_id does not exactly the lifetime/state of DCO. This is especially for p2p NCP where a reconnection can change the peer id. Also use this new field with value -1 to mean not installed, replacing the dco_peer_added field. Also ensure that we have a failure adding a new peer, we don't try to set options for that peer or generating keys for it. Patch v2: fix one comparison checking for 0 instead of -1 Patch v3: make recovery after failing dco_add_peer more robust and the comparison that lead to not deleting a peer. Signed-off-by: Arne Schwabe Acked-by: Gert Doering --- src/openvpn/dco.c | 24 ++++++------ src/openvpn/forward.c | 2 +- src/openvpn/init.c | 4 +- src/openvpn/multi.c | 80 +++++++++++++++++++++++----------------- src/openvpn/ssl.c | 1 + src/openvpn/ssl_common.h | 9 ++++- 6 files changed, 70 insertions(+), 50 deletions(-) diff --git a/src/openvpn/dco.c b/src/openvpn/dco.c index f190d038b..47fb00037 100644 --- a/src/openvpn/dco.c +++ b/src/openvpn/dco.c @@ -55,7 +55,7 @@ dco_install_key(struct tls_multi *multi, struct key_state *ks, const char *ciphername) { - msg(D_DCO_DEBUG, "%s: peer_id=%d keyid=%d", __func__, multi->peer_id, + msg(D_DCO_DEBUG, "%s: peer_id=%d keyid=%d", __func__, multi->dco_peer_id, ks->key_id); /* Install a key in the PRIMARY slot only when no other key exist. @@ -69,7 +69,7 @@ dco_install_key(struct tls_multi *multi, struct key_state *ks, slot = OVPN_KEY_SLOT_SECONDARY; } - int ret = dco_new_key(multi->dco, multi->peer_id, ks->key_id, slot, + int ret = dco_new_key(multi->dco, multi->dco_peer_id, ks->key_id, slot, encrypt_key, encrypt_iv, decrypt_key, decrypt_iv, ciphername); @@ -133,7 +133,7 @@ dco_get_secondary_key(struct tls_multi *multi, const struct key_state *primary) void dco_update_keys(dco_context_t *dco, struct tls_multi *multi) { - msg(D_DCO_DEBUG, "%s: peer_id=%d", __func__, multi->peer_id); + msg(D_DCO_DEBUG, "%s: peer_id=%d", __func__, multi->dco_peer_id); /* this function checks if keys have to be swapped or erased, therefore it * can't do much if we don't have any key installed @@ -151,14 +151,14 @@ dco_update_keys(dco_context_t *dco, struct tls_multi *multi) { msg(D_DCO, "No encryption key found. Purging data channel keys"); - int ret = dco_del_key(dco, multi->peer_id, OVPN_KEY_SLOT_PRIMARY); + int ret = dco_del_key(dco, multi->dco_peer_id, OVPN_KEY_SLOT_PRIMARY); if (ret < 0) { msg(D_DCO, "Cannot delete primary key during wipe: %s (%d)", strerror(-ret), ret); return; } - ret = dco_del_key(dco, multi->peer_id, OVPN_KEY_SLOT_SECONDARY); + ret = dco_del_key(dco, multi->dco_peer_id, OVPN_KEY_SLOT_SECONDARY); if (ret < 0) { msg(D_DCO, "Cannot delete secondary key during wipe: %s (%d)", strerror(-ret), ret); @@ -184,7 +184,7 @@ dco_update_keys(dco_context_t *dco, struct tls_multi *multi) msg(D_DCO_DEBUG, "Swapping primary and secondary keys, now: id1=%d id2=%d", primary->key_id, secondary ? secondary->key_id : -1); - int ret = dco_swap_keys(dco, multi->peer_id); + int ret = dco_swap_keys(dco, multi->dco_peer_id); if (ret < 0) { msg(D_DCO, "Cannot swap keys: %s (%d)", strerror(-ret), ret); @@ -202,7 +202,7 @@ dco_update_keys(dco_context_t *dco, struct tls_multi *multi) /* if we have no secondary key anymore, inform DCO about it */ if (!secondary && multi->dco_keys_installed == 2) { - int ret = dco_del_key(dco, multi->peer_id, OVPN_KEY_SLOT_SECONDARY); + int ret = dco_del_key(dco, multi->dco_peer_id, OVPN_KEY_SLOT_SECONDARY); if (ret < 0) { msg(D_DCO, "Cannot delete secondary key: %s (%d)", strerror(-ret), ret); @@ -465,7 +465,7 @@ dco_p2p_add_new_peer(struct context *c) return ret; } - c->c2.tls_multi->dco_peer_added = true; + c->c2.tls_multi->dco_peer_id = multi->peer_id; c->c2.link_socket->info.lsa->actual.dco_installed = true; return 0; @@ -479,10 +479,10 @@ dco_remove_peer(struct context *c) return; } - if (c->c1.tuntap && c->c2.tls_multi && c->c2.tls_multi->dco_peer_added) + if (c->c1.tuntap && c->c2.tls_multi && c->c2.tls_multi->dco_peer_id != -1) { - dco_del_peer(&c->c1.tuntap->dco, c->c2.tls_multi->peer_id); - c->c2.tls_multi->dco_peer_added = false; + dco_del_peer(&c->c1.tuntap->dco, c->c2.tls_multi->dco_peer_id); + c->c2.tls_multi->dco_peer_id = -1; } } @@ -585,7 +585,7 @@ dco_multi_add_new_peer(struct multi_context *m, struct multi_instance *mi) return ret; } - c->c2.tls_multi->dco_peer_added = true; + c->c2.tls_multi->dco_peer_id = peer_id; if (c->mode == CM_CHILD_TCP) { diff --git a/src/openvpn/forward.c b/src/openvpn/forward.c index 1dcaabd8e..3b5b04074 100644 --- a/src/openvpn/forward.c +++ b/src/openvpn/forward.c @@ -1734,7 +1734,7 @@ process_outgoing_link(struct context *c) if (should_use_dco_socket(c->c2.to_link_addr)) { size = dco_do_write(&c->c1.tuntap->dco, - c->c2.tls_multi->peer_id, + c->c2.tls_multi->dco_peer_id, &c->c2.to_link); } else diff --git a/src/openvpn/init.c b/src/openvpn/init.c index 1b30c8f0a..0e4769775 100644 --- a/src/openvpn/init.c +++ b/src/openvpn/init.c @@ -2151,14 +2151,14 @@ do_deferred_options_part2(struct context *c) && (c->options.ping_send_timeout || c->c2.frame.mss_fix)) { int ret = dco_set_peer(&c->c1.tuntap->dco, - c->c2.tls_multi->peer_id, + c->c2.tls_multi->dco_peer_id, c->options.ping_send_timeout, c->options.ping_rec_timeout, c->c2.frame.mss_fix); if (ret < 0) { msg(D_DCO, "Cannot set parameters for DCO peer (id=%u): %s", - c->c2.tls_multi->peer_id, strerror(-ret)); + c->c2.tls_multi->dco_peer_id, strerror(-ret)); return false; } } diff --git a/src/openvpn/multi.c b/src/openvpn/multi.c index b9b087e01..0a23c2bcf 100644 --- a/src/openvpn/multi.c +++ b/src/openvpn/multi.c @@ -2305,6 +2305,42 @@ cleanup: return ret; } +static bool +multi_client_setup_dco_initial(struct multi_context *m, + struct multi_instance *mi, + struct gc_arena *gc) +{ + if (!dco_enabled(&mi->context.options)) + { + /* DCO not enabled, nothing to do, return sucess */ + return true; + } + int ret = dco_multi_add_new_peer(m, mi); + if (ret < 0) + { + msg(D_DCO, "Cannot add peer to DCO for %s: %s (%d)", + multi_instance_string(mi, false, gc), strerror(-ret), ret); + return false; + } + + if (mi->context.options.ping_send_timeout || mi->context.c2.frame.mss_fix) + { + ret = dco_set_peer(&mi->context.c1.tuntap->dco, + mi->context.c2.tls_multi->dco_peer_id, + mi->context.options.ping_send_timeout, + mi->context.options.ping_rec_timeout, + mi->context.c2.frame.mss_fix); + if (ret < 0) + { + msg(D_DCO, "Cannot set DCO peer parameters for %s (id=%u): %s", + multi_instance_string(mi, false, gc), + mi->context.c2.tls_multi->dco_peer_id, strerror(-ret)); + return false; + } + } + return true; +} + /** * Generates the data channel keys */ @@ -2432,39 +2468,16 @@ multi_client_connect_late_setup(struct multi_context *m, { mi->context.c2.tls_multi->multi_state = CAS_FAILED; } + /* only continue if setting protocol options worked */ + else if (!multi_client_setup_dco_initial(m, mi, &gc)) + { + mi->context.c2.tls_multi->multi_state = CAS_FAILED; + } /* Generate data channel keys only if setting protocol options - * has not failed */ - else + * and DCO initial setup has not failed */ + else if (!multi_client_generate_tls_keys(&mi->context)) { - if (dco_enabled(&mi->context.options)) - { - int ret = dco_multi_add_new_peer(m, mi); - if (ret < 0) - { - msg(D_DCO, "Cannot add peer to DCO: %s (%d)", strerror(-ret), ret); - mi->context.c2.tls_multi->multi_state = CAS_FAILED; - } - - if (mi->context.options.ping_send_timeout || mi->context.c2.frame.mss_fix) - { - int ret = dco_set_peer(&mi->context.c1.tuntap->dco, - mi->context.c2.tls_multi->peer_id, - mi->context.options.ping_send_timeout, - mi->context.options.ping_rec_timeout, - mi->context.c2.frame.mss_fix); - if (ret < 0) - { - msg(D_DCO, "Cannot set parameters for DCO peer (id=%u): %s", - mi->context.c2.tls_multi->peer_id, strerror(-ret)); - mi->context.c2.tls_multi->multi_state = CAS_FAILED; - } - } - } - - if (!multi_client_generate_tls_keys(&mi->context)) - { - mi->context.c2.tls_multi->multi_state = CAS_FAILED; - } + mi->context.c2.tls_multi->multi_state = CAS_FAILED; } /* send push reply if ready */ @@ -2472,7 +2485,6 @@ multi_client_connect_late_setup(struct multi_context *m, { process_incoming_push_request(&mi->context); } - gc_free(&gc); } @@ -3226,8 +3238,8 @@ process_incoming_del_peer(struct multi_context *m, struct multi_instance *mi, } /* When kernel already deleted the peer, the socket is no longer - * installed and we don't need to cleanup the state in the kernel */ - mi->context.c2.tls_multi->dco_peer_added = false; + * installed, and we do not need to clean up the state in the kernel */ + mi->context.c2.tls_multi->dco_peer_id = -1; mi->context.sig->signal_text = reason; multi_signal_instance(m, mi, SIGTERM); } diff --git a/src/openvpn/ssl.c b/src/openvpn/ssl.c index a73a2b714..818100c23 100644 --- a/src/openvpn/ssl.c +++ b/src/openvpn/ssl.c @@ -1315,6 +1315,7 @@ tls_multi_init(struct tls_options *tls_options) /* get command line derived options */ ret->opt = *tls_options; + ret->dco_peer_id = -1; return ret; } diff --git a/src/openvpn/ssl_common.h b/src/openvpn/ssl_common.h index 24d40ab83..e967970dd 100644 --- a/src/openvpn/ssl_common.h +++ b/src/openvpn/ssl_common.h @@ -661,7 +661,14 @@ struct tls_multi /* Only used when DCO is used to remember how many keys we installed * for this session */ int dco_keys_installed; - bool dco_peer_added; + /** + * This is the handle that DCO uses to identify this session with the + * kernel. + * + * We keep this separate as the normal peer_id can change during + * p2p NCP and we need to track the id that is really used. + */ + int dco_peer_id; dco_context_t *dco; };