From patchwork Wed Sep 21 00:49:28 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arne Schwabe X-Patchwork-Id: 2781 Return-Path: Delivered-To: patchwork@openvpn.net Delivered-To: patchwork@openvpn.net Received: from director12.mail.ord1d.rsapps.net ([172.27.255.56]) by backend30.mail.ord1d.rsapps.net with LMTP id QMSUAnTsKmO4PgAAIUCqbw (envelope-from ) for ; Wed, 21 Sep 2022 06:50:28 -0400 Received: from proxy11.mail.iad3a.rsapps.net ([172.27.255.56]) by director12.mail.ord1d.rsapps.net with LMTP id sF+FAXTsKmPTbwAAIasKDg (envelope-from ) for ; Wed, 21 Sep 2022 06:50:28 -0400 Received: from smtp36.gate.iad3a ([172.27.255.56]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) by proxy11.mail.iad3a.rsapps.net with LMTPS id eOC3NXPsKmPtLAAAxCvdqw (envelope-from ) for ; Wed, 21 Sep 2022 06:50:27 -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: smtp36.gate.iad3a.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: 337dcfe8-399b-11ed-bfeb-525400575b2b-1-1 Received: from [216.105.38.7] ([216.105.38.7:57314] helo=lists.sourceforge.net) by smtp36.gate.iad3a.rsapps.net (envelope-from ) (ecelerity 4.2.38.62370 r(:)) with ESMTPS (cipher=DHE-RSA-AES256-GCM-SHA384) id 6D/66-18604-37CEA236; Wed, 21 Sep 2022 06:50:27 -0400 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 1oaxId-0004FF-VS; Wed, 21 Sep 2022 10:49:51 +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 1oaxIb-0004Es-FZ for openvpn-devel@lists.sourceforge.net; Wed, 21 Sep 2022 10:49:49 +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: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:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=emcAGVWPrBEXlEplvBrL6MT/0XUp1bCip2Jo5jiMoYQ=; b=BiYrUCNs5ODis5OzZwYfNeedwK AEnoHMSqQBNLSohFVCB+rZn1swS/2w0CkujIjg6CIS3txwpkhosu4eZMY+4DTHoW9CuqOLr/wSJIf 9PJGf6OSGDmnkaGC2OZ7sAJMmtBTFnWCbujP/2nPM8V67WwA0hWptuGC5vvhIrMEhs5U=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=Content-Transfer-Encoding:MIME-Version: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:In-Reply-To: References:List-Id:List-Help:List-Unsubscribe:List-Subscribe:List-Post: List-Owner:List-Archive; bh=emcAGVWPrBEXlEplvBrL6MT/0XUp1bCip2Jo5jiMoYQ=; b=b vnLm8ZhKFJXtO23ANh86qCPNP3UlMDNuUTago8kI/wbzkaDbyOm6WmdPYHMhQjGUeTz6pXXASad4w 7duPe+s5lqoBVldUbyGK9kIf/AnPd1cGvgOQHRnTYh5gTQuMZvD61epUfMS+z7cnrAtz9xF9DZfKs U8jO9/DPHIsALsik=; 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 1oaxIW-00FNio-Bv for openvpn-devel@lists.sourceforge.net; Wed, 21 Sep 2022 10:49:49 +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 1oaxII-000IOi-Pl for openvpn-devel@lists.sourceforge.net; Wed, 21 Sep 2022 12:49:30 +0200 Received: (nullmailer pid 3452316 invoked by uid 10006); Wed, 21 Sep 2022 10:49:30 -0000 From: Arne Schwabe To: openvpn-devel@lists.sourceforge.net Date: Wed, 21 Sep 2022 12:49:28 +0200 Message-Id: <20220921104930.3452270-1-arne@rfc2549.org> X-Mailer: git-send-email 2.25.1 MIME-Version: 1.0 X-Spam-Report: Spam detection software, running on the system "util-spamd-1.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: This ensures that control packets are actually smaller than the maximum control channel packet size. Since OpenVPN will consider a control message packet complete when the TLS record is complete, we have to ensure that the SSL library will still write one record, so the receiving side will only be ab [...] Content analysis details: (0.3 points, 6.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.2 HEADER_FROM_DIFFERENT_DOMAINS From and EnvelopeFrom 2nd level mail domains are different 0.0 SPF_NONE SPF: sender does not publish an SPF Record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record X-Headers-End: 1oaxIW-00FNio-Bv Subject: [Openvpn-devel] [PATCH v4 1/3] Ensure that control channel packet are respecting maximum packet size 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 This ensures that control packets are actually smaller than the maximum control channel packet size. Since OpenVPN will consider a control message packet complete when the TLS record is complete, we have to ensure that the SSL library will still write one record, so the receiving side will only be able to get/read the control message content when a TLS record is complete. To achieve this goal, this commit does: - Split one read from TLS library into multiple control channel packets, splitting one TLS record into multiple control packets. - increase allowed number of outstanding packets to 6 from 4 on the sender side. This is still okay with older implementations as receivers will have room for 8. - calculate the overhead for control channel message to allow staying below that threshold. - remove maxlen from key_state_read_ciphertext and related functions as we now always allow control channel messages to be up to TLS_CHANNEL_BUF_SIZE in size and no longer limit this by the mtu of control packets as the implemented splitting will take care of larger payloads from the SSL library Note this commit has a warning message that references max-packet-size that is introduced in the next commit. In this commit the packet size is not yet configurable. Patch v2: avoid assertion about to large buffer by sticking to 1250 max control size in this commit and leaving larger sizes for the --max-packet-size commit. Also fix various other small problems and grammar fixes. Patch v3: grammar fixes Patch v4: adjust tls-mtu to max-packet-size in message. Signed-off-by: Arne Schwabe Acked-By: Frank Lichtenheld --- src/openvpn/reliable.c | 55 ++++++++++---- src/openvpn/reliable.h | 32 +++++++- src/openvpn/ssl.c | 155 ++++++++++++++++++++++++++++++++------ src/openvpn/ssl_backend.h | 8 +- src/openvpn/ssl_mbedtls.c | 14 +--- src/openvpn/ssl_openssl.c | 16 ++-- src/openvpn/ssl_pkt.h | 4 +- 7 files changed, 215 insertions(+), 69 deletions(-) diff --git a/src/openvpn/reliable.c b/src/openvpn/reliable.c index 734736256..3ccb73976 100644 --- a/src/openvpn/reliable.c +++ b/src/openvpn/reliable.c @@ -41,6 +41,14 @@ #include "memdbg.h" +/* calculates test - base while allowing for base or test wraparound. test is + * assumed to be higher than base */ +static inline packet_id_type +subtract_pid(const packet_id_type test, const packet_id_type base) +{ + return test - base; +} + /* * verify that test - base < extent while allowing for base or test wraparound */ @@ -49,22 +57,7 @@ reliable_pid_in_range1(const packet_id_type test, const packet_id_type base, const unsigned int extent) { - if (test >= base) - { - if (test - base < extent) - { - return true; - } - } - else - { - if ((test+0x80000000u) - (base+0x80000000u) < extent) - { - return true; - } - } - - return false; + return subtract_pid(test, base) < extent; } /* @@ -498,6 +491,36 @@ reliable_get_buf(struct reliable *rel) return NULL; } +int +reliable_get_num_output_sequenced_available(struct reliable *rel) +{ + struct gc_arena gc = gc_new(); + packet_id_type min_id = 0; + bool min_id_defined = false; + + /* find minimum active packet_id */ + for (int i = 0; i < rel->size; ++i) + { + const struct reliable_entry *e = &rel->array[i]; + if (e->active) + { + if (!min_id_defined || reliable_pid_min(e->packet_id, min_id)) + { + min_id_defined = true; + min_id = e->packet_id; + } + } + } + + int ret = rel->size; + if (min_id_defined) + { + ret -= subtract_pid(rel->packet_id, min_id); + } + gc_free(&gc); + return ret; +} + /* grab a free buffer, fail if buffer clogged by unacknowledged low packet IDs */ struct buffer * reliable_get_buf_output_sequenced(struct reliable *rel) diff --git a/src/openvpn/reliable.h b/src/openvpn/reliable.h index b9863efe3..7fffe397d 100644 --- a/src/openvpn/reliable.h +++ b/src/openvpn/reliable.h @@ -46,7 +46,7 @@ * be stored in one \c reliable_ack * structure. */ -#define RELIABLE_CAPACITY 8 /**< The maximum number of packets that +#define RELIABLE_CAPACITY 12 /**< The maximum number of packets that * the reliability layer for one VPN * tunnel in one direction can store. */ @@ -93,7 +93,7 @@ struct reliable int size; interval_t initial_timeout; packet_id_type packet_id; - int offset; + int offset; /**< Offset of the bufs in the reliable_entry array */ bool hold; /* don't xmit until reliable_schedule_now is called */ struct reliable_entry array[RELIABLE_CAPACITY]; }; @@ -178,6 +178,20 @@ reliable_ack_empty(struct reliable_ack *ack) return !ack->len; } +/** + * Returns the number of packets that need to be acked. + * + * @param ack The acknowledgment structure to check. + * + * @returns the number of outstanding acks + */ +static inline int +reliable_ack_outstanding(struct reliable_ack *ack) +{ + return ack->len; +} + + /** * Write a packet ID acknowledgment record to a buffer. * @@ -385,6 +399,20 @@ void reliable_mark_deleted(struct reliable *rel, struct buffer *buf); */ struct buffer *reliable_get_buf_output_sequenced(struct reliable *rel); + +/** + * Counts the number of free buffers in output that can be potentially used + * for sending + * + * @param rel The reliable structure in which to search for a free + * entry. + * + * @return the number of buffer that are available for sending without + * breaking ack sequence + * */ +int +reliable_get_num_output_sequenced_available(struct reliable *rel); + /** * Mark the reliable entry associated with the given buffer as * active outgoing. diff --git a/src/openvpn/ssl.c b/src/openvpn/ssl.c index 672cd9c84..b69258be8 100644 --- a/src/openvpn/ssl.c +++ b/src/openvpn/ssl.c @@ -305,7 +305,7 @@ tls_init_control_channel_frame_parameters(const struct frame *data_channel_frame * if --tls-auth is enabled. */ - /* calculate the maximum overhead that control channel frames may have */ + /* calculates the maximum overhead that control channel frames can have */ int overhead = 0; /* Socks */ @@ -324,8 +324,10 @@ tls_init_control_channel_frame_parameters(const struct frame *data_channel_frame /* Previous OpenVPN version calculated the maximum size and buffer of a * control frame depending on the overhead of the data channel frame * overhead and limited its maximum size to 1250. We always allocate the - * 1250 buffer size since a lot of code blindly assumes a large buffer - * (e.g. PUSH_BUNDLE_SIZE) and set frame->mtu_mtu as suggestion for the + * TLS_CHANNEL_BUF_SIZE buffer size since a lot of code blindly assumes + * a large buffer (e.g. PUSH_BUNDLE_SIZE) and also our peer might have + * a higher size configured and we still want to be able to receive the + * packets. frame->mtu_mtu is set as suggestion for the maximum packet * size */ frame->buf.payload_size = 1250 + overhead; @@ -335,6 +337,47 @@ tls_init_control_channel_frame_parameters(const struct frame *data_channel_frame frame->tun_mtu = min_int(data_channel_frame->tun_mtu, 1250); } +/** + * calculate the maximum overhead that control channel frames have + * This includes header, op code and everything apart from the + * payload itself. This method is a bit pessimistic and might give higher + * overhead than we actually have */ +static int +calc_control_channel_frame_overhead(const struct tls_session *session) +{ + const struct key_state *ks = &session->key[KS_PRIMARY]; + int overhead = 0; + + /* TCP length field and opcode */ + overhead += 3; + + /* our own session id */ + overhead += SID_SIZE; + + /* ACK array and remote SESSION ID (part of the ACK array) */ + overhead += ACK_SIZE(min_int(reliable_ack_outstanding(ks->rec_ack), CONTROL_SEND_ACK_MAX)); + + /* Message packet id */ + overhead += sizeof(packet_id_type); + + if (session->tls_wrap.mode == TLS_WRAP_CRYPT) + { + overhead += tls_crypt_buf_overhead(); + } + else if (session->tls_wrap.mode == TLS_WRAP_AUTH) + { + overhead += hmac_ctx_size(session->tls_wrap.opt.key_ctx_bi.encrypt.hmac); + overhead += packet_id_size(true); + } + + /* Add the typical UDP overhead for an IPv6 UDP packet. TCP+IPv6 has a + * larger overhead but the risk of a TCP connection getting dropped because + * we try to send a too large packet is basically zero */ + overhead += datagram_overhead(AF_INET6, PROTO_UDP); + + return overhead; +} + void init_ssl_lib(void) { @@ -2656,7 +2699,7 @@ read_incoming_tls_plaintext(struct key_state *ks, struct buffer *buf, { ASSERT(buf_init(buf, 0)); - int status = key_state_read_plaintext(&ks->ks_ssl, buf, TLS_CHANNEL_BUF_SIZE); + int status = key_state_read_plaintext(&ks->ks_ssl, buf); update_time(); if (status == -1) @@ -2675,6 +2718,92 @@ read_incoming_tls_plaintext(struct key_state *ks, struct buffer *buf, return true; } +static bool +write_outgoing_tls_ciphertext(struct tls_session *session, bool *state_change) +{ + struct key_state *ks = &session->key[KS_PRIMARY]; + + int rel_avail = reliable_get_num_output_sequenced_available(ks->send_reliable); + if (rel_avail == 0) + { + return true; + } + + /* We need to determine how much space is actually available in the control + * channel frame */ + + int max_pkt_len = min_int(TLS_CHANNEL_BUF_SIZE, session->opt->frame.tun_mtu); + + + /* Subtract overhead */ + max_pkt_len -= calc_control_channel_frame_overhead(session); + + /* calculate total available length for outgoing tls ciphertext */ + int maxlen = max_pkt_len * rel_avail; + + /* Is first packet one that will have a WKC appended? */ + if (control_packet_needs_wkc(ks)) + { + maxlen -= buf_len(session->tls_wrap.tls_crypt_v2_wkc); + } + + /* Not enough space available to send a full control channel packet */ + if (maxlen < TLS_CHANNEL_BUF_SIZE) + { + if (rel_avail == TLS_RELIABLE_N_SEND_BUFFERS) + { + msg(D_TLS_ERRORS, "--max-packet-size setting too low. Unable to " + "send control channel message."); + } + msg(D_REL_LOW, "Reliable: Send queue full, postponing TLS send"); + return true; + } + + /* This seems a bit wasteful to allocate every time */ + struct gc_arena gc = gc_new(); + struct buffer tmp = alloc_buf_gc(TLS_CHANNEL_BUF_SIZE, &gc); + + int status = key_state_read_ciphertext(&ks->ks_ssl, &tmp); + + if (status == -1) + { + msg(D_TLS_ERRORS, + "TLS Error: Ciphertext -> reliable TCP/UDP transport read error"); + gc_free(&gc); + return false; + } + if (status == 1) + { + /* Split the TLS ciphertext (TLS record) into multiple small packets + * that respect tls_mtu */ + while (tmp.len) + { + int len = max_pkt_len; + int opcode = P_CONTROL_V1; + if (control_packet_needs_wkc(ks)) + { + opcode = P_CONTROL_WKC_V1; + len = max_int(0, len - buf_len(session->tls_wrap.tls_crypt_v2_wkc)); + } + /* do not send more than available */ + len = min_int(len, tmp.len); + + struct buffer *buf = reliable_get_buf_output_sequenced(ks->send_reliable); + /* we assert here since we checked for its availibility before */ + ASSERT(buf); + buf_copy_n(buf, &tmp, len); + + reliable_mark_active_outgoing(ks->send_reliable, buf, opcode); + INCR_GENERATED; + *state_change = true; + } + dmsg(D_TLS_DEBUG, "Outgoing Ciphertext -> Reliable"); + } + + gc_free(&gc); + return true; +} + static bool tls_process_state(struct tls_multi *multi, @@ -2829,26 +2958,10 @@ tls_process_state(struct tls_multi *multi, buf = reliable_get_buf_output_sequenced(ks->send_reliable); if (buf) { - int status = key_state_read_ciphertext(&ks->ks_ssl, buf, multi->opt.frame.tun_mtu); - - if (status == -1) + if (!write_outgoing_tls_ciphertext(session, &state_change)) { - msg(D_TLS_ERRORS, - "TLS Error: Ciphertext -> reliable TCP/UDP transport read error"); goto error; } - if (status == 1) - { - int opcode = P_CONTROL_V1; - if (control_packet_needs_wkc(ks)) - { - opcode = P_CONTROL_WKC_V1; - } - reliable_mark_active_outgoing(ks->send_reliable, buf, opcode); - INCR_GENERATED; - state_change = true; - dmsg(D_TLS_DEBUG, "Outgoing Ciphertext -> Reliable"); - } } } diff --git a/src/openvpn/ssl_backend.h b/src/openvpn/ssl_backend.h index 1bd336999..215425d41 100644 --- a/src/openvpn/ssl_backend.h +++ b/src/openvpn/ssl_backend.h @@ -461,7 +461,6 @@ int key_state_write_plaintext_const(struct key_state_ssl *ks_ssl, * @param ks_ssl - The security parameter state for this %key * session. * @param buf - A buffer in which to store the ciphertext. - * @param maxlen - The maximum number of bytes to extract. * * @return The return value indicates whether the data was successfully * processed: @@ -470,8 +469,8 @@ int key_state_write_plaintext_const(struct key_state_ssl *ks_ssl, * later to retry. * - \c -1: An error occurred. */ -int key_state_read_ciphertext(struct key_state_ssl *ks_ssl, struct buffer *buf, - int maxlen); +int key_state_read_ciphertext(struct key_state_ssl *ks_ssl, struct buffer *buf); + /** @} name Functions for packets to be sent to a remote OpenVPN peer */ @@ -517,8 +516,7 @@ int key_state_write_ciphertext(struct key_state_ssl *ks_ssl, * later to retry. * - \c -1: An error occurred. */ -int key_state_read_plaintext(struct key_state_ssl *ks_ssl, struct buffer *buf, - int maxlen); +int key_state_read_plaintext(struct key_state_ssl *ks_ssl, struct buffer *buf); /** @} name Functions for packets received from a remote OpenVPN peer */ diff --git a/src/openvpn/ssl_mbedtls.c b/src/openvpn/ssl_mbedtls.c index b0785bae9..ea06cf703 100644 --- a/src/openvpn/ssl_mbedtls.c +++ b/src/openvpn/ssl_mbedtls.c @@ -1285,8 +1285,7 @@ key_state_write_plaintext_const(struct key_state_ssl *ks, const uint8_t *data, i } int -key_state_read_ciphertext(struct key_state_ssl *ks, struct buffer *buf, - int maxlen) +key_state_read_ciphertext(struct key_state_ssl *ks, struct buffer *buf) { int retval = 0; int len = 0; @@ -1304,10 +1303,6 @@ key_state_read_ciphertext(struct key_state_ssl *ks, struct buffer *buf, } len = buf_forward_capacity(buf); - if (maxlen < len) - { - len = maxlen; - } retval = endless_buf_read(&ks->bio_ctx->out, BPTR(buf), len); @@ -1388,8 +1383,7 @@ key_state_write_ciphertext(struct key_state_ssl *ks, struct buffer *buf) } int -key_state_read_plaintext(struct key_state_ssl *ks, struct buffer *buf, - int maxlen) +key_state_read_plaintext(struct key_state_ssl *ks, struct buffer *buf) { int retval = 0; int len = 0; @@ -1407,10 +1401,6 @@ key_state_read_plaintext(struct key_state_ssl *ks, struct buffer *buf, } len = buf_forward_capacity(buf); - if (maxlen < len) - { - len = maxlen; - } retval = mbedtls_ssl_read(ks->ctx, BPTR(buf), len); diff --git a/src/openvpn/ssl_openssl.c b/src/openvpn/ssl_openssl.c index 710c9c06d..cd6d84246 100644 --- a/src/openvpn/ssl_openssl.c +++ b/src/openvpn/ssl_openssl.c @@ -1871,7 +1871,7 @@ bio_write_post(const int status, struct buffer *buf) * Read from an OpenSSL BIO in non-blocking mode. */ static int -bio_read(BIO *bio, struct buffer *buf, int maxlen, const char *desc) +bio_read(BIO *bio, struct buffer *buf, const char *desc) { int i; int ret = 0; @@ -1882,10 +1882,6 @@ bio_read(BIO *bio, struct buffer *buf, int maxlen, const char *desc) else { int len = buf_forward_capacity(buf); - if (maxlen < len) - { - len = maxlen; - } /* * BIO_read brackets most of the serious RSA @@ -2012,15 +2008,14 @@ key_state_write_plaintext_const(struct key_state_ssl *ks_ssl, const uint8_t *dat } int -key_state_read_ciphertext(struct key_state_ssl *ks_ssl, struct buffer *buf, - int maxlen) +key_state_read_ciphertext(struct key_state_ssl *ks_ssl, struct buffer *buf) { int ret = 0; perf_push(PERF_BIO_READ_CIPHERTEXT); ASSERT(NULL != ks_ssl); - ret = bio_read(ks_ssl->ct_out, buf, maxlen, "tls_read_ciphertext"); + ret = bio_read(ks_ssl->ct_out, buf, "tls_read_ciphertext"); perf_pop(); return ret; @@ -2042,15 +2037,14 @@ key_state_write_ciphertext(struct key_state_ssl *ks_ssl, struct buffer *buf) } int -key_state_read_plaintext(struct key_state_ssl *ks_ssl, struct buffer *buf, - int maxlen) +key_state_read_plaintext(struct key_state_ssl *ks_ssl, struct buffer *buf) { int ret = 0; perf_push(PERF_BIO_READ_PLAINTEXT); ASSERT(NULL != ks_ssl); - ret = bio_read(ks_ssl->ssl_bio, buf, maxlen, "tls_read_plaintext"); + ret = bio_read(ks_ssl->ssl_bio, buf, "tls_read_plaintext"); perf_pop(); return ret; diff --git a/src/openvpn/ssl_pkt.h b/src/openvpn/ssl_pkt.h index 45e0a81f5..9bb3ca958 100644 --- a/src/openvpn/ssl_pkt.h +++ b/src/openvpn/ssl_pkt.h @@ -67,8 +67,8 @@ /* * Define number of buffers for send and receive in the reliability layer. */ -#define TLS_RELIABLE_N_SEND_BUFFERS 4 /* also window size for reliability layer */ -#define TLS_RELIABLE_N_REC_BUFFERS 8 +#define TLS_RELIABLE_N_SEND_BUFFERS 6 /* also window size for reliability layer */ +#define TLS_RELIABLE_N_REC_BUFFERS 12 /* * Used in --mode server mode to check tls-auth signature on initial From patchwork Wed Sep 21 00:49:29 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arne Schwabe X-Patchwork-Id: 2783 Return-Path: Delivered-To: patchwork@openvpn.net Delivered-To: patchwork@openvpn.net Received: from director14.mail.ord1d.rsapps.net ([172.27.255.7]) by backend30.mail.ord1d.rsapps.net with LMTP id QAHfL4XsKmMBPwAAIUCqbw (envelope-from ) for ; Wed, 21 Sep 2022 06:50:45 -0400 Received: from proxy6.mail.iad3a.rsapps.net ([172.27.255.7]) by director14.mail.ord1d.rsapps.net with LMTP id kKt7L4XsKmMaFwAAeJ7fFg (envelope-from ) for ; Wed, 21 Sep 2022 06:50:45 -0400 Received: from smtp14.gate.iad3a ([172.27.255.7]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) by proxy6.mail.iad3a.rsapps.net with LMTPS id uMxYJ4XsKmMMJgAA8udqhg (envelope-from ) for ; Wed, 21 Sep 2022 06:50:45 -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: smtp14.gate.iad3a.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: 3d5fb418-399b-11ed-af79-5254005d41e3-1-1 Received: from [216.105.38.7] ([216.105.38.7:54016] helo=lists.sourceforge.net) by smtp14.gate.iad3a.rsapps.net (envelope-from ) (ecelerity 4.2.38.62370 r(:)) with ESMTPS (cipher=DHE-RSA-AES256-GCM-SHA384) id 5B/E1-29534-38CEA236; Wed, 21 Sep 2022 06:50: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.95) (envelope-from ) id 1oaxIZ-0002UA-PH; Wed, 21 Sep 2022 10:49:47 +0000 Received: from [172.30.20.202] (helo=mx.sourceforge.net) by sfs-ml-1.v29.lw.sourceforge.com with esmtps (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.95) (envelope-from ) id 1oaxIX-0002Tq-Pl for openvpn-devel@lists.sourceforge.net; Wed, 21 Sep 2022 10:49:45 +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=JyebsX85jIC0ek/pbQ9b/1QlZj3ZbNrBuhGpQLAlJFw=; b=SP8gnPbSDMP1moBNZ5Bv+CP3B+ CNJYfbJAxzi9AWkkNtajGSPQWnF+rXxYX5nFAZui1grudrxUo9MBEWE1vyF8T6pVzo9Kh6b8rEFp1 3jrO8HkvoGhiRqYntEWRbH1syvNmOXOEsb6p3mextRR7ogzcHmrzzMsCwTyNZS4Uh7do=; 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=JyebsX85jIC0ek/pbQ9b/1QlZj3ZbNrBuhGpQLAlJFw=; b=SUgFuQo0PEoHp/Z3rkYVm3FOSe WKIwD1866oSSR9uA5D5KidErxqF+mROBB3CPJEKRfANtBab8R9V/hTdYTd//eBWGhbSvsYcEBEoKQ /ctjoPuMwQmOpLFJajwlgn342uw3Cx7yJE/VeKie7fLrrPTRlvLDdj5BhQCVUoqfZIHc=; Received: from mail.blinkt.de ([192.26.174.232]) by sfi-mx-2.v28.lw.sourceforge.com with esmtps (TLS1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.95) id 1oaxIW-0005Eo-F9 for openvpn-devel@lists.sourceforge.net; Wed, 21 Sep 2022 10:49:45 +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 1oaxII-000IOk-QY for openvpn-devel@lists.sourceforge.net; Wed, 21 Sep 2022 12:49:30 +0200 Received: (nullmailer pid 3452319 invoked by uid 10006); Wed, 21 Sep 2022 10:49:30 -0000 From: Arne Schwabe To: openvpn-devel@lists.sourceforge.net Date: Wed, 21 Sep 2022 12:49:29 +0200 Message-Id: <20220921104930.3452270-2-arne@rfc2549.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220921104930.3452270-1-arne@rfc2549.org> References: <20220921104930.3452270-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: Currently control packet size is controlled by tun-mtu in a very non-obvious way since the control overhead is not taken into account and control channel packet will end up with a different size than [...] 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.2 HEADER_FROM_DIFFERENT_DOMAINS From and EnvelopeFrom 2nd level mail domains are different 0.0 SPF_NONE SPF: sender does not publish an SPF Record X-Headers-End: 1oaxIW-0005Eo-F9 Subject: [Openvpn-devel] [PATCH v4 2/3] Allow setting control channel packet size with max-packet-size 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 Currently control packet size is controlled by tun-mtu in a very non-obvious way since the control overhead is not taken into account and control channel packet will end up with a different size than data channel packet. Instead we decouple this and introduce max-packet-size. Control packet size defaults to 1250 if max-packet-size is not set. Patch v2: rebase on latest patch set Patch v3: Introduce TLS_CHANNEL_MTU_MIN define and give explaination of its value. Patch v4: introduce max-packet-size instead of tls-mtu Signed-off-by: Arne Schwabe --- Changes.rst | 9 +++++++++ doc/man-sections/link-options.rst | 16 ++++++++++++++++ src/openvpn/common.h | 10 ++++++++++ src/openvpn/init.c | 8 ++++++-- src/openvpn/mtu.h | 5 +++++ src/openvpn/options.c | 21 +++++++++++++++++++++ src/openvpn/options.h | 1 + src/openvpn/ssl.c | 26 ++++++++++++++------------ src/openvpn/ssl.h | 8 +++----- 9 files changed, 85 insertions(+), 19 deletions(-) diff --git a/Changes.rst b/Changes.rst index 275f8d647..25b0e9846 100644 --- a/Changes.rst +++ b/Changes.rst @@ -88,6 +88,12 @@ Data channel offloading with ovpn-dco which brings DATA_V2 packet support. +Improved control channel packet size control (``max-packet-size``) + The size of control channel is no longer tied to + ``--link-mtu``/``--tun-mtu`` and can be set using ``--max-packet-size``. + Setting the size to small sizes no longer breaks the OpenVPN protocol in + certain situations. + Deprecated features ------------------- ``inetd`` has been removed @@ -150,6 +156,9 @@ User-visible Changes - Option ``--nobind`` is default when ``--client`` or ``--pull`` is used in the configuration - :code:`link_mtu` parameter is removed from environment or replaced with 0 when scripts are called with parameters. This parameter is unreliable and no longer internally calculated. +- control channel packet maximum size is no longer influenced by ``--link-mtu``/``--tun-mtu`` + and must be set by ``--max-packet-size`` now. + Overview of changes in 2.5 ========================== diff --git a/doc/man-sections/link-options.rst b/doc/man-sections/link-options.rst index 373193aa3..176c2b0db 100644 --- a/doc/man-sections/link-options.rst +++ b/doc/man-sections/link-options.rst @@ -454,3 +454,19 @@ the local and the remote host. if mode server: socket-flags TCP_NODELAY push "socket-flags TCP_NODELAY" + +--max-packet-size size + This option will instruct OpenVPN to try to limit the maximum on-write packet + size by restricting the control channel packet size and setting ``--mssfix``. + + OpenVPN will try to keep its control channel messages below this size but + due to some constraints in the protocol this is not always possible. If the + option is not set, the control packet maximum size defaults to 1250. + The control channel packet size will be restricted to values between + 512 and 2048. The maximum packet size includes encapsulation overhead like + UDP and IP. + + For ``--mssfix`` it will expand to: + :: + + mssfix size mtu \ No newline at end of file diff --git a/src/openvpn/common.h b/src/openvpn/common.h index b94680885..056c25438 100644 --- a/src/openvpn/common.h +++ b/src/openvpn/common.h @@ -68,6 +68,16 @@ typedef unsigned long ptr_type; */ #define TLS_CHANNEL_BUF_SIZE 2048 +/* TLS control buffer minimum size, this size is not actually inherent to + * the protocol but. Our current sending window is 6 and the receive window + * is 8 or 12 depending on the OpenVPN version. We need to be able to send + * a TLS record of size TLS_CHANNEL_BUF_SIZE. Splitting this into more than + * 6 packets (with overhead) would complicate our sending logic a lot more, so + * we settle here for a "round" number that allow with overhead of ~100 bytes + * to be larger than TLS_CHANNEL_BUF_SIZE. E.g. 6x ~400 > 2048. + * */ +#define TLS_CHANNEL_MTU_MIN 512 + /* * This parameter controls the maximum size of a bundle * of pushed options. diff --git a/src/openvpn/init.c b/src/openvpn/init.c index 034168441..305cc40f6 100644 --- a/src/openvpn/init.c +++ b/src/openvpn/init.c @@ -2627,6 +2627,10 @@ frame_finalize_options(struct context *c, const struct options *o) * space */ size_t payload_size = max_int(1500, frame->tun_mtu); + /* we need to be also large enough to hold larger control channel packets + * if configured */ + payload_size = max_int(payload_size, o->ce.tls_mtu); + /* The extra tun needs to be added to the payload size */ if (o->ce.tun_mtu_defined) { @@ -3172,7 +3176,7 @@ do_init_frame_tls(struct context *c) { if (c->c2.tls_multi) { - tls_multi_init_finalize(c->c2.tls_multi, &c->c2.frame); + tls_multi_init_finalize(c->c2.tls_multi, c->options.ce.tls_mtu); ASSERT(c->c2.tls_multi->opt.frame.buf.payload_size <= c->c2.frame.buf.payload_size); frame_print(&c->c2.tls_multi->opt.frame, D_MTU_INFO, @@ -3180,7 +3184,7 @@ do_init_frame_tls(struct context *c) } if (c->c2.tls_auth_standalone) { - tls_init_control_channel_frame_parameters(&c->c2.frame, &c->c2.tls_auth_standalone->frame); + tls_init_control_channel_frame_parameters(&c->c2.tls_auth_standalone->frame, c->options.ce.tls_mtu); frame_print(&c->c2.tls_auth_standalone->frame, D_MTU_INFO, "TLS-Auth MTU parms"); c->c2.tls_auth_standalone->tls_wrap.work = alloc_buf_gc(BUF_SIZE(&c->c2.frame), &c->c2.gc); diff --git a/src/openvpn/mtu.h b/src/openvpn/mtu.h index d4856f166..370806fb5 100644 --- a/src/openvpn/mtu.h +++ b/src/openvpn/mtu.h @@ -79,6 +79,11 @@ */ #define MSSFIX_DEFAULT 1492 +/* + * Default maximum size of control channel packets + */ +#define TLS_MTU_DEFAULT 1250 + /* * Alignment of payload data such as IP packet or * ethernet frame. diff --git a/src/openvpn/options.c b/src/openvpn/options.c index e44993c03..a7385118e 100644 --- a/src/openvpn/options.c +++ b/src/openvpn/options.c @@ -825,6 +825,7 @@ init_options(struct options *o, const bool init_gc) o->ce.bind_local = true; o->ce.tun_mtu = TUN_MTU_DEFAULT; o->ce.link_mtu = LINK_MTU_DEFAULT; + o->ce.tls_mtu = TLS_MTU_DEFAULT; o->ce.mtu_discover_type = -1; o->ce.mssfix = 0; o->ce.mssfix_default = true; @@ -1711,6 +1712,7 @@ show_connection_entry(const struct connection_entry *o) SHOW_BOOL(link_mtu_defined); SHOW_INT(tun_mtu_extra); SHOW_BOOL(tun_mtu_extra_defined); + SHOW_INT(tls_mtu); SHOW_INT(mtu_discover_type); @@ -6442,6 +6444,25 @@ add_option(struct options *options, options->ce.tun_mtu_extra = positive_atoi(p[1]); options->ce.tun_mtu_extra_defined = true; } + else if (streq(p[0], "max-packet-size") && p[1] && !p[2]) + { + VERIFY_PERMISSION(OPT_P_MTU|OPT_P_CONNECTION); + int maxmtu = positive_atoi(p[1]); + options->ce.tls_mtu = constrain_int(maxmtu, TLS_CHANNEL_MTU_MIN, TLS_CHANNEL_BUF_SIZE); + + if (maxmtu < TLS_CHANNEL_MTU_MIN || maxmtu > TLS_CHANNEL_BUF_SIZE) + { + msg(M_WARN, "max-packet-size value outside of allowed control " + "channel packet size (%d to %d), will use %d " + "instead", TLS_CHANNEL_MTU_MIN, TLS_CHANNEL_BUF_SIZE, + options->ce.tls_mtu); + } + + /* also set mssfix maxmtu mtu */ + options->ce.mssfix = maxmtu; + options->ce.mssfix_default = false; + options->ce.mssfix_encap = true; + } #ifdef ENABLE_FRAGMENT else if (streq(p[0], "mtu-dynamic")) { diff --git a/src/openvpn/options.h b/src/openvpn/options.h index e83bc0ed8..c9065a5fa 100644 --- a/src/openvpn/options.h +++ b/src/openvpn/options.h @@ -123,6 +123,7 @@ struct connection_entry bool tun_mtu_extra_defined; int link_mtu; /* MTU of device over which tunnel packets pass via TCP/UDP */ bool link_mtu_defined; /* true if user overriding parm with command line option */ + int tls_mtu; /* Maximum MTU for the control channel messages */ /* Advanced MTU negotiation and datagram fragmentation options */ int mtu_discover_type; /* used if OS supports setting Path MTU discovery options on socket */ diff --git a/src/openvpn/ssl.c b/src/openvpn/ssl.c index b69258be8..5f246db3b 100644 --- a/src/openvpn/ssl.c +++ b/src/openvpn/ssl.c @@ -297,8 +297,7 @@ tls_limit_reneg_bytes(const char *ciphername, int *reneg_bytes) } void -tls_init_control_channel_frame_parameters(const struct frame *data_channel_frame, - struct frame *frame) +tls_init_control_channel_frame_parameters(struct frame *frame, int tls_mtu) { /* * frame->extra_frame is already initialized with tls_auth buffer requirements, @@ -323,18 +322,21 @@ tls_init_control_channel_frame_parameters(const struct frame *data_channel_frame /* Previous OpenVPN version calculated the maximum size and buffer of a * control frame depending on the overhead of the data channel frame - * overhead and limited its maximum size to 1250. We always allocate the - * TLS_CHANNEL_BUF_SIZE buffer size since a lot of code blindly assumes - * a large buffer (e.g. PUSH_BUNDLE_SIZE) and also our peer might have - * a higher size configured and we still want to be able to receive the - * packets. frame->mtu_mtu is set as suggestion for the maximum packet - * size */ - frame->buf.payload_size = 1250 + overhead; + * overhead and limited its maximum size to 1250. Since control frames + * also need to fit into data channel buffer we have the same + * default of 1500 + 100 as data channel buffers have. Increasing + * control channel mtu beyond this limit also increases the data channel + * buffers */ + frame->buf.payload_size = max_int(1500, tls_mtu) + 100; frame->buf.headroom = overhead; frame->buf.tailroom = overhead; - frame->tun_mtu = min_int(data_channel_frame->tun_mtu, 1250); + frame->tun_mtu = tls_mtu; + + /* Ensure the tun-mtu stays in a valid range */ + frame->tun_mtu = min_int(frame->tun_mtu, TLS_CHANNEL_BUF_SIZE); + frame->tun_mtu = max_int(frame->tun_mtu, TLS_CHANNEL_MTU_MIN); } /** @@ -1300,9 +1302,9 @@ tls_multi_init(struct tls_options *tls_options) } void -tls_multi_init_finalize(struct tls_multi *multi, const struct frame *frame) +tls_multi_init_finalize(struct tls_multi *multi, int tls_mtu) { - tls_init_control_channel_frame_parameters(frame, &multi->opt.frame); + tls_init_control_channel_frame_parameters(&multi->opt.frame, tls_mtu); /* initialize the active and untrusted sessions */ tls_session_init(multi, &multi->session[TM_ACTIVE]); diff --git a/src/openvpn/ssl.h b/src/openvpn/ssl.h index 8ca4c4aa8..eddaca8cd 100644 --- a/src/openvpn/ssl.h +++ b/src/openvpn/ssl.h @@ -166,10 +166,9 @@ struct tls_multi *tls_multi_init(struct tls_options *tls_options); * * @param multi - The \c tls_multi structure of which to finalize * initialization. - * @param frame - The data channel's \c frame structure. + * @param tls_mtu - maximum allowed size for control channel packets */ -void tls_multi_init_finalize(struct tls_multi *multi, - const struct frame *frame); +void tls_multi_init_finalize(struct tls_multi *multi, int tls_mtu); /* * Initialize a standalone tls-auth verification object. @@ -181,8 +180,7 @@ struct tls_auth_standalone *tls_auth_standalone_init(struct tls_options *tls_opt * Setups the control channel frame size parameters from the data channel * parameters */ -void tls_init_control_channel_frame_parameters(const struct frame *data_channel_frame, - struct frame *frame); +void tls_init_control_channel_frame_parameters(struct frame *frame, int tls_mtu); /* * Set local and remote option compatibility strings. From patchwork Wed Sep 21 00:49:30 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arne Schwabe X-Patchwork-Id: 2782 Return-Path: Delivered-To: patchwork@openvpn.net Delivered-To: patchwork@openvpn.net Received: from director12.mail.ord1d.rsapps.net ([172.27.255.58]) by backend30.mail.ord1d.rsapps.net with LMTP id OMnVFITsKmPgPgAAIUCqbw (envelope-from ) for ; Wed, 21 Sep 2022 06:50:44 -0400 Received: from proxy2.mail.iad3a.rsapps.net ([172.27.255.58]) by director12.mail.ord1d.rsapps.net with LMTP id uMe8E4TsKmO5aAAAIasKDg (envelope-from ) for ; Wed, 21 Sep 2022 06:50:44 -0400 Received: from smtp32.gate.iad3a ([172.27.255.58]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) by proxy2.mail.iad3a.rsapps.net with LMTPS id 4LbLC4TsKmPteQAABcWvHw (envelope-from ) for ; Wed, 21 Sep 2022 06:50: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: smtp32.gate.iad3a.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: 3d269d5e-399b-11ed-8cb6-5254001741cc-1-1 Received: from [216.105.38.7] ([216.105.38.7:57414] helo=lists.sourceforge.net) by smtp32.gate.iad3a.rsapps.net (envelope-from ) (ecelerity 4.2.38.62370 r(:)) with ESMTPS (cipher=DHE-RSA-AES256-GCM-SHA384) id BB/44-11881-38CEA236; Wed, 21 Sep 2022 06:50:43 -0400 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 1oaxId-0004F8-Ip; Wed, 21 Sep 2022 10:49:51 +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 1oaxIa-0004El-SF for openvpn-devel@lists.sourceforge.net; Wed, 21 Sep 2022 10:49:48 +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=rxO2hSDNXo2IR1wzLxxrfskulA4nedIAclr+TfRVboc=; b=D409SCfj0lrNsAfhcwgrvk9bn1 IP7HoTjXaQ6sdvPCszr4LIZqM+ClRl3OATR1IEKetuFXqMOBnLXiW3QJiTGqux9AhTc4eBqTS6TY4 ARasdy6CxmTdpz84FqkJtgjTEmKVTqm2A+pYsT0wL3nJkjbFAsCyIbivF7BiTVZp2wpM=; 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=rxO2hSDNXo2IR1wzLxxrfskulA4nedIAclr+TfRVboc=; b=UIXfj37XUWpLFySm5rEdlzn6SR tGMtvA3+hw0cc675IygO12jNo7tmSD3ZS++bK9cnieE2XJiShlg/pl1QyNgdq0WwUWl+2Z/oxnmFO JSlLDg7TnMPuTITgdSObct7u3MbCtA1jqiUpxbkMbO8e4wcFf6u0wIwuWKiUiyaiJF0o=; 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 1oaxIW-00FNip-Bx for openvpn-devel@lists.sourceforge.net; Wed, 21 Sep 2022 10:49:48 +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 1oaxII-000IOm-RI for openvpn-devel@lists.sourceforge.net; Wed, 21 Sep 2022 12:49:30 +0200 Received: (nullmailer pid 3452321 invoked by uid 10006); Wed, 21 Sep 2022 10:49:30 -0000 From: Arne Schwabe To: openvpn-devel@lists.sourceforge.net Date: Wed, 21 Sep 2022 12:49:30 +0200 Message-Id: <20220921104930.3452270-3-arne@rfc2549.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220921104930.3452270-1-arne@rfc2549.org> References: <20220921104930.3452270-1-arne@rfc2549.org> MIME-Version: 1.0 X-Spam-Report: Spam detection software, running on the system "util-spamd-1.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: Patch v4: rebase Signed-off-by: Arne Schwabe --- tests/unit_tests/openvpn/Makefile.am | 5 +- tests/unit_tests/openvpn/mock_get_random.c | 10 ++++ tests/unit_tests/openvpn/test_packet_id.c | 55 +++++ [...] Content analysis details: (0.3 points, 6.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 URIBL_BLOCKED ADMINISTRATOR NOTICE: The query to URIBL was blocked. See http://wiki.apache.org/spamassassin/DnsBlocklists#dnsbl-block for more information. [URIs: makefile.am] 0.2 HEADER_FROM_DIFFERENT_DOMAINS From and EnvelopeFrom 2nd level mail domains are different 0.0 SPF_NONE SPF: sender does not publish an SPF Record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record X-Headers-End: 1oaxIW-00FNip-Bx Subject: [Openvpn-devel] [PATCH v4 3/3] Add unit test for reliable_get_num_output_sequenced_available 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 Patch v4: rebase Signed-off-by: Arne Schwabe Acked-By: Frank Lichtenheld --- tests/unit_tests/openvpn/Makefile.am | 5 +- tests/unit_tests/openvpn/mock_get_random.c | 10 ++++ tests/unit_tests/openvpn/test_packet_id.c | 55 ++++++++++++++++++++++ 3 files changed, 69 insertions(+), 1 deletion(-) diff --git a/tests/unit_tests/openvpn/Makefile.am b/tests/unit_tests/openvpn/Makefile.am index 65cf9549c..c7846f3e6 100644 --- a/tests/unit_tests/openvpn/Makefile.am +++ b/tests/unit_tests/openvpn/Makefile.am @@ -61,7 +61,10 @@ packet_id_testdriver_SOURCES = test_packet_id.c mock_msg.c mock_msg.h \ $(openvpn_srcdir)/buffer.c \ $(openvpn_srcdir)/otime.c \ $(openvpn_srcdir)/packet_id.c \ - $(openvpn_srcdir)/platform.c + $(openvpn_srcdir)/platform.c \ + $(openvpn_srcdir)/reliable.c \ + $(openvpn_srcdir)/session_id.c + pkt_testdriver_CFLAGS = @TEST_CFLAGS@ \ -I$(openvpn_includedir) -I$(compat_srcdir) -I$(openvpn_srcdir) diff --git a/tests/unit_tests/openvpn/mock_get_random.c b/tests/unit_tests/openvpn/mock_get_random.c index d0d2574ae..787b5e33e 100644 --- a/tests/unit_tests/openvpn/mock_get_random.c +++ b/tests/unit_tests/openvpn/mock_get_random.c @@ -26,6 +26,7 @@ #include #include #include +#include #include unsigned long @@ -34,3 +35,12 @@ get_random(void) /* rand() is not very random, but it's C99 and this is just for testing */ return rand(); } + +void +prng_bytes(uint8_t *output, int len) +{ + for (int i = 0; i < len; i++) + { + output[i] = rand(); + } +} diff --git a/tests/unit_tests/openvpn/test_packet_id.c b/tests/unit_tests/openvpn/test_packet_id.c index a3d4db285..c610d9727 100644 --- a/tests/unit_tests/openvpn/test_packet_id.c +++ b/tests/unit_tests/openvpn/test_packet_id.c @@ -36,6 +36,7 @@ #include #include "packet_id.h" +#include "reliable.h" #include "mock_msg.h" @@ -156,6 +157,59 @@ test_packet_id_write_long_wrap(void **state) assert_true(data->test_buf_data.buf_time == htonl(now)); } +static void +test_get_num_output_sequenced_available(void **state) +{ + + struct reliable *rel = malloc(sizeof(struct reliable)); + reliable_init(rel, 100, 50, 8, false); + + rel->array[5].active = true; + rel->array[5].packet_id = 100; + + rel->packet_id = 103; + + assert_int_equal(5, reliable_get_num_output_sequenced_available(rel)); + + rel->array[6].active = true; + rel->array[6].packet_id = 97; + assert_int_equal(2, reliable_get_num_output_sequenced_available(rel)); + + /* test ids close to int/unsigned int barrier */ + + rel->array[5].active = true; + rel->array[5].packet_id = (0x80000000u -3); + rel->array[6].active = false; + rel->packet_id = (0x80000000u -1); + + assert_int_equal(6, reliable_get_num_output_sequenced_available(rel)); + + rel->array[5].active = true; + rel->array[5].packet_id = (0x80000000u -3); + rel->packet_id = 0x80000001u; + + assert_int_equal(4, reliable_get_num_output_sequenced_available(rel)); + + + /* test wrapping */ + rel->array[5].active = true; + rel->array[5].packet_id = (0xffffffffu -3); + rel->array[6].active = false; + rel->packet_id = (0xffffffffu - 1); + + assert_int_equal(6, reliable_get_num_output_sequenced_available(rel)); + + rel->array[2].packet_id = 0; + rel->array[2].active = true; + + assert_int_equal(6, reliable_get_num_output_sequenced_available(rel)); + + rel->packet_id = 3; + assert_int_equal(1, reliable_get_num_output_sequenced_available(rel)); + + reliable_free(rel); +} + int main(void) { @@ -178,6 +232,7 @@ main(void) cmocka_unit_test_setup_teardown(test_packet_id_write_long_wrap, test_packet_id_write_setup, test_packet_id_write_teardown), + cmocka_unit_test(test_get_num_output_sequenced_available) }; return cmocka_run_group_tests_name("packet_id tests", tests, NULL, NULL);