Package: release.debian.org
Severity: normal
User: release.debian....@packages.debian.org
Usertags: unblock

Hi

Please unblock package openvpn

The update fixes security issues, in CVE-2017-7478 which is
pre-authentication (and does not affect stable version).

Detail are in
https://community.openvpn.net/openvpn/wiki/QuarkslabAndCryptographyEngineerAudits

Changelog:

+openvpn (2.4.0-5) unstable; urgency=high
+
+  * Change typo fix in command line help.
+  * SECURITY UPDATE: pre-authentication denial-of-service vulnerability
+    (both client and server) from a too-large control packet.
+    - debian/patches/CVE-2017-7478.patch: Do not assert on too-large
+      control packet
+    - CVE-2017-7478
+  * SECURITY UPDATE: authenticated remote DoS vulnerability due to
+    packet ID rollover
+    - debian/patches/CVE-2017-7479-prereq.patch: merge
+      packet_id_alloc_outgoing() into packet_id_write()
+    - debian/patches/CVE-2017-7479.patch: do not assert when packet ID
+      rollover occurs
+    - CVE-2017-7479
+  * SECURITY UPDATE: auth tokens left in memory after de-auth
+    - debian/patches/wipe_tokens_on_de-auth.patch: always wipe token
+      as soon as a TLS session is considered broken.
+   * Kudos to Steve Beattie <sbeat...@ubuntu.com> for doing all the
+     backporting work for this upload.
+
+ -- Alberto Gonzalez Iniesta <a...@inittab.org>  Thu, 11 May 2017 14:15:21 
+0200

unblock openvpn/2.4.0-5

Attached is as well the complete debdiff.

Regards,
Salvatore
diff -Nru openvpn-2.4.0/debian/changelog openvpn-2.4.0/debian/changelog
--- openvpn-2.4.0/debian/changelog	2017-02-02 14:15:42.000000000 +0100
+++ openvpn-2.4.0/debian/changelog	2017-05-11 14:15:21.000000000 +0200
@@ -1,3 +1,26 @@
+openvpn (2.4.0-5) unstable; urgency=high
+
+  * Change typo fix in command line help.
+  * SECURITY UPDATE: pre-authentication denial-of-service vulnerability
+    (both client and server) from a too-large control packet.
+    - debian/patches/CVE-2017-7478.patch: Do not assert on too-large
+      control packet
+    - CVE-2017-7478
+  * SECURITY UPDATE: authenticated remote DoS vulnerability due to
+    packet ID rollover
+    - debian/patches/CVE-2017-7479-prereq.patch: merge
+      packet_id_alloc_outgoing() into packet_id_write()
+    - debian/patches/CVE-2017-7479.patch: do not assert when packet ID
+      rollover occurs
+    - CVE-2017-7479
+  * SECURITY UPDATE: auth tokens left in memory after de-auth
+    - debian/patches/wipe_tokens_on_de-auth.patch: always wipe token
+      as soon as a TLS session is considered broken.
+   * Kudos to Steve Beattie <sbeat...@ubuntu.com> for doing all the
+     backporting work for this upload.
+
+ -- Alberto Gonzalez Iniesta <a...@inittab.org>  Thu, 11 May 2017 14:15:21 +0200
+
 openvpn (2.4.0-4) unstable; urgency=medium
 
   * Add NEWS entries on possible 2.4 migration issues.
