This diff from hshoexer@ some time ago fixes the encapsulation mode
used in NAT-T negotiations. Mitja has been running this for ages,
I need it too, and it makes sense to have it seen by more people and
in the list archives for people who need it until it can be fixed
in tree.

Currently we always send "ENCAPSULATION_MODE = TUNNEL" even for a
NAT-T exchange, which is totally wrong.

The RFC-compliant attribute to send would be "ENCAPSULATION_MODE =
UDP_ENCAP_TUNNEL" but this does not have wide vendor support,
actually we need to use 61443 (UDP_ENCAP_TUNNEL_DRAFT).

This diff doesn't affect interoperability with OpenBSD but without
it, it's not possible to make a NAT-T connection with Cisco ASA
(seen some time ago, but still occurs with current firmware).

Without the diff this is seen in crypto debug logging on the ASA:

Aug 04 08:24:48 [IKEv1]Phase 2 failure:  Mismatched attribute types for class 
Encapsulation Mode:  Rcv'd: Tunnel  Cfg'd: UDP Tunnel(NAT-T)

With a diff using UDP_ENCAP_TUNNEL:

Aug 04 08:29:32 [IKEv1]Phase 2 failure:  Mismatched attribute types for class 
Encapsulation Mode:  Rcv'd: UDP Tunnel(NAT-T)  Cfg'd: UDP Tunnel(NAT-T)

(yeah, obviously a cisco bug as they should accept either the draft
or RFC value, but it's years old and still present in current versions;
even if they do fix it sometime, you need paid support to get new
software for these boxes so often people will not upgrade them).


With the diff below, all is OK, sessions come up correctly.


# sh ver

Cisco Adaptive Security Appliance Software Version 8.4(1) 
Device Manager Version 6.4(1)

Compiled on Mon 31-Jan-11 02:11 by builders
System image file is "disk0:/asa841-k8.bin"
Config file at boot was "startup-config"

vpn4-pl7 up 19 hours 11 mins

Hardware:   ASA5505, 512 MB RAM, CPU Geode 500 MHz
Internal ATA Compact Flash, 128MB
BIOS Flash M50FW016 @ 0xfff00000, 2048KB

(note to IPsec hackers: if you need gear to test interop with cisco,
the basic ASA 5505 licensed for 10 IPsec tunnels is pretty inexpensive).


Index: attribute.c
===================================================================
RCS file: /cvs/src/sbin/isakmpd/attribute.c,v
retrieving revision 1.12
diff -u -p -r1.12 attribute.c
--- attribute.c 8 Apr 2005 22:32:09 -0000       1.12
+++ attribute.c 4 Aug 2011 08:31:13 -0000
@@ -37,6 +37,9 @@
 #include "log.h"
 #include "isakmp.h"
 #include "util.h"
+#if 1  /* XXX hshoexer */
+#include "sa.h"
+#endif
 
 u_int8_t *
 attribute_set_basic(u_int8_t *buf, u_int16_t type, u_int16_t value)
@@ -108,3 +111,30 @@ attribute_set_constant(char *section, ch
        *attr = attribute_set_basic(*attr, attr_class, value);
        return 0;
 }
+
+#if 1  /* XXX hshoexer */
+int
+attribute_set_encap(char *section, char *tag, struct constant_map *map,
+    int attr_class, u_int8_t **attr, u_int32_t flags)
+{
+       char    *name;
+       int      value;
+
+       name = conf_get_str(section, tag);
+       if (!name) {
+               LOG_DBG((LOG_MISC, 70,
+                   "attribute_set_constant: no %s in the %s section", tag,
+                   section));
+               return -1;
+       }
+       if (flags & SA_FLAG_NAT_T_ENABLE) {
+               if (strcmp(name, "TUNNEL") == 0)
+                       name = "UDP_ENCAP_TUNNEL_DRAFT";
+               else if (strcmp(name, "TRANSPORT") == 0)
+                       name = "UDP_ENCAP_TRANSPORT_DRAFT";
+       }
+       value = constant_value(map, name);
+       *attr = attribute_set_basic(*attr, attr_class, value);
+       return 0;
+}
+#endif
Index: attribute.h
===================================================================
RCS file: /cvs/src/sbin/isakmpd/attribute.h,v
retrieving revision 1.6
diff -u -p -r1.6 attribute.h
--- attribute.h 14 May 2004 08:42:56 -0000      1.6
+++ attribute.h 4 Aug 2011 08:31:13 -0000
@@ -41,6 +41,10 @@ extern int    attribute_map(u_int8_t *, si
 extern u_int8_t        *attribute_set_basic(u_int8_t *, u_int16_t, u_int16_t);
 extern int      attribute_set_constant(char *, char *, struct constant_map *,
                     int, u_int8_t **);
+#if 1  /* XXX hshoexer */
+extern int      attribute_set_encap(char *, char *, struct constant_map *,
+                    int, u_int8_t **, u_int32_t);
+#endif
 extern u_int8_t        *attribute_set_var(u_int8_t *, u_int16_t, u_int8_t *,
                     u_int16_t);
 
Index: ike_quick_mode.c
===================================================================
RCS file: /cvs/src/sbin/isakmpd/ike_quick_mode.c,v
retrieving revision 1.106
diff -u -p -r1.106 ike_quick_mode.c
--- ike_quick_mode.c    23 Apr 2011 03:17:04 -0000      1.106
+++ ike_quick_mode.c    4 Aug 2011 08:31:13 -0000
@@ -621,9 +621,16 @@ initiator_send_HASH_SA_NONCE(struct mess
                                        }
                                        conf_free_list(life_conf);
                                }
+#if 1  /* XXX hshoexer */
+                               attribute_set_encap(xf->field,
+                                   "ENCAPSULATION_MODE", ipsec_encap_cst,
+                                   IPSEC_ATTR_ENCAPSULATION_MODE, &attr,
+                                   msg->isakmp_sa->flags);
+#else
                                attribute_set_constant(xf->field,
                                    "ENCAPSULATION_MODE", ipsec_encap_cst,
                                    IPSEC_ATTR_ENCAPSULATION_MODE, &attr);
+#endif
 
                                if (proto_id != IPSEC_PROTO_IPCOMP) {
                                        attribute_set_constant(xf->field,

Reply via email to