From 3682a3b0b1c99c61735cab2619cbf2dcc06cde99 Mon Sep 17 00:00:00 2001 From: Linus Heckemann Date: Fri, 4 Oct 2019 12:33:31 +0200 Subject: [PATCH] ipsecTools: ship patch directly No longer available since anonscm.debian.org is shut down (#39927). Replacement obtained from OpenSUSE source package http://download.opensuse.org/repositories/openSUSE:/Factory/standard/src/ipsec-tools-0.8.2-9.6.src.rpm --- .../linux/ipsec-tools/CVE-2016-10396.patch | 193 ++++++++++++++++++ .../os-specific/linux/ipsec-tools/default.nix | 5 +- 2 files changed, 194 insertions(+), 4 deletions(-) create mode 100644 pkgs/os-specific/linux/ipsec-tools/CVE-2016-10396.patch diff --git a/pkgs/os-specific/linux/ipsec-tools/CVE-2016-10396.patch b/pkgs/os-specific/linux/ipsec-tools/CVE-2016-10396.patch new file mode 100644 index 000000000000..b644d46f8c9d --- /dev/null +++ b/pkgs/os-specific/linux/ipsec-tools/CVE-2016-10396.patch @@ -0,0 +1,193 @@ +From: Antoine_Beaupre +Acked-by: Jiri Bohac +Subject: PR/51682: Avoid DoS with fragment out of order insertion; keep fragments sorted in the list. +References: bsc#1047443, CVE-2016-10396 + + + +Index: a/src/racoon/handler.h +=================================================================== +--- a/src/racoon/handler.h.orig 2018-01-26 18:05:21.114764376 +0100 ++++ a/src/racoon/handler.h 2018-01-26 18:05:33.986741103 +0100 +@@ -141,6 +141,7 @@ struct ph1handle { + #endif + #ifdef ENABLE_FRAG + int frag; /* IKE phase 1 fragmentation */ ++ int frag_last_index; + struct isakmp_frag_item *frag_chain; /* Received fragments */ + #endif + +Index: a/src/racoon/isakmp.c +=================================================================== +--- a/src/racoon/isakmp.c.orig 2018-01-26 18:05:21.118764369 +0100 ++++ a/src/racoon/isakmp.c 2018-01-26 18:05:33.986741103 +0100 +@@ -1069,6 +1069,7 @@ isakmp_ph1begin_i(rmconf, remote, local) + iph1->frag = 1; + else + iph1->frag = 0; ++ iph1->frag_last_index = 0; + iph1->frag_chain = NULL; + #endif + iph1->approval = NULL; +@@ -1173,6 +1174,7 @@ isakmp_ph1begin_r(msg, remote, local, et + #endif + #ifdef ENABLE_FRAG + iph1->frag = 0; ++ iph1->frag_last_index = 0; + iph1->frag_chain = NULL; + #endif + iph1->approval = NULL; +Index: a/src/racoon/isakmp_frag.c +=================================================================== +--- a/src/racoon/isakmp_frag.c.orig 2018-01-26 18:05:21.118764369 +0100 ++++ a/src/racoon/isakmp_frag.c 2018-01-26 18:05:33.986741103 +0100 +@@ -173,6 +173,43 @@ vendorid_frag_cap(gen) + return ntohl(hp[MD5_DIGEST_LENGTH / sizeof(*hp)]); + } + ++static int ++isakmp_frag_insert(struct ph1handle *iph1, struct isakmp_frag_item *item) ++{ ++ struct isakmp_frag_item *pitem = NULL; ++ struct isakmp_frag_item *citem = iph1->frag_chain; ++ ++ /* no frag yet, just insert at beginning of list */ ++ if (iph1->frag_chain == NULL) { ++ iph1->frag_chain = item; ++ return 0; ++ } ++ ++ do { ++ /* duplicate fragment number, abort (CVE-2016-10396) */ ++ if (citem->frag_num == item->frag_num) ++ return -1; ++ ++ /* need to insert before current item */ ++ if (citem->frag_num > item->frag_num) { ++ if (pitem != NULL) ++ pitem->frag_next = item; ++ else ++ /* insert at the beginning of the list */ ++ iph1->frag_chain = item; ++ item->frag_next = citem; ++ return 0; ++ } ++ ++ pitem = citem; ++ citem = citem->frag_next; ++ } while (citem != NULL); ++ ++ /* we reached the end of the list, insert */ ++ pitem->frag_next = item; ++ return 0; ++} ++ + int + isakmp_frag_extract(iph1, msg) + struct ph1handle *iph1; +@@ -224,39 +261,43 @@ isakmp_frag_extract(iph1, msg) + item->frag_next = NULL; + item->frag_packet = buf; + +- /* Look for the last frag while inserting the new item in the chain */ +- if (item->frag_last) +- last_frag = item->frag_num; ++ /* Check for the last frag before inserting the new item in the chain */ ++ if (item->frag_last) { ++ /* if we have the last fragment, indices must match */ ++ if (iph1->frag_last_index != 0 && ++ item->frag_last != iph1->frag_last_index) { ++ plog(LLV_ERROR, LOCATION, NULL, ++ "Repeated last fragment index mismatch\n"); ++ racoon_free(item); ++ vfree(buf); ++ return -1; ++ } + +- if (iph1->frag_chain == NULL) { +- iph1->frag_chain = item; +- } else { +- struct isakmp_frag_item *current; ++ last_frag = iph1->frag_last_index = item->frag_num; ++ } + +- current = iph1->frag_chain; +- while (current->frag_next) { +- if (current->frag_last) +- last_frag = item->frag_num; +- current = current->frag_next; +- } +- current->frag_next = item; ++ /* insert fragment into chain */ ++ if (isakmp_frag_insert(iph1, item) == -1) { ++ plog(LLV_ERROR, LOCATION, NULL, ++ "Repeated fragment index mismatch\n"); ++ racoon_free(item); ++ vfree(buf); ++ return -1; + } + +- /* If we saw the last frag, check if the chain is complete */ ++ /* If we saw the last frag, check if the chain is complete ++ * we have a sorted list now, so just walk through */ + if (last_frag != 0) { ++ item = iph1->frag_chain; + for (i = 1; i <= last_frag; i++) { +- item = iph1->frag_chain; +- do { +- if (item->frag_num == i) +- break; +- item = item->frag_next; +- } while (item != NULL); +- ++ if (item->frag_num != i) ++ break; ++ item = item->frag_next; + if (item == NULL) /* Not found */ + break; + } + +- if (item != NULL) /* It is complete */ ++ if (i > last_frag) /* It is complete */ + return 1; + } + +@@ -291,15 +332,9 @@ isakmp_frag_reassembly(iph1) + } + data = buf->v; + ++ item = iph1->frag_chain; + for (i = 1; i <= frag_count; i++) { +- item = iph1->frag_chain; +- do { +- if (item->frag_num == i) +- break; +- item = item->frag_next; +- } while (item != NULL); +- +- if (item == NULL) { ++ if (item->frag_num != i) { + plog(LLV_ERROR, LOCATION, NULL, + "Missing fragment #%d\n", i); + vfree(buf); +@@ -308,6 +343,7 @@ isakmp_frag_reassembly(iph1) + } + memcpy(data, item->frag_packet->v, item->frag_packet->l); + data += item->frag_packet->l; ++ item = item->frag_next; + } + + out: + + +diff -u -p -r1.50 -r1.51 +--- a/src/racoon/isakmp_inf.c 2013/04/12 09:53:10 1.50 ++++ a/src/racoon/isakmp_inf.c 2017/01/24 19:23:56 1.51 +@@ -720,6 +720,7 @@ isakmp_info_send_nx(isakmp, remote, loca + #endif + #ifdef ENABLE_FRAG + iph1->frag = 0; ++ iph1->frag_last_index = 0; + iph1->frag_chain = NULL; + #endif + diff --git a/pkgs/os-specific/linux/ipsec-tools/default.nix b/pkgs/os-specific/linux/ipsec-tools/default.nix index 0aa074b4df8f..551fc61f8145 100644 --- a/pkgs/os-specific/linux/ipsec-tools/default.nix +++ b/pkgs/os-specific/linux/ipsec-tools/default.nix @@ -19,10 +19,7 @@ stdenv.mkDerivation rec { patches = [ ./dont-create-localstatedir-during-install.patch ./CVE-2015-4047.patch - (fetchpatch { - url = "https://anonscm.debian.org/cgit/pkg-ipsec-tools/pkg-ipsec-tools.git/plain/debian/patches/CVE-2016-10396.patch?id=62ac12648a4eb7c5ba5dba0f81998d1acf310d8b"; - sha256 = "1kf7j2pf1blni52z7q41n0yisqb7gvk01lvldr319zaxxg7rm84a"; - }) + ./CVE-2016-10396.patch ]; # fix build with newer gcc versions