Line data Source code
1 : /* $OpenBSD: ip_ipsp.c,v 1.232 2018/08/28 15:15:02 mpi Exp $ */
2 : /*
3 : * The authors of this code are John Ioannidis (ji@tla.org),
4 : * Angelos D. Keromytis (kermit@csd.uch.gr),
5 : * Niels Provos (provos@physnet.uni-hamburg.de) and
6 : * Niklas Hallqvist (niklas@appli.se).
7 : *
8 : * The original version of this code was written by John Ioannidis
9 : * for BSD/OS in Athens, Greece, in November 1995.
10 : *
11 : * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996,
12 : * by Angelos D. Keromytis.
13 : *
14 : * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis
15 : * and Niels Provos.
16 : *
17 : * Additional features in 1999 by Angelos D. Keromytis and Niklas Hallqvist.
18 : *
19 : * Copyright (c) 1995, 1996, 1997, 1998, 1999 by John Ioannidis,
20 : * Angelos D. Keromytis and Niels Provos.
21 : * Copyright (c) 1999 Niklas Hallqvist.
22 : * Copyright (c) 2001, Angelos D. Keromytis.
23 : *
24 : * Permission to use, copy, and modify this software with or without fee
25 : * is hereby granted, provided that this entire notice is included in
26 : * all copies of any software which is or includes a copy or
27 : * modification of this software.
28 : * You may use this code under the GNU public license if you so wish. Please
29 : * contribute changes back to the authors under this freer than GPL license
30 : * so that we may further the use of strong encryption without limitations to
31 : * all.
32 : *
33 : * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
34 : * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
35 : * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
36 : * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
37 : * PURPOSE.
38 : */
39 :
40 : #include "pf.h"
41 : #include "pfsync.h"
42 :
43 : #include <sys/param.h>
44 : #include <sys/systm.h>
45 : #include <sys/mbuf.h>
46 : #include <sys/socket.h>
47 : #include <sys/kernel.h>
48 : #include <sys/timeout.h>
49 :
50 : #include <net/if.h>
51 : #include <net/route.h>
52 :
53 : #include <netinet/in.h>
54 : #include <netinet/ip.h>
55 : #include <netinet/in_pcb.h>
56 : #include <netinet/ip_var.h>
57 : #include <netinet/ip_ipip.h>
58 :
59 : #if NPF > 0
60 : #include <net/pfvar.h>
61 : #endif
62 :
63 : #if NPFSYNC > 0
64 : #include <net/if_pfsync.h>
65 : #endif
66 :
67 : #include <netinet/ip_ipsp.h>
68 : #include <net/pfkeyv2.h>
69 :
70 : #ifdef DDB
71 : #include <ddb/db_output.h>
72 : void tdb_hashstats(void);
73 : #endif
74 :
75 : #ifdef ENCDEBUG
76 : #define DPRINTF(x) if (encdebug) printf x
77 : #else
78 : #define DPRINTF(x)
79 : #endif
80 :
81 : void tdb_rehash(void);
82 : void tdb_reaper(void *);
83 : void tdb_timeout(void *);
84 : void tdb_firstuse(void *);
85 : void tdb_soft_timeout(void *);
86 : void tdb_soft_firstuse(void *);
87 : int tdb_hash(u_int, u_int32_t, union sockaddr_union *, u_int8_t);
88 :
89 : int ipsec_in_use = 0;
90 : u_int64_t ipsec_last_added = 0;
91 : int ipsec_ids_idle = 100; /* keep free ids for 100s */
92 :
93 : /* Protected by the NET_LOCK(). */
94 : u_int32_t ipsec_ids_next_flow = 1; /* may not be zero */
95 : struct ipsec_ids_tree ipsec_ids_tree;
96 : struct ipsec_ids_flows ipsec_ids_flows;
97 : struct ipsec_policy_head ipsec_policy_head =
98 : TAILQ_HEAD_INITIALIZER(ipsec_policy_head);
99 :
100 : void ipsp_ids_timeout(void *);
101 : static inline int ipsp_ids_cmp(const struct ipsec_ids *,
102 : const struct ipsec_ids *);
103 : static inline int ipsp_ids_flow_cmp(const struct ipsec_ids *,
104 : const struct ipsec_ids *);
105 0 : RBT_PROTOTYPE(ipsec_ids_tree, ipsec_ids, id_node_flow, ipsp_ids_cmp);
106 0 : RBT_PROTOTYPE(ipsec_ids_flows, ipsec_ids, id_node_id, ipsp_ids_flow_cmp);
107 0 : RBT_GENERATE(ipsec_ids_tree, ipsec_ids, id_node_flow, ipsp_ids_cmp);
108 0 : RBT_GENERATE(ipsec_ids_flows, ipsec_ids, id_node_id, ipsp_ids_flow_cmp);
109 :
110 : /*
111 : * This is the proper place to define the various encapsulation transforms.
112 : */
113 :
114 : struct xformsw xformsw[] = {
115 : #ifdef IPSEC
116 : {
117 : .xf_type = XF_IP4,
118 : .xf_flags = 0,
119 : .xf_name = "IPv4 Simple Encapsulation",
120 : .xf_attach = ipe4_attach,
121 : .xf_init = ipe4_init,
122 : .xf_zeroize = ipe4_zeroize,
123 : .xf_input = ipe4_input,
124 : .xf_output = ipip_output,
125 : },
126 : {
127 : .xf_type = XF_AH,
128 : .xf_flags = XFT_AUTH,
129 : .xf_name = "IPsec AH",
130 : .xf_attach = ah_attach,
131 : .xf_init = ah_init,
132 : .xf_zeroize = ah_zeroize,
133 : .xf_input = ah_input,
134 : .xf_output = ah_output,
135 : },
136 : {
137 : .xf_type = XF_ESP,
138 : .xf_flags = XFT_CONF|XFT_AUTH,
139 : .xf_name = "IPsec ESP",
140 : .xf_attach = esp_attach,
141 : .xf_init = esp_init,
142 : .xf_zeroize = esp_zeroize,
143 : .xf_input = esp_input,
144 : .xf_output = esp_output,
145 : },
146 : {
147 : .xf_type = XF_IPCOMP,
148 : .xf_flags = XFT_COMP,
149 : .xf_name = "IPcomp",
150 : .xf_attach = ipcomp_attach,
151 : .xf_init = ipcomp_init,
152 : .xf_zeroize = ipcomp_zeroize,
153 : .xf_input = ipcomp_input,
154 : .xf_output = ipcomp_output,
155 : },
156 : #endif /* IPSEC */
157 : #ifdef TCP_SIGNATURE
158 : {
159 : .xf_type = XF_TCPSIGNATURE,
160 : .xf_flags = XFT_AUTH,
161 : .xf_name = "TCP MD5 Signature Option, RFC 2385",
162 : .xf_attach = tcp_signature_tdb_attach,
163 : .xf_init = tcp_signature_tdb_init,
164 : .xf_zeroize = tcp_signature_tdb_zeroize,
165 : .xf_input = tcp_signature_tdb_input,
166 : .xf_output = tcp_signature_tdb_output,
167 : }
168 : #endif /* TCP_SIGNATURE */
169 : };
170 :
171 : struct xformsw *xformswNXFORMSW = &xformsw[nitems(xformsw)];
172 :
173 : #define TDB_HASHSIZE_INIT 32
174 :
175 : /* Protected by the NET_LOCK(). */
176 : static SIPHASH_KEY tdbkey;
177 : static struct tdb **tdbh = NULL;
178 : static struct tdb **tdbdst = NULL;
179 : static struct tdb **tdbsrc = NULL;
180 : static u_int tdb_hashmask = TDB_HASHSIZE_INIT - 1;
181 : static int tdb_count;
182 :
183 : /*
184 : * Our hashing function needs to stir things with a non-zero random multiplier
185 : * so we cannot be DoS-attacked via choosing of the data to hash.
186 : */
187 : int
188 0 : tdb_hash(u_int rdomain, u_int32_t spi, union sockaddr_union *dst,
189 : u_int8_t proto)
190 : {
191 0 : SIPHASH_CTX ctx;
192 :
193 0 : NET_ASSERT_LOCKED();
194 :
195 0 : SipHash24_Init(&ctx, &tdbkey);
196 0 : SipHash24_Update(&ctx, &rdomain, sizeof(rdomain));
197 0 : SipHash24_Update(&ctx, &spi, sizeof(spi));
198 0 : SipHash24_Update(&ctx, &proto, sizeof(proto));
199 0 : SipHash24_Update(&ctx, dst, dst->sa.sa_len);
200 :
201 0 : return (SipHash24_End(&ctx) & tdb_hashmask);
202 0 : }
203 :
204 : /*
205 : * Reserve an SPI; the SA is not valid yet though. We use 0 as
206 : * an error return value.
207 : */
208 : u_int32_t
209 0 : reserve_spi(u_int rdomain, u_int32_t sspi, u_int32_t tspi,
210 : union sockaddr_union *src, union sockaddr_union *dst,
211 : u_int8_t sproto, int *errval)
212 : {
213 : struct tdb *tdbp, *exists;
214 : u_int32_t spi;
215 : int nums;
216 :
217 0 : NET_ASSERT_LOCKED();
218 :
219 : /* Don't accept ranges only encompassing reserved SPIs. */
220 0 : if (sproto != IPPROTO_IPCOMP &&
221 0 : (tspi < sspi || tspi <= SPI_RESERVED_MAX)) {
222 0 : (*errval) = EINVAL;
223 0 : return 0;
224 : }
225 0 : if (sproto == IPPROTO_IPCOMP && (tspi < sspi ||
226 0 : tspi <= CPI_RESERVED_MAX ||
227 0 : tspi >= CPI_PRIVATE_MIN)) {
228 0 : (*errval) = EINVAL;
229 0 : return 0;
230 : }
231 :
232 : /* Limit the range to not include reserved areas. */
233 0 : if (sspi <= SPI_RESERVED_MAX)
234 0 : sspi = SPI_RESERVED_MAX + 1;
235 :
236 : /* For IPCOMP the CPI is only 16 bits long, what a good idea.... */
237 :
238 0 : if (sproto == IPPROTO_IPCOMP) {
239 : u_int32_t t;
240 0 : if (sspi >= 0x10000)
241 0 : sspi = 0xffff;
242 0 : if (tspi >= 0x10000)
243 0 : tspi = 0xffff;
244 0 : if (sspi > tspi) {
245 : t = sspi; sspi = tspi; tspi = t;
246 0 : }
247 0 : }
248 :
249 0 : if (sspi == tspi) /* Asking for a specific SPI. */
250 0 : nums = 1;
251 : else
252 : nums = 100; /* Arbitrarily chosen */
253 :
254 : /* allocate ahead of time to avoid potential sleeping race in loop */
255 0 : tdbp = tdb_alloc(rdomain);
256 :
257 0 : while (nums--) {
258 0 : if (sspi == tspi) /* Specific SPI asked. */
259 0 : spi = tspi;
260 : else /* Range specified */
261 0 : spi = sspi + arc4random_uniform(tspi - sspi);
262 :
263 : /* Don't allocate reserved SPIs. */
264 0 : if (spi >= SPI_RESERVED_MIN && spi <= SPI_RESERVED_MAX)
265 0 : continue;
266 : else
267 0 : spi = htonl(spi);
268 :
269 : /* Check whether we're using this SPI already. */
270 0 : exists = gettdb(rdomain, spi, dst, sproto);
271 0 : if (exists)
272 0 : continue;
273 :
274 :
275 0 : tdbp->tdb_spi = spi;
276 0 : memcpy(&tdbp->tdb_dst.sa, &dst->sa, dst->sa.sa_len);
277 0 : memcpy(&tdbp->tdb_src.sa, &src->sa, src->sa.sa_len);
278 0 : tdbp->tdb_sproto = sproto;
279 0 : tdbp->tdb_flags |= TDBF_INVALID; /* Mark SA invalid for now. */
280 0 : tdbp->tdb_satype = SADB_SATYPE_UNSPEC;
281 0 : puttdb(tdbp);
282 :
283 : #ifdef IPSEC
284 : /* Setup a "silent" expiration (since TDBF_INVALID's set). */
285 0 : if (ipsec_keep_invalid > 0) {
286 0 : tdbp->tdb_flags |= TDBF_TIMER;
287 0 : tdbp->tdb_exp_timeout = ipsec_keep_invalid;
288 0 : timeout_add_sec(&tdbp->tdb_timer_tmo,
289 0 : ipsec_keep_invalid);
290 0 : }
291 : #endif
292 :
293 0 : return spi;
294 : }
295 :
296 0 : (*errval) = EEXIST;
297 0 : tdb_free(tdbp);
298 0 : return 0;
299 0 : }
300 :
301 : /*
302 : * An IPSP SAID is really the concatenation of the SPI found in the
303 : * packet, the destination address of the packet and the IPsec protocol.
304 : * When we receive an IPSP packet, we need to look up its tunnel descriptor
305 : * block, based on the SPI in the packet and the destination address (which
306 : * is really one of our addresses if we received the packet!
307 : */
308 : struct tdb *
309 0 : gettdb(u_int rdomain, u_int32_t spi, union sockaddr_union *dst, u_int8_t proto)
310 : {
311 : u_int32_t hashval;
312 : struct tdb *tdbp;
313 :
314 0 : NET_ASSERT_LOCKED();
315 :
316 0 : if (tdbh == NULL)
317 0 : return (struct tdb *) NULL;
318 :
319 0 : hashval = tdb_hash(rdomain, spi, dst, proto);
320 :
321 0 : for (tdbp = tdbh[hashval]; tdbp != NULL; tdbp = tdbp->tdb_hnext)
322 0 : if ((tdbp->tdb_spi == spi) && (tdbp->tdb_sproto == proto) &&
323 0 : (tdbp->tdb_rdomain == rdomain) &&
324 0 : !memcmp(&tdbp->tdb_dst, dst, dst->sa.sa_len))
325 : break;
326 :
327 0 : return tdbp;
328 0 : }
329 :
330 : /*
331 : * Same as gettdb() but compare SRC as well, so we
332 : * use the tdbsrc[] hash table. Setting spi to 0
333 : * matches all SPIs.
334 : */
335 : struct tdb *
336 0 : gettdbbysrcdst(u_int rdomain, u_int32_t spi, union sockaddr_union *src,
337 : union sockaddr_union *dst, u_int8_t proto)
338 : {
339 : u_int32_t hashval;
340 : struct tdb *tdbp;
341 0 : union sockaddr_union su_null;
342 :
343 0 : NET_ASSERT_LOCKED();
344 :
345 0 : if (tdbsrc == NULL)
346 0 : return (struct tdb *) NULL;
347 :
348 0 : hashval = tdb_hash(rdomain, 0, src, proto);
349 :
350 0 : for (tdbp = tdbsrc[hashval]; tdbp != NULL; tdbp = tdbp->tdb_snext)
351 0 : if (tdbp->tdb_sproto == proto &&
352 0 : (spi == 0 || tdbp->tdb_spi == spi) &&
353 0 : (tdbp->tdb_rdomain == rdomain) &&
354 0 : ((tdbp->tdb_flags & TDBF_INVALID) == 0) &&
355 0 : (tdbp->tdb_dst.sa.sa_family == AF_UNSPEC ||
356 0 : !memcmp(&tdbp->tdb_dst, dst, dst->sa.sa_len)) &&
357 0 : !memcmp(&tdbp->tdb_src, src, src->sa.sa_len))
358 : break;
359 :
360 0 : if (tdbp != NULL)
361 0 : return (tdbp);
362 :
363 0 : memset(&su_null, 0, sizeof(su_null));
364 0 : su_null.sa.sa_len = sizeof(struct sockaddr);
365 0 : hashval = tdb_hash(rdomain, 0, &su_null, proto);
366 :
367 0 : for (tdbp = tdbsrc[hashval]; tdbp != NULL; tdbp = tdbp->tdb_snext)
368 0 : if (tdbp->tdb_sproto == proto &&
369 0 : (spi == 0 || tdbp->tdb_spi == spi) &&
370 0 : (tdbp->tdb_rdomain == rdomain) &&
371 0 : ((tdbp->tdb_flags & TDBF_INVALID) == 0) &&
372 0 : (tdbp->tdb_dst.sa.sa_family == AF_UNSPEC ||
373 0 : !memcmp(&tdbp->tdb_dst, dst, dst->sa.sa_len)) &&
374 0 : tdbp->tdb_src.sa.sa_family == AF_UNSPEC)
375 : break;
376 :
377 0 : return (tdbp);
378 0 : }
379 :
380 : /*
381 : * Check that IDs match. Return true if so. The t* range of
382 : * arguments contains information from TDBs; the p* range of
383 : * arguments contains information from policies or already
384 : * established TDBs.
385 : */
386 : int
387 0 : ipsp_aux_match(struct tdb *tdb,
388 : struct ipsec_ids *ids,
389 : struct sockaddr_encap *pfilter,
390 : struct sockaddr_encap *pfiltermask)
391 : {
392 0 : if (ids != NULL)
393 0 : if (tdb->tdb_ids == NULL ||
394 0 : !ipsp_ids_match(tdb->tdb_ids, ids))
395 0 : return 0;
396 :
397 : /* Check for filter matches. */
398 0 : if (pfilter != NULL && pfiltermask != NULL &&
399 0 : tdb->tdb_filter.sen_type) {
400 : /*
401 : * XXX We should really be doing a subnet-check (see
402 : * whether the TDB-associated filter is a subset
403 : * of the policy's. For now, an exact match will solve
404 : * most problems (all this will do is make every
405 : * policy get its own SAs).
406 : */
407 0 : if (memcmp(&tdb->tdb_filter, pfilter,
408 0 : sizeof(struct sockaddr_encap)) ||
409 0 : memcmp(&tdb->tdb_filtermask, pfiltermask,
410 : sizeof(struct sockaddr_encap)))
411 0 : return 0;
412 : }
413 :
414 0 : return 1;
415 0 : }
416 :
417 : /*
418 : * Get an SA given the remote address, the security protocol type, and
419 : * the desired IDs.
420 : */
421 : struct tdb *
422 0 : gettdbbydst(u_int rdomain, union sockaddr_union *dst, u_int8_t sproto,
423 : struct ipsec_ids *ids,
424 : struct sockaddr_encap *filter, struct sockaddr_encap *filtermask)
425 : {
426 : u_int32_t hashval;
427 : struct tdb *tdbp;
428 :
429 0 : NET_ASSERT_LOCKED();
430 :
431 0 : if (tdbdst == NULL)
432 0 : return (struct tdb *) NULL;
433 :
434 0 : hashval = tdb_hash(rdomain, 0, dst, sproto);
435 :
436 0 : for (tdbp = tdbdst[hashval]; tdbp != NULL; tdbp = tdbp->tdb_dnext)
437 0 : if ((tdbp->tdb_sproto == sproto) &&
438 0 : (tdbp->tdb_rdomain == rdomain) &&
439 0 : ((tdbp->tdb_flags & TDBF_INVALID) == 0) &&
440 0 : (!memcmp(&tdbp->tdb_dst, dst, dst->sa.sa_len))) {
441 : /* Do IDs match ? */
442 0 : if (!ipsp_aux_match(tdbp, ids, filter, filtermask))
443 : continue;
444 : break;
445 : }
446 :
447 0 : return tdbp;
448 0 : }
449 :
450 : /*
451 : * Get an SA given the source address, the security protocol type, and
452 : * the desired IDs.
453 : */
454 : struct tdb *
455 0 : gettdbbysrc(u_int rdomain, union sockaddr_union *src, u_int8_t sproto,
456 : struct ipsec_ids *ids,
457 : struct sockaddr_encap *filter, struct sockaddr_encap *filtermask)
458 : {
459 : u_int32_t hashval;
460 : struct tdb *tdbp;
461 :
462 0 : NET_ASSERT_LOCKED();
463 :
464 0 : if (tdbsrc == NULL)
465 0 : return (struct tdb *) NULL;
466 :
467 0 : hashval = tdb_hash(rdomain, 0, src, sproto);
468 :
469 0 : for (tdbp = tdbsrc[hashval]; tdbp != NULL; tdbp = tdbp->tdb_snext)
470 0 : if ((tdbp->tdb_sproto == sproto) &&
471 0 : (tdbp->tdb_rdomain == rdomain) &&
472 0 : ((tdbp->tdb_flags & TDBF_INVALID) == 0) &&
473 0 : (!memcmp(&tdbp->tdb_src, src, src->sa.sa_len))) {
474 : /* Check whether IDs match */
475 0 : if (!ipsp_aux_match(tdbp, ids, filter,
476 : filtermask))
477 : continue;
478 : break;
479 : }
480 :
481 0 : return tdbp;
482 0 : }
483 :
484 : #if DDB
485 :
486 : #define NBUCKETS 16
487 : void
488 0 : tdb_hashstats(void)
489 : {
490 0 : int i, cnt, buckets[NBUCKETS];
491 : struct tdb *tdbp;
492 :
493 0 : if (tdbh == NULL) {
494 0 : db_printf("no tdb hash table\n");
495 0 : return;
496 : }
497 :
498 0 : memset(buckets, 0, sizeof(buckets));
499 0 : for (i = 0; i <= tdb_hashmask; i++) {
500 : cnt = 0;
501 0 : for (tdbp = tdbh[i]; cnt < NBUCKETS - 1 && tdbp != NULL;
502 0 : tdbp = tdbp->tdb_hnext)
503 0 : cnt++;
504 0 : buckets[cnt]++;
505 : }
506 :
507 0 : db_printf("tdb cnt\t\tbucket cnt\n");
508 0 : for (i = 0; i < NBUCKETS; i++)
509 0 : if (buckets[i] > 0)
510 0 : db_printf("%d%s\t\t%d\n", i, i == NBUCKETS - 1 ?
511 : "+" : "", buckets[i]);
512 0 : }
513 : #endif /* DDB */
514 :
515 : int
516 0 : tdb_walk(u_int rdomain, int (*walker)(struct tdb *, void *, int), void *arg)
517 : {
518 : int i, rval = 0;
519 : struct tdb *tdbp, *next;
520 :
521 0 : NET_ASSERT_LOCKED();
522 :
523 0 : if (tdbh == NULL)
524 0 : return ENOENT;
525 :
526 0 : for (i = 0; i <= tdb_hashmask; i++)
527 0 : for (tdbp = tdbh[i]; rval == 0 && tdbp != NULL; tdbp = next) {
528 0 : next = tdbp->tdb_hnext;
529 :
530 0 : if (rdomain != tdbp->tdb_rdomain)
531 : continue;
532 :
533 0 : if (i == tdb_hashmask && next == NULL)
534 0 : rval = walker(tdbp, (void *)arg, 1);
535 : else
536 0 : rval = walker(tdbp, (void *)arg, 0);
537 : }
538 :
539 0 : return rval;
540 0 : }
541 :
542 : void
543 0 : tdb_timeout(void *v)
544 : {
545 0 : struct tdb *tdb = v;
546 :
547 0 : NET_LOCK();
548 0 : if (tdb->tdb_flags & TDBF_TIMER) {
549 : /* If it's an "invalid" TDB do a silent expiration. */
550 0 : if (!(tdb->tdb_flags & TDBF_INVALID))
551 0 : pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_HARD);
552 0 : tdb_delete(tdb);
553 0 : }
554 0 : NET_UNLOCK();
555 0 : }
556 :
557 : void
558 0 : tdb_firstuse(void *v)
559 : {
560 0 : struct tdb *tdb = v;
561 :
562 0 : NET_LOCK();
563 0 : if (tdb->tdb_flags & TDBF_SOFT_FIRSTUSE) {
564 : /* If the TDB hasn't been used, don't renew it. */
565 0 : if (tdb->tdb_first_use != 0)
566 0 : pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_HARD);
567 0 : tdb_delete(tdb);
568 0 : }
569 0 : NET_UNLOCK();
570 0 : }
571 :
572 : void
573 0 : tdb_soft_timeout(void *v)
574 : {
575 0 : struct tdb *tdb = v;
576 :
577 0 : NET_LOCK();
578 0 : if (tdb->tdb_flags & TDBF_SOFT_TIMER) {
579 : /* Soft expirations. */
580 0 : pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_SOFT);
581 0 : tdb->tdb_flags &= ~TDBF_SOFT_TIMER;
582 0 : }
583 0 : NET_UNLOCK();
584 0 : }
585 :
586 : void
587 0 : tdb_soft_firstuse(void *v)
588 : {
589 0 : struct tdb *tdb = v;
590 :
591 0 : NET_LOCK();
592 0 : if (tdb->tdb_flags & TDBF_SOFT_FIRSTUSE) {
593 : /* If the TDB hasn't been used, don't renew it. */
594 0 : if (tdb->tdb_first_use != 0)
595 0 : pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_SOFT);
596 0 : tdb->tdb_flags &= ~TDBF_SOFT_FIRSTUSE;
597 0 : }
598 0 : NET_UNLOCK();
599 0 : }
600 :
601 : void
602 0 : tdb_rehash(void)
603 : {
604 : struct tdb **new_tdbh, **new_tdbdst, **new_srcaddr, *tdbp, *tdbnp;
605 0 : u_int i, old_hashmask = tdb_hashmask;
606 : u_int32_t hashval;
607 :
608 0 : NET_ASSERT_LOCKED();
609 :
610 0 : tdb_hashmask = (tdb_hashmask << 1) | 1;
611 :
612 0 : arc4random_buf(&tdbkey, sizeof(tdbkey));
613 0 : new_tdbh = mallocarray(tdb_hashmask + 1, sizeof(struct tdb *), M_TDB,
614 : M_WAITOK | M_ZERO);
615 0 : new_tdbdst = mallocarray(tdb_hashmask + 1, sizeof(struct tdb *), M_TDB,
616 : M_WAITOK | M_ZERO);
617 0 : new_srcaddr = mallocarray(tdb_hashmask + 1, sizeof(struct tdb *), M_TDB,
618 : M_WAITOK | M_ZERO);
619 :
620 0 : for (i = 0; i <= old_hashmask; i++) {
621 0 : for (tdbp = tdbh[i]; tdbp != NULL; tdbp = tdbnp) {
622 0 : tdbnp = tdbp->tdb_hnext;
623 0 : hashval = tdb_hash(tdbp->tdb_rdomain,
624 0 : tdbp->tdb_spi, &tdbp->tdb_dst,
625 0 : tdbp->tdb_sproto);
626 0 : tdbp->tdb_hnext = new_tdbh[hashval];
627 0 : new_tdbh[hashval] = tdbp;
628 : }
629 :
630 0 : for (tdbp = tdbdst[i]; tdbp != NULL; tdbp = tdbnp) {
631 0 : tdbnp = tdbp->tdb_dnext;
632 0 : hashval = tdb_hash(tdbp->tdb_rdomain,
633 0 : 0, &tdbp->tdb_dst,
634 0 : tdbp->tdb_sproto);
635 0 : tdbp->tdb_dnext = new_tdbdst[hashval];
636 0 : new_tdbdst[hashval] = tdbp;
637 : }
638 :
639 0 : for (tdbp = tdbsrc[i]; tdbp != NULL; tdbp = tdbnp) {
640 0 : tdbnp = tdbp->tdb_snext;
641 0 : hashval = tdb_hash(tdbp->tdb_rdomain,
642 0 : 0, &tdbp->tdb_src,
643 0 : tdbp->tdb_sproto);
644 0 : tdbp->tdb_snext = new_srcaddr[hashval];
645 0 : new_srcaddr[hashval] = tdbp;
646 : }
647 : }
648 :
649 0 : free(tdbh, M_TDB, 0);
650 0 : tdbh = new_tdbh;
651 :
652 0 : free(tdbdst, M_TDB, 0);
653 0 : tdbdst = new_tdbdst;
654 :
655 0 : free(tdbsrc, M_TDB, 0);
656 0 : tdbsrc = new_srcaddr;
657 0 : }
658 :
659 : /*
660 : * Add TDB in the hash table.
661 : */
662 : void
663 0 : puttdb(struct tdb *tdbp)
664 : {
665 : u_int32_t hashval;
666 :
667 0 : NET_ASSERT_LOCKED();
668 :
669 0 : if (tdbh == NULL) {
670 0 : arc4random_buf(&tdbkey, sizeof(tdbkey));
671 0 : tdbh = mallocarray(tdb_hashmask + 1, sizeof(struct tdb *),
672 : M_TDB, M_WAITOK | M_ZERO);
673 0 : tdbdst = mallocarray(tdb_hashmask + 1, sizeof(struct tdb *),
674 : M_TDB, M_WAITOK | M_ZERO);
675 0 : tdbsrc = mallocarray(tdb_hashmask + 1, sizeof(struct tdb *),
676 : M_TDB, M_WAITOK | M_ZERO);
677 0 : }
678 :
679 0 : hashval = tdb_hash(tdbp->tdb_rdomain, tdbp->tdb_spi,
680 0 : &tdbp->tdb_dst, tdbp->tdb_sproto);
681 :
682 : /*
683 : * Rehash if this tdb would cause a bucket to have more than
684 : * two items and if the number of tdbs exceed 10% of the
685 : * bucket count. This number is arbitratily chosen and is
686 : * just a measure to not keep rehashing when adding and
687 : * removing tdbs which happens to always end up in the same
688 : * bucket, which is not uncommon when doing manual keying.
689 : */
690 0 : if (tdbh[hashval] != NULL && tdbh[hashval]->tdb_hnext != NULL &&
691 0 : tdb_count * 10 > tdb_hashmask + 1) {
692 0 : tdb_rehash();
693 0 : hashval = tdb_hash(tdbp->tdb_rdomain, tdbp->tdb_spi,
694 0 : &tdbp->tdb_dst, tdbp->tdb_sproto);
695 0 : }
696 :
697 0 : tdbp->tdb_hnext = tdbh[hashval];
698 0 : tdbh[hashval] = tdbp;
699 :
700 0 : hashval = tdb_hash(tdbp->tdb_rdomain, 0, &tdbp->tdb_dst,
701 0 : tdbp->tdb_sproto);
702 0 : tdbp->tdb_dnext = tdbdst[hashval];
703 0 : tdbdst[hashval] = tdbp;
704 :
705 0 : hashval = tdb_hash(tdbp->tdb_rdomain, 0, &tdbp->tdb_src,
706 0 : tdbp->tdb_sproto);
707 0 : tdbp->tdb_snext = tdbsrc[hashval];
708 0 : tdbsrc[hashval] = tdbp;
709 :
710 0 : tdb_count++;
711 0 : if ((tdbp->tdb_flags & (TDBF_INVALID|TDBF_TUNNELING)) == TDBF_TUNNELING)
712 0 : ipsecstat_inc(ipsec_tunnels);
713 :
714 0 : ipsec_last_added = time_second;
715 0 : }
716 :
717 : void
718 0 : tdb_unlink(struct tdb *tdbp)
719 : {
720 : struct tdb *tdbpp;
721 : u_int32_t hashval;
722 :
723 0 : NET_ASSERT_LOCKED();
724 :
725 0 : if (tdbh == NULL)
726 0 : return;
727 :
728 0 : hashval = tdb_hash(tdbp->tdb_rdomain, tdbp->tdb_spi,
729 0 : &tdbp->tdb_dst, tdbp->tdb_sproto);
730 :
731 0 : if (tdbh[hashval] == tdbp) {
732 0 : tdbh[hashval] = tdbp->tdb_hnext;
733 0 : } else {
734 0 : for (tdbpp = tdbh[hashval]; tdbpp != NULL;
735 : tdbpp = tdbpp->tdb_hnext) {
736 0 : if (tdbpp->tdb_hnext == tdbp) {
737 0 : tdbpp->tdb_hnext = tdbp->tdb_hnext;
738 0 : break;
739 : }
740 : }
741 : }
742 :
743 0 : tdbp->tdb_hnext = NULL;
744 :
745 0 : hashval = tdb_hash(tdbp->tdb_rdomain, 0, &tdbp->tdb_dst,
746 0 : tdbp->tdb_sproto);
747 :
748 0 : if (tdbdst[hashval] == tdbp) {
749 0 : tdbdst[hashval] = tdbp->tdb_dnext;
750 0 : } else {
751 0 : for (tdbpp = tdbdst[hashval]; tdbpp != NULL;
752 : tdbpp = tdbpp->tdb_dnext) {
753 0 : if (tdbpp->tdb_dnext == tdbp) {
754 0 : tdbpp->tdb_dnext = tdbp->tdb_dnext;
755 0 : break;
756 : }
757 : }
758 : }
759 :
760 0 : tdbp->tdb_dnext = NULL;
761 :
762 0 : hashval = tdb_hash(tdbp->tdb_rdomain, 0, &tdbp->tdb_src,
763 0 : tdbp->tdb_sproto);
764 :
765 0 : if (tdbsrc[hashval] == tdbp) {
766 0 : tdbsrc[hashval] = tdbp->tdb_snext;
767 0 : }
768 : else {
769 0 : for (tdbpp = tdbsrc[hashval]; tdbpp != NULL;
770 : tdbpp = tdbpp->tdb_snext) {
771 0 : if (tdbpp->tdb_snext == tdbp) {
772 0 : tdbpp->tdb_snext = tdbp->tdb_snext;
773 0 : break;
774 : }
775 : }
776 : }
777 :
778 0 : tdbp->tdb_snext = NULL;
779 0 : tdb_count--;
780 0 : if ((tdbp->tdb_flags & (TDBF_INVALID|TDBF_TUNNELING)) ==
781 : TDBF_TUNNELING) {
782 0 : ipsecstat_dec(ipsec_tunnels);
783 0 : ipsecstat_inc(ipsec_prevtunnels);
784 0 : }
785 0 : }
786 :
787 : void
788 0 : tdb_delete(struct tdb *tdbp)
789 : {
790 0 : NET_ASSERT_LOCKED();
791 :
792 0 : tdb_unlink(tdbp);
793 0 : tdb_free(tdbp);
794 0 : }
795 :
796 : /*
797 : * Allocate a TDB and initialize a few basic fields.
798 : */
799 : struct tdb *
800 0 : tdb_alloc(u_int rdomain)
801 : {
802 : struct tdb *tdbp;
803 :
804 0 : NET_ASSERT_LOCKED();
805 :
806 0 : tdbp = malloc(sizeof(*tdbp), M_TDB, M_WAITOK | M_ZERO);
807 :
808 0 : TAILQ_INIT(&tdbp->tdb_policy_head);
809 :
810 : /* Record establishment time. */
811 0 : tdbp->tdb_established = time_second;
812 :
813 : /* Save routing domain */
814 0 : tdbp->tdb_rdomain = rdomain;
815 :
816 : /* Initialize timeouts. */
817 0 : timeout_set_proc(&tdbp->tdb_timer_tmo, tdb_timeout, tdbp);
818 0 : timeout_set_proc(&tdbp->tdb_first_tmo, tdb_firstuse, tdbp);
819 0 : timeout_set_proc(&tdbp->tdb_stimer_tmo, tdb_soft_timeout, tdbp);
820 0 : timeout_set_proc(&tdbp->tdb_sfirst_tmo, tdb_soft_firstuse, tdbp);
821 :
822 0 : return tdbp;
823 : }
824 :
825 : void
826 0 : tdb_free(struct tdb *tdbp)
827 : {
828 : struct ipsec_policy *ipo;
829 :
830 0 : NET_ASSERT_LOCKED();
831 :
832 0 : if (tdbp->tdb_xform) {
833 0 : (*(tdbp->tdb_xform->xf_zeroize))(tdbp);
834 0 : tdbp->tdb_xform = NULL;
835 0 : }
836 :
837 : #if NPFSYNC > 0
838 : /* Cleanup pfsync references */
839 0 : pfsync_delete_tdb(tdbp);
840 : #endif
841 :
842 : /* Cleanup SPD references. */
843 0 : for (ipo = TAILQ_FIRST(&tdbp->tdb_policy_head); ipo;
844 0 : ipo = TAILQ_FIRST(&tdbp->tdb_policy_head)) {
845 0 : TAILQ_REMOVE(&tdbp->tdb_policy_head, ipo, ipo_tdb_next);
846 0 : ipo->ipo_tdb = NULL;
847 0 : ipo->ipo_last_searched = 0; /* Force a re-search. */
848 : }
849 :
850 0 : if (tdbp->tdb_ids) {
851 0 : ipsp_ids_free(tdbp->tdb_ids);
852 0 : tdbp->tdb_ids = NULL;
853 0 : }
854 :
855 : #if NPF > 0
856 0 : if (tdbp->tdb_tag) {
857 0 : pf_tag_unref(tdbp->tdb_tag);
858 0 : tdbp->tdb_tag = 0;
859 0 : }
860 : #endif
861 :
862 0 : if ((tdbp->tdb_onext) && (tdbp->tdb_onext->tdb_inext == tdbp))
863 0 : tdbp->tdb_onext->tdb_inext = NULL;
864 :
865 0 : if ((tdbp->tdb_inext) && (tdbp->tdb_inext->tdb_onext == tdbp))
866 0 : tdbp->tdb_inext->tdb_onext = NULL;
867 :
868 : /* Remove expiration timeouts. */
869 0 : tdbp->tdb_flags &= ~(TDBF_FIRSTUSE | TDBF_SOFT_FIRSTUSE | TDBF_TIMER |
870 : TDBF_SOFT_TIMER);
871 0 : timeout_del(&tdbp->tdb_timer_tmo);
872 0 : timeout_del(&tdbp->tdb_first_tmo);
873 0 : timeout_del(&tdbp->tdb_stimer_tmo);
874 0 : timeout_del(&tdbp->tdb_sfirst_tmo);
875 :
876 0 : timeout_set_proc(&tdbp->tdb_timer_tmo, tdb_reaper, tdbp);
877 0 : timeout_add(&tdbp->tdb_timer_tmo, 0);
878 0 : }
879 :
880 : void
881 0 : tdb_reaper(void *xtdbp)
882 : {
883 0 : struct tdb *tdbp = xtdbp;
884 :
885 0 : free(tdbp, M_TDB, 0);
886 0 : }
887 :
888 : /*
889 : * Do further initializations of a TDB.
890 : */
891 : int
892 0 : tdb_init(struct tdb *tdbp, u_int16_t alg, struct ipsecinit *ii)
893 : {
894 : struct xformsw *xsp;
895 : int err;
896 : #ifdef ENCDEBUG
897 : char buf[INET6_ADDRSTRLEN];
898 : #endif
899 :
900 0 : for (xsp = xformsw; xsp < xformswNXFORMSW; xsp++) {
901 0 : if (xsp->xf_type == alg) {
902 0 : err = (*(xsp->xf_init))(tdbp, xsp, ii);
903 0 : return err;
904 : }
905 : }
906 :
907 : DPRINTF(("%s: no alg %d for spi %08x, addr %s, proto %d\n", __func__,
908 : alg, ntohl(tdbp->tdb_spi), ipsp_address(&tdbp->tdb_dst, buf,
909 : sizeof(buf)), tdbp->tdb_sproto));
910 :
911 0 : return EINVAL;
912 0 : }
913 :
914 : #ifdef ENCDEBUG
915 : /* Return a printable string for the address. */
916 : const char *
917 : ipsp_address(union sockaddr_union *sa, char *buf, socklen_t size)
918 : {
919 : switch (sa->sa.sa_family) {
920 : case AF_INET:
921 : return inet_ntop(AF_INET, &sa->sin.sin_addr,
922 : buf, (size_t)size);
923 :
924 : #ifdef INET6
925 : case AF_INET6:
926 : return inet_ntop(AF_INET6, &sa->sin6.sin6_addr,
927 : buf, (size_t)size);
928 : #endif /* INET6 */
929 :
930 : default:
931 : return "(unknown address family)";
932 : }
933 : }
934 : #endif /* ENCDEBUG */
935 :
936 : /* Check whether an IP{4,6} address is unspecified. */
937 : int
938 0 : ipsp_is_unspecified(union sockaddr_union addr)
939 : {
940 0 : switch (addr.sa.sa_family) {
941 : case AF_INET:
942 0 : if (addr.sin.sin_addr.s_addr == INADDR_ANY)
943 0 : return 1;
944 : else
945 0 : return 0;
946 :
947 : #ifdef INET6
948 : case AF_INET6:
949 0 : if (IN6_IS_ADDR_UNSPECIFIED(&addr.sin6.sin6_addr))
950 0 : return 1;
951 : else
952 0 : return 0;
953 : #endif /* INET6 */
954 :
955 : case 0: /* No family set. */
956 : default:
957 0 : return 1;
958 : }
959 0 : }
960 :
961 : int
962 0 : ipsp_ids_match(struct ipsec_ids *a, struct ipsec_ids *b)
963 : {
964 0 : return a == b;
965 : }
966 :
967 : struct ipsec_ids *
968 0 : ipsp_ids_insert(struct ipsec_ids *ids)
969 : {
970 : struct ipsec_ids *found;
971 : u_int32_t start_flow;
972 :
973 0 : NET_ASSERT_LOCKED();
974 :
975 0 : found = RBT_INSERT(ipsec_ids_tree, &ipsec_ids_tree, ids);
976 0 : if (found) {
977 : /* if refcount was zero, then timeout is running */
978 0 : if (found->id_refcount++ == 0)
979 0 : timeout_del(&found->id_timeout);
980 : DPRINTF(("%s: ids %p count %d\n", __func__,
981 : found, found->id_refcount));
982 0 : return found;
983 : }
984 0 : ids->id_flow = start_flow = ipsec_ids_next_flow;
985 0 : if (++ipsec_ids_next_flow == 0)
986 : ipsec_ids_next_flow = 1;
987 0 : while (RBT_INSERT(ipsec_ids_flows, &ipsec_ids_flows, ids) != NULL) {
988 0 : ids->id_flow = ipsec_ids_next_flow;
989 0 : if (++ipsec_ids_next_flow == 0)
990 : ipsec_ids_next_flow = 1;
991 0 : if (ipsec_ids_next_flow == start_flow) {
992 : DPRINTF(("ipsec_ids_next_flow exhausted %u\n",
993 : ipsec_ids_next_flow));
994 0 : return NULL;
995 : }
996 : }
997 0 : ids->id_refcount = 1;
998 : DPRINTF(("%s: new ids %p flow %u\n", __func__, ids, ids->id_flow));
999 0 : timeout_set_proc(&ids->id_timeout, ipsp_ids_timeout, ids);
1000 0 : return ids;
1001 0 : }
1002 :
1003 : struct ipsec_ids *
1004 0 : ipsp_ids_lookup(u_int32_t ipsecflowinfo)
1005 : {
1006 0 : struct ipsec_ids key;
1007 :
1008 0 : NET_ASSERT_LOCKED();
1009 :
1010 0 : key.id_flow = ipsecflowinfo;
1011 0 : return RBT_FIND(ipsec_ids_flows, &ipsec_ids_flows, &key);
1012 0 : }
1013 :
1014 : /* free ids only from delayed timeout */
1015 : void
1016 0 : ipsp_ids_timeout(void *arg)
1017 : {
1018 0 : struct ipsec_ids *ids = arg;
1019 :
1020 : DPRINTF(("%s: ids %p count %d\n", __func__, ids, ids->id_refcount));
1021 0 : KASSERT(ids->id_refcount == 0);
1022 :
1023 0 : NET_LOCK();
1024 0 : RBT_REMOVE(ipsec_ids_tree, &ipsec_ids_tree, ids);
1025 0 : RBT_REMOVE(ipsec_ids_flows, &ipsec_ids_flows, ids);
1026 0 : free(ids->id_local, M_CREDENTIALS, 0);
1027 0 : free(ids->id_remote, M_CREDENTIALS, 0);
1028 0 : free(ids, M_CREDENTIALS, 0);
1029 0 : NET_UNLOCK();
1030 0 : }
1031 :
1032 : /* decrements refcount, actual free happens in timeout */
1033 : void
1034 0 : ipsp_ids_free(struct ipsec_ids *ids)
1035 : {
1036 : /*
1037 : * If the refcount becomes zero, then a timeout is started. This
1038 : * timeout must be cancelled if refcount is increased from zero.
1039 : */
1040 : DPRINTF(("%s: ids %p count %d\n", __func__, ids, ids->id_refcount));
1041 0 : KASSERT(ids->id_refcount > 0);
1042 0 : if (--ids->id_refcount == 0)
1043 0 : timeout_add_sec(&ids->id_timeout, ipsec_ids_idle);
1044 0 : }
1045 :
1046 : static int
1047 0 : ipsp_id_cmp(struct ipsec_id *a, struct ipsec_id *b)
1048 : {
1049 0 : if (a->type > b->type)
1050 0 : return 1;
1051 0 : if (a->type < b->type)
1052 0 : return -1;
1053 0 : if (a->len > b->len)
1054 0 : return 1;
1055 0 : if (a->len < b->len)
1056 0 : return -1;
1057 0 : return memcmp(a + 1, b + 1, a->len);
1058 0 : }
1059 :
1060 : static inline int
1061 0 : ipsp_ids_cmp(const struct ipsec_ids *a, const struct ipsec_ids *b)
1062 : {
1063 : int ret;
1064 :
1065 0 : ret = ipsp_id_cmp(a->id_remote, b->id_remote);
1066 0 : if (ret != 0)
1067 0 : return ret;
1068 0 : return ipsp_id_cmp(a->id_local, b->id_local);
1069 0 : }
1070 :
1071 : static inline int
1072 0 : ipsp_ids_flow_cmp(const struct ipsec_ids *a, const struct ipsec_ids *b)
1073 : {
1074 0 : if (a->id_flow > b->id_flow)
1075 0 : return 1;
1076 0 : if (a->id_flow < b->id_flow)
1077 0 : return -1;
1078 0 : return 0;
1079 0 : }
|