You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

201 lines
5.7 KiB

  1. Description: Fix remotely exploitable DoS. http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-10396
  2. Source: vendor; https://gnats.netbsd.org/cgi-bin/query-pr-single.pl?number=51682
  3. Bug-debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=867986
  4. Index: ipsec-tools-0.8.2/src/racoon/isakmp_frag.c
  5. ===================================================================
  6. --- ipsec-tools-0.8.2.orig/src/racoon/isakmp_frag.c
  7. +++ ipsec-tools-0.8.2/src/racoon/isakmp_frag.c
  8. @@ -1,4 +1,4 @@
  9. -/* $NetBSD: isakmp_frag.c,v 1.5 2009/04/22 11:24:20 tteras Exp $ */
  10. +/* $NetBSD: isakmp_frag.c,v 1.5.36.1 2017/04/21 16:50:42 bouyer Exp $ */
  11. /* Id: isakmp_frag.c,v 1.4 2004/11/13 17:31:36 manubsd Exp */
  12. @@ -173,6 +173,43 @@ vendorid_frag_cap(gen)
  13. return ntohl(hp[MD5_DIGEST_LENGTH / sizeof(*hp)]);
  14. }
  15. +static int
  16. +isakmp_frag_insert(struct ph1handle *iph1, struct isakmp_frag_item *item)
  17. +{
  18. + struct isakmp_frag_item *pitem = NULL;
  19. + struct isakmp_frag_item *citem = iph1->frag_chain;
  20. +
  21. + /* no frag yet, just insert at beginning of list */
  22. + if (iph1->frag_chain == NULL) {
  23. + iph1->frag_chain = item;
  24. + return 0;
  25. + }
  26. +
  27. + do {
  28. + /* duplicate fragment number, abort (CVE-2016-10396) */
  29. + if (citem->frag_num == item->frag_num)
  30. + return -1;
  31. +
  32. + /* need to insert before current item */
  33. + if (citem->frag_num > item->frag_num) {
  34. + if (pitem != NULL)
  35. + pitem->frag_next = item;
  36. + else
  37. + /* insert at the beginning of the list */
  38. + iph1->frag_chain = item;
  39. + item->frag_next = citem;
  40. + return 0;
  41. + }
  42. +
  43. + pitem = citem;
  44. + citem = citem->frag_next;
  45. + } while (citem != NULL);
  46. +
  47. + /* we reached the end of the list, insert */
  48. + pitem->frag_next = item;
  49. + return 0;
  50. +}
  51. +
  52. int
  53. isakmp_frag_extract(iph1, msg)
  54. struct ph1handle *iph1;
  55. @@ -224,39 +261,43 @@ isakmp_frag_extract(iph1, msg)
  56. item->frag_next = NULL;
  57. item->frag_packet = buf;
  58. - /* Look for the last frag while inserting the new item in the chain */
  59. - if (item->frag_last)
  60. - last_frag = item->frag_num;
  61. + /* Check for the last frag before inserting the new item in the chain */
  62. + if (item->frag_last) {
  63. + /* if we have the last fragment, indices must match */
  64. + if (iph1->frag_last_index != 0 &&
  65. + item->frag_last != iph1->frag_last_index) {
  66. + plog(LLV_ERROR, LOCATION, NULL,
  67. + "Repeated last fragment index mismatch\n");
  68. + racoon_free(item);
  69. + vfree(buf);
  70. + return -1;
  71. + }
  72. - if (iph1->frag_chain == NULL) {
  73. - iph1->frag_chain = item;
  74. - } else {
  75. - struct isakmp_frag_item *current;
  76. + last_frag = iph1->frag_last_index = item->frag_num;
  77. + }
  78. - current = iph1->frag_chain;
  79. - while (current->frag_next) {
  80. - if (current->frag_last)
  81. - last_frag = item->frag_num;
  82. - current = current->frag_next;
  83. - }
  84. - current->frag_next = item;
  85. + /* insert fragment into chain */
  86. + if (isakmp_frag_insert(iph1, item) == -1) {
  87. + plog(LLV_ERROR, LOCATION, NULL,
  88. + "Repeated fragment index mismatch\n");
  89. + racoon_free(item);
  90. + vfree(buf);
  91. + return -1;
  92. }
  93. - /* If we saw the last frag, check if the chain is complete */
  94. + /* If we saw the last frag, check if the chain is complete
  95. + * we have a sorted list now, so just walk through */
  96. if (last_frag != 0) {
  97. + item = iph1->frag_chain;
  98. for (i = 1; i <= last_frag; i++) {
  99. - item = iph1->frag_chain;
  100. - do {
  101. - if (item->frag_num == i)
  102. - break;
  103. - item = item->frag_next;
  104. - } while (item != NULL);
  105. -
  106. + if (item->frag_num != i)
  107. + break;
  108. + item = item->frag_next;
  109. if (item == NULL) /* Not found */
  110. break;
  111. }
  112. - if (item != NULL) /* It is complete */
  113. + if (i > last_frag) /* It is complete */
  114. return 1;
  115. }
  116. @@ -291,15 +332,9 @@ isakmp_frag_reassembly(iph1)
  117. }
  118. data = buf->v;
  119. + item = iph1->frag_chain;
  120. for (i = 1; i <= frag_count; i++) {
  121. - item = iph1->frag_chain;
  122. - do {
  123. - if (item->frag_num == i)
  124. - break;
  125. - item = item->frag_next;
  126. - } while (item != NULL);
  127. -
  128. - if (item == NULL) {
  129. + if (item->frag_num != i) {
  130. plog(LLV_ERROR, LOCATION, NULL,
  131. "Missing fragment #%d\n", i);
  132. vfree(buf);
  133. @@ -308,6 +343,7 @@ isakmp_frag_reassembly(iph1)
  134. }
  135. memcpy(data, item->frag_packet->v, item->frag_packet->l);
  136. data += item->frag_packet->l;
  137. + item = item->frag_next;
  138. }
  139. out:
  140. Index: ipsec-tools-0.8.2/src/racoon/isakmp_inf.c
  141. ===================================================================
  142. --- ipsec-tools-0.8.2.orig/src/racoon/isakmp_inf.c
  143. +++ ipsec-tools-0.8.2/src/racoon/isakmp_inf.c
  144. @@ -720,6 +720,7 @@ isakmp_info_send_nx(isakmp, remote, loca
  145. #endif
  146. #ifdef ENABLE_FRAG
  147. iph1->frag = 0;
  148. + iph1->frag_last_index = 0;
  149. iph1->frag_chain = NULL;
  150. #endif
  151. Index: ipsec-tools-0.8.2/src/racoon/isakmp.c
  152. ===================================================================
  153. --- ipsec-tools-0.8.2.orig/src/racoon/isakmp.c
  154. +++ ipsec-tools-0.8.2/src/racoon/isakmp.c
  155. @@ -1071,6 +1071,7 @@ isakmp_ph1begin_i(rmconf, remote, local)
  156. iph1->frag = 1;
  157. else
  158. iph1->frag = 0;
  159. + iph1->frag_last_index = 0;
  160. iph1->frag_chain = NULL;
  161. #endif
  162. iph1->approval = NULL;
  163. @@ -1175,6 +1176,7 @@ isakmp_ph1begin_r(msg, remote, local, et
  164. #endif
  165. #ifdef ENABLE_FRAG
  166. iph1->frag = 0;
  167. + iph1->frag_last_index = 0;
  168. iph1->frag_chain = NULL;
  169. #endif
  170. iph1->approval = NULL;
  171. Index: ipsec-tools-0.8.2/src/racoon/handler.h
  172. ===================================================================
  173. --- ipsec-tools-0.8.2.orig/src/racoon/handler.h
  174. +++ ipsec-tools-0.8.2/src/racoon/handler.h
  175. @@ -1,4 +1,4 @@
  176. -/* $NetBSD: handler.h,v 1.25 2010/11/17 10:40:41 tteras Exp $ */
  177. +/* $NetBSD: handler.h,v 1.26 2017/01/24 19:23:56 christos Exp $ */
  178. /* Id: handler.h,v 1.19 2006/02/25 08:25:12 manubsd Exp */
  179. @@ -141,6 +141,7 @@ struct ph1handle {
  180. #endif
  181. #ifdef ENABLE_FRAG
  182. int frag; /* IKE phase 1 fragmentation */
  183. + int frag_last_index;
  184. struct isakmp_frag_item *frag_chain; /* Received fragments */
  185. #endif