Hello all,

if I enable NAT-T support with "./configure --enable-natt", but without putting the directive "nat_traversal on" in the config file, racoon doesn't succeed in negotiating SAs in transport mode with ah between two hosts connected by a crossover cable.

Here come setkey and racoon confs for both sides :

* on the initiator side :
spdadd 192.168.0.1/32 192.168.0.2/32 any -P out ipsec ah/transport//unique;
spdadd 192.168.0.2/32 192.168.0.1/32 any -P in ipsec ah/transport//unique;

and

path pre_shared_key "/root/psk.set";

remote 192.168.0.2
{
       exchange_mode main,base,aggressive;

       my_identifier address 192.168.0.1;

       lifetime time 16 hour ;

       proposal {
          encryption_algorithm des ;
          hash_algorithm md5 ;
          authentication_method pre_shared_key ;
          dh_group 1 ;
      }

}

sainfo address 192.168.0.1/32 any address 192.168.0.2/32 any
{
        pfs_group 1;
        lifetime time 8 hour;
        encryption_algorithm des;
        authentication_algorithm hmac_md5;
        compression_algorithm deflate;
}



* on the responder side :
spdadd 192.168.0.2/32 192.168.0.1/32 any -P out ipsec ah/transport//unique;
spdadd 192.168.0.1/32 192.168.0.2/32 any -P in ipsec ah/transport//unique;

and

path pre_shared_key "/root/psk.set";

remote 192.168.0.1
{
       exchange_mode main,base,aggressive;

       my_identifier address 192.168.0.2;

       lifetime time 16 hour ;

       proposal {
          encryption_algorithm des ;
          hash_algorithm md5 ;
          authentication_method pre_shared_key ;
          dh_group 1 ;
      }

}

sainfo address 192.168.0.2/32 any address 192.168.0.1/32 any
{
        pfs_group 1;
        lifetime time 8 hour;
        encryption_algorithm des;
        authentication_algorithm hmac_md5;
        compression_algorithm deflate;
}


Here come the debug messages I get when launching racoon with -vvv :

