[Openswan dev] Re: [PATCH] Openswan and OS X with NAT-T
Peter Van der Beken
peterv at propagandism.org
Thu Sep 29 01:19:04 CEST 2005
Michael Richardson wrote:
> Paul> NAT-Traversal: Result using RFC 3947 (NAT-Traversal):
> Paul> both are NATed
>
> It means that the hash on the server side ports/data is wrong.
> Apple probably screwed that up too. I'm disinclined to ship the patch
> based upon that knowledge.
Bah! Looking at the debugging info on both ends confirms that they
inverted the messages for the hashes, they send the hash for the local
side first and then the hash for the remote side, whereas the RFC
specifies that the receiver should get the local side first and then the
remote side. I attached an updated patch that handles this bug too
(still 2.3.1, sorry!). It's getting uglier with every iteration :-(.
I do think that http://bugs.xelerance.com/view.php?id=442 is right, in
nat_traversal_add_natd the hash for the second packet is computed using
&(md->iface->ip_addr) and ntohs(st->st_remoteport), I think that last
one should be ntohs(st->st_localport).
Peter
-------------- next part --------------
diff -ru openswan-2.3.1.orig/include/ietf_constants.h openswan-2.3.1/include/ietf_constants.h
--- openswan-2.3.1.orig/include/ietf_constants.h 2005-03-21 04:54:42.000000000 +0100
+++ openswan-2.3.1/include/ietf_constants.h 2005-09-27 00:50:20.000000000 +0200
@@ -270,6 +270,8 @@
#define ISAKMP_NEXT_D 12 /* Delete */
#define ISAKMP_NEXT_VID 13 /* Vendor ID */
#define ISAKMP_NEXT_ATTR 14 /* Mode config Attribute */
+#define ISAKMP_NEXT_NATD_BADDRAFTS 15 /* NAT-Traversal: NAT-D (bad drafts) */
+ /* !!! Conflicts with RFC 3547 */
#define ISAKMP_NEXT_NATD_RFC 20 /* NAT-Traversal: NAT-D (rfc) */
#define ISAKMP_NEXT_NATOA_RFC 21 /* NAT-Traversal: NAT-OA (rfc) */
#define ISAKMP_NEXT_ROOF 22 /* roof on payload types */
diff -ru openswan-2.3.1.orig/lib/libopenswan/constants.c openswan-2.3.1/lib/libopenswan/constants.c
--- openswan-2.3.1.orig/lib/libopenswan/constants.c 2005-01-23 19:53:35.000000000 +0100
+++ openswan-2.3.1/lib/libopenswan/constants.c 2005-09-27 00:50:20.000000000 +0200
@@ -123,7 +123,7 @@
"ISAKMP_NEXT_D",
"ISAKMP_NEXT_VID",
"ISAKMP_NEXT_MODECFG", /* 14 */
- "ISAKMP_NEXT_15",
+ "ISAKMP_NEXT_NAT-D",
"ISAKMP_NEXT_16",
"ISAKMP_NEXT_17",
"ISAKMP_NEXT_18",
@@ -916,9 +916,9 @@
const char *const natt_type_bitnames[] = {
"draft-ietf-ipsec-nat-t-ike-00/01", /* 0 */
"draft-ietf-ipsec-nat-t-ike-02/03",
+ "draft-ietf-ipsec-nat-t-ike (OS X)",
"RFC 3947 (NAT-Traversal)",
- "3", /* 3 */
- "4", "5", "6", "7",
+ "4", "5", "6", "7", /* 4 */
"8", "9", "10", "11",
"12", "13", "14", "15",
"16", "17", "18", "19",
diff -ru openswan-2.3.1.orig/programs/pluto/demux.c openswan-2.3.1/programs/pluto/demux.c
--- openswan-2.3.1.orig/programs/pluto/demux.c 2005-03-21 05:01:52.000000000 +0100
+++ openswan-2.3.1/programs/pluto/demux.c 2005-09-27 00:50:20.000000000 +0200
@@ -2029,6 +2029,16 @@
np = ISAKMP_NEXT_NATOA_RFC; /* NAT-OA relocated */
sd = payload_descs[np];
break;
+ case ISAKMP_NEXT_NATD_BADDRAFTS:
+ if (st && (st->hidden_variables.st_nat_traversal & NAT_T_WITH_NATD_BADDRAFT_VALUES)) {
+ /*
+ * Only accept this value if we're in compatibility mode with
+ * the bad drafts of the RFC
+ */
+ np = ISAKMP_NEXT_NATD_RFC; /* NAT-D relocated */
+ sd = payload_descs[np];
+ break;
+ }
#endif
default:
loglog(RC_LOG_SERIOUS, "%smessage ignored because it contains an unknown or"
diff -ru openswan-2.3.1.orig/programs/pluto/nat_traversal.c openswan-2.3.1/programs/pluto/nat_traversal.c
--- openswan-2.3.1.orig/programs/pluto/nat_traversal.c 2005-03-21 00:16:16.000000000 +0100
+++ openswan-2.3.1/programs/pluto/nat_traversal.c 2005-09-28 22:06:42.000000000 +0200
@@ -211,6 +211,9 @@
case VID_NATT_IETF_03:
return LELEM(NAT_TRAVERSAL_IETF_02_03);
break;
+ case VID_NATT_DRAFT_IETF_IPSEC_NAT_T_IKE:
+ return LELEM(NAT_TRAVERSAL_OSX);
+ break;
case VID_NATT_RFC:
return LELEM(NAT_TRAVERSAL_RFC);
break;
@@ -224,6 +227,10 @@
struct payload_digest *p;
struct state *st = md->st;
int i;
+ u_int32_t first_type, other_type;
+ const ip_address *first_ip, *other_ip;
+ u_int16_t first_port, other_port;
+ bool invert = (st->hidden_variables.st_nat_traversal & LELEM(NAT_TRAVERSAL_OSX));
if (!st || !md->iface || !st->st_oakley.hasher) {
loglog(RC_LOG_SERIOUS, "NAT-Traversal: assert failed %s:%d",
@@ -247,34 +254,59 @@
}
/**
- * First one with my IP & port
+ * First one with my IP & port to detect NAT behind me
+ */
+ first_type = LELEM(NAT_TRAVERSAL_NAT_BHND_ME);
+ first_ip = &(md->iface->addr);
+ first_port = ntohs(st->st_localport);
+
+ /**
+ * Others with sender IP & port to detect NAT behind peer
*/
+ other_type = LELEM(NAT_TRAVERSAL_NAT_BHND_PEER);
+ other_ip = &(md->sender);
+ other_port = ntohs(md->sender_port);
+
+ if (invert) {
+ /**
+ * Apple's OS X implementation is broken, they inverted the messages.
+ */
+ u_int32_t type = other_type;
+ const ip_address *ip = other_ip;
+ u_int16_t port = other_port;
+
+ other_type = first_type;
+ other_ip = first_ip;
+ other_port = first_port;
+ first_type = type;
+ first_ip = ip;
+ first_port = port;
+ }
+
p = md->chain[ISAKMP_NEXT_NATD_RFC];
_natd_hash(st->st_oakley.hasher, hash
, st->st_icookie, st->st_rcookie
- , &(md->iface->addr)
- , ntohs(st->st_localport));
+ , first_ip
+ , first_port);
if (!( (pbs_left(&p->pbs) == st->st_oakley.hasher->hash_digest_len)
&& (memcmp(p->pbs.cur, hash, st->st_oakley.hasher->hash_digest_len)==0)))
{
#ifdef NAT_D_DEBUG
DBG(DBG_NATT,
- DBG_log("NAT_TRAVERSAL_NAT_BHND_ME");
+ DBG_log(invert ? "NAT_TRAVERSAL_NAT_BHND_PEER" : "NAT_TRAVERSAL_NAT_BHND_ME");
DBG_dump("expected NAT-D:", hash,
st->st_oakley.hasher->hash_digest_len);
DBG_dump("received NAT-D:", p->pbs.cur, pbs_left(&p->pbs));
);
#endif
- st->hidden_variables.st_nat_traversal |= LELEM(NAT_TRAVERSAL_NAT_BHND_ME);
+ st->hidden_variables.st_nat_traversal |= first_type;
}
- /**
- * The others with sender IP & port
- */
_natd_hash(st->st_oakley.hasher, hash
, st->st_icookie, st->st_rcookie
- , &(md->sender), ntohs(md->sender_port));
+ , other_ip
+ , other_port);
for (p = p->next, i=0 ; p != NULL; p = p->next) {
if ( (pbs_left(&p->pbs) == st->st_oakley.hasher->hash_digest_len)
@@ -288,7 +320,7 @@
if (!i) {
#ifdef NAT_D_DEBUG
DBG(DBG_NATT,
- DBG_log("NAT_TRAVERSAL_NAT_BHND_PEER");
+ DBG_log(invert ? "NAT_TRAVERSAL_NAT_BHND_ME" : "NAT_TRAVERSAL_NAT_BHND_PEER");
DBG_dump("expected NAT-D:", hash,
st->st_oakley.hasher->hash_digest_len);
p = md->chain[ISAKMP_NEXT_NATD_RFC];
@@ -297,7 +329,7 @@
}
);
#endif
- st->hidden_variables.st_nat_traversal |= LELEM(NAT_TRAVERSAL_NAT_BHND_PEER);
+ st->hidden_variables.st_nat_traversal |= other_type;
}
st->hidden_variables.st_natd = md->sender;
@@ -314,6 +346,8 @@
char hash[MAX_DIGEST_LEN];
struct state *st = md->st;
unsigned int nat_np;
+ const ip_address *first_ip, *second_ip;
+ u_int16_t first_port, second_port;
if (!st || !st->st_oakley.hasher) {
loglog(RC_LOG_SERIOUS, "NAT-Traversal: assert failed %s:%d",
@@ -324,7 +358,9 @@
DBG(DBG_EMITTING, DBG_log("sending NATD payloads"));
nat_np = (st->hidden_variables.st_nat_traversal & NAT_T_WITH_RFC_VALUES
- ? ISAKMP_NEXT_NATD_RFC : ISAKMP_NEXT_NATD_DRAFTS);
+ ? ISAKMP_NEXT_NATD_RFC
+ : (st->hidden_variables.st_nat_traversal & NAT_T_WITH_NATD_BADDRAFT_VALUES
+ ? ISAKMP_NEXT_NATD_BADDRAFTS : ISAKMP_NEXT_NATD_DRAFTS));
if (!out_modify_previous_np(nat_np, outs)) {
return FALSE;
}
@@ -332,17 +368,36 @@
/**
* First one with sender IP & port
*/
+ first_ip = &(md->sender);
+ first_port = ntohs(md->sender_port);
+
+ /**
+ * Second one with my IP & port
+ */
+ second_ip = &(md->iface->addr);
+ second_port = ntohs(st->st_localport);
+
+ if (st->hidden_variables.st_nat_traversal & LELEM(NAT_TRAVERSAL_OSX)) {
+ const ip_address *ip = second_ip;
+ u_int16_t port = second_port;
+
+ second_ip = first_ip;
+ second_port = first_port;
+ first_ip = ip;
+ first_port = port;
+ }
+
if(st->st_connection->forceencaps) {
_natd_hash(st->st_oakley.hasher
, hash, st->st_icookie
, is_zero_cookie(st->st_rcookie) ? md->hdr.isa_rcookie : st->st_rcookie
- , &(md->sender)
+ , first_ip
, 0);
} else {
_natd_hash(st->st_oakley.hasher, hash, st->st_icookie
, is_zero_cookie(st->st_rcookie) ? md->hdr.isa_rcookie : st->st_rcookie
- , &(md->sender)
- , ntohs(md->sender_port));
+ , first_ip
+ , first_port);
}
if (!out_generic_raw(nat_np, &isakmp_nat_d, outs
@@ -352,20 +407,18 @@
return FALSE;
}
- /**
- * Second one with my IP & port
- */
if(st->st_connection->forceencaps) {
_natd_hash(st->st_oakley.hasher, hash
, st->st_icookie
, is_zero_cookie(st->st_rcookie) ? md->hdr.isa_rcookie : st->st_rcookie
- , &(md->iface->addr),0);
+ , second_ip
+ , 0);
} else {
_natd_hash(st->st_oakley.hasher, hash
, st->st_icookie
, is_zero_cookie(st->st_rcookie) ? md->hdr.isa_rcookie : st->st_rcookie
- , &(md->iface->addr)
- , ntohs(st->st_remoteport));
+ , second_ip
+ , second_port);
}
return (out_generic_raw(np, &isakmp_nat_d, outs,
hash, st->st_oakley.hasher->hash_digest_len, "NAT-D"));
@@ -541,9 +594,12 @@
case LELEM(NAT_TRAVERSAL_IETF_02_03):
mth = natt_type_bitnames[1];
break;
- case LELEM(NAT_TRAVERSAL_RFC):
+ case LELEM(NAT_TRAVERSAL_OSX):
mth = natt_type_bitnames[2];
break;
+ case LELEM(NAT_TRAVERSAL_RFC):
+ mth = natt_type_bitnames[3];
+ break;
}
switch (nt & NAT_T_DETECTED) {
case 0:
diff -ru openswan-2.3.1.orig/programs/pluto/nat_traversal.h openswan-2.3.1/programs/pluto/nat_traversal.h
--- openswan-2.3.1.orig/programs/pluto/nat_traversal.h 2005-01-23 20:17:25.000000000 +0100
+++ openswan-2.3.1/programs/pluto/nat_traversal.h 2005-09-27 00:50:20.000000000 +0200
@@ -21,7 +21,8 @@
#define NAT_TRAVERSAL_IETF_00_01 1
#define NAT_TRAVERSAL_IETF_02_03 2
-#define NAT_TRAVERSAL_RFC 3
+#define NAT_TRAVERSAL_OSX 3
+#define NAT_TRAVERSAL_RFC 4
#define NAT_TRAVERSAL_NAT_BHND_ME 30
#define NAT_TRAVERSAL_NAT_BHND_PEER 31
@@ -33,7 +34,7 @@
*/
#define NAT_T_WITH_NATD \
( LELEM(NAT_TRAVERSAL_IETF_00_01) | LELEM(NAT_TRAVERSAL_IETF_02_03) | \
- LELEM(NAT_TRAVERSAL_RFC) )
+ LELEM(NAT_TRAVERSAL_OSX) | LELEM(NAT_TRAVERSAL_RFC) )
/**
* NAT-Traversal methods which need NAT-OA
*/
@@ -45,12 +46,20 @@
*/
#define NAT_T_WITH_KA \
( LELEM(NAT_TRAVERSAL_IETF_00_01) | LELEM(NAT_TRAVERSAL_IETF_02_03) | \
- LELEM(NAT_TRAVERSAL_RFC) )
+ LELEM(NAT_TRAVERSAL_OSX) | LELEM(NAT_TRAVERSAL_RFC) )
/**
* NAT-Traversal methods which use floating port
*/
#define NAT_T_WITH_PORT_FLOATING \
- ( LELEM(NAT_TRAVERSAL_IETF_02_03) | LELEM(NAT_TRAVERSAL_RFC) )
+ ( LELEM(NAT_TRAVERSAL_IETF_02_03) | LELEM(NAT_TRAVERSAL_OSX) | \
+ LELEM(NAT_TRAVERSAL_RFC) )
+
+/**
+ * NAT-Traversal methods which use a value for NAT-D from draft versions of the
+ * RFC which conflict with values from RFC 3547
+ */
+#define NAT_T_WITH_NATD_BADDRAFT_VALUES \
+ ( LELEM(NAT_TRAVERSAL_OSX) )
/**
* NAT-Traversal methods which use officials values (RFC)
@@ -59,6 +68,12 @@
( LELEM(NAT_TRAVERSAL_RFC) )
/**
+ * NAT-Traversal methods which use officials values (RFC) for encapsulation
+ */
+#define NAT_T_WITH_ENCAPSULATION_RFC_VALUES \
+ ( LELEM(NAT_TRAVERSAL_OSX) | LELEM(NAT_TRAVERSAL_RFC) )
+
+/**
* NAT-Traversal detected
*/
#define NAT_T_DETECTED \
@@ -137,11 +152,11 @@
#define NAT_T_ENCAPSULATION_MODE(st,nat_t_policy) ( \
((st)->hidden_variables.st_nat_traversal & NAT_T_DETECTED) \
? ( ((nat_t_policy) & POLICY_TUNNEL) \
- ? ( ((st)->hidden_variables.st_nat_traversal & NAT_T_WITH_RFC_VALUES) \
+ ? ( ((st)->hidden_variables.st_nat_traversal & NAT_T_WITH_ENCAPSULATION_RFC_VALUES) \
? (ENCAPSULATION_MODE_UDP_TUNNEL_RFC) \
: (ENCAPSULATION_MODE_UDP_TUNNEL_DRAFTS) \
) \
- : ( ((st)->hidden_variables.st_nat_traversal & NAT_T_WITH_RFC_VALUES) \
+ : ( ((st)->hidden_variables.st_nat_traversal & NAT_T_WITH_ENCAPSULATION_RFC_VALUES) \
? (ENCAPSULATION_MODE_UDP_TRANSPORT_RFC) \
: (ENCAPSULATION_MODE_UDP_TRANSPORT_DRAFTS) \
) \
diff -ru openswan-2.3.1.orig/programs/pluto/spdb_struct.c openswan-2.3.1/programs/pluto/spdb_struct.c
--- openswan-2.3.1.orig/programs/pluto/spdb_struct.c 2005-02-15 02:54:20.000000000 +0100
+++ openswan-2.3.1/programs/pluto/spdb_struct.c 2005-09-27 00:50:20.000000000 +0200
@@ -1458,7 +1458,7 @@
#endif
case ENCAPSULATION_MODE_UDP_TUNNEL_DRAFTS:
- if (st->hidden_variables.st_nat_traversal & NAT_T_WITH_RFC_VALUES) {
+ if (st->hidden_variables.st_nat_traversal & NAT_T_WITH_ENCAPSULATION_RFC_VALUES) {
loglog(RC_LOG_SERIOUS,
"%s must only be used with old IETF drafts",
enum_name(&enc_mode_names, val));
@@ -1487,7 +1487,7 @@
case ENCAPSULATION_MODE_UDP_TUNNEL_RFC:
if ((st->hidden_variables.st_nat_traversal & NAT_T_DETECTED) &&
- (st->hidden_variables.st_nat_traversal & NAT_T_WITH_RFC_VALUES)) {
+ (st->hidden_variables.st_nat_traversal & NAT_T_WITH_ENCAPSULATION_RFC_VALUES)) {
attrs->encapsulation = val - ENCAPSULATION_MODE_UDP_TUNNEL_RFC + ENCAPSULATION_MODE_TUNNEL;
}
else if (st->hidden_variables.st_nat_traversal & NAT_T_DETECTED) {
diff -ru openswan-2.3.1.orig/programs/pluto/vendor.c openswan-2.3.1/programs/pluto/vendor.c
--- openswan-2.3.1.orig/programs/pluto/vendor.c 2005-09-26 01:13:27.000000000 +0200
+++ openswan-2.3.1/programs/pluto/vendor.c 2005-09-27 00:50:20.000000000 +0200
@@ -378,6 +378,7 @@
case VID_NATT_IETF_02:
case VID_NATT_IETF_02_N:
case VID_NATT_IETF_03:
+ case VID_NATT_DRAFT_IETF_IPSEC_NAT_T_IKE:
case VID_NATT_RFC:
vid_usefull = 1;
if(!nat_traversal_support_port_floating) {
More information about the Dev
mailing list