diff -Nru openvpn-2.4.0/debian/patches/CVE-2017-7478.patch openvpn-2.4.0/debian/patches/CVE-2017-7478.patch
--- openvpn-2.4.0/debian/patches/CVE-2017-7478.patch	1970-01-01 01:00:00.000000000 +0100
+++ openvpn-2.4.0/debian/patches/CVE-2017-7478.patch	2017-05-11 14:15:21.000000000 +0200
@@ -0,0 +1,55 @@
+From be66408610a52f81c9c895a8973958ead55a4e57 Mon Sep 17 00:00:00 2001
+From: Steffan Karger <steffan.kar...@fox-it.com>
+Date: Tue, 9 May 2017 15:40:25 +0300
+Subject: [PATCH] Don't assert out on receiving too-large control packets
+ (CVE-2017-xxx)
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Commit 3c1b19e0 changed the maximum size of accepted control channel
+packets.  This was needed for crypto negotiation (which is needed for a
+nice transition to a new default cipher), but exposed a DoS
+vulnerability.  The vulnerability was found during the OpenVPN 2.4 code
+audit by Quarkslab (commisioned by OSTIF).
+
+To fix the issue, we should not ASSERT() on external input (in this case
+the received packet size), but instead gracefully error out and drop the
+invalid packet.
+
+Signed-off-by: Steffan Karger <steffan.kar...@fox-it.com>
+Signed-off-by: Samuli Seppänen <sam...@openvpn.net>
+
+CVE-2017-7478
+
+  Security
+  --------
+  - This release fixes a pre-authentication denial-of-service attack on both
+    clients and servers.  By sending a too-large control packet, OpenVPN 2.4.0 or
+    2.4.1 can be forced to hit an ASSERT() and stop the process.  If
+    ``--tls-auth`` or ``--tls-crypt`` is used, only attackers that have the
+    ``--tls-auth`` or ``--tls-crypt`` key can mount an attack. (CVE-2017-xxx)
+
+---
+ Changes.rst       | 8 ++++++++
+ src/openvpn/ssl.c | 7 ++++++-
+ 2 files changed, 14 insertions(+), 1 deletion(-)
+
+Index: openvpn-2.4.0/src/openvpn/ssl.c
+===================================================================
+--- openvpn-2.4.0.orig/src/openvpn/ssl.c
++++ openvpn-2.4.0/src/openvpn/ssl.c
+@@ -3708,7 +3708,12 @@ tls_pre_decrypt(struct tls_multi *multi,
+                                 /* Save incoming ciphertext packet to reliable buffer */
+                                 struct buffer *in = reliable_get_buf(ks->rec_reliable);
+                                 ASSERT(in);
+-                                ASSERT(buf_copy(in, buf));
++                                if(!buf_copy(in, buf))
++                                {
++                                    msg(D_MULTI_DROPPED,
++                                        "Incoming control channel packet too big, dropping.");
++                                    goto error;
++                                }
+                                 reliable_mark_active_incoming(ks->rec_reliable, in, id, op);
+                             }
+ 
diff -Nru openvpn-2.4.0/debian/patches/CVE-2017-7479.patch openvpn-2.4.0/debian/patches/CVE-2017-7479.patch
--- openvpn-2.4.0/debian/patches/CVE-2017-7479.patch	1970-01-01 01:00:00.000000000 +0100
+++ openvpn-2.4.0/debian/patches/CVE-2017-7479.patch	2017-05-11 14:15:21.000000000 +0200
@@ -0,0 +1,193 @@
+From ac08b27cfa693d9be592bb2597c260635aee9e68 Mon Sep 17 00:00:00 2001
+From: Steffan Karger <steffan.kar...@fox-it.com>
+Date: Tue, 25 Apr 2017 10:00:44 +0200
+Subject: [PATCH 2/2] Drop packets instead of asserting out if packet id rolls
+ over
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Previously, if a mode was selected where packet ids are not allowed to roll
+over, but renegotiation does not succeed for some reason (e.g. no password
+entered in time, certificate expired or a malicious peer that refuses the
+renegotiaion on purpose) we would continue to use the old keys.  Until the
+packet ID would roll over and we would ASSERT() out.
+
+Given that this can be triggered on purpose by an authenticated peer, this
+is a fix for an authenticated remote DoS vulnerability.  An attack is
+rather inefficient though; a peer would need to get us to send 2^32
+packets (min-size packet is IP+UDP+OPCODE+PID+TAG (no payload), results in
+(20+8+1+4+16)×2^32 bytes, or approx. 196 GB).
+
+Signed-off-by: Steffan Karger <steffan.kar...@fox-it.com>
+
+CVE-2017-7479
+
+---
+ src/openvpn/crypto.c                      | 25 ++++++++++++++++---------
+ src/openvpn/packet_id.c                   | 22 ++++++++++++++++------
+ src/openvpn/packet_id.h                   |  1 +
+ src/openvpn/tls_crypt.c                   |  6 +++++-
+ tests/unit_tests/openvpn/test_packet_id.c | 11 +++++++++--
+ 5 files changed, 47 insertions(+), 18 deletions(-)
+
+Index: openvpn-2.4.0/src/openvpn/crypto.c
+===================================================================
+--- openvpn-2.4.0.orig/src/openvpn/crypto.c
++++ openvpn-2.4.0/src/openvpn/crypto.c
+@@ -93,7 +93,11 @@ openvpn_encrypt_aead(struct buffer *buf,
+         buf_set_write(&iv_buffer, iv, iv_len);
+ 
+         /* IV starts with packet id to make the IV unique for packet */
+-        ASSERT(packet_id_write(&opt->packet_id.send, &iv_buffer, false, false));
++        if (!packet_id_write(&opt->packet_id.send, &iv_buffer, false, false))
++        {
++            msg(D_CRYPT_ERRORS, "ENCRYPT ERROR: packet ID roll over");
++            goto err;
++        }
+ 
+         /* Remainder of IV consists of implicit part (unique per session) */
+         ASSERT(buf_write(&iv_buffer, ctx->implicit_iv, ctx->implicit_iv_len));
+@@ -194,11 +198,13 @@ openvpn_encrypt_v1(struct buffer *buf, s
+                 }
+ 
+                 /* Put packet ID in plaintext buffer */
+-                if (packet_id_initialized(&opt->packet_id))
++                if (packet_id_initialized(&opt->packet_id)
++                    && !packet_id_write(&opt->packet_id.send, buf,
++                                        opt->flags & CO_PACKET_ID_LONG_FORM,
++                                        true))
+                 {
+-                    ASSERT(packet_id_write(&opt->packet_id.send, buf,
+-                                           opt->flags & CO_PACKET_ID_LONG_FORM,
+-                                           true));
++                    msg(D_CRYPT_ERRORS, "ENCRYPT ERROR: packet ID roll over");
++                    goto err;
+                 }
+             }
+             else if (cipher_kt_mode_ofb_cfb(cipher_kt))
+@@ -258,11 +264,12 @@ openvpn_encrypt_v1(struct buffer *buf, s
+         }
+         else                            /* No Encryption */
+         {
+-            if (packet_id_initialized(&opt->packet_id))
++            if (packet_id_initialized(&opt->packet_id)
++                && !packet_id_write(&opt->packet_id.send, buf,
++                                    opt->flags & CO_PACKET_ID_LONG_FORM, true))
+             {
+-                ASSERT(packet_id_write(&opt->packet_id.send, buf,
+-                        BOOL_CAST(opt->flags & CO_PACKET_ID_LONG_FORM),
+-                        true));
++                msg(D_CRYPT_ERRORS, "ENCRYPT ERROR: packet ID roll over");
++                goto err;
+             }
+             if (ctx->hmac)
+             {
+Index: openvpn-2.4.0/src/openvpn/packet_id.c
+===================================================================
+--- openvpn-2.4.0.orig/src/openvpn/packet_id.c
++++ openvpn-2.4.0/src/openvpn/packet_id.c
+@@ -325,27 +325,37 @@ packet_id_read(struct packet_id_net *pin
+     return true;
+ }
+ 
+-static void
++static bool
+ packet_id_send_update(struct packet_id_send *p, bool long_form)
+ {
+     if (!p->time)
+     {
+         p->time = now;
+     }
+-    p->id++;
+-    if (!p->id)
++    if (p->id == PACKET_ID_MAX)
+     {
+-        ASSERT(long_form);
++        /* Packet ID only allowed to roll over if using long form and time has
++         * moved forward since last roll over.
++         */
++        if (!long_form || now <= p->time)
++        {
++            return false;
++        }
+         p->time = now;
+-        p->id = 1;
++        p->id = 0;
+     }
++    p->id++;
++    return true;
+ }
+ 
+ bool
+ packet_id_write(struct packet_id_send *p, struct buffer *buf, bool long_form,
+         bool prepend)
+ {
+-    packet_id_send_update(p, long_form);
++    if (!packet_id_send_update(p, long_form))
++    {
++        return false;
++    }
+ 
+     const packet_id_type net_id = htonpid(p->id);
+     const net_time_t net_time = htontime(p->time);
+Index: openvpn-2.4.0/src/openvpn/packet_id.h
+===================================================================
+--- openvpn-2.4.0.orig/src/openvpn/packet_id.h
++++ openvpn-2.4.0/src/openvpn/packet_id.h
+@@ -50,6 +50,7 @@
+  * to for network transmission.
+  */
+ typedef uint32_t packet_id_type;
++#define PACKET_ID_MAX UINT32_MAX
+ typedef uint32_t net_time_t;
+ 
+ /*
+Index: openvpn-2.4.0/src/openvpn/tls_crypt.c
+===================================================================
+--- openvpn-2.4.0.orig/src/openvpn/tls_crypt.c
++++ openvpn-2.4.0/src/openvpn/tls_crypt.c
+@@ -95,7 +95,11 @@ tls_crypt_wrap(const struct buffer *src,
+          format_hex(BPTR(src), BLEN(src), 80, &gc));
+ 
+     /* Get packet ID */
+-    ASSERT(packet_id_write(&opt->packet_id.send, dst, true, false));
++    if (!packet_id_write(&opt->packet_id.send, dst, true, false))
++    {
++        msg(D_CRYPT_ERRORS, "TLS-CRYPT ERROR: packet ID roll over.");
++        goto err;
++    }
+ 
+     dmsg(D_PACKET_CONTENT, "TLS-CRYPT WRAP AD: %s",
+          format_hex(BPTR(dst), BLEN(dst), 0, &gc));
+Index: openvpn-2.4.0/tests/unit_tests/openvpn/test_packet_id.c
+===================================================================
+--- openvpn-2.4.0.orig/tests/unit_tests/openvpn/test_packet_id.c
++++ openvpn-2.4.0/tests/unit_tests/openvpn/test_packet_id.c
+@@ -129,8 +129,7 @@ test_packet_id_write_short_wrap(void **s
+     struct test_packet_id_write_data *data = *state;
+ 
+     data->pis.id = ~0;
+-    expect_assert_failure(
+-            packet_id_write(&data->pis, &data->test_buf, false, false));
++    assert_false(packet_id_write(&data->pis, &data->test_buf, false, false));
+ }
+ 
+ static void
+@@ -139,8 +138,16 @@ test_packet_id_write_long_wrap(void **st
+     struct test_packet_id_write_data *data = *state;
+ 
+     data->pis.id = ~0;
++    data->pis.time = 5006;
++
++    /* Write fails if time did not change */
++    now = 5006;
++    assert_false(packet_id_write(&data->pis, &data->test_buf, true, false));
++
++    /* Write succeeds if time moved forward */
+     now = 5010;
+     assert_true(packet_id_write(&data->pis, &data->test_buf, true, false));
++
+     assert(data->pis.id == 1);
+     assert(data->pis.time == now);
+     assert_true(data->test_buf_data.buf_id == htonl(1));
diff -Nru openvpn-2.4.0/debian/patches/CVE-2017-7479-prereq.patch openvpn-2.4.0/debian/patches/CVE-2017-7479-prereq.patch
--- openvpn-2.4.0/debian/patches/CVE-2017-7479-prereq.patch	1970-01-01 01:00:00.000000000 +0100
+++ openvpn-2.4.0/debian/patches/CVE-2017-7479-prereq.patch	2017-05-11 14:15:21.000000000 +0200
@@ -0,0 +1,443 @@
+From a87e1431baccd49a9344cfc63ab7446c4317fa2f Mon Sep 17 00:00:00 2001
+From: Steffan Karger <steffan.kar...@fox-it.com>
+Date: Fri, 5 May 2017 19:44:51 +0200
+Subject: [PATCH] cleanup: merge packet_id_alloc_outgoing() into
+ packet_id_write()
+
+The functions packet_id_alloc_outgoing() and packet_id_write() were
+always called in tandem.  Instead of forcing the caller to allocate a
+packet_id_net to do so, merge the two functions.  This simplifies the API
+and reduces the chance on mistakes in the future.
+
+This patch adds unit tests to verify the behaviour of packet_id_write().
+Verifying that we assert out correctly required the change to mock_msg.c.
+
+Signed-off-by: Steffan Karger <steffan.kar...@fox-it.com>
+Acked-by: Gert Doering <g...@greenie.muc.de>
+Acked-by: David Sommerseth <dav...@openvpn.net>
+Message-Id: <1494006291-3522-1-git-send-email-steffan.kar...@fox-it.com>
+URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg14541.html
+Signed-off-by: Gert Doering <g...@greenie.muc.de>
+
+[prerequisite for CVE-2017-7479. Adjusted to apply to 2.4.0 release -- sbeattie]
+
+---
+ src/openvpn/crypto.c                      |  20 ++--
+ src/openvpn/packet_id.c                   |  24 ++++-
+ src/openvpn/packet_id.h                   |  35 +++----
+ src/openvpn/tls_crypt.c                   |   6 +-
+ tests/unit_tests/openvpn/Makefile.am      |  13 ++-
+ tests/unit_tests/openvpn/mock_msg.c       |  15 ++-
+ tests/unit_tests/openvpn/test_packet_id.c | 168 ++++++++++++++++++++++++++++++
+ 7 files changed, 228 insertions(+), 53 deletions(-)
+ create mode 100644 tests/unit_tests/openvpn/test_packet_id.c
+
+Index: openvpn-2.4.0/src/openvpn/crypto.c
+===================================================================
+--- openvpn-2.4.0.orig/src/openvpn/crypto.c
++++ openvpn-2.4.0/src/openvpn/crypto.c
+@@ -85,7 +85,6 @@ openvpn_encrypt_aead(struct buffer *buf,
+     /* Prepare IV */
+     {
+         struct buffer iv_buffer;
+-        struct packet_id_net pin;
+         uint8_t iv[OPENVPN_MAX_IV_LENGTH] = {0};
+         const int iv_len = cipher_ctx_iv_length(ctx->cipher);
+ 
+@@ -94,8 +93,7 @@ openvpn_encrypt_aead(struct buffer *buf,
+         buf_set_write(&iv_buffer, iv, iv_len);
+ 
+         /* IV starts with packet id to make the IV unique for packet */
+-        packet_id_alloc_outgoing(&opt->packet_id.send, &pin, false);
+-        ASSERT(packet_id_write(&pin, &iv_buffer, false, false));
++        ASSERT(packet_id_write(&opt->packet_id.send, &iv_buffer, false, false));
+ 
+         /* Remainder of IV consists of implicit part (unique per session) */
+         ASSERT(buf_write(&iv_buffer, ctx->implicit_iv, ctx->implicit_iv_len));
+@@ -198,23 +196,21 @@ openvpn_encrypt_v1(struct buffer *buf, s
+                 /* Put packet ID in plaintext buffer */
+                 if (packet_id_initialized(&opt->packet_id))
+                 {
+-                    struct packet_id_net pin;
+-                    packet_id_alloc_outgoing(&opt->packet_id.send, &pin, BOOL_CAST(opt->flags & CO_PACKET_ID_LONG_FORM));
+-                    ASSERT(packet_id_write(&pin, buf, BOOL_CAST(opt->flags & CO_PACKET_ID_LONG_FORM), true));
++                    ASSERT(packet_id_write(&opt->packet_id.send, buf,
++                                           opt->flags & CO_PACKET_ID_LONG_FORM,
++                                           true));
+                 }
+             }
+             else if (cipher_kt_mode_ofb_cfb(cipher_kt))
+             {
+-                struct packet_id_net pin;
+                 struct buffer b;
+ 
+                 /* IV and packet-ID required for this mode. */
+                 ASSERT(opt->flags & CO_USE_IV);
+                 ASSERT(packet_id_initialized(&opt->packet_id));
+ 
+-                packet_id_alloc_outgoing(&opt->packet_id.send, &pin, true);
+                 buf_set_write(&b, iv_buf, iv_size);
+-                ASSERT(packet_id_write(&pin, &b, true, false));
++                ASSERT(packet_id_write(&opt->packet_id.send, &b, true, false));
+             }
+             else /* We only support CBC, CFB, or OFB modes right now */
+             {
+@@ -264,9 +260,9 @@ openvpn_encrypt_v1(struct buffer *buf, s
+         {
+             if (packet_id_initialized(&opt->packet_id))
+             {
+-                struct packet_id_net pin;
+-                packet_id_alloc_outgoing(&opt->packet_id.send, &pin, BOOL_CAST(opt->flags & CO_PACKET_ID_LONG_FORM));
+-                ASSERT(packet_id_write(&pin, buf, BOOL_CAST(opt->flags & CO_PACKET_ID_LONG_FORM), true));
++                ASSERT(packet_id_write(&opt->packet_id.send, buf,
++                        BOOL_CAST(opt->flags & CO_PACKET_ID_LONG_FORM),
++                        true));
+             }
+             if (ctx->hmac)
+             {
+Index: openvpn-2.4.0/src/openvpn/packet_id.c
+===================================================================
+--- openvpn-2.4.0.orig/src/openvpn/packet_id.c
++++ openvpn-2.4.0/src/openvpn/packet_id.c
+@@ -325,12 +325,30 @@ packet_id_read(struct packet_id_net *pin
+     return true;
+ }
+ 
++static void
++packet_id_send_update(struct packet_id_send *p, bool long_form)
++{
++    if (!p->time)
++    {
++        p->time = now;
++    }
++    p->id++;
++    if (!p->id)
++    {
++        ASSERT(long_form);
++        p->time = now;
++        p->id = 1;
++    }
++}
++
+ bool
+-packet_id_write(const struct packet_id_net *pin, struct buffer *buf, bool long_form, bool prepend)
++packet_id_write(struct packet_id_send *p, struct buffer *buf, bool long_form,
++        bool prepend)
+ {
+-    packet_id_type net_id = htonpid(pin->id);
+-    net_time_t net_time = htontime(pin->time);
++    packet_id_send_update(p, long_form);
+ 
++    const packet_id_type net_id = htonpid(p->id);
++    const net_time_t net_time = htontime(p->time);
+     if (prepend)
+     {
+         if (long_form)
+Index: openvpn-2.4.0/src/openvpn/packet_id.h
+===================================================================
+--- openvpn-2.4.0.orig/src/openvpn/packet_id.h
++++ openvpn-2.4.0/src/openvpn/packet_id.h
+@@ -254,7 +254,18 @@ const char *packet_id_persist_print(cons
+ 
+ bool packet_id_read(struct packet_id_net *pin, struct buffer *buf, bool long_form);
+ 
+-bool packet_id_write(const struct packet_id_net *pin, struct buffer *buf, bool long_form, bool prepend);
++/**
++ * Write a packet ID to buf, and update the packet ID state.
++ *
++ * @param p             Packet ID state.
++ * @param buf           Buffer to write the packet ID too
++ * @param long_form     If true, also update and write time_t to buf
++ * @param prepend       If true, prepend to buffer, otherwise apppend.
++ *
++ * @return true if successful, false otherwise.
++ */
++bool packet_id_write(struct packet_id_send *p, struct buffer *buf,
++        bool long_form, bool prepend);
+ 
+ /*
+  * Inline functions.
+@@ -304,28 +315,6 @@ packet_id_close_to_wrapping(const struct
+     return p->id >= PACKET_ID_WRAP_TRIGGER;
+ }
+ 
+-/*
+- * Allocate an outgoing packet id.
+- * Sequence number ranges from 1 to 2^32-1.
+- * In long_form, a time_t is added as well.
+- */
+-static inline void
+-packet_id_alloc_outgoing(struct packet_id_send *p, struct packet_id_net *pin, bool long_form)
+-{
+-    if (!p->time)
+-    {
+-        p->time = now;
+-    }
+-    pin->id = ++p->id;
+-    if (!pin->id)
+-    {
+-        ASSERT(long_form);
+-        p->time = now;
+-        pin->id = p->id = 1;
+-    }
+-    pin->time = p->time;
+-}
+-
+ static inline bool
+ check_timestamp_delta(time_t remote, unsigned int max_delta)
+ {
+Index: openvpn-2.4.0/src/openvpn/tls_crypt.c
+===================================================================
+--- openvpn-2.4.0.orig/src/openvpn/tls_crypt.c
++++ openvpn-2.4.0/src/openvpn/tls_crypt.c
+@@ -95,11 +95,7 @@ tls_crypt_wrap(const struct buffer *src,
+          format_hex(BPTR(src), BLEN(src), 80, &gc));
+ 
+     /* Get packet ID */
+-    {
+-        struct packet_id_net pin;
+-        packet_id_alloc_outgoing(&opt->packet_id.send, &pin, true);
+-        packet_id_write(&pin, dst, true, false);
+-    }
++    ASSERT(packet_id_write(&opt->packet_id.send, dst, true, false));
+ 
+     dmsg(D_PACKET_CONTENT, "TLS-CRYPT WRAP AD: %s",
+          format_hex(BPTR(dst), BLEN(dst), 0, &gc));
+Index: openvpn-2.4.0/tests/unit_tests/openvpn/Makefile.am
+===================================================================
+--- openvpn-2.4.0.orig/tests/unit_tests/openvpn/Makefile.am
++++ openvpn-2.4.0/tests/unit_tests/openvpn/Makefile.am
+@@ -1,6 +1,6 @@
+ AUTOMAKE_OPTIONS = foreign
+ 
+-check_PROGRAMS = argv_testdriver buffer_testdriver
++check_PROGRAMS = argv_testdriver buffer_testdriver packet_id_testdriver
+ 
+ if ENABLE_CRYPTO
+ check_PROGRAMS += tls_crypt_testdriver
+@@ -27,6 +27,17 @@ buffer_testdriver_SOURCES = test_buffer.
+ 	$(openvpn_srcdir)/buffer.c \
+ 	$(openvpn_srcdir)/platform.c
+ 
++packet_id_testdriver_CFLAGS  = @TEST_CFLAGS@ \
++	-I$(openvpn_includedir) -I$(compat_srcdir) -I$(openvpn_srcdir) \
++	$(OPTIONAL_CRYPTO_CFLAGS)
++packet_id_testdriver_LDFLAGS = @TEST_LDFLAGS@ \
++	$(OPTIONAL_CRYPTO_LIBS)
++packet_id_testdriver_SOURCES = test_packet_id.c mock_msg.c \
++	$(openvpn_srcdir)/buffer.c \
++	$(openvpn_srcdir)/otime.c \
++	$(openvpn_srcdir)/packet_id.c \
++	$(openvpn_srcdir)/platform.c
++
+ tls_crypt_testdriver_CFLAGS  = @TEST_CFLAGS@ \
+ 	-I$(openvpn_includedir) -I$(compat_srcdir) -I$(openvpn_srcdir) \
+ 	$(OPTIONAL_CRYPTO_CFLAGS)
+Index: openvpn-2.4.0/tests/unit_tests/openvpn/mock_msg.c
+===================================================================
+--- openvpn-2.4.0.orig/tests/unit_tests/openvpn/mock_msg.c
++++ openvpn-2.4.0/tests/unit_tests/openvpn/mock_msg.c
+@@ -29,9 +29,12 @@
+ #endif
+ 
+ #include <stdarg.h>
+-#include <stdbool.h>
++#include <stddef.h>
+ #include <stdio.h>
+ #include <stdlib.h>
++#include <setjmp.h>
++#include <cmocka.h>
++
+ 
+ #include "errlevel.h"
+ #include "error.h"
+@@ -70,14 +73,8 @@ x_msg(const unsigned int flags, const ch
+ void
+ assert_failed(const char *filename, int line, const char *condition)
+ {
+-    if (condition)
+-    {
+-        printf("Assertion failed at %s:%d (%s)", filename, line, condition);
+-    }
+-    else
+-    {
+-        printf("Assertion failed at %s:%d", filename, line);
+-    }
++    mock_assert(false, condition ? condition : "", filename, line);
++    /* Keep compiler happy.  Should not happen, mock_assert() does not return */
+     exit(1);
+ }
+ 
+Index: openvpn-2.4.0/tests/unit_tests/openvpn/test_packet_id.c
+===================================================================
+--- /dev/null
++++ openvpn-2.4.0/tests/unit_tests/openvpn/test_packet_id.c
+@@ -0,0 +1,168 @@
++/*
++ *  OpenVPN -- An application to securely tunnel IP networks
++ *             over a single UDP port, with support for SSL/TLS-based
++ *             session authentication and key exchange,
++ *             packet encryption, packet authentication, and
++ *             packet compression.
++ *
++ *  Copyright (C) 2016 Fox Crypto B.V. <open...@fox-it.com>
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License version 2
++ *  as published by the Free Software Foundation.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ *
++ *  You should have received a copy of the GNU General Public License
++ *  along with this program (see the file COPYING included with this
++ *  distribution); if not, write to the Free Software Foundation, Inc.,
++ *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++
++#ifdef HAVE_CONFIG_H
++#include "config.h"
++#elif defined(_MSC_VER)
++#include "config-msvc.h"
++#endif
++
++#include "syshead.h"
++
++#include <stdarg.h>
++#include <stddef.h>
++#include <setjmp.h>
++#include <cmocka.h>
++
++#include "packet_id.h"
++
++#include "mock_msg.h"
++
++struct test_packet_id_write_data {
++    struct {
++        uint32_t buf_id;
++        uint32_t buf_time;
++    } test_buf_data;
++    struct buffer test_buf;
++    struct packet_id_send pis;
++};
++
++static int
++test_packet_id_write_setup(void **state) {
++    struct test_packet_id_write_data *data =
++            calloc(1, sizeof(struct test_packet_id_write_data));
++
++    if (!data)
++    {
++        return -1;
++    }
++
++    data->test_buf.data = (void *) &data->test_buf_data;
++    data->test_buf.capacity = sizeof(data->test_buf_data);
++
++    *state = data;
++    return 0;
++}
++
++static int
++test_packet_id_write_teardown(void **state) {
++    free(*state);
++    return 0;
++}
++
++static void
++test_packet_id_write_short(void **state)
++{
++    struct test_packet_id_write_data *data = *state;
++
++    now = 5010;
++    assert_true(packet_id_write(&data->pis, &data->test_buf, false, false));
++    assert_true(data->pis.id == 1);
++    assert_true(data->test_buf_data.buf_id == htonl(1));
++    assert_true(data->test_buf_data.buf_time == 0);
++}
++
++static void
++test_packet_id_write_long(void **state)
++{
++    struct test_packet_id_write_data *data = *state;
++
++    now = 5010;
++    assert_true(packet_id_write(&data->pis, &data->test_buf, true, false));
++    assert(data->pis.id == 1);
++    assert(data->pis.time == now);
++    assert_true(data->test_buf_data.buf_id == htonl(1));
++    assert_true(data->test_buf_data.buf_time == htonl(now));
++}
++
++static void
++test_packet_id_write_short_prepend(void **state)
++{
++    struct test_packet_id_write_data *data = *state;
++
++    data->test_buf.offset = sizeof(packet_id_type);
++    now = 5010;
++    assert_true(packet_id_write(&data->pis, &data->test_buf, false, true));
++    assert_true(data->pis.id == 1);
++    assert_true(data->test_buf_data.buf_id == htonl(1));
++    assert_true(data->test_buf_data.buf_time == 0);
++}
++
++static void
++test_packet_id_write_long_prepend(void **state)
++{
++    struct test_packet_id_write_data *data = *state;
++
++    data->test_buf.offset = sizeof(data->test_buf_data);
++    now = 5010;
++    assert_true(packet_id_write(&data->pis, &data->test_buf, true, true));
++    assert(data->pis.id == 1);
++    assert(data->pis.time == now);
++    assert_true(data->test_buf_data.buf_id == htonl(1));
++    assert_true(data->test_buf_data.buf_time == htonl(now));
++}
++
++static void
++test_packet_id_write_short_wrap(void **state)
++{
++    struct test_packet_id_write_data *data = *state;
++
++    data->pis.id = ~0;
++    expect_assert_failure(
++            packet_id_write(&data->pis, &data->test_buf, false, false));
++}
++
++static void
++test_packet_id_write_long_wrap(void **state)
++{
++    struct test_packet_id_write_data *data = *state;
++
++    data->pis.id = ~0;
++    now = 5010;
++    assert_true(packet_id_write(&data->pis, &data->test_buf, true, false));
++    assert(data->pis.id == 1);
++    assert(data->pis.time == now);
++    assert_true(data->test_buf_data.buf_id == htonl(1));
++    assert_true(data->test_buf_data.buf_time == htonl(now));
++}
++
++int
++main(void) {
++    const struct CMUnitTest tests[] = {
++            cmocka_unit_test_setup_teardown(test_packet_id_write_short,
++                    test_packet_id_write_setup, test_packet_id_write_teardown),
++            cmocka_unit_test_setup_teardown(test_packet_id_write_long,
++                    test_packet_id_write_setup, test_packet_id_write_teardown),
++            cmocka_unit_test_setup_teardown(test_packet_id_write_short_prepend,
++                    test_packet_id_write_setup, test_packet_id_write_teardown),
++            cmocka_unit_test_setup_teardown(test_packet_id_write_long_prepend,
++                    test_packet_id_write_setup, test_packet_id_write_teardown),
++            cmocka_unit_test_setup_teardown(test_packet_id_write_short_wrap,
++                    test_packet_id_write_setup, test_packet_id_write_teardown),
++            cmocka_unit_test_setup_teardown(test_packet_id_write_long_wrap,
++                    test_packet_id_write_setup, test_packet_id_write_teardown),
++    };
++
++    return cmocka_run_group_tests_name("packet_id tests", tests, NULL, NULL);
++}
diff -Nru openvpn-2.4.0/debian/patches/match-manpage-and-command-help.patch openvpn-2.4.0/debian/patches/match-manpage-and-command-help.patch
--- openvpn-2.4.0/debian/patches/match-manpage-and-command-help.patch	1970-01-01 01:00:00.000000000 +0100
+++ openvpn-2.4.0/debian/patches/match-manpage-and-command-help.patch	2017-05-11 14:12:03.000000000 +0200
@@ -0,0 +1,25 @@
+From a88d8ba3e81ca34fc2675805a273cd85875c8973 Mon Sep 17 00:00:00 2001
+From: Arne Schwabe <a...@rfc2549.org>
+Date: Wed, 4 Jan 2017 19:18:46 +0100
+Subject: [PATCH] Change command help to match man page and implementation
+
+---
+ src/openvpn/options.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/openvpn/options.c b/src/openvpn/options.c
+index bfedb6a..80143e6 100644
+--- a/src/openvpn/options.c
++++ b/src/openvpn/options.c
+@@ -198,7 +198,7 @@ static const char usage_message[] =
+     "                  is established.  Multiple routes can be specified.\n"
+     "                  netmask default: 255.255.255.255\n"
+     "                  gateway default: taken from --route-gateway or --ifconfig\n"
+-    "                  Specify default by leaving blank or setting to \"nil\".\n"
++    "                  Specify default by leaving blank or setting to \"default\".\n"
+     "--route-ipv6 network/bits [gateway] [metric] :\n"
+     "                  Add IPv6 route to routing table after connection\n"
+     "                  is established.  Multiple routes can be specified.\n"
+-- 
+2.10.1 (Apple Git-78)
+
diff -Nru openvpn-2.4.0/debian/patches/route_default_nil.patch openvpn-2.4.0/debian/patches/route_default_nil.patch
--- openvpn-2.4.0/debian/patches/route_default_nil.patch	2016-11-21 09:54:08.000000000 +0100
+++ openvpn-2.4.0/debian/patches/route_default_nil.patch	1970-01-01 01:00:00.000000000 +0100
@@ -1,15 +0,0 @@
-Description: Fix small wording in man page.
-Author: Alberto Gonzalez Iniesta <a...@inittab.org>
-Index: openvpn/doc/openvpn.8
-===================================================================
---- openvpn.orig/doc/openvpn.8	2016-11-21 09:54:04.404957249 +0100
-+++ openvpn/doc/openvpn.8	2016-11-21 09:54:04.400957231 +0100
-@@ -973,7 +973,7 @@
- otherwise 0.
- 
- The default can be specified by leaving an option blank or setting
--it to "default".
-+it to "nil".
- 
- The
- .B network
diff -Nru openvpn-2.4.0/debian/patches/series openvpn-2.4.0/debian/patches/series
--- openvpn-2.4.0/debian/patches/series	2016-12-27 18:46:31.000000000 +0100
+++ openvpn-2.4.0/debian/patches/series	2017-05-11 14:15:21.000000000 +0200
@@ -1,5 +1,9 @@
 auth-pam_libpam_so_filename.patch
 debian_nogroup_for_sample_files.patch
 openvpn-pkcs11warn.patch
-route_default_nil.patch
 kfreebsd_support.patch
+match-manpage-and-command-help.patch
+CVE-2017-7478.patch
+CVE-2017-7479-prereq.patch
+CVE-2017-7479.patch
+wipe_tokens_on_de-auth.patch
diff -Nru openvpn-2.4.0/debian/patches/wipe_tokens_on_de-auth.patch openvpn-2.4.0/debian/patches/wipe_tokens_on_de-auth.patch
--- openvpn-2.4.0/debian/patches/wipe_tokens_on_de-auth.patch	1970-01-01 01:00:00.000000000 +0100
+++ openvpn-2.4.0/debian/patches/wipe_tokens_on_de-auth.patch	2017-05-11 14:15:21.000000000 +0200
@@ -0,0 +1,118 @@
+From daab0a9fa8ff4f40e8a34707db0ac156d49fbfcb Mon Sep 17 00:00:00 2001
+From: David Sommerseth <dav...@openvpn.net>
+Date: Tue, 28 Mar 2017 22:53:46 +0200
+Subject: [PATCH] auth-token: Ensure tokens are always wiped on de-auth
+
+If tls_deauthenticate() was called, it could in some scenarios leave the
+authentication token for a session in memory.  This change just ensures
+auth-tokens are always wiped as soon as a TLS session is considered
+broken.
+
+Signed-off-by: David Sommerseth <dav...@openvpn.net>
+
+Acked-by: Steffan Karger <stef...@karger.me>
+Message-Id: <20170328205346.18844-1-dav...@openvpn.net>
+URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg14344.html
+Signed-off-by: David Sommerseth <dav...@openvpn.net>
+---
+ src/openvpn/ssl_verify.c | 47 +++++++++++++++++++++++++++--------------------
+ 1 file changed, 27 insertions(+), 20 deletions(-)
+
+Index: openvpn-2.4.0/src/openvpn/ssl_verify.c
+===================================================================
+--- openvpn-2.4.0.orig/src/openvpn/ssl_verify.c
++++ openvpn-2.4.0/src/openvpn/ssl_verify.c
+@@ -80,6 +80,28 @@ setenv_untrusted(struct tls_session *ses
+     setenv_link_socket_actual(session->opt->es, "untrusted", &session->untrusted_addr, SA_IP_PORT);
+ }
+ 
++
++/**
++ *  Wipes the authentication token out of the memory, frees and cleans up related buffers and flags
++ *
++ *  @param multi  Pointer to a multi object holding the auth_token variables
++ */
++static void
++wipe_auth_token(struct tls_multi *multi)
++{
++    if(multi)
++    {
++        if (multi->auth_token)
++        {
++            secure_memzero(multi->auth_token, AUTH_TOKEN_SIZE);
++            free(multi->auth_token);
++        }
++        multi->auth_token = NULL;
++        multi->auth_token_sent = false;
++    }
++}
++
++
+ /*
+  * Remove authenticated state from all sessions in the given tunnel
+  */
+@@ -88,10 +110,14 @@ tls_deauthenticate(struct tls_multi *mul
+ {
+     if (multi)
+     {
+-        int i, j;
+-        for (i = 0; i < TM_SIZE; ++i)
+-            for (j = 0; j < KS_SIZE; ++j)
++        wipe_auth_token(multi);
++        for (int i = 0; i < TM_SIZE; ++i)
++        {
++            for (int j = 0; j < KS_SIZE; ++j)
++            {
+                 multi->session[i].key[j].authenticated = false;
++            }
++        }
+     }
+ }
+ 
+@@ -1213,21 +1239,6 @@ verify_user_pass_management(struct tls_s
+ }
+ #endif /* ifdef MANAGEMENT_DEF_AUTH */
+ 
+-/**
+- *  Wipes the authentication token out of the memory, frees and cleans up related buffers and flags
+- *
+- *  @param multi  Pointer to a multi object holding the auth_token variables
+- */
+-static void
+-wipe_auth_token(struct tls_multi *multi)
+-{
+-    secure_memzero(multi->auth_token, AUTH_TOKEN_SIZE);
+-    free(multi->auth_token);
+-    multi->auth_token = NULL;
+-    multi->auth_token_sent = false;
+-}
+-
+-
+ /*
+  * Main username/password verification entry point
+  */
+@@ -1279,7 +1290,7 @@ verify_user_pass(struct user_pass *up, s
+         /* Ensure that the username has not changed */
+         if (!tls_lock_username(multi, up->username))
+         {
+-            wipe_auth_token(multi);
++            /* auth-token cleared in tls_lock_username() on failure */
+             ks->authenticated = false;
+             goto done;
+         }
+@@ -1300,7 +1311,6 @@ verify_user_pass(struct user_pass *up, s
+         if (memcmp_constant_time(multi->auth_token, up->password,
+                                  strlen(multi->auth_token)) != 0)
+         {
+-            wipe_auth_token(multi);
+             ks->authenticated = false;
+             tls_deauthenticate(multi);
+ 
+@@ -1472,6 +1482,7 @@ verify_final_auth_checks(struct tls_mult
+         if (!cn || !strcmp(cn, CCD_DEFAULT) || !test_file(path))
+         {
+             ks->authenticated = false;
++            wipe_auth_token(multi);
+             msg(D_TLS_ERRORS, "TLS Auth Error: --client-config-dir authentication failed for common name '%s' file='%s'",
+                 session->common_name,
+                 path ? path : "UNDEF");

Reply via email to