* on the initiator side :
2007-06-20 17:04:12: INFO: @(#)ipsec-tools 0.6.6 (http://ipsec-tools.sourceforge.net)
2007-06-20 17:04:12: INFO: @(#)This product linked OpenSSL 0.9.8a 11 Oct 2005 (http://www.openssl.org/)
2007-06-20 17:04:13: INFO: 127.0.0.1[500] used as isakmp port (fd=5)
2007-06-20 17:04:13: INFO: 127.0.0.1[500] used for NAT-T
2007-06-20 17:04:13: INFO: 192.168.0.1[500] used as isakmp port (fd=6)
2007-06-20 17:04:13: INFO: 192.168.0.1[500] used for NAT-T
2007-06-20 17:04:13: INFO: 10.16.0.111[500] used as isakmp port (fd=7)
2007-06-20 17:04:13: INFO: 10.16.0.111[500] used for NAT-T
2007-06-20 17:04:13: INFO: ::1[500] used as isakmp port (fd=8)
2007-06-20 17:04:13: INFO: fe80::250:fcff:fe4c:b50%eth2[500] used as isakmp port (fd=9)
2007-06-20 17:04:13: INFO: 2001:660:3008:c1c3:250:fcff:fe21:7c01[500] used as isakmp port (fd=10)
2007-06-20 17:04:13: INFO: fe80::250:fcff:fe21:7c01%eth0[500] used as isakmp port (fd=11)
2007-06-20 17:04:39: INFO: IPsec-SA request for 192.168.0.2 queued due to no phase1 found.
2007-06-20 17:04:39: INFO: initiate new phase 1 negotiation: 192.168.0.1[500]<=>192.168.0.2[500]
2007-06-20 17:04:39: INFO: begin Identity Protection mode.
2007-06-20 17:04:39: INFO: ISAKMP-SA established 192.168.0.1[500]-192.168.0.2[500] spi:eb562b5ff3a22756:e276f93e9ea0bc00
2007-06-20 17:04:40: INFO: initiate new phase 2 negotiation: 192.168.0.1[500]<=>192.168.0.2[500]


* on the responder side :
2007-06-20 17:00:25: INFO: @(#)ipsec-tools 0.6.6 (http://ipsec-tools.sourceforge.net)
2007-06-20 17:00:25: INFO: @(#)This product linked OpenSSL 0.9.8a 11 Oct 2005 (http://www.openssl.org/)
2007-06-20 17:00:26: INFO: 127.0.0.1[500] used as isakmp port (fd=5)
2007-06-20 17:00:26: INFO: 127.0.0.1[500] used for NAT-T
2007-06-20 17:00:26: INFO: 10.16.0.112[500] used as isakmp port (fd=6)
2007-06-20 17:00:26: INFO: 10.16.0.112[500] used for NAT-T
2007-06-20 17:00:26: INFO: 192.168.0.2[500] used as isakmp port (fd=7)
2007-06-20 17:00:26: INFO: 192.168.0.2[500] used for NAT-T
2007-06-20 17:00:26: INFO: ::1[500] used as isakmp port (fd=8)
2007-06-20 17:00:26: INFO: 2001:660:3008:c1c3:210:5aff:fe64:cb2b[500] used as isakmp port (fd=9)
2007-06-20 17:00:26: INFO: fe80::210:5aff:fe64:cb2b%eth0[500] used as isakmp port (fd=10)
2007-06-20 17:00:26: INFO: fe80::2b0:d0ff:fe65:e5ee%eth1[500] used as isakmp port (fd=11)
2007-06-20 17:00:35: INFO: respond new phase 1 negotiation: 192.168.0.2[500]<=>192.168.0.1[500]
2007-06-20 17:00:35: INFO: begin Identity Protection mode.
2007-06-20 17:00:35: INFO: ISAKMP-SA established 192.168.0.2[500]-192.168.0.1[500] spi:eb562b5ff3a22756:e276f93e9ea0bc00
2007-06-20 17:00:36: INFO: respond new phase 2 negotiation: 192.168.0.2[500]<=>192.168.0.1[500]
2007-06-20 17:00:36: ERROR: failed to get sainfo.
2007-06-20 17:00:36: ERROR: failed to get sainfo.
2007-06-20 17:00:36: ERROR: failed to pre-process packet.
2007-06-20 17:00:46: INFO: respond new phase 2 negotiation: 192.168.0.2[500]<=>192.168.0.1[500]
2007-06-20 17:00:46: ERROR: failed to get sainfo.
2007-06-20 17:00:46: ERROR: failed to get sainfo.
2007-06-20 17:00:46: ERROR: failed to pre-process packet.

I've found where this bug comes from :

* there are a lot of #ifndef ENABLE_NATT blocks where ports are not set to 0 anymore if ENABLE_NATT is set, in particular in isakmp.c: isakmp_ph2begin_r() where iph2->dst->sin_port and iph2->src->sin_port aren't set to 0 anymore.

* then the responder calls isakmp_quick.c:quick_r1recv(), which then calls isakmp_quick.c:get_sainfo_r(), ul_proto is any so iph2->id_p == NULL and iph2->id == NULL, and idsrc and iddst are set respectively to
ipsecdoi_sockaddr2id(iph2->src, prefixlen, IPSEC_ULPROTO_ANY);   and
ipsecdoi_sockaddr2id(iph2->dst, prefixlen, IPSEC_ULPROTO_ANY);

* iph2->src and iph2->dst ports are not set to 0 anymore so their value is 500, then the port field of struct ipsec_doi_b is set to 500

* then isakmp_quick.c:get_sainfo_r() calls sainfo.c:getsainfo() passing the return values of the two ipsecdoi_sockaddr2id as parameter 1 and 2 of getsainfo()

* in getsainfo(), when memcmp()'ing src->v with s->idsrc->v and dst->v with s->iddst->v, idsrc and iddst being sainfos of conf file, ports 500 are compared with ports 0 and memcmp fails

I think I have a little patch to fix this bug, at least a workaround ;-)   :
substitute this piece of code in ipsecdoi_sockaddr2id() :

((struct ipsecdoi_id_b *)new->v)->port = port == IPSEC_PORT_ANY ? 0 : port;

with :

if (ul_proto == IPSEC_ULPROTO_ANY) {
           ((struct ipsecdoi_id_b *)new->v)->port = 0;
}
else {
           ((struct ipsecdoi_id_b *)new->v)->port =
           port == IPSEC_PORT_ANY ? 0 : port;
}


Any comment would be appreciated.

Best regards,
  François-Gérard Radet