1 /* $NetBSD: nattraversal.c,v 1.6.6.1 2009/04/20 13:27:12 tteras Exp $ */
2
3 /*
4 * Copyright (C) 2004 SuSE Linux AG, Nuernberg, Germany.
5 * Contributed by: Michal Ludvig <mludvig@suse.cz>, SUSE Labs
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the project nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33 #include "config.h"
34
35 #include <sys/types.h>
36 #include <sys/param.h>
37
38 #ifdef __linux__
39 #include <linux/udp.h>
40 #endif
41 #if defined(__NetBSD__) || defined (__FreeBSD__)
42 #include <netinet/udp.h>
43 #endif
44
45 #include <stdlib.h>
46 #include <stdio.h>
47 #include <string.h>
48 #include <errno.h>
49 #include <ctype.h>
50
51 #include "var.h"
52 #include "misc.h"
53 #include "vmbuf.h"
54 #include "plog.h"
55 #include "debug.h"
56
57 #include "localconf.h"
58 #include "remoteconf.h"
59 #include "sockmisc.h"
60 #include "isakmp_var.h"
61 #include "isakmp.h"
62 #include "oakley.h"
63 #include "ipsec_doi.h"
64 #include "vendorid.h"
65 #include "handler.h"
66 #include "crypto_openssl.h"
67 #include "schedule.h"
68 #include "nattraversal.h"
69 #include "grabmyaddr.h"
70
71 struct natt_ka_addrs {
72 struct sockaddr *src;
73 struct sockaddr *dst;
74 unsigned in_use;
75
76 TAILQ_ENTRY(natt_ka_addrs) chain;
77 };
78
79 static TAILQ_HEAD(_natt_ka_addrs, natt_ka_addrs) ka_tree;
80
81 /*
82 * check if the given vid is NAT-T.
83 */
84 int
natt_vendorid(int vid)85 natt_vendorid (int vid)
86 {
87 return (
88 #ifdef ENABLE_NATT_00
89 vid == VENDORID_NATT_00 ||
90 #endif
91 #ifdef ENABLE_NATT_01
92 vid == VENDORID_NATT_01 ||
93 #endif
94 #ifdef ENABLE_NATT_02
95 vid == VENDORID_NATT_02 ||
96 vid == VENDORID_NATT_02_N ||
97 #endif
98 #ifdef ENABLE_NATT_03
99 vid == VENDORID_NATT_03 ||
100 #endif
101 #ifdef ENABLE_NATT_04
102 vid == VENDORID_NATT_04 ||
103 #endif
104 #ifdef ENABLE_NATT_05
105 vid == VENDORID_NATT_05 ||
106 #endif
107 #ifdef ENABLE_NATT_06
108 vid == VENDORID_NATT_06 ||
109 #endif
110 #ifdef ENABLE_NATT_07
111 vid == VENDORID_NATT_07 ||
112 #endif
113 #ifdef ENABLE_NATT_08
114 vid == VENDORID_NATT_08 ||
115 #endif
116 /* Always enable NATT RFC if ENABLE_NATT
117 */
118 vid == VENDORID_NATT_RFC);
119 }
120
121 vchar_t *
natt_hash_addr(struct ph1handle * iph1,struct sockaddr * addr)122 natt_hash_addr (struct ph1handle *iph1, struct sockaddr *addr)
123 {
124 vchar_t *natd;
125 vchar_t *buf;
126 char *ptr;
127 void *addr_ptr, *addr_port;
128 size_t buf_size, addr_size;
129
130 plog (LLV_INFO, LOCATION, addr, "Hashing %s with algo #%d %s\n",
131 saddr2str(addr), iph1->approval->hashtype,
132 (iph1->rmconf->nat_traversal == NATT_FORCE)?"(NAT-T forced)":"");
133
134 if (addr->sa_family == AF_INET) {
135 addr_size = sizeof (struct in_addr); /* IPv4 address */
136 addr_ptr = &((struct sockaddr_in *)addr)->sin_addr;
137 addr_port = &((struct sockaddr_in *)addr)->sin_port;
138 }
139 else if (addr->sa_family == AF_INET6) {
140 addr_size = sizeof (struct in6_addr); /* IPv6 address */
141 addr_ptr = &((struct sockaddr_in6 *)addr)->sin6_addr;
142 addr_port = &((struct sockaddr_in6 *)addr)->sin6_port;
143 }
144 else {
145 plog (LLV_ERROR, LOCATION, addr, "Unsupported address family #0x%x\n", addr->sa_family);
146 return NULL;
147 }
148
149 buf_size = 2 * sizeof (cookie_t); /* CKY-I + CKY+R */
150 buf_size += addr_size + 2; /* Address + Port */
151
152 if ((buf = vmalloc (buf_size)) == NULL)
153 return NULL;
154
155 ptr = buf->v;
156
157 /* Copy-in CKY-I */
158 memcpy (ptr, iph1->index.i_ck, sizeof (cookie_t));
159 ptr += sizeof (cookie_t);
160
161 /* Copy-in CKY-I */
162 memcpy (ptr, iph1->index.r_ck, sizeof (cookie_t));
163 ptr += sizeof (cookie_t);
164
165 /* Copy-in Address (or zeroes if NATT_FORCE) */
166 if (iph1->rmconf->nat_traversal == NATT_FORCE)
167 memset (ptr, 0, addr_size);
168 else
169 memcpy (ptr, addr_ptr, addr_size);
170 ptr += addr_size;
171
172 /* Copy-in Port number */
173 memcpy (ptr, addr_port, 2);
174
175 natd = oakley_hash (buf, iph1);
176 vfree(buf);
177
178 return natd;
179 }
180
181 int
natt_compare_addr_hash(struct ph1handle * iph1,vchar_t * natd_received,int natd_seq)182 natt_compare_addr_hash (struct ph1handle *iph1, vchar_t *natd_received,
183 int natd_seq)
184 {
185 vchar_t *natd_computed;
186 u_int32_t flag;
187 int verified = 0;
188
189 if (iph1->rmconf->nat_traversal == NATT_FORCE)
190 return verified;
191
192 if (natd_seq == 0) {
193 natd_computed = natt_hash_addr (iph1, iph1->local);
194 flag = NAT_DETECTED_ME;
195 }
196 else {
197 natd_computed = natt_hash_addr (iph1, iph1->remote);
198 flag = NAT_DETECTED_PEER;
199 }
200
201 if (natd_computed == NULL) {
202 plog(LLV_ERROR, LOCATION, NULL, "natd_computed allocation failed\n");
203 return verified; /* XXX should abort */
204 }
205
206 if (natd_received->l == natd_computed->l &&
207 memcmp (natd_received->v, natd_computed->v, natd_received->l) == 0) {
208 iph1->natt_flags &= ~flag;
209 verified = 1;
210 }
211
212 vfree (natd_computed);
213
214 return verified;
215 }
216
217 int
natt_udp_encap(int encmode)218 natt_udp_encap (int encmode)
219 {
220 return (encmode == IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC ||
221 encmode == IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC ||
222 encmode == IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT ||
223 encmode == IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT);
224 }
225
226 int
natt_fill_options(struct ph1natt_options * opts,int version)227 natt_fill_options (struct ph1natt_options *opts, int version)
228 {
229 if (! opts)
230 return -1;
231
232 opts->version = version;
233
234 switch (version) {
235 case VENDORID_NATT_00:
236 case VENDORID_NATT_01:
237 opts->float_port = 0; /* No port floating for those drafts */
238 opts->payload_nat_d = ISAKMP_NPTYPE_NATD_DRAFT;
239 opts->payload_nat_oa = ISAKMP_NPTYPE_NATOA_DRAFT;
240 opts->mode_udp_tunnel = IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT;
241 opts->mode_udp_transport = IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT;
242 opts->encaps_type = UDP_ENCAP_ESPINUDP_NON_IKE;
243 break;
244
245 case VENDORID_NATT_02:
246 case VENDORID_NATT_02_N:
247 case VENDORID_NATT_03:
248 opts->float_port = lcconf->port_isakmp_natt;
249 opts->payload_nat_d = ISAKMP_NPTYPE_NATD_DRAFT;
250 opts->payload_nat_oa = ISAKMP_NPTYPE_NATOA_DRAFT;
251 opts->mode_udp_tunnel = IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT;
252 opts->mode_udp_transport = IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT;
253 opts->encaps_type = UDP_ENCAP_ESPINUDP;
254 break;
255 case VENDORID_NATT_04:
256 case VENDORID_NATT_05:
257 case VENDORID_NATT_06:
258 case VENDORID_NATT_07:
259 case VENDORID_NATT_08:
260 opts->float_port = lcconf->port_isakmp_natt;
261 opts->payload_nat_d = ISAKMP_NPTYPE_NATD_BADDRAFT;
262 opts->payload_nat_oa = ISAKMP_NPTYPE_NATOA_BADDRAFT;
263 opts->mode_udp_tunnel = IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC;
264 opts->mode_udp_transport = IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC;
265 opts->encaps_type = UDP_ENCAP_ESPINUDP;
266 break;
267 case VENDORID_NATT_RFC:
268 opts->float_port = lcconf->port_isakmp_natt;
269 opts->payload_nat_d = ISAKMP_NPTYPE_NATD_RFC;
270 opts->payload_nat_oa = ISAKMP_NPTYPE_NATOA_RFC;
271 opts->mode_udp_tunnel = IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC;
272 opts->mode_udp_transport = IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC;
273 opts->encaps_type = UDP_ENCAP_ESPINUDP;
274 break;
275 default:
276 plog(LLV_ERROR, LOCATION, NULL,
277 "unsupported NAT-T version: %s\n",
278 vid_string_by_id(version));
279 return -1;
280 }
281
282 opts->mode_udp_diff = opts->mode_udp_tunnel - IPSECDOI_ATTR_ENC_MODE_TUNNEL;
283
284 return 0;
285 }
286
287 void
natt_float_ports(struct ph1handle * iph1)288 natt_float_ports (struct ph1handle *iph1)
289 {
290 if (! (iph1->natt_flags && NAT_DETECTED) )
291 return;
292 if (! iph1->natt_options->float_port){
293 /* Drafts 00 / 01, just schedule keepalive */
294 natt_keepalive_add_ph1 (iph1);
295 return;
296 }
297
298 set_port (iph1->local, iph1->natt_options->float_port);
299 set_port (iph1->remote, iph1->natt_options->float_port);
300 iph1->natt_flags |= NAT_PORTS_CHANGED | NAT_ADD_NON_ESP_MARKER;
301
302 natt_keepalive_add_ph1 (iph1);
303 }
304
305 void
natt_handle_vendorid(struct ph1handle * iph1,int vid_numeric)306 natt_handle_vendorid (struct ph1handle *iph1, int vid_numeric)
307 {
308 if (! iph1->natt_options)
309 iph1->natt_options = racoon_calloc (1, sizeof (*iph1->natt_options));
310
311 if (! iph1->natt_options) {
312 plog (LLV_ERROR, LOCATION, NULL,
313 "Allocating memory for natt_options failed!\n");
314 return;
315 }
316
317 if (iph1->natt_options->version < vid_numeric)
318 if (natt_fill_options (iph1->natt_options, vid_numeric) == 0)
319 iph1->natt_flags |= NAT_ANNOUNCED;
320 }
321
322 static void
natt_keepalive_delete(struct natt_ka_addrs * ka)323 natt_keepalive_delete (struct natt_ka_addrs *ka)
324 {
325 TAILQ_REMOVE (&ka_tree, ka, chain);
326 racoon_free (ka->src);
327 racoon_free (ka->dst);
328 racoon_free (ka);
329 }
330
331 /* NAT keepalive functions */
332 static void
natt_keepalive_send(void * param)333 natt_keepalive_send (void *param)
334 {
335 struct natt_ka_addrs *ka, *next = NULL;
336 char keepalive_packet[] = { 0xff };
337 size_t len;
338 int s;
339
340 for (ka = TAILQ_FIRST(&ka_tree); ka; ka = next) {
341 next = TAILQ_NEXT(ka, chain);
342
343 s = getsockmyaddr(ka->src);
344 if (s == -1) {
345 natt_keepalive_delete(ka);
346 continue;
347 }
348 plog (LLV_DEBUG, LOCATION, NULL, "KA: %s\n",
349 saddr2str_fromto("%s->%s", ka->src, ka->dst));
350 len = sendfromto(s, keepalive_packet, sizeof (keepalive_packet),
351 ka->src, ka->dst, 1);
352 if (len == -1)
353 plog(LLV_ERROR, LOCATION, NULL, "KA: sendfromto failed: %s\n",
354 strerror (errno));
355 }
356
357 sched_new (lcconf->natt_ka_interval, natt_keepalive_send, NULL);
358 }
359
360 void
natt_keepalive_init(void)361 natt_keepalive_init (void)
362 {
363 TAILQ_INIT(&ka_tree);
364
365 /* To disable sending KAs set natt_ka_interval=0 */
366 if (lcconf->natt_ka_interval > 0)
367 sched_new (lcconf->natt_ka_interval, natt_keepalive_send, NULL);
368 }
369
370 int
natt_keepalive_add(struct sockaddr * src,struct sockaddr * dst)371 natt_keepalive_add (struct sockaddr *src, struct sockaddr *dst)
372 {
373 struct natt_ka_addrs *ka = NULL, *new_addr;
374
375 TAILQ_FOREACH (ka, &ka_tree, chain) {
376 if (cmpsaddrstrict(ka->src, src) == 0 &&
377 cmpsaddrstrict(ka->dst, dst) == 0) {
378 ka->in_use++;
379 plog (LLV_INFO, LOCATION, NULL, "KA found: %s (in_use=%u)\n",
380 saddr2str_fromto("%s->%s", src, dst), ka->in_use);
381 return 0;
382 }
383 }
384
385 plog (LLV_INFO, LOCATION, NULL, "KA list add: %s\n", saddr2str_fromto("%s->%s", src, dst));
386
387 new_addr = (struct natt_ka_addrs *)racoon_malloc(sizeof(*new_addr));
388 if (! new_addr) {
389 plog (LLV_ERROR, LOCATION, NULL, "Can't allocate new KA list item\n");
390 return -1;
391 }
392
393 if ((new_addr->src = dupsaddr(src)) == NULL) {
394 racoon_free(new_addr);
395 plog (LLV_ERROR, LOCATION, NULL, "Can't allocate new KA list item\n");
396 return -1;
397 }
398 if ((new_addr->dst = dupsaddr(dst)) == NULL) {
399 racoon_free(new_addr);
400 plog (LLV_ERROR, LOCATION, NULL, "Can't allocate new KA list item\n");
401 return -1;
402 }
403 new_addr->in_use = 1;
404 TAILQ_INSERT_TAIL(&ka_tree, new_addr, chain);
405
406 return 0;
407 }
408
409 int
natt_keepalive_add_ph1(struct ph1handle * iph1)410 natt_keepalive_add_ph1 (struct ph1handle *iph1)
411 {
412 int ret = 0;
413
414 /* Should only the NATed host send keepalives?
415 If yes, add '(iph1->natt_flags & NAT_DETECTED_ME)'
416 to the following condition. */
417 if (iph1->natt_flags & NAT_DETECTED &&
418 ! (iph1->natt_flags & NAT_KA_QUEUED)) {
419 ret = natt_keepalive_add (iph1->local, iph1->remote);
420 if (ret == 0)
421 iph1->natt_flags |= NAT_KA_QUEUED;
422 }
423
424 return ret;
425 }
426
427 void
natt_keepalive_remove(struct sockaddr * src,struct sockaddr * dst)428 natt_keepalive_remove (struct sockaddr *src, struct sockaddr *dst)
429 {
430 struct natt_ka_addrs *ka, *next = NULL;
431
432 plog (LLV_INFO, LOCATION, NULL, "KA remove: %s\n", saddr2str_fromto("%s->%s", src, dst));
433
434 for (ka = TAILQ_FIRST(&ka_tree); ka; ka = next) {
435 next = TAILQ_NEXT(ka, chain);
436
437 plog (LLV_DEBUG, LOCATION, NULL, "KA tree dump: %s (in_use=%u)\n",
438 saddr2str_fromto("%s->%s", src, dst), ka->in_use);
439
440 if (cmpsaddrstrict(ka->src, src) == 0 &&
441 cmpsaddrstrict(ka->dst, dst) == 0 &&
442 -- ka->in_use <= 0) {
443
444 plog (LLV_DEBUG, LOCATION, NULL, "KA removing this one...\n");
445
446 natt_keepalive_delete (ka);
447 /* Should we break here? Every pair of addresses should
448 be inserted only once, but who knows :-) Lets traverse
449 the whole list... */
450 }
451 }
452 }
453
454 static struct remoteconf *
natt_enabled_in_rmconf_stub(struct remoteconf * rmconf,void * data)455 natt_enabled_in_rmconf_stub (struct remoteconf *rmconf, void *data)
456 {
457 return (rmconf->nat_traversal ? rmconf : NULL);
458 }
459
460 int
natt_enabled_in_rmconf()461 natt_enabled_in_rmconf ()
462 {
463 return foreachrmconf (natt_enabled_in_rmconf_stub, NULL) != NULL;
464 }
465
466
467 struct payload_list *
isakmp_plist_append_natt_vids(struct payload_list * plist,vchar_t * vid_natt[MAX_NATT_VID_COUNT])468 isakmp_plist_append_natt_vids (struct payload_list *plist, vchar_t *vid_natt[MAX_NATT_VID_COUNT]){
469 int i, vid_natt_i = 0;
470
471 if(vid_natt == NULL)
472 return NULL;
473
474 for (i = 0; i < MAX_NATT_VID_COUNT; i++)
475 vid_natt[i]=NULL;
476
477 /* Puts the olders VIDs last, as some implementations may choose the first
478 * NATT VID given
479 */
480
481 /* Always set RFC VID
482 */
483 if ((vid_natt[vid_natt_i] = set_vendorid(VENDORID_NATT_RFC)) != NULL)
484 vid_natt_i++;
485 #ifdef ENABLE_NATT_08
486 if ((vid_natt[vid_natt_i] = set_vendorid(VENDORID_NATT_08)) != NULL)
487 vid_natt_i++;
488 #endif
489 #ifdef ENABLE_NATT_07
490 if ((vid_natt[vid_natt_i] = set_vendorid(VENDORID_NATT_07)) != NULL)
491 vid_natt_i++;
492 #endif
493 #ifdef ENABLE_NATT_06
494 if ((vid_natt[vid_natt_i] = set_vendorid(VENDORID_NATT_06)) != NULL)
495 vid_natt_i++;
496 #endif
497 #ifdef ENABLE_NATT_05
498 if ((vid_natt[vid_natt_i] = set_vendorid(VENDORID_NATT_05)) != NULL)
499 vid_natt_i++;
500 #endif
501 #ifdef ENABLE_NATT_04
502 if ((vid_natt[vid_natt_i] = set_vendorid(VENDORID_NATT_04)) != NULL)
503 vid_natt_i++;
504 #endif
505 #ifdef ENABLE_NATT_03
506 if ((vid_natt[vid_natt_i] = set_vendorid(VENDORID_NATT_03)) != NULL)
507 vid_natt_i++;
508 #endif
509 #ifdef ENABLE_NATT_02
510 if ((vid_natt[vid_natt_i] = set_vendorid(VENDORID_NATT_02)) != NULL)
511 vid_natt_i++;
512 if ((vid_natt[vid_natt_i] = set_vendorid(VENDORID_NATT_02_N)) != NULL)
513 vid_natt_i++;
514 #endif
515 #ifdef ENABLE_NATT_01
516 if ((vid_natt[vid_natt_i] = set_vendorid(VENDORID_NATT_01)) != NULL)
517 vid_natt_i++;
518 #endif
519 #ifdef ENABLE_NATT_00
520 if ((vid_natt[vid_natt_i] = set_vendorid(VENDORID_NATT_00)) != NULL)
521 vid_natt_i++;
522 #endif
523 /* set VID payload for NAT-T */
524 for (i = 0; i < vid_natt_i; i++)
525 plist = isakmp_plist_append(plist, vid_natt[i], ISAKMP_NPTYPE_VID);
526
527 return plist;
528 }
529