summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlberto Gonzalez Iniesta <agi@inittab.org>2017-06-22 17:25:13 +0200
committerBernhard Schmidt <berni@debian.org>2017-06-29 22:05:44 +0200
commit3e3e9b32519a38f9316986b877163d37557b4f70 (patch)
tree9ee9a4a6f2813fe4ce4623bab80d6a6c30660854
parentafc11370be9fd149ab361ca183c9715777b50df0 (diff)
Import Debian changes 2.3.4-5+deb8u2debian/2.3.4-5+deb8u2
openvpn (2.3.4-5+deb8u2) jessie-security; urgency=high * SECURITY UPDATE: authenticated remote DoS vulnerability due to packet ID rollover. CVE-2017-7479. Kudos to Steve Beattie <sbeattie@ubuntu.com> for doing all the backporting work for this patch. - 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 * SECURITY UPDATE: (Closes: #865480) - CVE-2017-7508.patch. Fix remotely-triggerable ASSERT() on malformed IPv6 packet. - CVE-2017-7520.patch. Prevent two kinds of stack buffer OOB reads and a crash for invalid input data. - CVE-2017-7521.patch. Fix potential double-free in --x509-alt-username. - CVE-2017-7521bis.patch. Fix remote-triggerable memory leaks.
-rw-r--r--debian/changelog20
-rw-r--r--debian/patches/CVE-2017-7479-prereq.patch518
-rw-r--r--debian/patches/CVE-2017-7479.patch162
-rw-r--r--debian/patches/CVE-2017-7508.patch57
-rw-r--r--debian/patches/CVE-2017-7520.patch55
-rw-r--r--debian/patches/CVE-2017-7521.patch48
-rw-r--r--debian/patches/CVE-2017-7521bis.patch74
-rw-r--r--debian/patches/series6
8 files changed, 940 insertions, 0 deletions
diff --git a/debian/changelog b/debian/changelog
index 05e193c..6bc3fa9 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,23 @@
+openvpn (2.3.4-5+deb8u2) jessie-security; urgency=high
+
+ * SECURITY UPDATE: authenticated remote DoS vulnerability due to
+ packet ID rollover. CVE-2017-7479.
+ Kudos to Steve Beattie <sbeattie@ubuntu.com> for doing all the backporting
+ work for this patch.
+ - 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
+ * SECURITY UPDATE: (Closes: #865480)
+ - CVE-2017-7508.patch. Fix remotely-triggerable ASSERT() on malformed IPv6
+ packet.
+ - CVE-2017-7520.patch. Prevent two kinds of stack buffer OOB reads and a
+ crash for invalid input data.
+ - CVE-2017-7521.patch. Fix potential double-free in --x509-alt-username.
+ - CVE-2017-7521bis.patch. Fix remote-triggerable memory leaks.
+
+ -- Alberto Gonzalez Iniesta <agi@inittab.org> Thu, 22 Jun 2017 17:25:13 +0200
+
openvpn (2.3.4-5+deb8u1) stable; urgency=medium
* Add --no-block to if-up.d script to avoid hanging boot on
diff --git a/debian/patches/CVE-2017-7479-prereq.patch b/debian/patches/CVE-2017-7479-prereq.patch
new file mode 100644
index 0000000..4408185
--- /dev/null
+++ b/debian/patches/CVE-2017-7479-prereq.patch
@@ -0,0 +1,518 @@
+From 5d747770efa0611cc6cfeb6b3a5853bf51046d53 Mon Sep 17 00:00:00 2001
+From: Steffan Karger <steffan.karger@fox-it.com>
+Date: Tue, 9 May 2017 21:10:36 +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.
+
+This patch was cherry-picked from a87e1431 (master).
+
+Signed-off-by: Steffan Karger <steffan.karger@fox-it.com>
+Acked-by: David Sommerseth <davids@openvpn.net>
+Message-Id: <1494357036-3529-1-git-send-email-steffan.karger@fox-it.com>
+URL: http://www.mail-archive.com/search?l=mid&q=1494357036-3529-1-git-send-email-steffan.karger@fox-it.com
+Signed-off-by: David Sommerseth <davids@openvpn.net>
+
+[Ubuntu note: prereq for CVE-2017-7479 issue. Disabled all testscases,
+ as the infrastructure for that wasn't introduced until 2.3.12. -- sbeattie]
+
+---
+ configure.ac | 1 +
+ src/openvpn/crypto.c | 12 +--
+ src/openvpn/packet_id.c | 24 ++++-
+ src/openvpn/packet_id.h | 34 +++---
+ tests/unit_tests/Makefile.am | 2 +-
+ tests/unit_tests/openvpn/Makefile.am | 24 +++++
+ tests/unit_tests/openvpn/mock_msg.c | 98 +++++++++++++++++
+ tests/unit_tests/openvpn/mock_msg.h | 35 +++++++
+ tests/unit_tests/openvpn/test_packet_id.c | 169 ++++++++++++++++++++++++++++++
+ 9 files changed, 365 insertions(+), 34 deletions(-)
+ create mode 100644 tests/unit_tests/openvpn/Makefile.am
+ create mode 100644 tests/unit_tests/openvpn/mock_msg.c
+ create mode 100644 tests/unit_tests/openvpn/mock_msg.h
+ create mode 100644 tests/unit_tests/openvpn/test_packet_id.c
+
+Index: openvpn-2.3.4/src/openvpn/crypto.c
+===================================================================
+--- openvpn-2.3.4.orig/src/openvpn/crypto.c
++++ openvpn-2.3.4/src/openvpn/crypto.c
+@@ -114,23 +114,19 @@ openvpn_encrypt (struct buffer *buf, str
+ /* Put packet ID in plaintext buffer or IV, depending on cipher mode */
+ if (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));
+ }
+ }
+ else if (mode == OPENVPN_MODE_CFB || mode == OPENVPN_MODE_OFB)
+ {
+- struct packet_id_net pin;
+ struct buffer b;
+
+ ASSERT (opt->flags & CO_USE_IV); /* IV and packet-ID required */
+ ASSERT (opt->packet_id); /* for this mode. */
+
+- packet_id_alloc_outgoing (&opt->packet_id->send, &pin, true);
+ memset (iv_buf, 0, iv_size);
+ 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 */
+ {
+@@ -188,9 +184,7 @@ openvpn_encrypt (struct buffer *buf, str
+ {
+ if (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));
+ }
+ work = *buf;
+ }
+Index: openvpn-2.3.4/src/openvpn/packet_id.c
+===================================================================
+--- openvpn-2.3.4.orig/src/openvpn/packet_id.c
++++ openvpn-2.3.4/src/openvpn/packet_id.c
+@@ -294,12 +294,30 @@ packet_id_read (struct packet_id_net *pi
+ 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.3.4/src/openvpn/packet_id.h
+===================================================================
+--- openvpn-2.3.4.orig/src/openvpn/packet_id.h
++++ openvpn-2.3.4/src/openvpn/packet_id.h
+@@ -252,7 +252,19 @@ const char *packet_id_persist_print (con
+ */
+
+ 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.
+@@ -294,26 +306,6 @@ packet_id_close_to_wrapping (const struc
+ 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.3.4/tests/unit_tests/openvpn/Makefile.am
+===================================================================
+--- /dev/null
++++ openvpn-2.3.4/tests/unit_tests/openvpn/Makefile.am
+@@ -0,0 +1,24 @@
++AUTOMAKE_OPTIONS = foreign
++
++check_PROGRAMS=
++
++if ENABLE_CRYPTO
++check_PROGRAMS += packet_id_testdriver
++endif
++
++TESTS = $(check_PROGRAMS)
++
++openvpn_includedir = $(top_srcdir)/include
++openvpn_srcdir = $(top_srcdir)/src/openvpn
++compat_srcdir = $(top_srcdir)/src/compat
++
++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
+Index: openvpn-2.3.4/tests/unit_tests/openvpn/mock_msg.c
+===================================================================
+--- /dev/null
++++ openvpn-2.3.4/tests/unit_tests/openvpn/mock_msg.c
+@@ -0,0 +1,98 @@
++/*
++ * 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-2017 Fox Crypto B.V. <openvpn@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 <stdarg.h>
++#include <stddef.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <setjmp.h>
++#include <cmocka.h>
++
++
++#include "errlevel.h"
++#include "error.h"
++
++#include "mock_msg.h"
++
++unsigned int x_debug_level = 0; /* Default to (almost) no debugging output */
++bool fatal_error_triggered = false;
++
++void
++mock_set_debug_level(int level)
++{
++ x_debug_level = level;
++}
++
++void
++x_msg_va(const unsigned int flags, const char *format,
++ va_list arglist)
++{
++ if (flags & M_FATAL)
++ {
++ fatal_error_triggered = true;
++ printf("FATAL ERROR:");
++ }
++ vprintf(format, arglist);
++ printf("\n");
++}
++
++void
++x_msg(const unsigned int flags, const char *format, ...)
++{
++ va_list arglist;
++ va_start(arglist, format);
++ x_msg_va(flags, format, arglist);
++ va_end(arglist);
++}
++
++void
++assert_failed(const char *filename, int line, const char *condition)
++{
++ mock_assert(false, condition ? condition : "", filename, line);
++ /* Keep compiler happy. Should not happen, mock_assert() does not return */
++ exit(1);
++}
++
++/*
++ * Fail memory allocation. Don't use msg() because it tries
++ * to allocate memory as part of its operation.
++ */
++void
++out_of_memory(void)
++{
++ fprintf(stderr, "Out of Memory\n");
++ exit(1);
++}
++
++bool
++dont_mute(unsigned int flags)
++{
++ return true;
++}
+Index: openvpn-2.3.4/tests/unit_tests/openvpn/mock_msg.h
+===================================================================
+--- /dev/null
++++ openvpn-2.3.4/tests/unit_tests/openvpn/mock_msg.h
+@@ -0,0 +1,35 @@
++/*
++ * 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-2017 Fox Crypto B.V. <openvpn@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
++ */
++
++#ifndef MOCK_MSG_H
++#define MOCK_MSG_H
++
++/**
++ * Mock debug level defaults to 0, which gives clean(-ish) test reports. Call
++ * this function from your test driver to increase debug output when you
++ * need debug output.
++ */
++void mock_set_debug_level(int level);
++
++#endif /* MOCK_MSG */
+Index: openvpn-2.3.4/tests/unit_tests/openvpn/test_packet_id.c
+===================================================================
+--- /dev/null
++++ openvpn-2.3.4/tests/unit_tests/openvpn/test_packet_id.c
+@@ -0,0 +1,169 @@
++/*
++ * 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. <openvpn@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 <assert.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 --git a/debian/patches/CVE-2017-7479.patch b/debian/patches/CVE-2017-7479.patch
new file mode 100644
index 0000000..5cbc1ee
--- /dev/null
+++ b/debian/patches/CVE-2017-7479.patch
@@ -0,0 +1,162 @@
+From ac08b27cfa693d9be592bb2597c260635aee9e68 Mon Sep 17 00:00:00 2001
+From: Steffan Karger <steffan.karger@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.karger@fox-it.com>
+
+CVE-2017-7479
+
+[Ubuntu note: 2.3.x does not support tlscrypt, so that portion of patch
+was dropped; other backporting to 2.3.x]. --sbeattie
+
+---
+ 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.3.2/src/openvpn/crypto.c
+===================================================================
+--- openvpn-2.3.2.orig/src/openvpn/crypto.c
++++ openvpn-2.3.2/src/openvpn/crypto.c
+@@ -112,9 +112,13 @@ openvpn_encrypt (struct buffer *buf, str
+ prng_bytes (iv_buf, iv_size);
+
+ /* Put packet ID in plaintext buffer or IV, depending on cipher mode */
+- if (opt->packet_id)
++ if (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;
+ }
+ }
+ else if (mode == OPENVPN_MODE_CFB || mode == OPENVPN_MODE_OFB)
+@@ -182,9 +186,12 @@ openvpn_encrypt (struct buffer *buf, str
+ }
+ else /* No Encryption */
+ {
+- if (opt->packet_id)
++ if (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;
+ }
+ work = *buf;
+ }
+Index: openvpn-2.3.2/src/openvpn/packet_id.c
+===================================================================
+--- openvpn-2.3.2.orig/src/openvpn/packet_id.c
++++ openvpn-2.3.2/src/openvpn/packet_id.c
+@@ -294,27 +294,37 @@ packet_id_read (struct packet_id_net *pi
+ 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.3.2/src/openvpn/packet_id.h
+===================================================================
+--- openvpn-2.3.2.orig/src/openvpn/packet_id.h
++++ openvpn-2.3.2/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.3.2/tests/unit_tests/openvpn/test_packet_id.c
+===================================================================
+--- openvpn-2.3.2.orig/tests/unit_tests/openvpn/test_packet_id.c
++++ openvpn-2.3.2/tests/unit_tests/openvpn/test_packet_id.c
+@@ -130,8 +130,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
+@@ -140,8 +139,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 --git a/debian/patches/CVE-2017-7508.patch b/debian/patches/CVE-2017-7508.patch
new file mode 100644
index 0000000..f096553
--- /dev/null
+++ b/debian/patches/CVE-2017-7508.patch
@@ -0,0 +1,57 @@
+commit fc61d1bda112ffc669dbde961fab19f60b3c7439
+Author: Gert Doering <gert@greenie.muc.de>
+Date: Tue Jun 13 22:08:32 2017 +0200
+
+ Fix remotely-triggerable ASSERT() on malformed IPv6 packet.
+
+ Correct sanity checks on IPv6 packet length in mss_fixup_ipv6(),
+ and change the ASSERT() check in mss_fixup_dowork() into a simple
+ "return" (= the TCP header will simply not be inspected further).
+
+ CVE-2017-7508 has been assigned due to the serious nature of the
+ bug: it can be used to remotely shutdown an openvpn server or
+ client, if IPv6 and --mssfix are enabled and the IPv6 networks used
+ inside the VPN are known.
+
+ Found by Guido Vranken <guidovranken@gmail.com>.
+
+ v2: style changes
+
+ CVE: 2017-7508
+ Signed-off-by: Gert Doering <gert@greenie.muc.de>
+ Acked-by: Steffan Karger <steffan.karger@fox-it.com>
+ Message-Id: <20170613200832.15027-1-gert@greenie.muc.de>
+ URL: https://www.mail-archive.com/search?l=mid&q=20170613200832.15027-1-gert@greenie.muc.de
+ Signed-off-by: Gert Doering <gert@greenie.muc.de>
+ (cherry picked from commit c3f47077a7756de5929094569421a95aa66f2022)
+
+diff --git a/src/openvpn/mss.c b/src/openvpn/mss.c
+index f930942a..c91751d1 100644
+--- a/src/openvpn/mss.c
++++ b/src/openvpn/mss.c
+@@ -110,8 +110,12 @@ mss_fixup_ipv6 (struct buffer *buf, int maxmss)
+ if ( pip6->nexthdr != OPENVPN_IPPROTO_TCP )
+ return;
+
++ /* skip IPv6 header (40 bytes),
++ * verify remainder is large enough to contain a full TCP header
++ */
+ newbuf = *buf;
+- if ( buf_advance( &newbuf, 40 ) )
++ if (buf_advance( &newbuf, 40 )
++ && BLEN(&newbuf) >= (int) sizeof(struct openvpn_tcphdr))
+ {
+ struct openvpn_tcphdr *tc = (struct openvpn_tcphdr *) BPTR (&newbuf);
+ if (tc->flags & OPENVPN_TCPH_SYN_MASK)
+@@ -133,7 +137,10 @@ mss_fixup_dowork (struct buffer *buf, uint16_t maxmss)
+ int accumulate;
+ struct openvpn_tcphdr *tc;
+
+- ASSERT (BLEN (buf) >= (int) sizeof (struct openvpn_tcphdr));
++ if (BLEN(buf) < (int) sizeof(struct openvpn_tcphdr))
++ {
++ return;
++ }
+
+ verify_align_4 (buf);
+ tc = (struct openvpn_tcphdr *) BPTR (buf);
diff --git a/debian/patches/CVE-2017-7520.patch b/debian/patches/CVE-2017-7520.patch
new file mode 100644
index 0000000..e74cec0
--- /dev/null
+++ b/debian/patches/CVE-2017-7520.patch
@@ -0,0 +1,55 @@
+commit f38a4a105979b87ebebe9be1c3d323116d3fb924
+Author: Guido Vranken <guidovranken@gmail.com>
+Date: Fri May 19 14:04:25 2017 +0200
+
+ Prevent two kinds of stack buffer OOB reads and a crash for invalid input data
+
+ Pre-authentication remote crash/information disclosure for clients
+
+ If clients use a HTTP proxy with NTLM authentication (i.e.
+ "--http-proxy <server> <port> [<authfile>|'auto'|'auto-nct'] ntlm2"),
+ a man-in-the-middle attacker between the client and the proxy can
+ cause the client to crash or disclose at most 96 bytes of stack
+ memory. The disclosed stack memory is likely to contain the proxy
+ password.
+
+ If the proxy password is not reused, this is unlikely to compromise
+ the security of the OpenVPN tunnel itself. Clients who do not use
+ the --http-proxy option with ntlm2 authentication are not affected.
+
+ CVE: 2017-7520
+ Signed-off-by: Guido Vranken <guidovranken@gmail.com>
+ Acked-by: Gert Doering <gert@greenie.muc.de>
+ Message-Id: <CAO5O-EJvHKid-zTj+hmFG_3Gv78ixqCayE9=C62DZaxN32WNtQ@mail.gmail.com>
+ URL: https://www.mail-archive.com/search?l=mid&q=CAO5O-EJvHKid-zTj+hmFG_3Gv78ixqCayE9=C62DZaxN32WNtQ@mail.gmail.com
+ Signed-off-by: Gert Doering <gert@greenie.muc.de>
+ (cherry picked from commit 7718c8984f04b507c1885f363970e2124e3c6c77)
+
+Index: openvpn-2.3.4/src/openvpn/ntlm.c
+===================================================================
+--- openvpn-2.3.4.orig/src/openvpn/ntlm.c
++++ openvpn-2.3.4/src/openvpn/ntlm.c
+@@ -193,7 +193,7 @@ ntlm_phase_3 (const struct http_proxy_in
+ */
+
+ char pwbuf[sizeof (p->up.password) * 2]; /* for unicode password */
+- char buf2[128]; /* decoded reply from proxy */
++ unsigned char buf2[128]; /* decoded reply from proxy */
+ unsigned char phase3[464];
+
+ char md4_hash[MD4_DIGEST_LENGTH+5];
+@@ -282,7 +282,13 @@ ntlm_phase_3 (const struct http_proxy_in
+ tib_len = buf2[0x28];/* Get Target Information block size */
+ if (tib_len > 96) tib_len = 96;
+ {
+- char *tib_ptr = buf2 + buf2[0x2c]; /* Get Target Information block pointer */
++ char *tib_ptr;
++ int tib_pos = buf2[0x2c];
++ if (tib_pos + tib_len > sizeof(buf2))
++ {
++ return NULL;
++ }
++ tib_ptr = buf2 + tib_pos; /* Get Target Information block pointer */
+ memcpy(&ntlmv2_blob[0x1c], tib_ptr, tib_len); /* Copy Target Information block into the blob */
+ }
+ } else {
diff --git a/debian/patches/CVE-2017-7521.patch b/debian/patches/CVE-2017-7521.patch
new file mode 100644
index 0000000..085550c
--- /dev/null
+++ b/debian/patches/CVE-2017-7521.patch
@@ -0,0 +1,48 @@
+commit 1dde0cd6e5e6a0f2f45ec9969b7ff1b6537514ad
+Author: Steffan Karger <steffan.karger@fox-it.com>
+Date: Mon Jun 19 11:28:40 2017 +0200
+
+ Fix potential double-free in --x509-alt-username (CVE-2017-7521)
+
+ We didn't check the return value of ASN1_STRING_to_UTF8() in
+ extract_x509_extension(). Ignoring such a failure could result in buf
+ being free'd twice. An error in ASN1_STRING_to_UTF8() can be caused
+ remotely if the peer can make the local process run out of memory.
+
+ The problem can only be triggered for configurations that use the
+ --x509-alt-username option with an x509 extension (i.e. the option
+ parameter starts with "ext:").
+
+ This issue was discovered, analysed and reported to the OpenVPN team by
+ Guido Vranken.
+
+ Extensive testing by Guido Vranken gives confidence that this function
+ is very unlikely to fail in real-world usage (using subjectAltName or
+ issuerAltName extensions) for other reasons than memory exhaustion.
+
+ CVE: 2017-7521
+ Signed-off-by: Steffan Karger <steffan.karger@fox-it.com>
+ Acked-by: Gert Doering <gert@greenie.muc.de>
+ Acked-by: David Sommerseth <davids@openvpn.net>
+ Acked-by: Guido Vranken <guidovranken@gmail.com>
+ Message-Id: <1497864520-12219-6-git-send-email-steffan.karger@fox-it.com>
+ URL: https://www.mail-archive.com/search?l=mid&q=1497864520-12219-6-git-send-email-steffan.karger@fox-it.com
+ Signed-off-by: Gert Doering <gert@greenie.muc.de>
+ (cherry picked from commit cb4e35ece4a5b70b10ef9013be3bff263d82f32b)
+
+Index: openvpn-2.3.4/src/openvpn/ssl_verify_openssl.c
+===================================================================
+--- openvpn-2.3.4.orig/src/openvpn/ssl_verify_openssl.c
++++ openvpn-2.3.4/src/openvpn/ssl_verify_openssl.c
+@@ -124,7 +124,10 @@ bool extract_x509_extension(X509 *cert,
+ switch (name->type)
+ {
+ case GEN_EMAIL:
+- ASN1_STRING_to_UTF8((unsigned char**)&buf, name->d.ia5);
++ if (ASN1_STRING_to_UTF8((unsigned char **)&buf, name->d.ia5) < 0)
++ {
++ continue;
++ }
+ if ( strlen (buf) != name->d.ia5->length )
+ {
+ msg (D_TLS_ERRORS, "ASN1 ERROR: string contained terminating zero");
diff --git a/debian/patches/CVE-2017-7521bis.patch b/debian/patches/CVE-2017-7521bis.patch
new file mode 100644
index 0000000..a986ef0
--- /dev/null
+++ b/debian/patches/CVE-2017-7521bis.patch
@@ -0,0 +1,74 @@
+commit 84e1775961de1c9d2ab32159fc03f758591f5238
+Author: Steffan Karger <steffan.karger@fox-it.com>
+Date: Mon Jun 19 11:28:38 2017 +0200
+
+ Fix remote-triggerable memory leaks (CVE-2017-7521)
+
+ Several of our OpenSSL-specific certificate-parsing code paths did not
+ always clear all allocated memory. Since a client can cause a few bytes
+ of memory to be leaked for each connection attempt, a client can cause a
+ server to run out of memory and thereby kill the server. That makes this
+ a (quite inefficient) DoS attack.
+
+ When using the --x509-alt-username option on openssl builds with an
+ extension (argument prefixed with "ext:", e.g. "ext:subjectAltName"), the
+ code would not free all allocated memory. Fix this by using the proper
+ free function.
+
+ If ASN1_STRING_to_UTF8() returns 0, it didn't fail and *did* allocate
+ memory. So also free the returned buffer if it returns 0.
+
+ These issues were found, analysed and reported to the OpenVPN team by Guido
+ Vranken.
+
+ CVE: 2017-7521
+ Signed-off-by: Steffan Karger <steffan.karger@fox-it.com>
+ Acked-by: Gert Doering <gert@greenie.muc.de>
+ Acked-by: David Sommerseth <davids@openvpn.net>
+ Acked-by: Guido Vranken <guidovranken@gmail.com>
+ Message-Id: <1497864520-12219-4-git-send-email-steffan.karger@fox-it.com>
+ URL: https://www.mail-archive.com/search?l=mid&q=1497864520-12219-4-git-send-email-steffan.karger@fox-it.com
+ Signed-off-by: Gert Doering <gert@greenie.muc.de>
+ (cherry picked from commit 2d032c7fcdfd692c851ea2fa858b4c2d9ea7d52d)
+
+Index: openvpn-2.3.4/src/openvpn/ssl_verify_openssl.c
+===================================================================
+--- openvpn-2.3.4.orig/src/openvpn/ssl_verify_openssl.c
++++ openvpn-2.3.4/src/openvpn/ssl_verify_openssl.c
+@@ -144,7 +144,7 @@ bool extract_x509_extension(X509 *cert,
+ break;
+ }
+ }
+- sk_GENERAL_NAME_free (extensions);
++ GENERAL_NAMES_free(extensions);
+ }
+ return retval;
+ }
+@@ -191,8 +191,7 @@ extract_x509_field_ssl (X509_NAME *x509,
+ asn1 = X509_NAME_ENTRY_get_data(x509ne);
+ if (!asn1)
+ return FAILURE;
+- tmp = ASN1_STRING_to_UTF8(&buf, asn1);
+- if (tmp <= 0)
++ if (ASN1_STRING_to_UTF8(&buf, asn1) < 0)
+ return FAILURE;
+
+ strncpynt(out, (char *)buf, size);
+@@ -364,7 +363,7 @@ x509_setenv_track (const struct x509_tra
+ ASN1_STRING *val = X509_NAME_ENTRY_get_data (ent);
+ unsigned char *buf;
+ buf = (unsigned char *)1; /* bug in OpenSSL 0.9.6b ASN1_STRING_to_UTF8 requires this workaround */
+- if (ASN1_STRING_to_UTF8 (&buf, val) > 0)
++ if (ASN1_STRING_to_UTF8 (&buf, val) >= 0)
+ {
+ do_setenv_x509(es, xt->name, (char *)buf, depth);
+ OPENSSL_free (buf);
+@@ -440,7 +439,7 @@ x509_setenv (struct env_set *es, int cer
+ if (!objbuf)
+ continue;
+ buf = (unsigned char *)1; /* bug in OpenSSL 0.9.6b ASN1_STRING_to_UTF8 requires this workaround */
+- if (ASN1_STRING_to_UTF8 (&buf, val) <= 0)
++ if (ASN1_STRING_to_UTF8 (&buf, val) < 0)
+ continue;
+ name_expand_size = 64 + strlen (objbuf);
+ name_expand = (char *) malloc (name_expand_size);
diff --git a/debian/patches/series b/debian/patches/series
index 22a08e6..dcff610 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -10,3 +10,9 @@ better_systemd_detection.patch
client_connect_tmp_files.patch
0001-Drop-too-short-control-channel-packets-instead-of-as.patch
update_sample_certs.patch
+CVE-2017-7479-prereq.patch
+CVE-2017-7479.patch
+CVE-2017-7521.patch
+CVE-2017-7521bis.patch
+CVE-2017-7520.patch
+CVE-2017-7508.patch