trac#301: fixed IPsec SAs flush in purge_remote() when NAT-T enabled but no NAT-T on tunnel

This commit is contained in:
vanhu 2009-02-11 15:18:59 +00:00
parent cdc8049f5c
commit 3723c0b8cf
3 changed files with 85 additions and 3 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: isakmp.c,v 1.50 2009/02/03 20:21:45 tteras Exp $ */
/* $NetBSD: isakmp.c,v 1.51 2009/02/11 15:18:59 vanhu Exp $ */
/* Id: isakmp.c,v 1.74 2006/05/07 21:32:59 manubsd Exp */
@ -3322,12 +3322,22 @@ purge_remote(iph1)
* check in/outbound SAs.
* Select only SAs where src == local and dst == remote (outgoing)
* or src == remote and dst == local (incoming).
* XXX we sometime have src/dst ports set to 0 and want to match
* iph1->local/remote with ports set to 500. This is a bug, see trac:2
*/
#ifdef ENABLE_NATT
if ((cmpsaddrmagic(iph1->local, src) || cmpsaddrmagic(iph1->remote, dst)) &&
(cmpsaddrmagic(iph1->local, dst) || cmpsaddrmagic(iph1->remote, src))) {
msg = next;
continue;
}
#else
if ((CMPSADDR(iph1->local, src) || CMPSADDR(iph1->remote, dst)) &&
(CMPSADDR(iph1->local, dst) || CMPSADDR(iph1->remote, src))) {
msg = next;
continue;
}
#endif
proto_id = pfkey2ipsecdoi_proto(msg->sadb_msg_satype);
iph2 = getph2bysaidx(src, dst, proto_id, sa->sadb_sa_spi);

View File

@ -1,4 +1,4 @@
/* $NetBSD: sockmisc.c,v 1.12 2008/09/03 09:57:28 tteras Exp $ */
/* $NetBSD: sockmisc.c,v 1.13 2009/02/11 15:18:59 vanhu Exp $ */
/* Id: sockmisc.c,v 1.24 2006/05/07 21:32:59 manubsd Exp */
@ -63,6 +63,7 @@
#include "gcmalloc.h"
#include "debugrm.h"
#include "libpfkey.h"
#include "isakmp_var.h"
#ifdef NOUSE_PRIVSEP
#define BIND bind
@ -196,6 +197,76 @@ cmpsaddrwild(addr1, addr2)
return 0;
}
/*
* compare two sockaddr with port, taking care specific situation:
* one addr has 0 as port, and the other has 500 (network order), return equal
* OUT: 0: equal.
* 1: not equal.
*/
int
cmpsaddrmagic(addr1, addr2)
const struct sockaddr *addr1;
const struct sockaddr *addr2;
{
caddr_t sa1, sa2;
u_short port1, port2;
if (addr1 == 0 && addr2 == 0)
return 0;
if (addr1 == 0 || addr2 == 0)
return 1;
#ifdef __linux__
if (addr1->sa_family != addr2->sa_family)
return 1;
#else
if (addr1->sa_len != addr2->sa_len
|| addr1->sa_family != addr2->sa_family)
return 1;
#endif /* __linux__ */
switch (addr1->sa_family) {
case AF_INET:
sa1 = (caddr_t)&((struct sockaddr_in *)addr1)->sin_addr;
sa2 = (caddr_t)&((struct sockaddr_in *)addr2)->sin_addr;
port1 = ((struct sockaddr_in *)addr1)->sin_port;
port2 = ((struct sockaddr_in *)addr2)->sin_port;
plog(LLV_DEBUG, LOCATION, NULL, "cmpsaddr_magic: port1 == %d, port2 == %d\n", port1, port2);
if (!((port1 == IPSEC_PORT_ANY && port2 == ntohs(PORT_ISAKMP)) ||
(port2 == IPSEC_PORT_ANY && port1 == ntohs(PORT_ISAKMP)) ||
(port1 == port2))){
plog(LLV_DEBUG, LOCATION, NULL, "cmpsaddr_magic: ports mismatch\n");
return 1;
}
plog(LLV_DEBUG, LOCATION, NULL, "cmpsaddr_magic: ports matched\n");
if (memcmp(sa1, sa2, sizeof(struct in_addr)) != 0)
return 1;
break;
#ifdef INET6
case AF_INET6:
sa1 = (caddr_t)&((struct sockaddr_in6 *)addr1)->sin6_addr;
sa2 = (caddr_t)&((struct sockaddr_in6 *)addr2)->sin6_addr;
port1 = ((struct sockaddr_in6 *)addr1)->sin6_port;
port2 = ((struct sockaddr_in6 *)addr2)->sin6_port;
if (!((port1 == IPSEC_PORT_ANY && port2 == PORT_ISAKMP) ||
(port2 == IPSEC_PORT_ANY && port1 == PORT_ISAKMP) ||
(port1 == port2)))
return 1;
if (memcmp(sa1, sa2, sizeof(struct in6_addr)) != 0)
return 1;
if (((struct sockaddr_in6 *)addr1)->sin6_scope_id !=
((struct sockaddr_in6 *)addr2)->sin6_scope_id)
return 1;
break;
#endif
default:
return 1;
}
return 0;
}
/*
* compare two sockaddr with strict match on port.
* OUT: 0: equal.

View File

@ -1,4 +1,4 @@
/* $NetBSD: sockmisc.h,v 1.8 2008/04/02 19:02:50 manu Exp $ */
/* $NetBSD: sockmisc.h,v 1.9 2009/02/11 15:18:59 vanhu Exp $ */
/* Id: sockmisc.h,v 1.9 2005/10/05 16:55:41 manubsd Exp */
@ -57,6 +57,7 @@ extern const int niflags;
extern int cmpsaddrwop __P((const struct sockaddr *, const struct sockaddr *));
extern int cmpsaddrwild __P((const struct sockaddr *, const struct sockaddr *));
extern int cmpsaddrstrict __P((const struct sockaddr *, const struct sockaddr *));
extern int cmpsaddrmagic __P((const struct sockaddr *, const struct sockaddr *));
#ifdef ENABLE_NATT
#define CMPSADDR(saddr1, saddr2) cmpsaddrstrict((saddr1), (saddr2))