Line data Source code
1 : /* $OpenBSD: ip_spd.c,v 1.98 2018/06/25 11:11:41 mpi Exp $ */
2 : /*
3 : * The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu)
4 : *
5 : * Copyright (c) 2000-2001 Angelos D. Keromytis.
6 : *
7 : * Permission to use, copy, and modify this software with or without fee
8 : * is hereby granted, provided that this entire notice is included in
9 : * all copies of any software which is or includes a copy or
10 : * modification of this software.
11 : * You may use this code under the GNU public license if you so wish. Please
12 : * contribute changes back to the authors under this freer than GPL license
13 : * so that we may further the use of strong encryption without limitations to
14 : * all.
15 : *
16 : * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
17 : * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
18 : * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
19 : * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
20 : * PURPOSE.
21 : */
22 :
23 : #include <sys/param.h>
24 : #include <sys/systm.h>
25 : #include <sys/mbuf.h>
26 : #include <sys/socket.h>
27 : #include <sys/kernel.h>
28 : #include <sys/socketvar.h>
29 : #include <sys/domain.h>
30 : #include <sys/protosw.h>
31 : #include <sys/pool.h>
32 : #include <sys/timeout.h>
33 :
34 : #include <net/route.h>
35 : #include <net/netisr.h>
36 :
37 : #include <netinet/in.h>
38 : #include <netinet/ip.h>
39 : #include <netinet/ip_var.h>
40 : #include <netinet/in_pcb.h>
41 : #include <netinet/ip_ipsp.h>
42 : #include <net/pfkeyv2.h>
43 :
44 : int ipsp_acquire_sa(struct ipsec_policy *, union sockaddr_union *,
45 : union sockaddr_union *, struct sockaddr_encap *, struct mbuf *);
46 : struct ipsec_acquire *ipsp_pending_acquire(struct ipsec_policy *,
47 : union sockaddr_union *);
48 : void ipsp_delete_acquire_timo(void *);
49 : void ipsp_delete_acquire(struct ipsec_acquire *);
50 :
51 : struct pool ipsec_policy_pool;
52 : struct pool ipsec_acquire_pool;
53 : int ipsec_policy_pool_initialized = 0;
54 :
55 : /* Protected by the NET_LOCK(). */
56 : int ipsec_acquire_pool_initialized = 0;
57 : struct radix_node_head **spd_tables;
58 : unsigned int spd_table_max;
59 : TAILQ_HEAD(ipsec_acquire_head, ipsec_acquire) ipsec_acquire_head =
60 : TAILQ_HEAD_INITIALIZER(ipsec_acquire_head);
61 :
62 : struct radix_node_head *
63 0 : spd_table_get(unsigned int rtableid)
64 : {
65 : unsigned int rdomain;
66 :
67 0 : NET_ASSERT_LOCKED();
68 :
69 0 : if (spd_tables == NULL)
70 0 : return (NULL);
71 :
72 0 : rdomain = rtable_l2(rtableid);
73 0 : if (rdomain > spd_table_max)
74 0 : return (NULL);
75 :
76 0 : return (spd_tables[rdomain]);
77 0 : }
78 :
79 : struct radix_node_head *
80 0 : spd_table_add(unsigned int rtableid)
81 : {
82 0 : struct radix_node_head *rnh = NULL;
83 : unsigned int rdomain;
84 : void *p;
85 :
86 0 : NET_ASSERT_LOCKED();
87 :
88 0 : rdomain = rtable_l2(rtableid);
89 0 : if (spd_tables == NULL || rdomain > spd_table_max) {
90 0 : if ((p = mallocarray(rdomain + 1, sizeof(*rnh),
91 0 : M_RTABLE, M_NOWAIT|M_ZERO)) == NULL)
92 0 : return (NULL);
93 :
94 0 : if (spd_tables != NULL) {
95 0 : memcpy(p, spd_tables, sizeof(*rnh) * (spd_table_max+1));
96 0 : free(spd_tables, M_RTABLE, 0);
97 0 : }
98 0 : spd_tables = p;
99 0 : spd_table_max = rdomain;
100 0 : }
101 :
102 0 : if (spd_tables[rdomain] == NULL) {
103 0 : if (rn_inithead((void **)&rnh,
104 0 : offsetof(struct sockaddr_encap, sen_type)) == 0)
105 0 : rnh = NULL;
106 0 : spd_tables[rdomain] = rnh;
107 0 : }
108 :
109 0 : return (spd_tables[rdomain]);
110 0 : }
111 :
112 : int
113 0 : spd_table_walk(unsigned int rtableid,
114 : int (*func)(struct ipsec_policy *, void *, unsigned int), void *arg)
115 : {
116 : struct radix_node_head *rnh;
117 0 : int (*walker)(struct radix_node *, void *, u_int) = (void *)func;
118 : int error;
119 :
120 0 : rnh = spd_table_get(rtableid);
121 0 : if (rnh == NULL)
122 0 : return (0);
123 :
124 : /* EGAIN means the tree changed. */
125 0 : while ((error = rn_walktree(rnh, walker, arg)) == EAGAIN)
126 0 : continue;
127 :
128 0 : return (error);
129 0 : }
130 :
131 : /*
132 : * Lookup at the SPD based on the headers contained on the mbuf. The second
133 : * argument indicates what protocol family the header at the beginning of
134 : * the mbuf is. hlen is the offset of the transport protocol header
135 : * in the mbuf.
136 : *
137 : * Return combinations (of return value and in *error):
138 : * - NULL/0 -> no IPsec required on packet
139 : * - NULL/-EINVAL -> silently drop the packet
140 : * - NULL/errno -> drop packet and return error
141 : * or a pointer to a TDB (and 0 in *error).
142 : *
143 : * In the case of incoming flows, only the first three combinations are
144 : * returned.
145 : */
146 : struct tdb *
147 0 : ipsp_spd_lookup(struct mbuf *m, int af, int hlen, int *error, int direction,
148 : struct tdb *tdbp, struct inpcb *inp, u_int32_t ipsecflowinfo)
149 : {
150 : struct radix_node_head *rnh;
151 : struct radix_node *rn;
152 0 : union sockaddr_union sdst, ssrc;
153 0 : struct sockaddr_encap *ddst, dst;
154 : struct ipsec_policy *ipo;
155 : struct ipsec_ids *ids = NULL;
156 : int signore = 0, dignore = 0;
157 0 : u_int rdomain = rtable_l2(m->m_pkthdr.ph_rtableid);
158 :
159 0 : NET_ASSERT_LOCKED();
160 :
161 : /*
162 : * If there are no flows in place, there's no point
163 : * continuing with the SPD lookup.
164 : */
165 0 : if (!ipsec_in_use && inp == NULL) {
166 0 : *error = 0;
167 0 : return NULL;
168 : }
169 :
170 : /*
171 : * If an input packet is destined to a BYPASS socket, just accept it.
172 : */
173 0 : if ((inp != NULL) && (direction == IPSP_DIRECTION_IN) &&
174 0 : (inp->inp_seclevel[SL_ESP_TRANS] == IPSEC_LEVEL_BYPASS) &&
175 0 : (inp->inp_seclevel[SL_ESP_NETWORK] == IPSEC_LEVEL_BYPASS) &&
176 0 : (inp->inp_seclevel[SL_AUTH] == IPSEC_LEVEL_BYPASS)) {
177 0 : *error = 0;
178 0 : return NULL;
179 : }
180 :
181 0 : memset(&dst, 0, sizeof(dst));
182 0 : memset(&sdst, 0, sizeof(union sockaddr_union));
183 0 : memset(&ssrc, 0, sizeof(union sockaddr_union));
184 : ddst = (struct sockaddr_encap *)&dst;
185 0 : ddst->sen_family = PF_KEY;
186 0 : ddst->sen_len = SENT_LEN;
187 :
188 0 : switch (af) {
189 : case AF_INET:
190 0 : if (hlen < sizeof (struct ip) || m->m_pkthdr.len < hlen) {
191 0 : *error = EINVAL;
192 0 : return NULL;
193 : }
194 0 : ddst->sen_direction = direction;
195 0 : ddst->sen_type = SENT_IP4;
196 :
197 0 : m_copydata(m, offsetof(struct ip, ip_src),
198 0 : sizeof(struct in_addr), (caddr_t) &(ddst->sen_ip_src));
199 0 : m_copydata(m, offsetof(struct ip, ip_dst),
200 0 : sizeof(struct in_addr), (caddr_t) &(ddst->sen_ip_dst));
201 0 : m_copydata(m, offsetof(struct ip, ip_p), sizeof(u_int8_t),
202 0 : (caddr_t) &(ddst->sen_proto));
203 :
204 0 : sdst.sin.sin_family = ssrc.sin.sin_family = AF_INET;
205 0 : sdst.sin.sin_len = ssrc.sin.sin_len =
206 : sizeof(struct sockaddr_in);
207 0 : ssrc.sin.sin_addr = ddst->sen_ip_src;
208 0 : sdst.sin.sin_addr = ddst->sen_ip_dst;
209 :
210 : /*
211 : * If TCP/UDP, extract the port numbers to use in the lookup.
212 : */
213 0 : switch (ddst->sen_proto) {
214 : case IPPROTO_UDP:
215 : case IPPROTO_TCP:
216 : /* Make sure there's enough data in the packet. */
217 0 : if (m->m_pkthdr.len < hlen + 2 * sizeof(u_int16_t)) {
218 0 : *error = EINVAL;
219 0 : return NULL;
220 : }
221 :
222 : /*
223 : * Luckily, the offset of the src/dst ports in
224 : * both the UDP and TCP headers is the same (first
225 : * two 16-bit values in the respective headers),
226 : * so we can just copy them.
227 : */
228 0 : m_copydata(m, hlen, sizeof(u_int16_t),
229 0 : (caddr_t) &(ddst->sen_sport));
230 0 : m_copydata(m, hlen + sizeof(u_int16_t), sizeof(u_int16_t),
231 0 : (caddr_t) &(ddst->sen_dport));
232 0 : break;
233 :
234 : default:
235 0 : ddst->sen_sport = 0;
236 0 : ddst->sen_dport = 0;
237 0 : }
238 :
239 : break;
240 :
241 : #ifdef INET6
242 : case AF_INET6:
243 0 : if (hlen < sizeof (struct ip6_hdr) || m->m_pkthdr.len < hlen) {
244 0 : *error = EINVAL;
245 0 : return NULL;
246 : }
247 0 : ddst->sen_type = SENT_IP6;
248 0 : ddst->sen_ip6_direction = direction;
249 :
250 0 : m_copydata(m, offsetof(struct ip6_hdr, ip6_src),
251 : sizeof(struct in6_addr),
252 0 : (caddr_t) &(ddst->sen_ip6_src));
253 0 : m_copydata(m, offsetof(struct ip6_hdr, ip6_dst),
254 : sizeof(struct in6_addr),
255 0 : (caddr_t) &(ddst->sen_ip6_dst));
256 0 : m_copydata(m, offsetof(struct ip6_hdr, ip6_nxt),
257 : sizeof(u_int8_t),
258 0 : (caddr_t) &(ddst->sen_ip6_proto));
259 :
260 0 : sdst.sin6.sin6_family = ssrc.sin6.sin6_family = AF_INET6;
261 0 : sdst.sin6.sin6_len = ssrc.sin6.sin6_len =
262 : sizeof(struct sockaddr_in6);
263 0 : in6_recoverscope(&ssrc.sin6, &ddst->sen_ip6_src);
264 0 : in6_recoverscope(&sdst.sin6, &ddst->sen_ip6_dst);
265 :
266 : /*
267 : * If TCP/UDP, extract the port numbers to use in the lookup.
268 : */
269 0 : switch (ddst->sen_ip6_proto) {
270 : case IPPROTO_UDP:
271 : case IPPROTO_TCP:
272 : /* Make sure there's enough data in the packet. */
273 0 : if (m->m_pkthdr.len < hlen + 2 * sizeof(u_int16_t)) {
274 0 : *error = EINVAL;
275 0 : return NULL;
276 : }
277 :
278 : /*
279 : * Luckily, the offset of the src/dst ports in
280 : * both the UDP and TCP headers is the same
281 : * (first two 16-bit values in the respective
282 : * headers), so we can just copy them.
283 : */
284 0 : m_copydata(m, hlen, sizeof(u_int16_t),
285 0 : (caddr_t) &(ddst->sen_ip6_sport));
286 0 : m_copydata(m, hlen + sizeof(u_int16_t), sizeof(u_int16_t),
287 0 : (caddr_t) &(ddst->sen_ip6_dport));
288 0 : break;
289 :
290 : default:
291 0 : ddst->sen_ip6_sport = 0;
292 0 : ddst->sen_ip6_dport = 0;
293 0 : }
294 :
295 : break;
296 : #endif /* INET6 */
297 :
298 : default:
299 0 : *error = EAFNOSUPPORT;
300 0 : return NULL;
301 : }
302 :
303 : /* Actual SPD lookup. */
304 0 : if ((rnh = spd_table_get(rdomain)) == NULL ||
305 0 : (rn = rn_match((caddr_t)&dst, rnh)) == NULL) {
306 : /*
307 : * Return whatever the socket requirements are, there are no
308 : * system-wide policies.
309 : */
310 0 : *error = 0;
311 0 : return ipsp_spd_inp(m, af, hlen, error, direction,
312 : tdbp, inp, NULL);
313 : }
314 0 : ipo = (struct ipsec_policy *)rn;
315 :
316 0 : switch (ipo->ipo_type) {
317 : case IPSP_PERMIT:
318 0 : *error = 0;
319 0 : return ipsp_spd_inp(m, af, hlen, error, direction, tdbp,
320 : inp, ipo);
321 :
322 : case IPSP_DENY:
323 0 : *error = EHOSTUNREACH;
324 0 : return NULL;
325 :
326 : case IPSP_IPSEC_USE:
327 : case IPSP_IPSEC_ACQUIRE:
328 : case IPSP_IPSEC_REQUIRE:
329 : case IPSP_IPSEC_DONTACQ:
330 : /* Nothing more needed here. */
331 : break;
332 :
333 : default:
334 0 : *error = EINVAL;
335 0 : return NULL;
336 : }
337 :
338 : /* Check for non-specific destination in the policy. */
339 0 : switch (ipo->ipo_dst.sa.sa_family) {
340 : case AF_INET:
341 0 : if ((ipo->ipo_dst.sin.sin_addr.s_addr == INADDR_ANY) ||
342 0 : (ipo->ipo_dst.sin.sin_addr.s_addr == INADDR_BROADCAST))
343 0 : dignore = 1;
344 : break;
345 :
346 : #ifdef INET6
347 : case AF_INET6:
348 0 : if ((IN6_IS_ADDR_UNSPECIFIED(&ipo->ipo_dst.sin6.sin6_addr)) ||
349 0 : (memcmp(&ipo->ipo_dst.sin6.sin6_addr, &in6mask128,
350 0 : sizeof(in6mask128)) == 0))
351 0 : dignore = 1;
352 : break;
353 : #endif /* INET6 */
354 : }
355 :
356 : /* Likewise for source. */
357 0 : switch (ipo->ipo_src.sa.sa_family) {
358 : case AF_INET:
359 0 : if (ipo->ipo_src.sin.sin_addr.s_addr == INADDR_ANY)
360 0 : signore = 1;
361 : break;
362 :
363 : #ifdef INET6
364 : case AF_INET6:
365 0 : if (IN6_IS_ADDR_UNSPECIFIED(&ipo->ipo_src.sin6.sin6_addr))
366 0 : signore = 1;
367 : break;
368 : #endif /* INET6 */
369 : }
370 :
371 : /* Do we have a cached entry ? If so, check if it's still valid. */
372 0 : if ((ipo->ipo_tdb) && (ipo->ipo_tdb->tdb_flags & TDBF_INVALID)) {
373 0 : TAILQ_REMOVE(&ipo->ipo_tdb->tdb_policy_head, ipo,
374 : ipo_tdb_next);
375 0 : ipo->ipo_tdb = NULL;
376 0 : }
377 :
378 : /* Outgoing packet policy check. */
379 0 : if (direction == IPSP_DIRECTION_OUT) {
380 : /*
381 : * If the packet is destined for the policy-specified
382 : * gateway/endhost, and the socket has the BYPASS
383 : * option set, skip IPsec processing.
384 : */
385 0 : if ((inp != NULL) &&
386 0 : (inp->inp_seclevel[SL_ESP_TRANS] == IPSEC_LEVEL_BYPASS) &&
387 0 : (inp->inp_seclevel[SL_ESP_NETWORK] ==
388 0 : IPSEC_LEVEL_BYPASS) &&
389 0 : (inp->inp_seclevel[SL_AUTH] == IPSEC_LEVEL_BYPASS)) {
390 : /* Direct match. */
391 0 : if (dignore ||
392 0 : !memcmp(&sdst, &ipo->ipo_dst, sdst.sa.sa_len)) {
393 0 : *error = 0;
394 0 : return NULL;
395 : }
396 : }
397 :
398 0 : if (ipsecflowinfo)
399 0 : ids = ipsp_ids_lookup(ipsecflowinfo);
400 :
401 : /* Check that the cached TDB (if present), is appropriate. */
402 0 : if (ipo->ipo_tdb) {
403 0 : if ((ipo->ipo_last_searched <= ipsec_last_added) ||
404 0 : (ipo->ipo_sproto != ipo->ipo_tdb->tdb_sproto) ||
405 0 : memcmp(dignore ? &sdst : &ipo->ipo_dst,
406 : &ipo->ipo_tdb->tdb_dst,
407 : ipo->ipo_tdb->tdb_dst.sa.sa_len))
408 : goto nomatchout;
409 :
410 0 : if (!ipsp_aux_match(ipo->ipo_tdb,
411 0 : ids ? ids : ipo->ipo_ids,
412 0 : &ipo->ipo_addr, &ipo->ipo_mask))
413 : goto nomatchout;
414 :
415 : /* Cached entry is good. */
416 0 : *error = 0;
417 0 : return ipsp_spd_inp(m, af, hlen, error, direction,
418 : tdbp, inp, ipo);
419 :
420 : nomatchout:
421 : /* Cached TDB was not good. */
422 0 : TAILQ_REMOVE(&ipo->ipo_tdb->tdb_policy_head, ipo,
423 : ipo_tdb_next);
424 0 : ipo->ipo_tdb = NULL;
425 0 : ipo->ipo_last_searched = 0;
426 0 : }
427 :
428 : /*
429 : * If no SA has been added since the last time we did a
430 : * lookup, there's no point searching for one. However, if the
431 : * destination gateway is left unspecified (or is all-1's),
432 : * always lookup since this is a generic-match rule
433 : * (otherwise, we can have situations where SAs to some
434 : * destinations exist but are not used, possibly leading to an
435 : * explosion in the number of acquired SAs).
436 : */
437 0 : if (ipo->ipo_last_searched <= ipsec_last_added) {
438 : /* "Touch" the entry. */
439 0 : if (dignore == 0)
440 0 : ipo->ipo_last_searched = time_second;
441 :
442 : /* Find an appropriate SA from the existing ones. */
443 0 : ipo->ipo_tdb =
444 0 : gettdbbydst(rdomain,
445 0 : dignore ? &sdst : &ipo->ipo_dst,
446 0 : ipo->ipo_sproto,
447 0 : ids ? ids: ipo->ipo_ids,
448 0 : &ipo->ipo_addr, &ipo->ipo_mask);
449 0 : if (ipo->ipo_tdb) {
450 0 : TAILQ_INSERT_TAIL(&ipo->ipo_tdb->tdb_policy_head,
451 : ipo, ipo_tdb_next);
452 0 : *error = 0;
453 0 : return ipsp_spd_inp(m, af, hlen, error,
454 : direction, tdbp, inp, ipo);
455 : }
456 : }
457 :
458 : /* So, we don't have an SA -- just a policy. */
459 0 : switch (ipo->ipo_type) {
460 : case IPSP_IPSEC_REQUIRE:
461 : /* Acquire SA through key management. */
462 0 : if (ipsp_acquire_sa(ipo,
463 0 : dignore ? &sdst : &ipo->ipo_dst,
464 0 : signore ? NULL : &ipo->ipo_src, ddst, m) != 0) {
465 0 : *error = EACCES;
466 0 : return NULL;
467 : }
468 :
469 : /* FALLTHROUGH */
470 : case IPSP_IPSEC_DONTACQ:
471 0 : *error = -EINVAL; /* Silently drop packet. */
472 0 : return NULL;
473 :
474 : case IPSP_IPSEC_ACQUIRE:
475 : /* Acquire SA through key management. */
476 0 : ipsp_acquire_sa(ipo, dignore ? &sdst : &ipo->ipo_dst,
477 0 : signore ? NULL : &ipo->ipo_src, ddst, NULL);
478 :
479 : /* FALLTHROUGH */
480 : case IPSP_IPSEC_USE:
481 0 : *error = 0;
482 0 : return ipsp_spd_inp(m, af, hlen, error, direction,
483 : tdbp, inp, ipo);
484 : }
485 : } else { /* IPSP_DIRECTION_IN */
486 0 : if (tdbp != NULL) {
487 : /* Direct match in the cache. */
488 0 : if (ipo->ipo_tdb == tdbp) {
489 0 : *error = 0;
490 0 : return ipsp_spd_inp(m, af, hlen, error,
491 : direction, tdbp, inp, ipo);
492 : }
493 :
494 0 : if (memcmp(dignore ? &ssrc : &ipo->ipo_dst,
495 0 : &tdbp->tdb_src, tdbp->tdb_src.sa.sa_len) ||
496 0 : (ipo->ipo_sproto != tdbp->tdb_sproto))
497 : goto nomatchin;
498 :
499 : /* Match source/dest IDs. */
500 0 : if (ipo->ipo_ids)
501 0 : if (tdbp->tdb_ids == NULL ||
502 0 : !ipsp_ids_match(ipo->ipo_ids, tdbp->tdb_ids))
503 : goto nomatchin;
504 :
505 : /* Add it to the cache. */
506 0 : if (ipo->ipo_tdb)
507 0 : TAILQ_REMOVE(&ipo->ipo_tdb->tdb_policy_head,
508 : ipo, ipo_tdb_next);
509 0 : ipo->ipo_tdb = tdbp;
510 0 : TAILQ_INSERT_TAIL(&tdbp->tdb_policy_head, ipo,
511 : ipo_tdb_next);
512 0 : *error = 0;
513 0 : return ipsp_spd_inp(m, af, hlen, error, direction,
514 : tdbp, inp, ipo);
515 :
516 : nomatchin: /* Nothing needed here, falling through */
517 : ;
518 : }
519 :
520 : /* Check whether cached entry applies. */
521 0 : if (ipo->ipo_tdb) {
522 : /*
523 : * We only need to check that the correct
524 : * security protocol and security gateway are
525 : * set; IDs will be the same since the cached
526 : * entry is linked on this policy.
527 : */
528 0 : if (ipo->ipo_sproto == ipo->ipo_tdb->tdb_sproto &&
529 0 : !memcmp(&ipo->ipo_tdb->tdb_src,
530 : dignore ? &ssrc : &ipo->ipo_dst,
531 : ipo->ipo_tdb->tdb_src.sa.sa_len))
532 : goto skipinputsearch;
533 :
534 : /* Not applicable, unlink. */
535 0 : TAILQ_REMOVE(&ipo->ipo_tdb->tdb_policy_head, ipo,
536 : ipo_tdb_next);
537 0 : ipo->ipo_last_searched = 0;
538 0 : ipo->ipo_tdb = NULL;
539 0 : }
540 :
541 : /* Find whether there exists an appropriate SA. */
542 0 : if (ipo->ipo_last_searched <= ipsec_last_added) {
543 0 : if (dignore == 0)
544 0 : ipo->ipo_last_searched = time_second;
545 :
546 0 : ipo->ipo_tdb =
547 0 : gettdbbysrc(rdomain,
548 0 : dignore ? &ssrc : &ipo->ipo_dst,
549 0 : ipo->ipo_sproto, ipo->ipo_ids,
550 0 : &ipo->ipo_addr, &ipo->ipo_mask);
551 0 : if (ipo->ipo_tdb)
552 0 : TAILQ_INSERT_TAIL(&ipo->ipo_tdb->tdb_policy_head,
553 : ipo, ipo_tdb_next);
554 : }
555 : skipinputsearch:
556 :
557 0 : switch (ipo->ipo_type) {
558 : case IPSP_IPSEC_REQUIRE:
559 : /* If appropriate SA exists, don't acquire another. */
560 0 : if (ipo->ipo_tdb) {
561 0 : *error = -EINVAL;
562 0 : return NULL;
563 : }
564 :
565 : /* Acquire SA through key management. */
566 0 : if ((*error = ipsp_acquire_sa(ipo,
567 0 : dignore ? &ssrc : &ipo->ipo_dst,
568 0 : signore ? NULL : &ipo->ipo_src, ddst, m)) != 0)
569 0 : return NULL;
570 :
571 : /* FALLTHROUGH */
572 : case IPSP_IPSEC_DONTACQ:
573 : /* Drop packet. */
574 0 : *error = -EINVAL;
575 0 : return NULL;
576 :
577 : case IPSP_IPSEC_ACQUIRE:
578 : /* If appropriate SA exists, don't acquire another. */
579 0 : if (ipo->ipo_tdb) {
580 0 : *error = 0;
581 0 : return ipsp_spd_inp(m, af, hlen, error,
582 : direction, tdbp, inp, ipo);
583 : }
584 :
585 : /* Acquire SA through key management. */
586 0 : ipsp_acquire_sa(ipo, dignore ? &ssrc : &ipo->ipo_dst,
587 0 : signore ? NULL : &ipo->ipo_src, ddst, NULL);
588 :
589 : /* FALLTHROUGH */
590 : case IPSP_IPSEC_USE:
591 0 : *error = 0;
592 0 : return ipsp_spd_inp(m, af, hlen, error, direction,
593 : tdbp, inp, ipo);
594 : }
595 : }
596 :
597 : /* Shouldn't ever get this far. */
598 0 : *error = EINVAL;
599 0 : return NULL;
600 0 : }
601 :
602 : /*
603 : * Delete a policy from the SPD.
604 : */
605 : int
606 0 : ipsec_delete_policy(struct ipsec_policy *ipo)
607 : {
608 : struct ipsec_acquire *ipa;
609 : struct radix_node_head *rnh;
610 0 : struct radix_node *rn = (struct radix_node *)ipo;
611 : int err = 0;
612 :
613 0 : NET_ASSERT_LOCKED();
614 :
615 0 : if (--ipo->ipo_ref_count > 0)
616 0 : return 0;
617 :
618 : /* Delete from SPD. */
619 0 : if ((rnh = spd_table_get(ipo->ipo_rdomain)) == NULL ||
620 0 : rn_delete(&ipo->ipo_addr, &ipo->ipo_mask, rnh, rn) == NULL)
621 0 : return (ESRCH);
622 :
623 0 : if (ipo->ipo_tdb != NULL)
624 0 : TAILQ_REMOVE(&ipo->ipo_tdb->tdb_policy_head, ipo,
625 : ipo_tdb_next);
626 :
627 0 : while ((ipa = TAILQ_FIRST(&ipo->ipo_acquires)) != NULL)
628 0 : ipsp_delete_acquire(ipa);
629 :
630 0 : TAILQ_REMOVE(&ipsec_policy_head, ipo, ipo_list);
631 :
632 0 : if (ipo->ipo_ids)
633 0 : ipsp_ids_free(ipo->ipo_ids);
634 :
635 0 : ipsec_in_use--;
636 :
637 0 : pool_put(&ipsec_policy_pool, ipo);
638 :
639 0 : return err;
640 0 : }
641 :
642 : void
643 0 : ipsp_delete_acquire_timo(void *v)
644 : {
645 0 : struct ipsec_acquire *ipa = v;
646 :
647 0 : NET_LOCK();
648 0 : ipsp_delete_acquire(ipa);
649 0 : NET_UNLOCK();
650 0 : }
651 :
652 : /*
653 : * Delete a pending IPsec acquire record.
654 : */
655 : void
656 0 : ipsp_delete_acquire(struct ipsec_acquire *ipa)
657 : {
658 0 : NET_ASSERT_LOCKED();
659 :
660 0 : timeout_del(&ipa->ipa_timeout);
661 0 : TAILQ_REMOVE(&ipsec_acquire_head, ipa, ipa_next);
662 0 : if (ipa->ipa_policy != NULL)
663 0 : TAILQ_REMOVE(&ipa->ipa_policy->ipo_acquires, ipa,
664 : ipa_ipo_next);
665 0 : pool_put(&ipsec_acquire_pool, ipa);
666 0 : }
667 :
668 : /*
669 : * Find out if there's an ACQUIRE pending.
670 : * XXX Need a better structure.
671 : */
672 : struct ipsec_acquire *
673 0 : ipsp_pending_acquire(struct ipsec_policy *ipo, union sockaddr_union *gw)
674 : {
675 : struct ipsec_acquire *ipa;
676 :
677 0 : NET_ASSERT_LOCKED();
678 :
679 0 : TAILQ_FOREACH (ipa, &ipo->ipo_acquires, ipa_ipo_next) {
680 0 : if (!memcmp(gw, &ipa->ipa_addr, gw->sa.sa_len))
681 0 : return ipa;
682 : }
683 :
684 0 : return NULL;
685 0 : }
686 :
687 : /*
688 : * Signal key management that we need an SA.
689 : * XXX For outgoing policies, we could try to hold on to the mbuf.
690 : */
691 : int
692 0 : ipsp_acquire_sa(struct ipsec_policy *ipo, union sockaddr_union *gw,
693 : union sockaddr_union *laddr, struct sockaddr_encap *ddst, struct mbuf *m)
694 : {
695 : struct ipsec_acquire *ipa;
696 :
697 0 : NET_ASSERT_LOCKED();
698 :
699 : /* Check whether request has been made already. */
700 0 : if ((ipa = ipsp_pending_acquire(ipo, gw)) != NULL)
701 0 : return 0;
702 :
703 : /* Add request in cache and proceed. */
704 0 : if (ipsec_acquire_pool_initialized == 0) {
705 0 : ipsec_acquire_pool_initialized = 1;
706 0 : pool_init(&ipsec_acquire_pool, sizeof(struct ipsec_acquire),
707 : 0, IPL_SOFTNET, 0, "ipsec acquire", NULL);
708 0 : }
709 :
710 0 : ipa = pool_get(&ipsec_acquire_pool, PR_NOWAIT|PR_ZERO);
711 0 : if (ipa == NULL)
712 0 : return ENOMEM;
713 :
714 0 : ipa->ipa_addr = *gw;
715 :
716 0 : timeout_set_proc(&ipa->ipa_timeout, ipsp_delete_acquire_timo, ipa);
717 :
718 0 : ipa->ipa_info.sen_len = ipa->ipa_mask.sen_len = SENT_LEN;
719 0 : ipa->ipa_info.sen_family = ipa->ipa_mask.sen_family = PF_KEY;
720 :
721 : /* Just copy the right information. */
722 0 : switch (ipo->ipo_addr.sen_type) {
723 : case SENT_IP4:
724 0 : ipa->ipa_info.sen_type = ipa->ipa_mask.sen_type = SENT_IP4;
725 0 : ipa->ipa_info.sen_direction = ipo->ipo_addr.sen_direction;
726 0 : ipa->ipa_mask.sen_direction = ipo->ipo_mask.sen_direction;
727 :
728 0 : if (ipsp_is_unspecified(ipo->ipo_dst)) {
729 0 : ipa->ipa_info.sen_ip_src = ddst->sen_ip_src;
730 0 : ipa->ipa_mask.sen_ip_src.s_addr = INADDR_BROADCAST;
731 :
732 0 : ipa->ipa_info.sen_ip_dst = ddst->sen_ip_dst;
733 0 : ipa->ipa_mask.sen_ip_dst.s_addr = INADDR_BROADCAST;
734 0 : } else {
735 0 : ipa->ipa_info.sen_ip_src = ipo->ipo_addr.sen_ip_src;
736 0 : ipa->ipa_mask.sen_ip_src = ipo->ipo_mask.sen_ip_src;
737 :
738 0 : ipa->ipa_info.sen_ip_dst = ipo->ipo_addr.sen_ip_dst;
739 0 : ipa->ipa_mask.sen_ip_dst = ipo->ipo_mask.sen_ip_dst;
740 : }
741 :
742 0 : ipa->ipa_info.sen_proto = ipo->ipo_addr.sen_proto;
743 0 : ipa->ipa_mask.sen_proto = ipo->ipo_mask.sen_proto;
744 :
745 0 : if (ipo->ipo_addr.sen_proto) {
746 0 : ipa->ipa_info.sen_sport = ipo->ipo_addr.sen_sport;
747 0 : ipa->ipa_mask.sen_sport = ipo->ipo_mask.sen_sport;
748 :
749 0 : ipa->ipa_info.sen_dport = ipo->ipo_addr.sen_dport;
750 0 : ipa->ipa_mask.sen_dport = ipo->ipo_mask.sen_dport;
751 0 : }
752 : break;
753 :
754 : #ifdef INET6
755 : case SENT_IP6:
756 0 : ipa->ipa_info.sen_type = ipa->ipa_mask.sen_type = SENT_IP6;
757 0 : ipa->ipa_info.sen_ip6_direction =
758 0 : ipo->ipo_addr.sen_ip6_direction;
759 0 : ipa->ipa_mask.sen_ip6_direction =
760 0 : ipo->ipo_mask.sen_ip6_direction;
761 :
762 0 : if (ipsp_is_unspecified(ipo->ipo_dst)) {
763 0 : ipa->ipa_info.sen_ip6_src = ddst->sen_ip6_src;
764 0 : ipa->ipa_mask.sen_ip6_src = in6mask128;
765 :
766 0 : ipa->ipa_info.sen_ip6_dst = ddst->sen_ip6_dst;
767 0 : ipa->ipa_mask.sen_ip6_dst = in6mask128;
768 0 : } else {
769 0 : ipa->ipa_info.sen_ip6_src = ipo->ipo_addr.sen_ip6_src;
770 0 : ipa->ipa_mask.sen_ip6_src = ipo->ipo_mask.sen_ip6_src;
771 :
772 0 : ipa->ipa_info.sen_ip6_dst = ipo->ipo_addr.sen_ip6_dst;
773 0 : ipa->ipa_mask.sen_ip6_dst = ipo->ipo_mask.sen_ip6_dst;
774 : }
775 :
776 0 : ipa->ipa_info.sen_ip6_proto = ipo->ipo_addr.sen_ip6_proto;
777 0 : ipa->ipa_mask.sen_ip6_proto = ipo->ipo_mask.sen_ip6_proto;
778 :
779 0 : if (ipo->ipo_mask.sen_ip6_proto) {
780 0 : ipa->ipa_info.sen_ip6_sport =
781 0 : ipo->ipo_addr.sen_ip6_sport;
782 0 : ipa->ipa_mask.sen_ip6_sport =
783 0 : ipo->ipo_mask.sen_ip6_sport;
784 0 : ipa->ipa_info.sen_ip6_dport =
785 0 : ipo->ipo_addr.sen_ip6_dport;
786 0 : ipa->ipa_mask.sen_ip6_dport =
787 0 : ipo->ipo_mask.sen_ip6_dport;
788 0 : }
789 : break;
790 : #endif /* INET6 */
791 :
792 : default:
793 0 : pool_put(&ipsec_acquire_pool, ipa);
794 0 : return 0;
795 : }
796 :
797 : #ifdef IPSEC
798 0 : timeout_add_sec(&ipa->ipa_timeout, ipsec_expire_acquire);
799 : #endif
800 :
801 0 : TAILQ_INSERT_TAIL(&ipsec_acquire_head, ipa, ipa_next);
802 0 : TAILQ_INSERT_TAIL(&ipo->ipo_acquires, ipa, ipa_ipo_next);
803 0 : ipa->ipa_policy = ipo;
804 :
805 : /* PF_KEYv2 notification message. */
806 0 : return pfkeyv2_acquire(ipo, gw, laddr, &ipa->ipa_seq, ddst);
807 0 : }
808 :
809 : /*
810 : * Deal with PCB security requirements.
811 : */
812 : struct tdb *
813 0 : ipsp_spd_inp(struct mbuf *m, int af, int hlen, int *error, int direction,
814 : struct tdb *tdbp, struct inpcb *inp, struct ipsec_policy *ipo)
815 : {
816 : /* Sanity check. */
817 0 : if (inp == NULL)
818 : goto justreturn;
819 :
820 : /* We only support IPSEC_LEVEL_BYPASS or IPSEC_LEVEL_AVAIL */
821 :
822 0 : if (inp->inp_seclevel[SL_ESP_TRANS] == IPSEC_LEVEL_BYPASS &&
823 0 : inp->inp_seclevel[SL_ESP_NETWORK] == IPSEC_LEVEL_BYPASS &&
824 0 : inp->inp_seclevel[SL_AUTH] == IPSEC_LEVEL_BYPASS)
825 : goto justreturn;
826 :
827 0 : if (inp->inp_seclevel[SL_ESP_TRANS] == IPSEC_LEVEL_AVAIL &&
828 0 : inp->inp_seclevel[SL_ESP_NETWORK] == IPSEC_LEVEL_AVAIL &&
829 0 : inp->inp_seclevel[SL_AUTH] == IPSEC_LEVEL_AVAIL)
830 : goto justreturn;
831 :
832 0 : *error = -EINVAL;
833 0 : return NULL;
834 :
835 : justreturn:
836 0 : if (ipo != NULL)
837 0 : return ipo->ipo_tdb;
838 : else
839 0 : return NULL;
840 0 : }
841 :
842 : /*
843 : * Find a pending ACQUIRE record based on its sequence number.
844 : * XXX Need to use a better data structure.
845 : */
846 : struct ipsec_acquire *
847 0 : ipsec_get_acquire(u_int32_t seq)
848 : {
849 : struct ipsec_acquire *ipa;
850 :
851 0 : NET_ASSERT_LOCKED();
852 :
853 0 : TAILQ_FOREACH (ipa, &ipsec_acquire_head, ipa_next)
854 0 : if (ipa->ipa_seq == seq)
855 0 : return ipa;
856 :
857 0 : return NULL;
858 0 : }
|