Annotation of sys/netinet/ip_spd.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: ip_spd.c,v 1.53 2007/02/14 00:53:48 jsg 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/protosw.h>
30:
31: #include <net/if.h>
32: #include <net/route.h>
33: #include <net/netisr.h>
34:
35: #ifdef INET
36: #include <netinet/in.h>
37: #include <netinet/in_systm.h>
38: #include <netinet/ip.h>
39: #include <netinet/in_pcb.h>
40: #include <netinet/in_var.h>
41: #endif /* INET */
42:
43: #ifdef INET6
44: #ifndef INET
45: #include <netinet/in.h>
46: #endif
47: #include <netinet6/in6_var.h>
48: #endif /* INET6 */
49:
50: #include <netinet/ip_ipsp.h>
51: #include <net/pfkeyv2.h>
52:
53: #ifdef ENCDEBUG
54: #define DPRINTF(x) if (encdebug) printf x
55: #else
56: #define DPRINTF(x)
57: #endif
58:
59: struct pool ipsec_policy_pool;
60: struct pool ipsec_acquire_pool;
61: int ipsec_policy_pool_initialized = 0;
62: int ipsec_acquire_pool_initialized = 0;
63:
64: /*
65: * Lookup at the SPD based on the headers contained on the mbuf. The second
66: * argument indicates what protocol family the header at the beginning of
67: * the mbuf is. hlen is the offset of the transport protocol header
68: * in the mbuf.
69: *
70: * Return combinations (of return value and in *error):
71: * - NULL/0 -> no IPsec required on packet
72: * - NULL/-EINVAL -> silently drop the packet
73: * - NULL/errno -> drop packet and return error
74: * or a pointer to a TDB (and 0 in *error).
75: *
76: * In the case of incoming flows, only the first three combinations are
77: * returned.
78: */
79: struct tdb *
80: ipsp_spd_lookup(struct mbuf *m, int af, int hlen, int *error, int direction,
81: struct tdb *tdbp, struct inpcb *inp)
82: {
83: struct route_enc re0, *re = &re0;
84: union sockaddr_union sdst, ssrc;
85: struct sockaddr_encap *ddst;
86: struct ipsec_policy *ipo;
87: int signore = 0, dignore = 0;
88:
89: /*
90: * If there are no flows in place, there's no point
91: * continuing with the SPD lookup.
92: */
93: if (!ipsec_in_use && inp == NULL) {
94: *error = 0;
95: return NULL;
96: }
97:
98: /*
99: * If an input packet is destined to a BYPASS socket, just accept it.
100: */
101: if ((inp != NULL) && (direction == IPSP_DIRECTION_IN) &&
102: (inp->inp_seclevel[SL_ESP_TRANS] == IPSEC_LEVEL_BYPASS) &&
103: (inp->inp_seclevel[SL_ESP_NETWORK] == IPSEC_LEVEL_BYPASS) &&
104: (inp->inp_seclevel[SL_AUTH] == IPSEC_LEVEL_BYPASS)) {
105: *error = 0;
106: return NULL;
107: }
108:
109: bzero((caddr_t) re, sizeof(struct route_enc));
110: bzero((caddr_t) &sdst, sizeof(union sockaddr_union));
111: bzero((caddr_t) &ssrc, sizeof(union sockaddr_union));
112: ddst = (struct sockaddr_encap *) &re->re_dst;
113: ddst->sen_family = PF_KEY;
114: ddst->sen_len = SENT_LEN;
115:
116: switch (af) {
117: #ifdef INET
118: case AF_INET:
119: if (hlen < sizeof (struct ip) || m->m_pkthdr.len < hlen) {
120: *error = EINVAL;
121: return NULL;
122: }
123: ddst->sen_direction = direction;
124: ddst->sen_type = SENT_IP4;
125:
126: m_copydata(m, offsetof(struct ip, ip_src),
127: sizeof(struct in_addr), (caddr_t) &(ddst->sen_ip_src));
128: m_copydata(m, offsetof(struct ip, ip_dst),
129: sizeof(struct in_addr), (caddr_t) &(ddst->sen_ip_dst));
130: m_copydata(m, offsetof(struct ip, ip_p), sizeof(u_int8_t),
131: (caddr_t) &(ddst->sen_proto));
132:
133: sdst.sin.sin_family = ssrc.sin.sin_family = AF_INET;
134: sdst.sin.sin_len = ssrc.sin.sin_len =
135: sizeof(struct sockaddr_in);
136: ssrc.sin.sin_addr = ddst->sen_ip_src;
137: sdst.sin.sin_addr = ddst->sen_ip_dst;
138:
139: /*
140: * If TCP/UDP, extract the port numbers to use in the lookup.
141: */
142: switch (ddst->sen_proto) {
143: case IPPROTO_UDP:
144: case IPPROTO_TCP:
145: /* Make sure there's enough data in the packet. */
146: if (m->m_pkthdr.len < hlen + 2 * sizeof(u_int16_t)) {
147: *error = EINVAL;
148: return NULL;
149: }
150:
151: /*
152: * Luckily, the offset of the src/dst ports in
153: * both the UDP and TCP headers is the same (first
154: * two 16-bit values in the respective headers),
155: * so we can just copy them.
156: */
157: m_copydata(m, hlen, sizeof(u_int16_t),
158: (caddr_t) &(ddst->sen_sport));
159: m_copydata(m, hlen + sizeof(u_int16_t), sizeof(u_int16_t),
160: (caddr_t) &(ddst->sen_dport));
161: break;
162:
163: default:
164: ddst->sen_sport = 0;
165: ddst->sen_dport = 0;
166: }
167:
168: break;
169: #endif /* INET */
170:
171: #ifdef INET6
172: case AF_INET6:
173: if (hlen < sizeof (struct ip6_hdr) || m->m_pkthdr.len < hlen) {
174: *error = EINVAL;
175: return NULL;
176: }
177: ddst->sen_type = SENT_IP6;
178: ddst->sen_ip6_direction = direction;
179:
180: m_copydata(m, offsetof(struct ip6_hdr, ip6_src),
181: sizeof(struct in6_addr),
182: (caddr_t) &(ddst->sen_ip6_src));
183: m_copydata(m, offsetof(struct ip6_hdr, ip6_dst),
184: sizeof(struct in6_addr),
185: (caddr_t) &(ddst->sen_ip6_dst));
186: m_copydata(m, offsetof(struct ip6_hdr, ip6_nxt),
187: sizeof(u_int8_t),
188: (caddr_t) &(ddst->sen_ip6_proto));
189:
190: sdst.sin6.sin6_family = ssrc.sin6.sin6_family = AF_INET6;
191: sdst.sin6.sin6_len = ssrc.sin6.sin6_family =
192: sizeof(struct sockaddr_in6);
193: in6_recoverscope(&ssrc.sin6, &ddst->sen_ip6_src, NULL);
194: in6_recoverscope(&sdst.sin6, &ddst->sen_ip6_dst, NULL);
195:
196: /*
197: * If TCP/UDP, extract the port numbers to use in the lookup.
198: */
199: switch (ddst->sen_ip6_proto) {
200: case IPPROTO_UDP:
201: case IPPROTO_TCP:
202: /* Make sure there's enough data in the packet. */
203: if (m->m_pkthdr.len < hlen + 2 * sizeof(u_int16_t)) {
204: *error = EINVAL;
205: return NULL;
206: }
207:
208: /*
209: * Luckily, the offset of the src/dst ports in
210: * both the UDP and TCP headers is the same
211: * (first two 16-bit values in the respective
212: * headers), so we can just copy them.
213: */
214: m_copydata(m, hlen, sizeof(u_int16_t),
215: (caddr_t) &(ddst->sen_ip6_sport));
216: m_copydata(m, hlen + sizeof(u_int16_t), sizeof(u_int16_t),
217: (caddr_t) &(ddst->sen_ip6_dport));
218: break;
219:
220: default:
221: ddst->sen_ip6_sport = 0;
222: ddst->sen_ip6_dport = 0;
223: }
224:
225: break;
226: #endif /* INET6 */
227:
228: default:
229: *error = EAFNOSUPPORT;
230: return NULL;
231: }
232:
233: /* Actual SPD lookup. */
234: rtalloc((struct route *) re);
235: if (re->re_rt == NULL) {
236: /*
237: * Return whatever the socket requirements are, there are no
238: * system-wide policies.
239: */
240: *error = 0;
241: return ipsp_spd_inp(m, af, hlen, error, direction,
242: tdbp, inp, NULL);
243: }
244:
245: /* Sanity check. */
246: if ((re->re_rt->rt_gateway == NULL) ||
247: (((struct sockaddr_encap *) re->re_rt->rt_gateway)->sen_type !=
248: SENT_IPSP)) {
249: RTFREE(re->re_rt);
250: *error = EHOSTUNREACH;
251: DPRINTF(("ip_spd_lookup: no gateway in SPD entry!"));
252: return NULL;
253: }
254:
255: ipo = ((struct sockaddr_encap *) (re->re_rt->rt_gateway))->sen_ipsp;
256: RTFREE(re->re_rt);
257: if (ipo == NULL) {
258: *error = EHOSTUNREACH;
259: DPRINTF(("ip_spd_lookup: no policy attached to SPD entry!"));
260: return NULL;
261: }
262:
263: switch (ipo->ipo_type) {
264: case IPSP_PERMIT:
265: *error = 0;
266: return ipsp_spd_inp(m, af, hlen, error, direction, tdbp,
267: inp, ipo);
268:
269: case IPSP_DENY:
270: *error = EHOSTUNREACH;
271: return NULL;
272:
273: case IPSP_IPSEC_USE:
274: case IPSP_IPSEC_ACQUIRE:
275: case IPSP_IPSEC_REQUIRE:
276: case IPSP_IPSEC_DONTACQ:
277: /* Nothing more needed here. */
278: break;
279:
280: default:
281: *error = EINVAL;
282: return NULL;
283: }
284:
285: /* Check for non-specific destination in the policy. */
286: switch (ipo->ipo_dst.sa.sa_family) {
287: #ifdef INET
288: case AF_INET:
289: if ((ipo->ipo_dst.sin.sin_addr.s_addr == INADDR_ANY) ||
290: (ipo->ipo_dst.sin.sin_addr.s_addr == INADDR_BROADCAST))
291: dignore = 1;
292: break;
293: #endif /* INET */
294:
295: #ifdef INET6
296: case AF_INET6:
297: if ((IN6_IS_ADDR_UNSPECIFIED(&ipo->ipo_dst.sin6.sin6_addr)) ||
298: (bcmp(&ipo->ipo_dst.sin6.sin6_addr, &in6mask128,
299: sizeof(in6mask128)) == 0))
300: dignore = 1;
301: break;
302: #endif /* INET6 */
303: }
304:
305: /* Likewise for source. */
306: switch (ipo->ipo_src.sa.sa_family) {
307: #ifdef INET
308: case AF_INET:
309: if (ipo->ipo_src.sin.sin_addr.s_addr == INADDR_ANY)
310: signore = 1;
311: break;
312: #endif /* INET */
313:
314: #ifdef INET6
315: case AF_INET6:
316: if (IN6_IS_ADDR_UNSPECIFIED(&ipo->ipo_src.sin6.sin6_addr))
317: signore = 1;
318: break;
319: #endif /* INET6 */
320: }
321:
322: /* Do we have a cached entry ? If so, check if it's still valid. */
323: if ((ipo->ipo_tdb) && (ipo->ipo_tdb->tdb_flags & TDBF_INVALID)) {
324: TAILQ_REMOVE(&ipo->ipo_tdb->tdb_policy_head, ipo,
325: ipo_tdb_next);
326: ipo->ipo_tdb = NULL;
327: }
328:
329: /* Outgoing packet policy check. */
330: if (direction == IPSP_DIRECTION_OUT) {
331: /*
332: * If the packet is destined for the policy-specified
333: * gateway/endhost, and the socket has the BYPASS
334: * option set, skip IPsec processing.
335: */
336: if ((inp != NULL) &&
337: (inp->inp_seclevel[SL_ESP_TRANS] == IPSEC_LEVEL_BYPASS) &&
338: (inp->inp_seclevel[SL_ESP_NETWORK] ==
339: IPSEC_LEVEL_BYPASS) &&
340: (inp->inp_seclevel[SL_AUTH] == IPSEC_LEVEL_BYPASS)) {
341: /* Direct match. */
342: if (dignore ||
343: !bcmp(&sdst, &ipo->ipo_dst, sdst.sa.sa_len)) {
344: *error = 0;
345: return NULL;
346: }
347: }
348:
349: /* Check that the cached TDB (if present), is appropriate. */
350: if (ipo->ipo_tdb) {
351: if ((ipo->ipo_last_searched <= ipsec_last_added) ||
352: (ipo->ipo_sproto != ipo->ipo_tdb->tdb_sproto) ||
353: bcmp(dignore ? &sdst : &ipo->ipo_dst,
354: &ipo->ipo_tdb->tdb_dst,
355: ipo->ipo_tdb->tdb_dst.sa.sa_len))
356: goto nomatchout;
357:
358: if (!ipsp_aux_match(ipo->ipo_tdb,
359: ipo->ipo_srcid, ipo->ipo_dstid,
360: ipo->ipo_local_cred, NULL,
361: &ipo->ipo_addr, &ipo->ipo_mask))
362: goto nomatchout;
363:
364: /* Cached entry is good. */
365: *error = 0;
366: return ipsp_spd_inp(m, af, hlen, error, direction,
367: tdbp, inp, ipo);
368:
369: nomatchout:
370: /* Cached TDB was not good. */
371: TAILQ_REMOVE(&ipo->ipo_tdb->tdb_policy_head, ipo,
372: ipo_tdb_next);
373: ipo->ipo_tdb = NULL;
374: ipo->ipo_last_searched = 0;
375: }
376:
377: /*
378: * If no SA has been added since the last time we did a
379: * lookup, there's no point searching for one. However, if the
380: * destination gateway is left unspecified (or is all-1's),
381: * always lookup since this is a generic-match rule
382: * (otherwise, we can have situations where SAs to some
383: * destinations exist but are not used, possibly leading to an
384: * explosion in the number of acquired SAs).
385: */
386: if (ipo->ipo_last_searched <= ipsec_last_added) {
387: /* "Touch" the entry. */
388: if (dignore == 0)
389: ipo->ipo_last_searched = time_second;
390:
391: /* Find an appropriate SA from the existing ones. */
392: ipo->ipo_tdb =
393: gettdbbyaddr(dignore ? &sdst : &ipo->ipo_dst,
394: ipo->ipo_sproto, ipo->ipo_srcid,
395: ipo->ipo_dstid, ipo->ipo_local_cred, m, af,
396: &ipo->ipo_addr, &ipo->ipo_mask);
397: if (ipo->ipo_tdb) {
398: TAILQ_INSERT_TAIL(&ipo->ipo_tdb->tdb_policy_head,
399: ipo, ipo_tdb_next);
400: *error = 0;
401: return ipsp_spd_inp(m, af, hlen, error,
402: direction, tdbp, inp, ipo);
403: }
404: }
405:
406: /* So, we don't have an SA -- just a policy. */
407: switch (ipo->ipo_type) {
408: case IPSP_IPSEC_REQUIRE:
409: /* Acquire SA through key management. */
410: if (ipsp_acquire_sa(ipo,
411: dignore ? &sdst : &ipo->ipo_dst,
412: signore ? NULL : &ipo->ipo_src, ddst, m) != 0) {
413: *error = EACCES;
414: return NULL;
415: }
416:
417: /* FALLTHROUGH */
418: case IPSP_IPSEC_DONTACQ:
419: *error = -EINVAL; /* Silently drop packet. */
420: return NULL;
421:
422: case IPSP_IPSEC_ACQUIRE:
423: /* Acquire SA through key management. */
424: ipsp_acquire_sa(ipo, dignore ? &sdst : &ipo->ipo_dst,
425: signore ? NULL : &ipo->ipo_src, ddst, NULL);
426:
427: /* FALLTHROUGH */
428: case IPSP_IPSEC_USE:
429: *error = 0;
430: return ipsp_spd_inp(m, af, hlen, error, direction,
431: tdbp, inp, ipo);
432: }
433: } else { /* IPSP_DIRECTION_IN */
434: if (tdbp != NULL) {
435: /* Direct match in the cache. */
436: if (ipo->ipo_tdb == tdbp) {
437: *error = 0;
438: return ipsp_spd_inp(m, af, hlen, error,
439: direction, tdbp, inp, ipo);
440: }
441:
442: if (bcmp(dignore ? &ssrc : &ipo->ipo_dst,
443: &tdbp->tdb_src, tdbp->tdb_src.sa.sa_len) ||
444: (ipo->ipo_sproto != tdbp->tdb_sproto))
445: goto nomatchin;
446:
447: /* Match source ID. */
448: if (ipo->ipo_srcid) {
449: if (tdbp->tdb_dstid == NULL ||
450: !ipsp_ref_match(ipo->ipo_srcid,
451: tdbp->tdb_dstid))
452: goto nomatchin;
453: }
454:
455: /* Match destination ID. */
456: if (ipo->ipo_dstid) {
457: if (tdbp->tdb_srcid == NULL ||
458: !ipsp_ref_match(ipo->ipo_dstid,
459: tdbp->tdb_srcid))
460: goto nomatchin;
461: }
462:
463: /* Add it to the cache. */
464: if (ipo->ipo_tdb)
465: TAILQ_REMOVE(&ipo->ipo_tdb->tdb_policy_head,
466: ipo, ipo_tdb_next);
467: ipo->ipo_tdb = tdbp;
468: TAILQ_INSERT_TAIL(&tdbp->tdb_policy_head, ipo,
469: ipo_tdb_next);
470: *error = 0;
471: return ipsp_spd_inp(m, af, hlen, error, direction,
472: tdbp, inp, ipo);
473:
474: nomatchin: /* Nothing needed here, falling through */
475: ;
476: }
477:
478: /* Check whether cached entry applies. */
479: if (ipo->ipo_tdb) {
480: /*
481: * We only need to check that the correct
482: * security protocol and security gateway are
483: * set; credentials/IDs will be the same,
484: * since the cached entry is linked on this
485: * policy.
486: */
487: if (ipo->ipo_sproto == ipo->ipo_tdb->tdb_sproto &&
488: !bcmp(&ipo->ipo_tdb->tdb_src,
489: dignore ? &ssrc : &ipo->ipo_dst,
490: ipo->ipo_tdb->tdb_src.sa.sa_len))
491: goto skipinputsearch;
492:
493: /* Not applicable, unlink. */
494: TAILQ_REMOVE(&ipo->ipo_tdb->tdb_policy_head, ipo,
495: ipo_tdb_next);
496: ipo->ipo_last_searched = 0;
497: ipo->ipo_tdb = NULL;
498: }
499:
500: /* Find whether there exists an appropriate SA. */
501: if (ipo->ipo_last_searched <= ipsec_last_added) {
502: if (dignore == 0)
503: ipo->ipo_last_searched = time_second;
504:
505: ipo->ipo_tdb =
506: gettdbbysrc(dignore ? &ssrc : &ipo->ipo_dst,
507: ipo->ipo_sproto, ipo->ipo_srcid,
508: ipo->ipo_dstid, m, af, &ipo->ipo_addr,
509: &ipo->ipo_mask);
510: if (ipo->ipo_tdb)
511: TAILQ_INSERT_TAIL(&ipo->ipo_tdb->tdb_policy_head,
512: ipo, ipo_tdb_next);
513: }
514: skipinputsearch:
515:
516: switch (ipo->ipo_type) {
517: case IPSP_IPSEC_REQUIRE:
518: /* If appropriate SA exists, don't acquire another. */
519: if (ipo->ipo_tdb) {
520: *error = -EINVAL;
521: return NULL;
522: }
523:
524: /* Acquire SA through key management. */
525: if ((*error = ipsp_acquire_sa(ipo,
526: dignore ? &ssrc : &ipo->ipo_dst,
527: signore ? NULL : &ipo->ipo_src, ddst, m)) != 0)
528: return NULL;
529:
530: /* FALLTHROUGH */
531: case IPSP_IPSEC_DONTACQ:
532: /* Drop packet. */
533: *error = -EINVAL;
534: return NULL;
535:
536: case IPSP_IPSEC_ACQUIRE:
537: /* If appropriate SA exists, don't acquire another. */
538: if (ipo->ipo_tdb) {
539: *error = 0;
540: return ipsp_spd_inp(m, af, hlen, error,
541: direction, tdbp, inp, ipo);
542: }
543:
544: /* Acquire SA through key management. */
545: ipsp_acquire_sa(ipo, dignore ? &ssrc : &ipo->ipo_dst,
546: signore ? NULL : &ipo->ipo_src, ddst, NULL);
547:
548: /* FALLTHROUGH */
549: case IPSP_IPSEC_USE:
550: *error = 0;
551: return ipsp_spd_inp(m, af, hlen, error, direction,
552: tdbp, inp, ipo);
553: }
554: }
555:
556: /* Shouldn't ever get this far. */
557: *error = EINVAL;
558: return NULL;
559: }
560:
561: /*
562: * Delete a policy from the SPD.
563: */
564: int
565: ipsec_delete_policy(struct ipsec_policy *ipo)
566: {
567: struct ipsec_acquire *ipa;
568: int err = 0;
569:
570: if (--ipo->ipo_ref_count > 0)
571: return 0;
572:
573: /* Delete from SPD. */
574: if (!(ipo->ipo_flags & IPSP_POLICY_SOCKET))
575: err = rtrequest(RTM_DELETE, (struct sockaddr *) &ipo->ipo_addr,
576: (struct sockaddr *) 0,
577: (struct sockaddr *) &ipo->ipo_mask,
578: 0, (struct rtentry **) 0, 0); /* XXX other tables? */
579:
580: if (ipo->ipo_tdb != NULL)
581: TAILQ_REMOVE(&ipo->ipo_tdb->tdb_policy_head, ipo,
582: ipo_tdb_next);
583:
584: while ((ipa = TAILQ_FIRST(&ipo->ipo_acquires)) != NULL)
585: ipsp_delete_acquire(ipa);
586:
587: TAILQ_REMOVE(&ipsec_policy_head, ipo, ipo_list);
588:
589: if (ipo->ipo_srcid)
590: ipsp_reffree(ipo->ipo_srcid);
591: if (ipo->ipo_dstid)
592: ipsp_reffree(ipo->ipo_dstid);
593: if (ipo->ipo_local_cred)
594: ipsp_reffree(ipo->ipo_local_cred);
595: if (ipo->ipo_local_auth)
596: ipsp_reffree(ipo->ipo_local_auth);
597:
598: pool_put(&ipsec_policy_pool, ipo);
599:
600: if (!(ipo->ipo_flags & IPSP_POLICY_SOCKET))
601: ipsec_in_use--;
602:
603: return err;
604: }
605:
606: /*
607: * Add a policy to the SPD.
608: */
609: struct ipsec_policy *
610: ipsec_add_policy(struct inpcb *inp, int af, int direction)
611: {
612: struct ipsec_policy *ipon;
613:
614: if (ipsec_policy_pool_initialized == 0) {
615: ipsec_policy_pool_initialized = 1;
616: pool_init(&ipsec_policy_pool, sizeof(struct ipsec_policy),
617: 0, 0, 0, "ipsec policy", NULL);
618: }
619:
620: ipon = pool_get(&ipsec_policy_pool, 0);
621: if (ipon == NULL)
622: return NULL;
623:
624: bzero(ipon, sizeof(struct ipsec_policy));
625:
626: ipon->ipo_ref_count = 1;
627: ipon->ipo_flags |= IPSP_POLICY_SOCKET;
628:
629: ipon->ipo_type = IPSP_IPSEC_REQUIRE; /* XXX */
630:
631: /* XXX
632: * We should actually be creating a linked list of
633: * policies (for tunnel/transport and ESP/AH), as needed.
634: */
635: ipon->ipo_sproto = IPPROTO_ESP;
636:
637: TAILQ_INIT(&ipon->ipo_acquires);
638: TAILQ_INSERT_HEAD(&ipsec_policy_head, ipon, ipo_list);
639:
640: ipsec_update_policy(inp, ipon, af, direction);
641:
642: return ipon;
643: }
644:
645: /*
646: * Update a PCB-attached policy.
647: */
648: void
649: ipsec_update_policy(struct inpcb *inp, struct ipsec_policy *ipon, int af,
650: int direction)
651: {
652: ipon->ipo_addr.sen_len = ipon->ipo_mask.sen_len = SENT_LEN;
653: ipon->ipo_addr.sen_family = ipon->ipo_mask.sen_family = PF_KEY;
654: ipon->ipo_src.sa.sa_family = ipon->ipo_dst.sa.sa_family = af;
655:
656: switch (af) {
657: case AF_INET:
658: #ifdef INET
659: ipon->ipo_addr.sen_type = ipon->ipo_mask.sen_type = SENT_IP4;
660: ipon->ipo_addr.sen_ip_src = inp->inp_laddr;
661: ipon->ipo_addr.sen_ip_dst = inp->inp_faddr;
662: ipon->ipo_addr.sen_sport = inp->inp_lport;
663: ipon->ipo_addr.sen_dport = inp->inp_fport;
664: ipon->ipo_addr.sen_proto =
665: inp->inp_socket->so_proto->pr_protocol;
666: ipon->ipo_addr.sen_direction = direction;
667:
668: ipon->ipo_mask.sen_ip_src.s_addr = 0xffffffff;
669: ipon->ipo_mask.sen_ip_dst.s_addr = 0xffffffff;
670: ipon->ipo_mask.sen_sport = ipon->ipo_mask.sen_dport = 0xffff;
671: ipon->ipo_mask.sen_proto = 0xff;
672: ipon->ipo_mask.sen_direction = direction;
673:
674: ipon->ipo_src.sa.sa_len = sizeof(struct sockaddr_in);
675: ipon->ipo_dst.sa.sa_len = sizeof(struct sockaddr_in);
676: ipon->ipo_src.sin.sin_addr = inp->inp_laddr;
677: ipon->ipo_dst.sin.sin_addr = inp->inp_faddr;
678: #endif /* INET */
679: break;
680:
681: case AF_INET6:
682: #ifdef INET6
683: ipon->ipo_addr.sen_type = ipon->ipo_mask.sen_type = SENT_IP6;
684: ipon->ipo_addr.sen_ip6_src = inp->inp_laddr6;
685: ipon->ipo_addr.sen_ip6_dst = inp->inp_faddr6;
686: ipon->ipo_addr.sen_ip6_sport = inp->inp_lport;
687: ipon->ipo_addr.sen_ip6_dport = inp->inp_fport;
688: ipon->ipo_addr.sen_ip6_proto =
689: inp->inp_socket->so_proto->pr_protocol;
690: ipon->ipo_addr.sen_ip6_direction = direction;
691:
692: ipon->ipo_mask.sen_ip6_src = in6mask128;
693: ipon->ipo_mask.sen_ip6_dst = in6mask128;
694: ipon->ipo_mask.sen_ip6_sport = 0xffff;
695: ipon->ipo_mask.sen_ip6_dport = 0xffff;
696: ipon->ipo_mask.sen_ip6_proto = 0xff;
697: ipon->ipo_mask.sen_ip6_direction = direction;
698:
699: ipon->ipo_src.sa.sa_len = sizeof(struct sockaddr_in6);
700: ipon->ipo_dst.sa.sa_len = sizeof(struct sockaddr_in6);
701: ipon->ipo_src.sin6.sin6_addr = inp->inp_laddr6;
702: ipon->ipo_dst.sin6.sin6_addr = inp->inp_faddr6;
703: #endif /* INET6 */
704: break;
705: }
706: }
707:
708: /*
709: * Delete a pending IPsec acquire record.
710: */
711: void
712: ipsp_delete_acquire(void *v)
713: {
714: struct ipsec_acquire *ipa = v;
715:
716: timeout_del(&ipa->ipa_timeout);
717: TAILQ_REMOVE(&ipsec_acquire_head, ipa, ipa_next);
718: if (ipa->ipa_policy != NULL)
719: TAILQ_REMOVE(&ipa->ipa_policy->ipo_acquires, ipa,
720: ipa_ipo_next);
721: pool_put(&ipsec_acquire_pool, ipa);
722: }
723:
724: /*
725: * Find out if there's an ACQUIRE pending.
726: * XXX Need a better structure.
727: */
728: struct ipsec_acquire *
729: ipsp_pending_acquire(struct ipsec_policy *ipo, union sockaddr_union *gw)
730: {
731: struct ipsec_acquire *ipa;
732:
733: TAILQ_FOREACH (ipa, &ipo->ipo_acquires, ipa_ipo_next) {
734: if (!bcmp(gw, &ipa->ipa_addr, gw->sa.sa_len))
735: return ipa;
736: }
737:
738: return NULL;
739: }
740:
741: /*
742: * Signal key management that we need an SA.
743: * XXX For outgoing policies, we could try to hold on to the mbuf.
744: */
745: int
746: ipsp_acquire_sa(struct ipsec_policy *ipo, union sockaddr_union *gw,
747: union sockaddr_union *laddr, struct sockaddr_encap *ddst, struct mbuf *m)
748: {
749: struct ipsec_acquire *ipa;
750:
751: /*
752: * If this is a socket policy, it has to have authentication
753: * information accompanying it --- can't tell key mgmt. to
754: * "find" it for us. This avoids abusing key mgmt. to authenticate
755: * on an application's behalf, even if the application doesn't
756: * have/know (and shouldn't) the appropriate authentication
757: * material (passphrase, private key, etc.)
758: */
759: if (ipo->ipo_flags & IPSP_POLICY_SOCKET &&
760: ipo->ipo_local_auth == NULL)
761: return EINVAL;
762:
763: /* Check whether request has been made already. */
764: if ((ipa = ipsp_pending_acquire(ipo, gw)) != NULL)
765: return 0;
766:
767: /* Add request in cache and proceed. */
768: if (ipsec_acquire_pool_initialized == 0) {
769: ipsec_acquire_pool_initialized = 1;
770: pool_init(&ipsec_acquire_pool, sizeof(struct ipsec_acquire),
771: 0, 0, 0, "ipsec acquire", NULL);
772: }
773:
774: ipa = pool_get(&ipsec_acquire_pool, 0);
775: if (ipa == NULL)
776: return ENOMEM;
777:
778: bzero(ipa, sizeof(struct ipsec_acquire));
779: bcopy(gw, &ipa->ipa_addr, sizeof(union sockaddr_union));
780:
781: timeout_set(&ipa->ipa_timeout, ipsp_delete_acquire, ipa);
782:
783: ipa->ipa_info.sen_len = ipa->ipa_mask.sen_len = SENT_LEN;
784: ipa->ipa_info.sen_family = ipa->ipa_mask.sen_family = PF_KEY;
785:
786: /* Just copy the right information. */
787: switch (ipo->ipo_addr.sen_type) {
788: #ifdef INET
789: case SENT_IP4:
790: ipa->ipa_info.sen_type = ipa->ipa_mask.sen_type = SENT_IP4;
791: ipa->ipa_info.sen_direction = ipo->ipo_addr.sen_direction;
792: ipa->ipa_mask.sen_direction = ipo->ipo_mask.sen_direction;
793:
794: if (ipo->ipo_mask.sen_ip_src.s_addr == INADDR_ANY ||
795: ipo->ipo_addr.sen_ip_src.s_addr == INADDR_ANY ||
796: ipsp_is_unspecified(ipo->ipo_dst)) {
797: ipa->ipa_info.sen_ip_src = ddst->sen_ip_src;
798: ipa->ipa_mask.sen_ip_src.s_addr = INADDR_BROADCAST;
799: } else {
800: ipa->ipa_info.sen_ip_src = ipo->ipo_addr.sen_ip_src;
801: ipa->ipa_mask.sen_ip_src = ipo->ipo_mask.sen_ip_src;
802: }
803:
804: if (ipo->ipo_mask.sen_ip_dst.s_addr == INADDR_ANY ||
805: ipo->ipo_addr.sen_ip_dst.s_addr == INADDR_ANY ||
806: ipsp_is_unspecified(ipo->ipo_dst)) {
807: ipa->ipa_info.sen_ip_dst = ddst->sen_ip_dst;
808: ipa->ipa_mask.sen_ip_dst.s_addr = INADDR_BROADCAST;
809: } else {
810: ipa->ipa_info.sen_ip_dst = ipo->ipo_addr.sen_ip_dst;
811: ipa->ipa_mask.sen_ip_dst = ipo->ipo_mask.sen_ip_dst;
812: }
813:
814: ipa->ipa_info.sen_proto = ipo->ipo_addr.sen_proto;
815: ipa->ipa_mask.sen_proto = ipo->ipo_mask.sen_proto;
816:
817: if (ipo->ipo_addr.sen_proto) {
818: ipa->ipa_info.sen_sport = ipo->ipo_addr.sen_sport;
819: ipa->ipa_mask.sen_sport = ipo->ipo_mask.sen_sport;
820:
821: ipa->ipa_info.sen_dport = ipo->ipo_addr.sen_dport;
822: ipa->ipa_mask.sen_dport = ipo->ipo_mask.sen_dport;
823: }
824: break;
825: #endif /* INET */
826:
827: #ifdef INET6
828: case SENT_IP6:
829: ipa->ipa_info.sen_type = ipa->ipa_mask.sen_type = SENT_IP6;
830: ipa->ipa_info.sen_ip6_direction =
831: ipo->ipo_addr.sen_ip6_direction;
832: ipa->ipa_mask.sen_ip6_direction =
833: ipo->ipo_mask.sen_ip6_direction;
834:
835: if (IN6_IS_ADDR_UNSPECIFIED(&ipo->ipo_mask.sen_ip6_src) ||
836: IN6_IS_ADDR_UNSPECIFIED(&ipo->ipo_addr.sen_ip6_src) ||
837: ipsp_is_unspecified(ipo->ipo_dst)) {
838: ipa->ipa_info.sen_ip6_src = ddst->sen_ip6_src;
839: ipa->ipa_mask.sen_ip6_src = in6mask128;
840: } else {
841: ipa->ipa_info.sen_ip6_src = ipo->ipo_addr.sen_ip6_src;
842: ipa->ipa_mask.sen_ip6_src = ipo->ipo_mask.sen_ip6_src;
843: }
844:
845: if (IN6_IS_ADDR_UNSPECIFIED(&ipo->ipo_mask.sen_ip6_dst) ||
846: IN6_IS_ADDR_UNSPECIFIED(&ipo->ipo_addr.sen_ip6_dst) ||
847: ipsp_is_unspecified(ipo->ipo_dst)) {
848: ipa->ipa_info.sen_ip6_dst = ddst->sen_ip6_dst;
849: ipa->ipa_mask.sen_ip6_dst = in6mask128;
850: } else {
851: ipa->ipa_info.sen_ip6_dst = ipo->ipo_addr.sen_ip6_dst;
852: ipa->ipa_mask.sen_ip6_dst = ipo->ipo_mask.sen_ip6_dst;
853: }
854:
855: ipa->ipa_info.sen_ip6_proto = ipo->ipo_addr.sen_ip6_proto;
856: ipa->ipa_mask.sen_ip6_proto = ipo->ipo_mask.sen_ip6_proto;
857:
858: if (ipo->ipo_mask.sen_ip6_proto) {
859: ipa->ipa_info.sen_ip6_sport =
860: ipo->ipo_addr.sen_ip6_sport;
861: ipa->ipa_mask.sen_ip6_sport =
862: ipo->ipo_mask.sen_ip6_sport;
863: ipa->ipa_info.sen_ip6_dport =
864: ipo->ipo_addr.sen_ip6_dport;
865: ipa->ipa_mask.sen_ip6_dport =
866: ipo->ipo_mask.sen_ip6_dport;
867: }
868: break;
869: #endif /* INET6 */
870:
871: default:
872: pool_put(&ipsec_acquire_pool, ipa);
873: return 0;
874: }
875:
876: timeout_add(&ipa->ipa_timeout, ipsec_expire_acquire * hz);
877:
878: TAILQ_INSERT_TAIL(&ipsec_acquire_head, ipa, ipa_next);
879: TAILQ_INSERT_TAIL(&ipo->ipo_acquires, ipa, ipa_ipo_next);
880: ipa->ipa_policy = ipo;
881:
882: /* PF_KEYv2 notification message. */
883: return pfkeyv2_acquire(ipo, gw, laddr, &ipa->ipa_seq, ddst);
884: }
885:
886: /*
887: * Deal with PCB security requirements.
888: */
889: struct tdb *
890: ipsp_spd_inp(struct mbuf *m, int af, int hlen, int *error, int direction,
891: struct tdb *tdbp, struct inpcb *inp, struct ipsec_policy *ipo)
892: {
893: struct ipsec_policy sipon;
894: struct tdb_ident *tdbi;
895: struct m_tag *mtag;
896: struct tdb *tdb = NULL;
897:
898: /* Sanity check. */
899: if (inp == NULL)
900: goto justreturn;
901:
902: /* Verify that we need to check for socket policy. */
903: if ((inp->inp_seclevel[SL_ESP_TRANS] == IPSEC_LEVEL_BYPASS ||
904: inp->inp_seclevel[SL_ESP_TRANS] == IPSEC_LEVEL_NONE) &&
905: (inp->inp_seclevel[SL_ESP_NETWORK] == IPSEC_LEVEL_BYPASS ||
906: inp->inp_seclevel[SL_ESP_NETWORK] == IPSEC_LEVEL_NONE) &&
907: (inp->inp_seclevel[SL_AUTH] == IPSEC_LEVEL_BYPASS ||
908: inp->inp_seclevel[SL_AUTH] == IPSEC_LEVEL_NONE))
909: goto justreturn;
910:
911: switch (direction) {
912: case IPSP_DIRECTION_IN:
913: /*
914: * Some further checking: if the socket has specified
915: * that it will accept unencrypted traffic, don't
916: * bother checking any further -- just accept the packet.
917: */
918: if ((inp->inp_seclevel[SL_ESP_TRANS] == IPSEC_LEVEL_AVAIL ||
919: inp->inp_seclevel[SL_ESP_TRANS] == IPSEC_LEVEL_USE) &&
920: (inp->inp_seclevel[SL_ESP_NETWORK] == IPSEC_LEVEL_AVAIL ||
921: inp->inp_seclevel[SL_ESP_NETWORK] == IPSEC_LEVEL_USE) &&
922: (inp->inp_seclevel[SL_AUTH] == IPSEC_LEVEL_AVAIL ||
923: inp->inp_seclevel[SL_AUTH] == IPSEC_LEVEL_USE))
924: goto justreturn;
925:
926: /* Initialize socket policy if unset. */
927: if (inp->inp_ipo == NULL) {
928: inp->inp_ipo = ipsec_add_policy(inp, af,
929: IPSP_DIRECTION_OUT);
930: if (inp->inp_ipo == NULL) {
931: *error = ENOBUFS;
932: return NULL;
933: }
934: }
935:
936: /*
937: * So we *must* have protected traffic. Let's see what
938: * we have received then.
939: */
940: if (inp->inp_tdb_in != NULL) {
941: if (inp->inp_tdb_in == tdbp)
942: goto justreturn; /* We received packet under a
943: * previously-accepted TDB. */
944:
945: /*
946: * We should be receiving protected traffic, and
947: * have an SA in place, but packet was received
948: * unprotected. Simply discard.
949: */
950: if (tdbp == NULL) {
951: *error = -EINVAL;
952: return NULL;
953: }
954:
955: /* Update, since we may need all the relevant info. */
956: ipsec_update_policy(inp, inp->inp_ipo, af,
957: IPSP_DIRECTION_OUT);
958:
959: /*
960: * Check that the TDB the packet was received under
961: * is acceptable under the socket policy. If so,
962: * accept the packet; otherwise, discard.
963: */
964: if (tdbp->tdb_sproto == inp->inp_ipo->ipo_sproto &&
965: !bcmp(&tdbp->tdb_src, &inp->inp_ipo->ipo_dst,
966: SA_LEN(&tdbp->tdb_src.sa)) &&
967: ipsp_aux_match(tdbp,
968: inp->inp_ipo->ipo_srcid,
969: inp->inp_ipo->ipo_dstid,
970: NULL, NULL,
971: &inp->inp_ipo->ipo_addr,
972: &inp->inp_ipo->ipo_mask))
973: goto justreturn;
974: else {
975: *error = -EINVAL;
976: return NULL;
977: }
978: } else {
979: /* Update, since we may need all the relevant info. */
980: ipsec_update_policy(inp, inp->inp_ipo, af,
981: IPSP_DIRECTION_OUT);
982:
983: /*
984: * If the packet was received under an SA, see if
985: * it's acceptable under socket policy. If it is,
986: * accept the packet.
987: */
988: if (tdbp != NULL &&
989: tdbp->tdb_sproto == inp->inp_ipo->ipo_sproto &&
990: !bcmp(&tdbp->tdb_src, &inp->inp_ipo->ipo_dst,
991: SA_LEN(&tdbp->tdb_src.sa)) &&
992: ipsp_aux_match(tdbp,
993: inp->inp_ipo->ipo_srcid,
994: inp->inp_ipo->ipo_dstid,
995: NULL, NULL,
996: &inp->inp_ipo->ipo_addr,
997: &inp->inp_ipo->ipo_mask))
998: goto justreturn;
999:
1000: /*
1001: * If the packet was not received under an SA, or
1002: * if the SA it was received under is not acceptable,
1003: * see if we already have an acceptable SA
1004: * established. If we do, discard packet.
1005: */
1006: if (inp->inp_ipo->ipo_last_searched <=
1007: ipsec_last_added) {
1008: inp->inp_ipo->ipo_last_searched = time_second;
1009:
1010: /* Do we have an SA already established ? */
1011: if (gettdbbysrc(&inp->inp_ipo->ipo_dst,
1012: inp->inp_ipo->ipo_sproto,
1013: inp->inp_ipo->ipo_srcid,
1014: inp->inp_ipo->ipo_dstid, m, af,
1015: &inp->inp_ipo->ipo_addr,
1016: &inp->inp_ipo->ipo_mask) != NULL) {
1017: *error = -EINVAL;
1018: return NULL;
1019: }
1020: /* Fall through */
1021: }
1022:
1023: /*
1024: * If we don't have an appropriate SA, acquire one
1025: * and discard the packet.
1026: */
1027: ipsp_acquire_sa(inp->inp_ipo, &inp->inp_ipo->ipo_dst,
1028: &inp->inp_ipo->ipo_src, &inp->inp_ipo->ipo_addr, m);
1029: *error = -EINVAL;
1030: return NULL;
1031: }
1032:
1033: break;
1034:
1035: case IPSP_DIRECTION_OUT:
1036: /* Do we have a cached entry ? */
1037: if (inp->inp_tdb_out != NULL) {
1038: /*
1039: * If we also have to apply a different TDB as
1040: * a result of a system-wide policy, add a tag
1041: * to the packet.
1042: */
1043: if (ipo != NULL && m != NULL &&
1044: ipo->ipo_tdb != NULL &&
1045: ipo->ipo_tdb != inp->inp_tdb_out) {
1046: tdb = inp->inp_tdb_out;
1047: goto tagandreturn;
1048: } else
1049: return inp->inp_tdb_out;
1050: }
1051:
1052: /*
1053: * We need to either find an SA with the appropriate
1054: * characteristics and link it to the PCB, or acquire
1055: * one.
1056: */
1057: /* XXX Only support one policy/protocol for now. */
1058: if (inp->inp_ipo != NULL) {
1059: if (inp->inp_ipo->ipo_last_searched <=
1060: ipsec_last_added) {
1061: inp->inp_ipo->ipo_last_searched = time_second;
1062:
1063: /* Update, just in case. */
1064: ipsec_update_policy(inp, inp->inp_ipo, af,
1065: IPSP_DIRECTION_OUT);
1066:
1067: tdb = gettdbbyaddr(&inp->inp_ipo->ipo_dst,
1068: inp->inp_ipo->ipo_sproto,
1069: inp->inp_ipo->ipo_srcid,
1070: inp->inp_ipo->ipo_dstid,
1071: inp->inp_ipo->ipo_local_cred, m, af,
1072: &inp->inp_ipo->ipo_addr,
1073: &inp->inp_ipo->ipo_mask);
1074: }
1075: } else {
1076: /*
1077: * Construct a pseudo-policy, with just the necessary
1078: * fields.
1079: */
1080: ipsec_update_policy(inp, &sipon, af,
1081: IPSP_DIRECTION_OUT);
1082:
1083: tdb = gettdbbyaddr(&sipon.ipo_dst, IPPROTO_ESP, NULL,
1084: NULL, NULL, m, af, &sipon.ipo_addr,
1085: &sipon.ipo_mask);
1086: }
1087:
1088: /* If we found an appropriate SA... */
1089: if (tdb != NULL) {
1090: tdb_add_inp(tdb, inp, 0); /* Latch onto PCB. */
1091:
1092: if (ipo != NULL && ipo->ipo_tdb != NULL &&
1093: ipo->ipo_tdb != inp->inp_tdb_out && m != NULL)
1094: goto tagandreturn;
1095: else
1096: return tdb;
1097: } else {
1098: /* Do we need to acquire one ? */
1099: switch (inp->inp_seclevel[SL_ESP_TRANS]) {
1100: case IPSEC_LEVEL_BYPASS:
1101: case IPSEC_LEVEL_AVAIL:
1102: /* No need to do anything. */
1103: goto justreturn;
1104: case IPSEC_LEVEL_USE:
1105: case IPSEC_LEVEL_REQUIRE:
1106: case IPSEC_LEVEL_UNIQUE:
1107: /* Initialize socket policy if unset. */
1108: if (inp->inp_ipo == NULL) {
1109: inp->inp_ipo = ipsec_add_policy(inp, af, IPSP_DIRECTION_OUT);
1110: if (inp->inp_ipo == NULL) {
1111: *error = ENOBUFS;
1112: return NULL;
1113: }
1114: }
1115:
1116: /* Acquire a new SA. */
1117: if ((*error = ipsp_acquire_sa(inp->inp_ipo,
1118: &inp->inp_ipo->ipo_dst,
1119: &inp->inp_ipo->ipo_src,
1120: &inp->inp_ipo->ipo_addr, m)) == 0)
1121: *error = -EINVAL;
1122:
1123: return NULL;
1124: default:
1125: DPRINTF(("ipsp_spd_inp: unknown sock security"
1126: " level %d",
1127: inp->inp_seclevel[SL_ESP_TRANS]));
1128: *error = -EINVAL;
1129: return NULL;
1130: }
1131: }
1132: break;
1133:
1134: default: /* Should never happen. */
1135: *error = -EINVAL;
1136: return NULL;
1137: }
1138:
1139: tagandreturn:
1140: if (tdb == NULL)
1141: goto justreturn;
1142:
1143: mtag = m_tag_get(PACKET_TAG_IPSEC_PENDING_TDB,
1144: sizeof (struct tdb_ident), M_NOWAIT);
1145: if (mtag == NULL) {
1146: *error = ENOMEM;
1147: return NULL;
1148: }
1149:
1150: tdbi = (struct tdb_ident *)(mtag + 1);
1151: tdbi->spi = ipo->ipo_tdb->tdb_spi;
1152: tdbi->proto = ipo->ipo_tdb->tdb_sproto;
1153: bcopy(&ipo->ipo_tdb->tdb_dst, &tdbi->dst,
1154: ipo->ipo_tdb->tdb_dst.sa.sa_len);
1155: m_tag_prepend(m, mtag);
1156: return tdb;
1157:
1158: justreturn:
1159: if (ipo != NULL)
1160: return ipo->ipo_tdb;
1161: else
1162: return NULL;
1163: }
1164:
1165: /*
1166: * Find a pending ACQUIRE record based on its sequence number.
1167: * XXX Need to use a better data structure.
1168: */
1169: struct ipsec_acquire *
1170: ipsec_get_acquire(u_int32_t seq)
1171: {
1172: struct ipsec_acquire *ipa;
1173:
1174: TAILQ_FOREACH (ipa, &ipsec_acquire_head, ipa_next)
1175: if (ipa->ipa_seq == seq)
1176: return ipa;
1177:
1178: return NULL;
1179: }
CVSweb