From patchwork Mon Jun 4 17:29:00 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Antonio Quartulli X-Patchwork-Id: 343 Return-Path: Delivered-To: patchwork@openvpn.net Delivered-To: patchwork@openvpn.net Received: from director7.mail.ord1d.rsapps.net ([172.31.255.6]) by backend30.mail.ord1d.rsapps.net (Dovecot) with LMTP id y0rYBeMDFltdLwAAIUCqbw for ; Mon, 04 Jun 2018 23:30:43 -0400 Received: from proxy9.mail.iad3b.rsapps.net ([172.31.255.6]) by director7.mail.ord1d.rsapps.net (Dovecot) with LMTP id gTYlAeMDFluPGwAAovjBpQ ; Mon, 04 Jun 2018 23:30:43 -0400 Received: from smtp33.gate.iad3b ([172.31.255.6]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) by proxy9.mail.iad3b.rsapps.net with LMTP id qM6DN+IDFlsaUQAAC4PSzw ; Mon, 04 Jun 2018 23:30:42 -0400 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: smtp33.gate.iad3b.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=unstable.cc X-Suspicious-Flag: YES X-Classification-ID: d2f39df6-6870-11e8-b4e0-525400fb5834-1-1 Received: from [216.105.38.7] ([216.105.38.7:16098] helo=lists.sourceforge.net) by smtp33.gate.iad3b.rsapps.net (envelope-from ) (ecelerity 4.2.1.56364 r(Core:4.2.1.14)) with ESMTPS (cipher=DHE-RSA-AES256-GCM-SHA384) id 65/21-06927-2E3061B5; Mon, 04 Jun 2018 23:30:42 -0400 Received: from [127.0.0.1] (helo=sfs-ml-1.v29.lw.sourceforge.com) by sfs-ml-1.v29.lw.sourceforge.com with esmtp (Exim 4.90_1) (envelope-from ) id 1fQ2fI-0004vJ-Cn; Tue, 05 Jun 2018 03:29:44 +0000 Received: from [172.30.20.202] (helo=mx.sourceforge.net) by sfs-ml-1.v29.lw.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.90_1) (envelope-from ) id 1fQ2fG-0004vD-QW for openvpn-devel@lists.sourceforge.net; Tue, 05 Jun 2018 03:29:42 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sourceforge.net; s=x; h=Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To: MIME-Version:Content-Type:Content-Transfer-Encoding:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=O6lUMb91ibxCINgrFkkMMZRmQNMTX9AOVUl47dxtnkw=; b=l3KlSppoymsgg7Ds6JjqxL9FiT GI7z1GTL0Y+jidTI3ooar842lCf9m1ftgBdxtDb+skKgwedrAts1atjH8KeH++HvscOV+/7Ac3NqY Tr3Nb0zIlWZFwM7QAC31txajs7yBSO+TbjYi3KON3bQmBBHHVRP9cccaEiJsiCOHsqEE=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To:MIME-Version: Content-Type:Content-Transfer-Encoding:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: In-Reply-To:References:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=O6lUMb91ibxCINgrFkkMMZRmQNMTX9AOVUl47dxtnkw=; b=EANYD/oFPneqp4CsqvhMknO3/x /jQ/SxH9iqz+dA8zFQWH8DJ3BX36Msza7u8iCLGhH0aIzV9hywvCI8XQywgAUv8fG9aVtK0N/5WZC NI4kvGKkJJ0mjvCN/GKQ4D4FbjerYeyFdR1rnCqsWdqwAcLEJ1MfVUim79d5QfYycyLg=; Received: from s2.neomailbox.net ([5.148.176.60]) by sfi-mx-2.v28.lw.sourceforge.com with esmtps (TLSv1.2:DHE-RSA-AES256-GCM-SHA384:256) (Exim 4.90_1) id 1fQ2fD-004wJ4-Nt for openvpn-devel@lists.sourceforge.net; Tue, 05 Jun 2018 03:29:42 +0000 From: Antonio Quartulli To: openvpn-devel@lists.sourceforge.net Date: Tue, 5 Jun 2018 11:29:00 +0800 Message-Id: <20180605032902.26440-1-a@unstable.cc> X-Spam-Report: Spam Filtering performed by mx.sourceforge.net. See http://spamassassin.org/tag/ for more details. -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [5.148.176.60 listed in list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record X-Headers-End: 1fQ2fD-004wJ4-Nt Subject: [Openvpn-devel] [PATCH v2 1/3] crypto: always reload tls-auth/crypt key contexts 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: , Cc: Antonio Quartulli MIME-Version: 1.0 Errors-To: openvpn-devel-bounces@lists.sourceforge.net X-getmail-retrieved-from-mailbox: Inbox In preparation to having tls-auth/crypt keys per connection block, it is important to ensure that such material is always reload upon SIGUSR1, no matter is persist-key was specified or not. This is required because when moving from one remote to the other the key may change and thus the key context needs to be refreshed. Trac: #720 Cc: Steffan Karger Signed-off-by: Antonio Quartulli --- v2: - introduce this patch src/openvpn/buffer.c | 29 +++++++++++++++ src/openvpn/buffer.h | 13 +++++++ src/openvpn/crypto.c | 20 ++-------- src/openvpn/init.c | 87 +++++++++++++++++++++++++++++--------------- 4 files changed, 102 insertions(+), 47 deletions(-) diff --git a/src/openvpn/buffer.c b/src/openvpn/buffer.c index becfeb93..cbf969a8 100644 --- a/src/openvpn/buffer.c +++ b/src/openvpn/buffer.c @@ -1332,3 +1332,32 @@ buffer_list_file(const char *fn, int max_line_len) } return bl; } + +struct buffer +keyfile_to_buffer(const char *file, int max_size, struct gc_arena *gc) +{ + size_t size; + struct buffer in = alloc_buf_gc(max_size, gc); + int fd = platform_open(file, O_RDONLY, 0); + if (fd == -1) + { + msg(M_ERR, "Cannot open key file '%s'", file); + } + + size = read(fd, in.data, in.capacity); + if (size < 0) + { + msg(M_FATAL, "Read error on key file ('%s')", file); + } + + if (size == in.capacity) + { + msg(M_FATAL, "Key file ('%s') can be a maximum of %d bytes", file, + (int)in.capacity); + } + close(fd); + + in.len = size; + + return in; +} diff --git a/src/openvpn/buffer.h b/src/openvpn/buffer.h index d848490a..ba9857eb 100644 --- a/src/openvpn/buffer.h +++ b/src/openvpn/buffer.h @@ -1112,4 +1112,17 @@ void buffer_list_aggregate_separator(struct buffer_list *bl, struct buffer_list *buffer_list_file(const char *fn, int max_line_len); +/** + * keyfile_to_buffer - copy the content of a file into a buffer + * + * @param file path to the file to read + * @param max_size maximum size of the buffer to allocate + * @param gc the garbage collector to use when allocating the buffer. It + * passed to alloc_buf_gc() and therefore can be NULL. + * + * @return the buffer storing the file content + */ +struct buffer keyfile_to_buffer(const char *file, int max_size, + struct gc_arena *gc); + #endif /* BUFFER_H */ diff --git a/src/openvpn/crypto.c b/src/openvpn/crypto.c index b59c1f73..f201b533 100644 --- a/src/openvpn/crypto.c +++ b/src/openvpn/crypto.c @@ -1224,7 +1224,7 @@ read_key_file(struct key2 *key2, const char *file, const unsigned int flags) { struct gc_arena gc = gc_new(); struct buffer in; - int fd, size; + int size; uint8_t hex_byte[3] = {0, 0, 0}; const char *error_filename = file; @@ -1268,22 +1268,8 @@ read_key_file(struct key2 *key2, const char *file, const unsigned int flags) } else /* 'file' is a filename which refers to a file containing the ascii key */ { - in = alloc_buf_gc(2048, &gc); - fd = platform_open(file, O_RDONLY, 0); - if (fd == -1) - { - msg(M_ERR, "Cannot open key file '%s'", file); - } - size = read(fd, in.data, in.capacity); - if (size < 0) - { - msg(M_FATAL, "Read error on key file ('%s')", file); - } - if (size == in.capacity) - { - msg(M_FATAL, "Key file ('%s') can be a maximum of %d bytes", file, (int)in.capacity); - } - close(fd); + in = keyfile_to_buffer(file, 2048, &gc); + size = in.len; } cp = (unsigned char *)in.data; diff --git a/src/openvpn/init.c b/src/openvpn/init.c index 36c1a4c4..15fef08d 100644 --- a/src/openvpn/init.c +++ b/src/openvpn/init.c @@ -2406,7 +2406,6 @@ key_schedule_free(struct key_schedule *ks, bool free_ssl_ctx) if (tls_ctx_initialised(&ks->ssl_ctx) && free_ssl_ctx) { tls_ctx_free(&ks->ssl_ctx); - free_key_ctx_bi(&ks->tls_wrap_key); } CLEAR(*ks); } @@ -2496,6 +2495,48 @@ do_init_crypto_static(struct context *c, const unsigned int flags) check_replay_consistency(&c->c1.ks.key_type, options->replay); } +/* + * Initialize the tls-auth/crypt key context + */ +static void +do_init_tls_wrap_key(struct context *c) +{ + const struct options *options = &c->options; + + /* TLS handshake authentication (--tls-auth) */ + if (options->tls_auth_file) + { + /* Initialize key_type for tls-auth with auth only */ + CLEAR(c->c1.ks.tls_auth_key_type); + if (!streq(options->authname, "none")) + { + c->c1.ks.tls_auth_key_type.digest = md_kt_get(options->authname); + c->c1.ks.tls_auth_key_type.hmac_length = + md_kt_size(c->c1.ks.tls_auth_key_type.digest); + } + else + { + msg(M_FATAL, "ERROR: tls-auth enabled, but no valid --auth " + "algorithm specified ('%s')", options->authname); + } + + crypto_read_openvpn_key(&c->c1.ks.tls_auth_key_type, + &c->c1.ks.tls_wrap_key, + options->tls_auth_file, + options->tls_auth_file_inline, + options->key_direction, + "Control Channel Authentication", "tls-auth"); + } + + /* TLS handshake encryption+authentication (--tls-crypt) */ + if (options->tls_crypt_file) + { + tls_crypt_init_key(&c->c1.ks.tls_wrap_key, + options->tls_crypt_file, + options->tls_crypt_inline, options->tls_server); + } +} + /* * Initialize the persistent component of OpenVPN's TLS mode, * which is preserved across SIGUSR1 resets. @@ -2545,35 +2586,8 @@ do_init_crypto_tls_c1(struct context *c) /* Initialize PRNG with config-specified digest */ prng_init(options->prng_hash, options->prng_nonce_secret_len); - /* TLS handshake authentication (--tls-auth) */ - if (options->tls_auth_file) - { - /* Initialize key_type for tls-auth with auth only */ - CLEAR(c->c1.ks.tls_auth_key_type); - if (!streq(options->authname, "none")) - { - c->c1.ks.tls_auth_key_type.digest = md_kt_get(options->authname); - c->c1.ks.tls_auth_key_type.hmac_length = - md_kt_size(c->c1.ks.tls_auth_key_type.digest); - } - else - { - msg(M_FATAL, "ERROR: tls-auth enabled, but no valid --auth " - "algorithm specified ('%s')", options->authname); - } - - crypto_read_openvpn_key(&c->c1.ks.tls_auth_key_type, - &c->c1.ks.tls_wrap_key, options->tls_auth_file, - options->tls_auth_file_inline, options->key_direction, - "Control Channel Authentication", "tls-auth"); - } - - /* TLS handshake encryption+authentication (--tls-crypt) */ - if (options->tls_crypt_file) - { - tls_crypt_init_key(&c->c1.ks.tls_wrap_key, options->tls_crypt_file, - options->tls_crypt_inline, options->tls_server); - } + /* initialize tls-auth/crypt key */ + do_init_tls_wrap_key(c); c->c1.ciphername = options->ciphername; c->c1.authname = options->authname; @@ -2595,6 +2609,12 @@ do_init_crypto_tls_c1(struct context *c) c->options.ciphername = c->c1.ciphername; c->options.authname = c->c1.authname; c->options.keysize = c->c1.keysize; + + /* + * tls-auth/crypt key can be configured per connection block, therefore + * we must reload it as it may have changed + */ + do_init_tls_wrap_key(c); } } @@ -3398,6 +3418,13 @@ do_close_tls(struct context *c) static void do_close_free_key_schedule(struct context *c, bool free_ssl_ctx) { + /* + * always free the tls_auth/crypt key. If persist_key is true, the key will + * be reloaded from memory (pre-cached) + */ + free_key_ctx_bi(&c->c1.ks.tls_wrap_key); + CLEAR(c->c1.ks.tls_wrap_key); + if (!(c->sig->signal_received == SIGUSR1 && c->options.persist_key)) { key_schedule_free(&c->c1.ks, free_ssl_ctx); From patchwork Mon Jun 4 17:29:01 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Antonio Quartulli X-Patchwork-Id: 344 Return-Path: Delivered-To: patchwork@openvpn.net Delivered-To: patchwork@openvpn.net Received: from director10.mail.ord1d.rsapps.net ([172.31.255.6]) by backend30.mail.ord1d.rsapps.net (Dovecot) with LMTP id JH4HF+QDFlv7SgAAIUCqbw for ; Mon, 04 Jun 2018 23:30:44 -0400 Received: from proxy16.mail.iad3b.rsapps.net ([172.31.255.6]) by director10.mail.ord1d.rsapps.net (Dovecot) with LMTP id xMnoAOQDFltsXgAApN4f7A ; Mon, 04 Jun 2018 23:30:44 -0400 Received: from smtp21.gate.iad3b ([172.31.255.6]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) by proxy16.mail.iad3b.rsapps.net with LMTP id QNacFeQDFlsqWAAAPj+4aA ; Mon, 04 Jun 2018 23:30:44 -0400 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: smtp21.gate.iad3b.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=unstable.cc X-Suspicious-Flag: YES X-Classification-ID: d3394590-6870-11e8-8bbc-525400cdc90a-1-1 Received: from [216.105.38.7] ([216.105.38.7:62642] helo=lists.sourceforge.net) by smtp21.gate.iad3b.rsapps.net (envelope-from ) (ecelerity 4.2.1.56364 r(Core:4.2.1.14)) with ESMTPS (cipher=DHE-RSA-AES256-GCM-SHA384) id 26/B4-16972-3E3061B5; Mon, 04 Jun 2018 23:30:43 -0400 Received: from [127.0.0.1] (helo=sfs-ml-1.v29.lw.sourceforge.com) by sfs-ml-1.v29.lw.sourceforge.com with esmtp (Exim 4.90_1) (envelope-from ) id 1fQ2fL-0004vr-Gy; Tue, 05 Jun 2018 03:29:47 +0000 Received: from [172.30.20.202] (helo=mx.sourceforge.net) by sfs-ml-1.v29.lw.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.90_1) (envelope-from ) id 1fQ2fK-0004vk-5z for openvpn-devel@lists.sourceforge.net; Tue, 05 Jun 2018 03:29:46 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sourceforge.net; s=x; h=References:In-Reply-To:Message-Id:Date:Subject:Cc: To:From:Sender:Reply-To:MIME-Version:Content-Type:Content-Transfer-Encoding: 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=pYEqRVuh5lnJtTAY9j8aXKYidFbfNlIY2gHrE6dVXNU=; b=RRsEGr55ItIOus0haFUCFIr0Ci oYCDL0BCdBSRSLHlT2AZ3kayn2qknIuhgvmtb+MjEJ++DkHs+wevn7y6Vceo4qkzKrhcbPoNSch2h ZLiuvNj9ZVCdbuNWhoYeBRFAA/UjefIT199N+H0uDl9KkX7iH+FqcpOkT9xhsehIoJc0=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To :MIME-Version:Content-Type:Content-Transfer-Encoding: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=pYEqRVuh5lnJtTAY9j8aXKYidFbfNlIY2gHrE6dVXNU=; b=LEJtWx1BK66ml91oMvwL+2kbAi 27FJLwmcC2687roJKnd5dV68X2CD7fR919grDx3CuxljNidFaTjui8E43PM6PT4KX4D+oisxi2+a7 N0Uf40XgjhwRm9UNGtjmv5XmTivklC/wEpr3VxIkOELMuR7don1mdVn+ZO/ufIT6PuDs=; Received: from s2.neomailbox.net ([5.148.176.60]) by sfi-mx-1.v28.lw.sourceforge.com with esmtps (TLSv1.2:DHE-RSA-AES256-GCM-SHA384:256) (Exim 4.90_1) id 1fQ2fG-00543U-Na for openvpn-devel@lists.sourceforge.net; Tue, 05 Jun 2018 03:29:46 +0000 From: Antonio Quartulli To: openvpn-devel@lists.sourceforge.net Date: Tue, 5 Jun 2018 11:29:01 +0800 Message-Id: <20180605032902.26440-2-a@unstable.cc> In-Reply-To: <20180605032902.26440-1-a@unstable.cc> References: <20180605032902.26440-1-a@unstable.cc> X-Spam-Report: Spam Filtering performed by mx.sourceforge.net. See http://spamassassin.org/tag/ for more details. -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [5.148.176.60 listed in list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record X-Headers-End: 1fQ2fG-00543U-Na Subject: [Openvpn-devel] [PATCH v2 2/3] make tls-auth a per-connection-block option 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: , Cc: Antonio Quartulli MIME-Version: 1.0 Errors-To: openvpn-devel-bounces@lists.sourceforge.net X-getmail-retrieved-from-mailbox: Inbox Different VPN servers may use different tls-auth keys. For this reason it is convenient to make tls-auth a per-connection-block option so that the user is allowed to specify one key per remote. If no tls-auth option is specified in a given connection block, the global one, if any, is used. If persist-key is specified, tls-auth keys are pre-loaded during startup (same as they were embeeded in the config file) so that later there is no need to access the key files. Trac: #720 Cc: Steffan Karger Signed-off-by: Antonio Quartulli --- v2: - convert tls-auth keyfile to inline key if persist-key was specified doc/openvpn.8 | 2 + src/openvpn/init.c | 10 ++--- src/openvpn/options.c | 90 +++++++++++++++++++++++++++++++++++-------- src/openvpn/options.h | 5 +++ 4 files changed, 85 insertions(+), 22 deletions(-) diff --git a/doc/openvpn.8 b/doc/openvpn.8 index 4114f408..8006ba29 100644 --- a/doc/openvpn.8 +++ b/doc/openvpn.8 @@ -361,6 +361,7 @@ block: .B fragment, .B http\-proxy, .B http\-proxy\-option, +.B key\-direction, .B link\-mtu, .B local, .B lport, @@ -372,6 +373,7 @@ block: .B remote, .B rport, .B socks\-proxy, +.B tls\-auth, .B tun\-mtu and .B tun\-mtu\-extra. diff --git a/src/openvpn/init.c b/src/openvpn/init.c index 15fef08d..22a74e36 100644 --- a/src/openvpn/init.c +++ b/src/openvpn/init.c @@ -2504,7 +2504,7 @@ do_init_tls_wrap_key(struct context *c) const struct options *options = &c->options; /* TLS handshake authentication (--tls-auth) */ - if (options->tls_auth_file) + if (options->ce.tls_auth_file) { /* Initialize key_type for tls-auth with auth only */ CLEAR(c->c1.ks.tls_auth_key_type); @@ -2522,9 +2522,9 @@ do_init_tls_wrap_key(struct context *c) crypto_read_openvpn_key(&c->c1.ks.tls_auth_key_type, &c->c1.ks.tls_wrap_key, - options->tls_auth_file, - options->tls_auth_file_inline, - options->key_direction, + options->ce.tls_auth_file, + options->ce.tls_auth_file_inline, + options->ce.key_direction, "Control Channel Authentication", "tls-auth"); } @@ -2803,7 +2803,7 @@ do_init_crypto_tls(struct context *c, const unsigned int flags) #endif /* TLS handshake authentication (--tls-auth) */ - if (options->tls_auth_file) + if (options->ce.tls_auth_file) { to.tls_wrap.mode = TLS_WRAP_AUTH; to.tls_wrap.opt.key_ctx_bi = c->c1.ks.tls_wrap_key; diff --git a/src/openvpn/options.c b/src/openvpn/options.c index 426057ab..7357f189 100644 --- a/src/openvpn/options.c +++ b/src/openvpn/options.c @@ -1506,6 +1506,10 @@ show_connection_entry(const struct connection_entry *o) #ifdef ENABLE_OCC SHOW_INT(explicit_exit_notification); #endif + + SHOW_STR(tls_auth_file); + SHOW_PARM(key_direction, keydirection2ascii(o->key_direction, false, true), + "%s"); } @@ -1786,7 +1790,6 @@ show_settings(const struct options *o) SHOW_BOOL(push_peer_info); SHOW_BOOL(tls_exit); - SHOW_STR(tls_auth_file); SHOW_STR(tls_crypt_file); #ifdef ENABLE_PKCS11 @@ -2869,6 +2872,23 @@ options_postprocess_mutate_ce(struct options *o, struct connection_entry *ce) } } + /* + * Set per-connection block tls-auth fields if no other method was defined + */ + if (!ce->tls_auth_file) + { + ce->tls_auth_file = o->tls_auth_file; + ce->tls_auth_file_inline = o->tls_auth_file_inline; + ce->key_direction = o->key_direction; + } + + /* pre-cache tls-auth key file if persist-key was specified */ + if (ce->tls_auth_file && !ce->tls_auth_file_inline && o->persist_key) + { + struct buffer in = keyfile_to_buffer(ce->tls_auth_file, 2048, &o->gc); + ce->tls_auth_file = INLINE_FILE_TAG; + ce->tls_auth_file_inline = (char *)in.data; + } } #ifdef _WIN32 @@ -3285,12 +3305,20 @@ options_postprocess_filechecks(struct options *options) options->crl_file, R_OK, "--crl-verify"); } - errs |= check_file_access(CHKACC_FILE|CHKACC_INLINE|CHKACC_PRIVATE, - options->tls_auth_file, R_OK, "--tls-auth"); + ASSERT(options->connection_list); + for (int i = 0; i < options->connection_list->len; ++i) + { + struct connection_entry *ce = options->connection_list->array[i]; + + errs |= check_file_access(CHKACC_FILE|CHKACC_INLINE|CHKACC_PRIVATE, + ce->tls_auth_file, R_OK, "--tls-auth"); + } + errs |= check_file_access(CHKACC_FILE|CHKACC_INLINE|CHKACC_PRIVATE, options->tls_crypt_file, R_OK, "--tls-crypt"); errs |= check_file_access(CHKACC_FILE|CHKACC_INLINE|CHKACC_PRIVATE, options->shared_secret_file, R_OK, "--secret"); + errs |= check_file_access(CHKACC_DIRPATH|CHKACC_FILEXSTWR, options->packet_id_file, R_OK|W_OK, "--replay-persist"); @@ -3647,7 +3675,7 @@ options_string(const struct options *o, { if (TLS_CLIENT || TLS_SERVER) { - if (o->tls_auth_file) + if (o->ce.tls_auth_file) { buf_printf(&out, ",tls-auth"); } @@ -7420,10 +7448,19 @@ add_option(struct options *options, { int key_direction; + VERIFY_PERMISSION(OPT_P_GENERAL|OPT_P_CONNECTION); + key_direction = ascii2keydirection(msglevel, p[1]); if (key_direction >= 0) { - options->key_direction = key_direction; + if (permission_mask & OPT_P_GENERAL) + { + options->key_direction = key_direction; + } + else if (permission_mask & OPT_P_CONNECTION) + { + options->ce.key_direction = key_direction; + } } else { @@ -7992,26 +8029,45 @@ add_option(struct options *options, } else if (streq(p[0], "tls-auth") && p[1] && !p[3]) { - VERIFY_PERMISSION(OPT_P_GENERAL); - if (streq(p[1], INLINE_FILE_TAG) && p[2]) + int key_direction = -1; + + VERIFY_PERMISSION(OPT_P_GENERAL|OPT_P_CONNECTION); + + if (permission_mask & OPT_P_GENERAL) { - options->tls_auth_file_inline = p[2]; + if (streq(p[1], INLINE_FILE_TAG) && p[2]) + { + options->tls_auth_file_inline = p[2]; + } + else if (p[2]) + { + key_direction = ascii2keydirection(msglevel, p[2]); + if (key_direction < 0) + { + goto err; + } + options->key_direction = key_direction; + } + options->tls_auth_file = p[1]; } - else if (p[2]) + else if (permission_mask & OPT_P_CONNECTION) { - int key_direction; - - key_direction = ascii2keydirection(msglevel, p[2]); - if (key_direction >= 0) + options->ce.key_direction = KEY_DIRECTION_BIDIRECTIONAL; + if (streq(p[1], INLINE_FILE_TAG) && p[2]) { - options->key_direction = key_direction; + options->ce.tls_auth_file_inline = p[2]; } - else + else if (p[2]) { - goto err; + key_direction = ascii2keydirection(msglevel, p[2]); + if (key_direction < 0) + { + goto err; + } + options->ce.key_direction = key_direction; } + options->ce.tls_auth_file = p[1]; } - options->tls_auth_file = p[1]; } else if (streq(p[0], "tls-crypt") && p[1] && !p[3]) { diff --git a/src/openvpn/options.h b/src/openvpn/options.h index f7d0145a..77c963d2 100644 --- a/src/openvpn/options.h +++ b/src/openvpn/options.h @@ -130,6 +130,11 @@ struct connection_entry #define CE_MAN_QUERY_REMOTE_MASK (0x07) #define CE_MAN_QUERY_REMOTE_SHIFT (2) unsigned int flags; + + /* Shared secret used for TLS control channel authentication */ + const char *tls_auth_file; + const char *tls_auth_file_inline; + int key_direction; }; struct remote_entry From patchwork Mon Jun 4 17:29:02 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Antonio Quartulli X-Patchwork-Id: 342 Return-Path: Delivered-To: patchwork@openvpn.net Delivered-To: patchwork@openvpn.net Received: from director10.mail.ord1d.rsapps.net ([172.31.255.6]) by backend30.mail.ord1d.rsapps.net (Dovecot) with LMTP id U+DmBuMDFlvySgAAIUCqbw for ; Mon, 04 Jun 2018 23:30:43 -0400 Received: from proxy20.mail.iad3b.rsapps.net ([172.31.255.6]) by director10.mail.ord1d.rsapps.net (Dovecot) with LMTP id qgrKAOMDFlv2TwAApN4f7A ; Mon, 04 Jun 2018 23:30:43 -0400 Received: from smtp39.gate.iad3b ([172.31.255.6]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) by proxy20.mail.iad3b.rsapps.net with LMTP id sHGvOOIDFluTCQAAcDxLoQ ; Mon, 04 Jun 2018 23:30:42 -0400 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: smtp39.gate.iad3b.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=unstable.cc X-Suspicious-Flag: YES X-Classification-ID: d2fdf2b0-6870-11e8-b29e-5254002be87c-1-1 Received: from [216.105.38.7] ([216.105.38.7:27811] helo=lists.sourceforge.net) by smtp39.gate.iad3b.rsapps.net (envelope-from ) (ecelerity 4.2.1.56364 r(Core:4.2.1.14)) with ESMTPS (cipher=DHE-RSA-AES256-GCM-SHA384) id BC/5D-30380-2E3061B5; Mon, 04 Jun 2018 23:30:42 -0400 Received: from [127.0.0.1] (helo=sfs-ml-4.v29.lw.sourceforge.com) by sfs-ml-4.v29.lw.sourceforge.com with esmtp (Exim 4.90_1) (envelope-from ) id 1fQ2fJ-0000N4-Ih; Tue, 05 Jun 2018 03:29:45 +0000 Received: from [172.30.20.202] (helo=mx.sourceforge.net) by sfs-ml-4.v29.lw.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.90_1) (envelope-from ) id 1fQ2fI-0000My-SX for openvpn-devel@lists.sourceforge.net; Tue, 05 Jun 2018 03:29:44 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sourceforge.net; s=x; h=References:In-Reply-To:Message-Id:Date:Subject:Cc: To:From:Sender:Reply-To:MIME-Version:Content-Type:Content-Transfer-Encoding: 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=P18FwWlxsVYqRcqnkRBWrVGtT9jHbjkWNP1zp+zBkTM=; b=dnaz9Sc2zcmjE7bxmzmxMF76KZ dALmrg4MHxmjGfqX/dvW2VC+jp7G8Myn7Lxql8W1QDMOvhZg9/U+CfTFALG3Yv9RzNAHmmVq7Amd2 AKA+AwOEuSAo0VZyu9vkNhsrQ1+GgdoM8nOgYh3iuF5adJekaSMEqlwOp1V9uYOD5XbI=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To :MIME-Version:Content-Type:Content-Transfer-Encoding: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=P18FwWlxsVYqRcqnkRBWrVGtT9jHbjkWNP1zp+zBkTM=; b=Izd7FxWhFd1RXhW3VM3eSiSLka LM2A05oJIDzYGH5ERTRCCGnaZUj683RsfbPLXYypIZfgeZyOv3rII7FPEeuz8mdV/I0RjTTK1hN5V iDnaR0hcjeeiWNBYbLnGrlHujQFaDz/ETLlYkTnEC7lQ+cs+D/8Ga6ZHcamg3/cf+NZs=; Received: from s2.neomailbox.net ([5.148.176.60]) by sfi-mx-1.v28.lw.sourceforge.com with esmtps (TLSv1.2:DHE-RSA-AES256-GCM-SHA384:256) (Exim 4.90_1) id 1fQ2fG-00543i-Lo for openvpn-devel@lists.sourceforge.net; Tue, 05 Jun 2018 03:29:44 +0000 From: Antonio Quartulli To: openvpn-devel@lists.sourceforge.net Date: Tue, 5 Jun 2018 11:29:02 +0800 Message-Id: <20180605032902.26440-3-a@unstable.cc> In-Reply-To: <20180605032902.26440-1-a@unstable.cc> References: <20180605032902.26440-1-a@unstable.cc> X-Spam-Report: Spam Filtering performed by mx.sourceforge.net. See http://spamassassin.org/tag/ for more details. -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [5.148.176.60 listed in list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record X-Headers-End: 1fQ2fG-00543i-Lo Subject: [Openvpn-devel] [PATCH v2 3/3] make tls-crypt a per-connection-block option 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: , Cc: Antonio Quartulli MIME-Version: 1.0 Errors-To: openvpn-devel-bounces@lists.sourceforge.net X-getmail-retrieved-from-mailbox: Inbox Similarly to tls-auth, different remotes may use different tls-crypt keys. Allow the user to define a different key in each connection block. If no tls-crypt option is specified in a given connection block, the global one, if any, is used. If persist-key is specified, tls-crypt keys are pre-loaded during startup (same as they were embeeded in the config file) so that later there is no need to access the key files. Trac: #720 Cc: Steffan Karger Signed-off-by: Antonio Quartulli --- v2: - convert tls-crypt keyfile to inline key if persist-key was specified doc/openvpn.8 | 1 + src/openvpn/init.c | 8 +++---- src/openvpn/options.c | 56 +++++++++++++++++++++++++++++++++++-------- src/openvpn/options.h | 4 ++++ 4 files changed, 55 insertions(+), 14 deletions(-) diff --git a/doc/openvpn.8 b/doc/openvpn.8 index 8006ba29..ac7307af 100644 --- a/doc/openvpn.8 +++ b/doc/openvpn.8 @@ -374,6 +374,7 @@ block: .B rport, .B socks\-proxy, .B tls\-auth, +.B tls\-crypt, .B tun\-mtu and .B tun\-mtu\-extra. diff --git a/src/openvpn/init.c b/src/openvpn/init.c index 22a74e36..99b5b12a 100644 --- a/src/openvpn/init.c +++ b/src/openvpn/init.c @@ -2529,11 +2529,11 @@ do_init_tls_wrap_key(struct context *c) } /* TLS handshake encryption+authentication (--tls-crypt) */ - if (options->tls_crypt_file) + if (options->ce.tls_crypt_file) { tls_crypt_init_key(&c->c1.ks.tls_wrap_key, - options->tls_crypt_file, - options->tls_crypt_inline, options->tls_server); + options->ce.tls_crypt_file, + options->ce.tls_crypt_inline, options->tls_server); } } @@ -2814,7 +2814,7 @@ do_init_crypto_tls(struct context *c, const unsigned int flags) } /* TLS handshake encryption (--tls-crypt) */ - if (options->tls_crypt_file) + if (options->ce.tls_crypt_file) { to.tls_wrap.mode = TLS_WRAP_CRYPT; to.tls_wrap.opt.key_ctx_bi = c->c1.ks.tls_wrap_key; diff --git a/src/openvpn/options.c b/src/openvpn/options.c index 7357f189..09f094d1 100644 --- a/src/openvpn/options.c +++ b/src/openvpn/options.c @@ -1510,6 +1510,7 @@ show_connection_entry(const struct connection_entry *o) SHOW_STR(tls_auth_file); SHOW_PARM(key_direction, keydirection2ascii(o->key_direction, false, true), "%s"); + SHOW_STR(tls_crypt_file); } @@ -1790,8 +1791,6 @@ show_settings(const struct options *o) SHOW_BOOL(push_peer_info); SHOW_BOOL(tls_exit); - SHOW_STR(tls_crypt_file); - #ifdef ENABLE_PKCS11 { int i; @@ -2726,7 +2725,7 @@ options_postprocess_verify_ce(const struct options *options, const struct connec notnull(options->priv_key_file, "private key file (--key) or PKCS#12 file (--pkcs12)"); } } - if (options->tls_auth_file && options->tls_crypt_file) + if (ce->tls_auth_file && ce->tls_crypt_file) { msg(M_USAGE, "--tls-auth and --tls-crypt are mutually exclusive"); } @@ -2875,7 +2874,7 @@ options_postprocess_mutate_ce(struct options *o, struct connection_entry *ce) /* * Set per-connection block tls-auth fields if no other method was defined */ - if (!ce->tls_auth_file) + if (!ce->tls_auth_file && !ce->tls_crypt_file) { ce->tls_auth_file = o->tls_auth_file; ce->tls_auth_file_inline = o->tls_auth_file_inline; @@ -2889,6 +2888,29 @@ options_postprocess_mutate_ce(struct options *o, struct connection_entry *ce) ce->tls_auth_file = INLINE_FILE_TAG; ce->tls_auth_file_inline = (char *)in.data; } + + /* + * Set per-connection block tls-crypt fields if no other method was defined + */ + if (!ce->tls_crypt_file && !ce->tls_auth_file) + { + ce->tls_crypt_file = o->tls_crypt_file; + ce->tls_crypt_inline = o->tls_crypt_inline; + } + + /* pre-cache tls-auth key file if persist-key was specified */ + if (ce->tls_crypt_file && !ce->tls_crypt_inline && o->persist_key) + { + struct buffer in = keyfile_to_buffer(ce->tls_crypt_file, 2048, &o->gc); + ce->tls_crypt_file = INLINE_FILE_TAG; + ce->tls_crypt_inline = (char *)in.data; + } + + /* + * NOTE: after the two blocks above, only one among tls-crypt and tls-auth + * will be set, because it is not allowed by the config parser to have both + * globally assigned. + */ } #ifdef _WIN32 @@ -3312,10 +3334,12 @@ options_postprocess_filechecks(struct options *options) errs |= check_file_access(CHKACC_FILE|CHKACC_INLINE|CHKACC_PRIVATE, ce->tls_auth_file, R_OK, "--tls-auth"); + + errs |= check_file_access(CHKACC_FILE|CHKACC_INLINE|CHKACC_PRIVATE, + ce->tls_crypt_file, R_OK, "--tls-crypt"); + } - errs |= check_file_access(CHKACC_FILE|CHKACC_INLINE|CHKACC_PRIVATE, - options->tls_crypt_file, R_OK, "--tls-crypt"); errs |= check_file_access(CHKACC_FILE|CHKACC_INLINE|CHKACC_PRIVATE, options->shared_secret_file, R_OK, "--secret"); @@ -8071,12 +8095,24 @@ add_option(struct options *options, } else if (streq(p[0], "tls-crypt") && p[1] && !p[3]) { - VERIFY_PERMISSION(OPT_P_GENERAL); - if (streq(p[1], INLINE_FILE_TAG) && p[2]) + VERIFY_PERMISSION(OPT_P_GENERAL|OPT_P_CONNECTION); + if (permission_mask & OPT_P_GENERAL) + { + if (streq(p[1], INLINE_FILE_TAG) && p[2]) + { + options->tls_crypt_inline = p[2]; + } + options->tls_crypt_file = p[1]; + } + else if (permission_mask & OPT_P_CONNECTION) { - options->tls_crypt_inline = p[2]; + if (streq(p[1], INLINE_FILE_TAG) && p[2]) + { + options->ce.tls_crypt_inline = p[2]; + } + options->ce.tls_crypt_file = p[1]; + } - options->tls_crypt_file = p[1]; } else if (streq(p[0], "key-method") && p[1] && !p[2]) { diff --git a/src/openvpn/options.h b/src/openvpn/options.h index 77c963d2..2c0902a9 100644 --- a/src/openvpn/options.h +++ b/src/openvpn/options.h @@ -135,6 +135,10 @@ struct connection_entry const char *tls_auth_file; const char *tls_auth_file_inline; int key_direction; + + /* Shared secret used for TLS control channel authenticated encryption */ + const char *tls_crypt_file; + const char *tls_crypt_inline; }; struct remote_entry