Line data Source code
1 : /* $OpenBSD: pfkeyv2.c,v 1.192 2018/09/12 11:24:38 mpi Exp $ */
2 :
3 : /*
4 : * @(#)COPYRIGHT 1.1 (NRL) 17 January 1995
5 : *
6 : * NRL grants permission for redistribution and use in source and binary
7 : * forms, with or without modification, of the software and documentation
8 : * created at NRL provided that the following conditions are met:
9 : *
10 : * 1. Redistributions of source code must retain the above copyright
11 : * notice, this list of conditions and the following disclaimer.
12 : * 2. Redistributions in binary form must reproduce the above copyright
13 : * notice, this list of conditions and the following disclaimer in the
14 : * documentation and/or other materials provided with the distribution.
15 : * 3. All advertising materials mentioning features or use of this software
16 : * must display the following acknowledgements:
17 : * This product includes software developed by the University of
18 : * California, Berkeley and its contributors.
19 : * This product includes software developed at the Information
20 : * Technology Division, US Naval Research Laboratory.
21 : * 4. Neither the name of the NRL nor the names of its contributors
22 : * may be used to endorse or promote products derived from this software
23 : * without specific prior written permission.
24 : *
25 : * THE SOFTWARE PROVIDED BY NRL IS PROVIDED BY NRL AND CONTRIBUTORS ``AS
26 : * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27 : * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
28 : * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NRL OR
29 : * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 : * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 : * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 : * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 : * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 : * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 : * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 : *
37 : * The views and conclusions contained in the software and documentation
38 : * are those of the authors and should not be interpreted as representing
39 : * official policies, either expressed or implied, of the US Naval
40 : * Research Laboratory (NRL).
41 : */
42 :
43 : /*
44 : * Copyright (c) 1995, 1996, 1997, 1998, 1999 Craig Metz. All rights reserved.
45 : *
46 : * Redistribution and use in source and binary forms, with or without
47 : * modification, are permitted provided that the following conditions
48 : * are met:
49 : * 1. Redistributions of source code must retain the above copyright
50 : * notice, this list of conditions and the following disclaimer.
51 : * 2. Redistributions in binary form must reproduce the above copyright
52 : * notice, this list of conditions and the following disclaimer in the
53 : * documentation and/or other materials provided with the distribution.
54 : * 3. Neither the name of the author nor the names of any contributors
55 : * may be used to endorse or promote products derived from this software
56 : * without specific prior written permission.
57 : *
58 : * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
59 : * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
60 : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
61 : * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
62 : * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
63 : * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
64 : * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
65 : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
66 : * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
67 : * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
68 : * SUCH DAMAGE.
69 : */
70 :
71 : #include "pf.h"
72 :
73 : #include <sys/param.h>
74 : #include <sys/socket.h>
75 : #include <sys/socketvar.h>
76 : #include <sys/protosw.h>
77 : #include <sys/domain.h>
78 : #include <sys/systm.h>
79 : #include <sys/mbuf.h>
80 : #include <sys/kernel.h>
81 : #include <sys/proc.h>
82 : #include <sys/pool.h>
83 : #include <sys/mutex.h>
84 :
85 : #include <net/route.h>
86 : #include <netinet/ip_ipsp.h>
87 : #include <net/pfkeyv2.h>
88 : #include <net/radix.h>
89 : #include <netinet/ip_ah.h>
90 : #include <netinet/ip_esp.h>
91 : #include <netinet/ip_ipcomp.h>
92 : #include <crypto/blf.h>
93 :
94 : #if NPF > 0
95 : #include <net/if.h>
96 : #include <net/pfvar.h>
97 : #endif
98 :
99 : #define PFKEYSNDQ 8192
100 : #define PFKEYRCVQ 8192
101 :
102 : static const struct sadb_alg ealgs[] = {
103 : { SADB_EALG_NULL, 0, 0, 0 },
104 : { SADB_EALG_3DESCBC, 64, 192, 192 },
105 : { SADB_X_EALG_BLF, 64, 40, BLF_MAXKEYLEN * 8},
106 : { SADB_X_EALG_CAST, 64, 40, 128},
107 : { SADB_X_EALG_AES, 128, 128, 256},
108 : { SADB_X_EALG_AESCTR, 128, 128 + 32, 256 + 32}
109 : };
110 :
111 : static const struct sadb_alg aalgs[] = {
112 : { SADB_AALG_SHA1HMAC, 0, 160, 160 },
113 : { SADB_AALG_MD5HMAC, 0, 128, 128 },
114 : { SADB_X_AALG_RIPEMD160HMAC, 0, 160, 160 },
115 : { SADB_X_AALG_SHA2_256, 0, 256, 256 },
116 : { SADB_X_AALG_SHA2_384, 0, 384, 384 },
117 : { SADB_X_AALG_SHA2_512, 0, 512, 512 }
118 : };
119 :
120 : static const struct sadb_alg calgs[] = {
121 : { SADB_X_CALG_DEFLATE, 0, 0, 0},
122 : { SADB_X_CALG_LZS, 0, 0, 0}
123 : };
124 :
125 : extern uint64_t sadb_exts_allowed_out[SADB_MAX+1];
126 : extern uint64_t sadb_exts_required_out[SADB_MAX+1];
127 :
128 : extern struct pool ipsec_policy_pool;
129 :
130 : extern struct radix_node_head **spd_tables;
131 :
132 : #define PFKEY_MSG_MAXSZ 4096
133 : const struct sockaddr pfkey_addr = { 2, PF_KEY, };
134 : struct domain pfkeydomain;
135 :
136 : /*
137 : * pfkey PCB
138 : *
139 : * Locks used to protect struct members in this file:
140 : * I immutable after creation
141 : * a atomic operations
142 : * l pkptable's lock
143 : * s socket lock
144 : */
145 : struct pkpcb {
146 : struct socket *kcb_socket; /* [I] associated socket */
147 :
148 : SRPL_ENTRY(pkpcb) kcb_list; /* [l] */
149 : struct refcnt kcb_refcnt; /* [a] */
150 : int kcb_flags; /* [s] */
151 : uint32_t kcb_reg; /* [s] Inc if SATYPE_MAX > 31 */
152 : uint32_t kcb_pid; /* [I] */
153 : unsigned int kcb_rdomain; /* [I] routing domain */
154 : };
155 : #define sotokeycb(so) ((struct pkpcb *)(so)->so_pcb)
156 : #define keylock(kp) solock((kp)->kcb_socket)
157 : #define keyunlock(kp, s) sounlock((kp)->kcb_socket, s)
158 :
159 :
160 : struct dump_state {
161 : struct sadb_msg *sadb_msg;
162 : struct socket *socket;
163 : };
164 :
165 : struct pkptable {
166 : SRPL_HEAD(, pkpcb) pkp_list;
167 : struct srpl_rc pkp_rc;
168 : struct rwlock pkp_lk;
169 : };
170 :
171 : struct pkptable pkptable;
172 : struct mutex pfkeyv2_mtx = MUTEX_INITIALIZER(IPL_NONE);
173 : static uint32_t pfkeyv2_seq = 1;
174 : static int nregistered = 0;
175 : static int npromisc = 0;
176 :
177 : void pfkey_init(void);
178 :
179 : int pfkeyv2_attach(struct socket *, int);
180 : int pfkeyv2_detach(struct socket *);
181 : int pfkeyv2_usrreq(struct socket *, int, struct mbuf *, struct mbuf *,
182 : struct mbuf *, struct proc *);
183 : int pfkeyv2_output(struct mbuf *, struct socket *, struct sockaddr *,
184 : struct mbuf *);
185 : int pfkey_sendup(struct pkpcb *, struct mbuf *, int);
186 : int pfkeyv2_sa_flush(struct tdb *, void *, int);
187 : int pfkeyv2_policy_flush(struct ipsec_policy *, void *, unsigned int);
188 : int pfkeyv2_sysctl_policydumper(struct ipsec_policy *, void *, unsigned int);
189 :
190 : void keycb_ref(void *, void *);
191 : void keycb_unref(void *, void *);
192 :
193 : /*
194 : * Wrapper around m_devget(); copy data from contiguous buffer to mbuf
195 : * chain.
196 : */
197 : int
198 0 : pfdatatopacket(void *data, int len, struct mbuf **packet)
199 : {
200 0 : if (!(*packet = m_devget(data, len, 0)))
201 0 : return (ENOMEM);
202 :
203 : /* Make sure, all data gets zeroized on free */
204 0 : (*packet)->m_flags |= M_ZEROIZE;
205 :
206 0 : return (0);
207 0 : }
208 :
209 : static struct protosw pfkeysw[] = {
210 : {
211 : .pr_type = SOCK_RAW,
212 : .pr_domain = &pfkeydomain,
213 : .pr_protocol = PF_KEY_V2,
214 : .pr_flags = PR_ATOMIC | PR_ADDR,
215 : .pr_output = pfkeyv2_output,
216 : .pr_usrreq = pfkeyv2_usrreq,
217 : .pr_attach = pfkeyv2_attach,
218 : .pr_detach = pfkeyv2_detach,
219 : .pr_sysctl = pfkeyv2_sysctl,
220 : }
221 : };
222 :
223 : struct domain pfkeydomain = {
224 : .dom_family = PF_KEY,
225 : .dom_name = "PF_KEY",
226 : .dom_init = pfkey_init,
227 : .dom_protosw = pfkeysw,
228 : .dom_protoswNPROTOSW = &pfkeysw[nitems(pfkeysw)],
229 : };
230 :
231 : void
232 0 : keycb_ref(void *null, void *v)
233 : {
234 0 : struct pkpcb *kp = v;
235 :
236 0 : refcnt_take(&kp->kcb_refcnt);
237 0 : }
238 :
239 : void
240 0 : keycb_unref(void *null, void *v)
241 : {
242 0 : struct pkpcb *kp = v;
243 :
244 0 : refcnt_rele_wake(&kp->kcb_refcnt);
245 0 : }
246 :
247 : void
248 0 : pfkey_init(void)
249 : {
250 0 : rn_init(sizeof(struct sockaddr_encap));
251 0 : srpl_rc_init(&pkptable.pkp_rc, keycb_ref, keycb_unref, NULL);
252 0 : rw_init(&pkptable.pkp_lk, "pfkey");
253 0 : SRPL_INIT(&pkptable.pkp_list);
254 0 : }
255 :
256 :
257 : /*
258 : * Attach a new PF_KEYv2 socket.
259 : */
260 : int
261 0 : pfkeyv2_attach(struct socket *so, int proto)
262 : {
263 : struct pkpcb *kp;
264 : int error;
265 :
266 0 : if ((so->so_state & SS_PRIV) == 0)
267 0 : return EACCES;
268 :
269 0 : kp = malloc(sizeof(struct pkpcb), M_PCB, M_WAITOK | M_ZERO);
270 0 : so->so_pcb = kp;
271 0 : refcnt_init(&kp->kcb_refcnt);
272 :
273 0 : error = soreserve(so, PFKEYSNDQ, PFKEYRCVQ);
274 0 : if (error) {
275 0 : free(kp, M_PCB, sizeof(struct pkpcb));
276 0 : return (error);
277 : }
278 :
279 0 : kp->kcb_socket = so;
280 :
281 0 : so->so_options |= SO_USELOOPBACK;
282 0 : soisconnected(so);
283 :
284 0 : kp->kcb_pid = curproc->p_p->ps_pid;
285 0 : kp->kcb_rdomain = rtable_l2(curproc->p_p->ps_rtableid);
286 :
287 0 : rw_enter(&pkptable.pkp_lk, RW_WRITE);
288 0 : SRPL_INSERT_HEAD_LOCKED(&pkptable.pkp_rc, &pkptable.pkp_list, kp, kcb_list);
289 0 : rw_exit(&pkptable.pkp_lk);
290 :
291 0 : return (0);
292 0 : }
293 :
294 : /*
295 : * Close a PF_KEYv2 socket.
296 : */
297 : int
298 0 : pfkeyv2_detach(struct socket *so)
299 : {
300 : struct pkpcb *kp;
301 :
302 0 : soassertlocked(so);
303 :
304 0 : kp = sotokeycb(so);
305 0 : if (kp == NULL)
306 0 : return ENOTCONN;
307 :
308 0 : if (kp->kcb_flags &
309 : (PFKEYV2_SOCKETFLAGS_REGISTERED|PFKEYV2_SOCKETFLAGS_PROMISC)) {
310 0 : mtx_enter(&pfkeyv2_mtx);
311 0 : if (kp->kcb_flags & PFKEYV2_SOCKETFLAGS_REGISTERED)
312 0 : nregistered--;
313 :
314 0 : if (kp->kcb_flags & PFKEYV2_SOCKETFLAGS_PROMISC)
315 0 : npromisc--;
316 0 : mtx_leave(&pfkeyv2_mtx);
317 0 : }
318 :
319 0 : rw_enter(&pkptable.pkp_lk, RW_WRITE);
320 0 : SRPL_REMOVE_LOCKED(&pkptable.pkp_rc, &pkptable.pkp_list, kp, pkpcb,
321 : kcb_list);
322 0 : rw_exit(&pkptable.pkp_lk);
323 :
324 : /* wait for all references to drop */
325 0 : refcnt_finalize(&kp->kcb_refcnt, "pfkeyrefs");
326 :
327 0 : so->so_pcb = NULL;
328 0 : KASSERT((so->so_state & SS_NOFDREF) == 0);
329 0 : free(kp, M_PCB, sizeof(struct pkpcb));
330 :
331 0 : return (0);
332 0 : }
333 :
334 : int
335 0 : pfkeyv2_usrreq(struct socket *so, int req, struct mbuf *m,
336 : struct mbuf *nam, struct mbuf *control, struct proc *p)
337 : {
338 : struct pkpcb *kp;
339 : int error = 0;
340 :
341 0 : if (req == PRU_CONTROL)
342 0 : return (EOPNOTSUPP);
343 :
344 0 : soassertlocked(so);
345 :
346 0 : if (control && control->m_len) {
347 : error = EOPNOTSUPP;
348 0 : goto release;
349 : }
350 :
351 0 : kp = sotokeycb(so);
352 0 : if (kp == NULL) {
353 : error = EINVAL;
354 0 : goto release;
355 : }
356 :
357 0 : switch (req) {
358 : /* no connect, bind, accept. Socket is connected from the start */
359 : case PRU_CONNECT:
360 : case PRU_BIND:
361 : case PRU_CONNECT2:
362 : case PRU_LISTEN:
363 : case PRU_ACCEPT:
364 : error = EOPNOTSUPP;
365 0 : break;
366 :
367 : case PRU_DISCONNECT:
368 : case PRU_ABORT:
369 0 : soisdisconnected(so);
370 0 : break;
371 : case PRU_SHUTDOWN:
372 0 : socantsendmore(so);
373 0 : break;
374 : case PRU_SENSE:
375 : /* stat: don't bother with a blocksize. */
376 0 : return (0);
377 :
378 : /* minimal support, just implement a fake peer address */
379 : case PRU_SOCKADDR:
380 : error = EINVAL;
381 0 : break;
382 : case PRU_PEERADDR:
383 0 : bcopy(&pfkey_addr, mtod(nam, caddr_t), pfkey_addr.sa_len);
384 0 : nam->m_len = pfkey_addr.sa_len;
385 0 : break;
386 :
387 : case PRU_RCVOOB:
388 : case PRU_RCVD:
389 0 : return (EOPNOTSUPP);
390 :
391 : case PRU_SENDOOB:
392 : error = EOPNOTSUPP;
393 0 : break;
394 : case PRU_SEND:
395 0 : if (nam) {
396 : error = EISCONN;
397 0 : break;
398 : }
399 0 : error = (*so->so_proto->pr_output)(m, so, NULL, NULL);
400 : m = NULL;
401 0 : break;
402 : default:
403 0 : panic("pfkeyv2_usrreq");
404 : }
405 :
406 : release:
407 0 : m_freem(control);
408 0 : m_freem(m);
409 0 : return (error);
410 0 : }
411 :
412 : int
413 0 : pfkeyv2_output(struct mbuf *mbuf, struct socket *so,
414 : struct sockaddr *dstaddr, struct mbuf *control)
415 : {
416 : void *message;
417 : int error = 0;
418 :
419 : #ifdef DIAGNOSTIC
420 0 : if (!mbuf || !(mbuf->m_flags & M_PKTHDR)) {
421 : error = EINVAL;
422 0 : goto ret;
423 : }
424 : #endif /* DIAGNOSTIC */
425 :
426 0 : if (mbuf->m_pkthdr.len > PFKEY_MSG_MAXSZ) {
427 : error = EMSGSIZE;
428 0 : goto ret;
429 : }
430 :
431 0 : if (!(message = malloc((unsigned long) mbuf->m_pkthdr.len,
432 : M_PFKEY, M_DONTWAIT))) {
433 : error = ENOMEM;
434 0 : goto ret;
435 : }
436 :
437 0 : m_copydata(mbuf, 0, mbuf->m_pkthdr.len, message);
438 :
439 0 : error = pfkeyv2_send(so, message, mbuf->m_pkthdr.len);
440 :
441 : ret:
442 0 : m_freem(mbuf);
443 0 : return (error);
444 : }
445 :
446 : int
447 0 : pfkey_sendup(struct pkpcb *kp, struct mbuf *m0, int more)
448 : {
449 0 : struct socket *so = kp->kcb_socket;
450 : struct mbuf *m;
451 :
452 0 : soassertlocked(so);
453 :
454 0 : if (more) {
455 0 : if (!(m = m_dup_pkt(m0, 0, M_DONTWAIT)))
456 0 : return (ENOMEM);
457 : } else
458 : m = m0;
459 :
460 0 : if (!sbappendaddr(so, &so->so_rcv, &pfkey_addr, m, NULL)) {
461 0 : m_freem(m);
462 0 : return (ENOBUFS);
463 : }
464 :
465 0 : sorwakeup(so);
466 0 : return (0);
467 0 : }
468 :
469 : /*
470 : * Send a PFKEYv2 message, possibly to many receivers, based on the
471 : * satype of the socket (which is set by the REGISTER message), and the
472 : * third argument.
473 : */
474 : int
475 0 : pfkeyv2_sendmessage(void **headers, int mode, struct socket *so,
476 : u_int8_t satype, int count, u_int rdomain)
477 : {
478 : int i, j, rval, s;
479 : void *p, *buffer = NULL;
480 0 : struct mbuf *packet;
481 : struct pkpcb *kp;
482 : struct sadb_msg *smsg;
483 0 : struct srp_ref sr;
484 :
485 : /* Find out how much space we'll need... */
486 : j = sizeof(struct sadb_msg);
487 :
488 0 : for (i = 1; i <= SADB_EXT_MAX; i++)
489 0 : if (headers[i])
490 0 : j += ((struct sadb_ext *)headers[i])->sadb_ext_len *
491 : sizeof(uint64_t);
492 :
493 : /* ...and allocate it */
494 0 : if (!(buffer = malloc(j + sizeof(struct sadb_msg), M_PFKEY,
495 : M_NOWAIT))) {
496 : rval = ENOMEM;
497 0 : goto ret;
498 : }
499 :
500 0 : p = buffer + sizeof(struct sadb_msg);
501 0 : bcopy(headers[0], p, sizeof(struct sadb_msg));
502 0 : ((struct sadb_msg *) p)->sadb_msg_len = j / sizeof(uint64_t);
503 0 : p += sizeof(struct sadb_msg);
504 :
505 : /* Copy payloads in the packet */
506 0 : for (i = 1; i <= SADB_EXT_MAX; i++)
507 0 : if (headers[i]) {
508 0 : ((struct sadb_ext *) headers[i])->sadb_ext_type = i;
509 0 : bcopy(headers[i], p, EXTLEN(headers[i]));
510 0 : p += EXTLEN(headers[i]);
511 0 : }
512 :
513 0 : if ((rval = pfdatatopacket(buffer + sizeof(struct sadb_msg),
514 0 : j, &packet)) != 0)
515 : goto ret;
516 :
517 0 : switch (mode) {
518 : case PFKEYV2_SENDMESSAGE_UNICAST:
519 : /*
520 : * Send message to the specified socket, plus all
521 : * promiscuous listeners.
522 : */
523 0 : s = solock(so);
524 0 : pfkey_sendup(sotokeycb(so), packet, 0);
525 0 : sounlock(so, s);
526 :
527 : /*
528 : * Promiscuous messages contain the original message
529 : * encapsulated in another sadb_msg header.
530 : */
531 0 : bzero(buffer, sizeof(struct sadb_msg));
532 0 : smsg = (struct sadb_msg *) buffer;
533 0 : smsg->sadb_msg_version = PF_KEY_V2;
534 0 : smsg->sadb_msg_type = SADB_X_PROMISC;
535 0 : smsg->sadb_msg_len = (sizeof(struct sadb_msg) + j) /
536 : sizeof(uint64_t);
537 0 : smsg->sadb_msg_seq = 0;
538 :
539 : /* Copy to mbuf chain */
540 0 : if ((rval = pfdatatopacket(buffer, sizeof(struct sadb_msg) + j,
541 0 : &packet)) != 0)
542 : goto ret;
543 :
544 : /*
545 : * Search for promiscuous listeners, skipping the
546 : * original destination.
547 : */
548 0 : SRPL_FOREACH(kp, &sr, &pkptable.pkp_list, kcb_list) {
549 0 : if (kp->kcb_socket == so || kp->kcb_rdomain != rdomain)
550 : continue;
551 :
552 0 : s = keylock(kp);
553 0 : if (kp->kcb_flags & PFKEYV2_SOCKETFLAGS_PROMISC)
554 0 : pfkey_sendup(kp, packet, 1);
555 0 : keyunlock(kp, s);
556 0 : }
557 0 : SRPL_LEAVE(&sr);
558 0 : m_freem(packet);
559 0 : break;
560 :
561 : case PFKEYV2_SENDMESSAGE_REGISTERED:
562 : /*
563 : * Send the message to all registered sockets that match
564 : * the specified satype (e.g., all IPSEC-ESP negotiators)
565 : */
566 0 : SRPL_FOREACH(kp, &sr, &pkptable.pkp_list, kcb_list) {
567 0 : if (kp->kcb_rdomain != rdomain)
568 : continue;
569 :
570 0 : s = keylock(kp);
571 0 : if (kp->kcb_flags & PFKEYV2_SOCKETFLAGS_REGISTERED) {
572 0 : if (!satype) {
573 : /* Just send to everyone registered */
574 0 : pfkey_sendup(kp, packet, 1);
575 0 : } else {
576 : /* Check for specified satype */
577 0 : if ((1 << satype) & kp->kcb_reg)
578 0 : pfkey_sendup(kp, packet, 1);
579 : }
580 : }
581 0 : keyunlock(kp, s);
582 0 : }
583 0 : SRPL_LEAVE(&sr);
584 : /* Free last/original copy of the packet */
585 0 : m_freem(packet);
586 :
587 : /* Encapsulate the original message "inside" an sadb_msg header */
588 0 : bzero(buffer, sizeof(struct sadb_msg));
589 0 : smsg = (struct sadb_msg *) buffer;
590 0 : smsg->sadb_msg_version = PF_KEY_V2;
591 0 : smsg->sadb_msg_type = SADB_X_PROMISC;
592 0 : smsg->sadb_msg_len = (sizeof(struct sadb_msg) + j) /
593 : sizeof(uint64_t);
594 0 : smsg->sadb_msg_seq = 0;
595 :
596 : /* Convert to mbuf chain */
597 0 : if ((rval = pfdatatopacket(buffer, sizeof(struct sadb_msg) + j,
598 0 : &packet)) != 0)
599 : goto ret;
600 :
601 : /* Send to all registered promiscuous listeners */
602 0 : SRPL_FOREACH(kp, &sr, &pkptable.pkp_list, kcb_list) {
603 0 : if (kp->kcb_rdomain != rdomain)
604 : continue;
605 :
606 0 : s = keylock(kp);
607 0 : if ((kp->kcb_flags & PFKEYV2_SOCKETFLAGS_PROMISC) &&
608 0 : !(kp->kcb_flags & PFKEYV2_SOCKETFLAGS_REGISTERED))
609 0 : pfkey_sendup(kp, packet, 1);
610 0 : keyunlock(kp, s);
611 0 : }
612 0 : SRPL_LEAVE(&sr);
613 0 : m_freem(packet);
614 0 : break;
615 :
616 : case PFKEYV2_SENDMESSAGE_BROADCAST:
617 : /* Send message to all sockets */
618 0 : SRPL_FOREACH(kp, &sr, &pkptable.pkp_list, kcb_list) {
619 0 : if (kp->kcb_rdomain != rdomain)
620 : continue;
621 :
622 0 : s = keylock(kp);
623 0 : pfkey_sendup(kp, packet, 1);
624 0 : keyunlock(kp, s);
625 0 : }
626 0 : SRPL_LEAVE(&sr);
627 0 : m_freem(packet);
628 0 : break;
629 : }
630 :
631 : ret:
632 0 : if (buffer != NULL) {
633 0 : bzero(buffer, j + sizeof(struct sadb_msg));
634 0 : free(buffer, M_PFKEY, 0);
635 0 : }
636 :
637 0 : return (rval);
638 0 : }
639 :
640 : /*
641 : * Get SPD information for an ACQUIRE. We setup the message such that
642 : * the SRC/DST payloads are relative to us (regardless of whether the
643 : * SPD rule was for incoming or outgoing packets).
644 : */
645 : int
646 0 : pfkeyv2_policy(struct ipsec_acquire *ipa, void **headers, void **buffer)
647 : {
648 0 : union sockaddr_union sunion;
649 : struct sadb_protocol *sp;
650 : int rval, i, dir;
651 0 : void *p;
652 :
653 : /* Find out how big a buffer we need */
654 : i = 4 * sizeof(struct sadb_address) + sizeof(struct sadb_protocol);
655 0 : bzero(&sunion, sizeof(union sockaddr_union));
656 :
657 0 : switch (ipa->ipa_info.sen_type) {
658 : case SENT_IP4:
659 : i += 4 * PADUP(sizeof(struct sockaddr_in));
660 0 : sunion.sa.sa_family = AF_INET;
661 0 : sunion.sa.sa_len = sizeof(struct sockaddr_in);
662 0 : dir = ipa->ipa_info.sen_direction;
663 0 : break;
664 :
665 : #ifdef INET6
666 : case SENT_IP6:
667 : i += 4 * PADUP(sizeof(struct sockaddr_in6));
668 0 : sunion.sa.sa_family = AF_INET6;
669 0 : sunion.sa.sa_len = sizeof(struct sockaddr_in6);
670 0 : dir = ipa->ipa_info.sen_ip6_direction;
671 0 : break;
672 : #endif /* INET6 */
673 :
674 : default:
675 0 : return (EINVAL);
676 : }
677 :
678 0 : if (!(p = malloc(i, M_PFKEY, M_NOWAIT | M_ZERO))) {
679 : rval = ENOMEM;
680 0 : goto ret;
681 : } else
682 0 : *buffer = p;
683 :
684 0 : if (dir == IPSP_DIRECTION_OUT)
685 0 : headers[SADB_X_EXT_SRC_FLOW] = p;
686 : else
687 0 : headers[SADB_X_EXT_DST_FLOW] = p;
688 0 : switch (sunion.sa.sa_family) {
689 : case AF_INET:
690 0 : sunion.sin.sin_addr = ipa->ipa_info.sen_ip_src;
691 0 : sunion.sin.sin_port = ipa->ipa_info.sen_sport;
692 0 : break;
693 :
694 : #ifdef INET6
695 : case AF_INET6:
696 0 : sunion.sin6.sin6_addr = ipa->ipa_info.sen_ip6_src;
697 0 : sunion.sin6.sin6_port = ipa->ipa_info.sen_ip6_sport;
698 0 : break;
699 : #endif /* INET6 */
700 : }
701 0 : export_address(&p, &sunion.sa);
702 :
703 0 : if (dir == IPSP_DIRECTION_OUT)
704 0 : headers[SADB_X_EXT_SRC_MASK] = p;
705 : else
706 0 : headers[SADB_X_EXT_DST_MASK] = p;
707 0 : switch (sunion.sa.sa_family) {
708 : case AF_INET:
709 0 : sunion.sin.sin_addr = ipa->ipa_mask.sen_ip_src;
710 0 : sunion.sin.sin_port = ipa->ipa_mask.sen_sport;
711 0 : break;
712 :
713 : #ifdef INET6
714 : case AF_INET6:
715 0 : sunion.sin6.sin6_addr = ipa->ipa_mask.sen_ip6_src;
716 0 : sunion.sin6.sin6_port = ipa->ipa_mask.sen_ip6_sport;
717 0 : break;
718 : #endif /* INET6 */
719 : }
720 0 : export_address(&p, &sunion.sa);
721 :
722 0 : if (dir == IPSP_DIRECTION_OUT)
723 0 : headers[SADB_X_EXT_DST_FLOW] = p;
724 : else
725 0 : headers[SADB_X_EXT_SRC_FLOW] = p;
726 0 : switch (sunion.sa.sa_family) {
727 : case AF_INET:
728 0 : sunion.sin.sin_addr = ipa->ipa_info.sen_ip_dst;
729 0 : sunion.sin.sin_port = ipa->ipa_info.sen_dport;
730 0 : break;
731 :
732 : #ifdef INET6
733 : case AF_INET6:
734 0 : sunion.sin6.sin6_addr = ipa->ipa_info.sen_ip6_dst;
735 0 : sunion.sin6.sin6_port = ipa->ipa_info.sen_ip6_dport;
736 0 : break;
737 : #endif /* INET6 */
738 : }
739 0 : export_address(&p, &sunion.sa);
740 :
741 0 : if (dir == IPSP_DIRECTION_OUT)
742 0 : headers[SADB_X_EXT_DST_MASK] = p;
743 : else
744 0 : headers[SADB_X_EXT_SRC_MASK] = p;
745 0 : switch (sunion.sa.sa_family) {
746 : case AF_INET:
747 0 : sunion.sin.sin_addr = ipa->ipa_mask.sen_ip_dst;
748 0 : sunion.sin.sin_port = ipa->ipa_mask.sen_dport;
749 0 : break;
750 :
751 : #ifdef INET6
752 : case AF_INET6:
753 0 : sunion.sin6.sin6_addr = ipa->ipa_mask.sen_ip6_dst;
754 0 : sunion.sin6.sin6_port = ipa->ipa_mask.sen_ip6_dport;
755 0 : break;
756 : #endif /* INET6 */
757 : }
758 0 : export_address(&p, &sunion.sa);
759 :
760 0 : headers[SADB_X_EXT_FLOW_TYPE] = p;
761 0 : sp = p;
762 0 : sp->sadb_protocol_len = sizeof(struct sadb_protocol) /
763 : sizeof(u_int64_t);
764 0 : switch (sunion.sa.sa_family) {
765 : case AF_INET:
766 0 : if (ipa->ipa_mask.sen_proto)
767 0 : sp->sadb_protocol_proto = ipa->ipa_info.sen_proto;
768 0 : sp->sadb_protocol_direction = ipa->ipa_info.sen_direction;
769 0 : break;
770 :
771 : #ifdef INET6
772 : case AF_INET6:
773 0 : if (ipa->ipa_mask.sen_ip6_proto)
774 0 : sp->sadb_protocol_proto = ipa->ipa_info.sen_ip6_proto;
775 0 : sp->sadb_protocol_direction = ipa->ipa_info.sen_ip6_direction;
776 0 : break;
777 : #endif /* INET6 */
778 : }
779 :
780 0 : rval = 0;
781 :
782 : ret:
783 0 : return (rval);
784 0 : }
785 :
786 : /*
787 : * Get all the information contained in an SA to a PFKEYV2 message.
788 : */
789 : int
790 0 : pfkeyv2_get(struct tdb *tdb, void **headers, void **buffer, int *lenp)
791 : {
792 : int rval, i;
793 0 : void *p;
794 :
795 : /* Find how much space we need */
796 : i = sizeof(struct sadb_sa) + sizeof(struct sadb_lifetime);
797 :
798 0 : if (tdb->tdb_soft_allocations || tdb->tdb_soft_bytes ||
799 0 : tdb->tdb_soft_timeout || tdb->tdb_soft_first_use)
800 0 : i += sizeof(struct sadb_lifetime);
801 :
802 0 : if (tdb->tdb_exp_allocations || tdb->tdb_exp_bytes ||
803 0 : tdb->tdb_exp_timeout || tdb->tdb_exp_first_use)
804 0 : i += sizeof(struct sadb_lifetime);
805 :
806 0 : if (tdb->tdb_last_used)
807 0 : i += sizeof(struct sadb_lifetime);
808 :
809 0 : i += sizeof(struct sadb_address) + PADUP(tdb->tdb_src.sa.sa_len);
810 0 : i += sizeof(struct sadb_address) + PADUP(tdb->tdb_dst.sa.sa_len);
811 :
812 0 : if (tdb->tdb_ids) {
813 0 : i += sizeof(struct sadb_ident) + PADUP(tdb->tdb_ids->id_local->len);
814 0 : i += sizeof(struct sadb_ident) + PADUP(tdb->tdb_ids->id_remote->len);
815 0 : }
816 :
817 0 : if (tdb->tdb_amxkey)
818 0 : i += sizeof(struct sadb_key) + PADUP(tdb->tdb_amxkeylen);
819 :
820 0 : if (tdb->tdb_emxkey)
821 0 : i += sizeof(struct sadb_key) + PADUP(tdb->tdb_emxkeylen);
822 :
823 0 : if (tdb->tdb_filter.sen_type) {
824 0 : i += 2 * sizeof(struct sadb_protocol);
825 :
826 : /* We'll need four of them: src, src mask, dst, dst mask. */
827 0 : switch (tdb->tdb_filter.sen_type) {
828 : case SENT_IP4:
829 0 : i += 4 * PADUP(sizeof(struct sockaddr_in));
830 0 : i += 4 * sizeof(struct sadb_address);
831 0 : break;
832 : #ifdef INET6
833 : case SENT_IP6:
834 0 : i += 4 * PADUP(sizeof(struct sockaddr_in6));
835 0 : i += 4 * sizeof(struct sadb_address);
836 0 : break;
837 : #endif /* INET6 */
838 : default:
839 : rval = EINVAL;
840 0 : goto ret;
841 : }
842 : }
843 :
844 0 : if (tdb->tdb_onext) {
845 0 : i += sizeof(struct sadb_sa);
846 0 : i += sizeof(struct sadb_address) +
847 0 : PADUP(tdb->tdb_onext->tdb_dst.sa.sa_len);
848 0 : i += sizeof(struct sadb_protocol);
849 0 : }
850 :
851 0 : if (tdb->tdb_udpencap_port)
852 0 : i += sizeof(struct sadb_x_udpencap);
853 :
854 : #if NPF > 0
855 0 : if (tdb->tdb_tag)
856 0 : i += sizeof(struct sadb_x_tag) + PADUP(PF_TAG_NAME_SIZE);
857 0 : if (tdb->tdb_tap)
858 0 : i += sizeof(struct sadb_x_tap);
859 : #endif
860 :
861 0 : if (lenp)
862 0 : *lenp = i;
863 :
864 0 : if (buffer == NULL) {
865 : rval = 0;
866 0 : goto ret;
867 : }
868 :
869 0 : if (!(p = malloc(i, M_PFKEY, M_NOWAIT | M_ZERO))) {
870 : rval = ENOMEM;
871 0 : goto ret;
872 : } else
873 0 : *buffer = p;
874 :
875 0 : headers[SADB_EXT_SA] = p;
876 :
877 0 : export_sa(&p, tdb); /* Export SA information (mostly flags) */
878 :
879 : /* Export lifetimes where applicable */
880 0 : headers[SADB_EXT_LIFETIME_CURRENT] = p;
881 0 : export_lifetime(&p, tdb, PFKEYV2_LIFETIME_CURRENT);
882 :
883 0 : if (tdb->tdb_soft_allocations || tdb->tdb_soft_bytes ||
884 0 : tdb->tdb_soft_first_use || tdb->tdb_soft_timeout) {
885 0 : headers[SADB_EXT_LIFETIME_SOFT] = p;
886 0 : export_lifetime(&p, tdb, PFKEYV2_LIFETIME_SOFT);
887 0 : }
888 :
889 0 : if (tdb->tdb_exp_allocations || tdb->tdb_exp_bytes ||
890 0 : tdb->tdb_exp_first_use || tdb->tdb_exp_timeout) {
891 0 : headers[SADB_EXT_LIFETIME_HARD] = p;
892 0 : export_lifetime(&p, tdb, PFKEYV2_LIFETIME_HARD);
893 0 : }
894 :
895 0 : if (tdb->tdb_last_used) {
896 0 : headers[SADB_X_EXT_LIFETIME_LASTUSE] = p;
897 0 : export_lifetime(&p, tdb, PFKEYV2_LIFETIME_LASTUSE);
898 0 : }
899 :
900 : /* Export TDB source address */
901 0 : headers[SADB_EXT_ADDRESS_SRC] = p;
902 0 : export_address(&p, &tdb->tdb_src.sa);
903 :
904 : /* Export TDB destination address */
905 0 : headers[SADB_EXT_ADDRESS_DST] = p;
906 0 : export_address(&p, &tdb->tdb_dst.sa);
907 :
908 : /* Export source/destination identities, if present */
909 0 : if (tdb->tdb_ids)
910 0 : export_identities(&p, tdb->tdb_ids, tdb->tdb_ids_swapped, headers);
911 :
912 : /* Export authentication key, if present */
913 0 : if (tdb->tdb_amxkey) {
914 0 : headers[SADB_EXT_KEY_AUTH] = p;
915 0 : export_key(&p, tdb, PFKEYV2_AUTHENTICATION_KEY);
916 0 : }
917 :
918 : /* Export encryption key, if present */
919 0 : if (tdb->tdb_emxkey) {
920 0 : headers[SADB_EXT_KEY_ENCRYPT] = p;
921 0 : export_key(&p, tdb, PFKEYV2_ENCRYPTION_KEY);
922 0 : }
923 :
924 : /* Export flow/filter, if present */
925 0 : if (tdb->tdb_filter.sen_type)
926 0 : export_flow(&p, IPSP_IPSEC_USE, &tdb->tdb_filter,
927 0 : &tdb->tdb_filtermask, headers);
928 :
929 0 : if (tdb->tdb_onext) {
930 0 : headers[SADB_X_EXT_SA2] = p;
931 0 : export_sa(&p, tdb->tdb_onext);
932 0 : headers[SADB_X_EXT_DST2] = p;
933 0 : export_address(&p, &tdb->tdb_onext->tdb_dst.sa);
934 0 : headers[SADB_X_EXT_SATYPE2] = p;
935 0 : export_satype(&p, tdb->tdb_onext);
936 0 : }
937 :
938 : /* Export UDP encapsulation port, if present */
939 0 : if (tdb->tdb_udpencap_port) {
940 0 : headers[SADB_X_EXT_UDPENCAP] = p;
941 0 : export_udpencap(&p, tdb);
942 0 : }
943 :
944 : #if NPF > 0
945 : /* Export tag information, if present */
946 0 : if (tdb->tdb_tag) {
947 0 : headers[SADB_X_EXT_TAG] = p;
948 0 : export_tag(&p, tdb);
949 0 : }
950 :
951 : /* Export tap enc(4) device information, if present */
952 0 : if (tdb->tdb_tap) {
953 0 : headers[SADB_X_EXT_TAP] = p;
954 0 : export_tap(&p, tdb);
955 0 : }
956 : #endif
957 :
958 0 : rval = 0;
959 :
960 : ret:
961 0 : return (rval);
962 0 : }
963 :
964 : /*
965 : * Dump a TDB.
966 : */
967 : int
968 0 : pfkeyv2_dump_walker(struct tdb *tdb, void *state, int last)
969 : {
970 0 : struct dump_state *dump_state = (struct dump_state *) state;
971 0 : void *headers[SADB_EXT_MAX+1], *buffer;
972 : int rval;
973 :
974 : /* If not satype was specified, dump all TDBs */
975 0 : if (!dump_state->sadb_msg->sadb_msg_satype ||
976 0 : (tdb->tdb_satype == dump_state->sadb_msg->sadb_msg_satype)) {
977 0 : bzero(headers, sizeof(headers));
978 0 : headers[0] = (void *) dump_state->sadb_msg;
979 :
980 : /* Get the information from the TDB to a PFKEYv2 message */
981 0 : if ((rval = pfkeyv2_get(tdb, headers, &buffer, NULL)) != 0)
982 0 : return (rval);
983 :
984 0 : if (last)
985 0 : ((struct sadb_msg *)headers[0])->sadb_msg_seq = 0;
986 :
987 : /* Send the message to the specified socket */
988 0 : rval = pfkeyv2_sendmessage(headers,
989 0 : PFKEYV2_SENDMESSAGE_UNICAST, dump_state->socket, 0, 0,
990 0 : tdb->tdb_rdomain);
991 :
992 0 : free(buffer, M_PFKEY, 0);
993 0 : if (rval)
994 0 : return (rval);
995 : }
996 :
997 0 : return (0);
998 0 : }
999 :
1000 : /*
1001 : * Delete an SA.
1002 : */
1003 : int
1004 0 : pfkeyv2_sa_flush(struct tdb *tdb, void *satype_vp, int last)
1005 : {
1006 0 : if (!(*((u_int8_t *) satype_vp)) ||
1007 0 : tdb->tdb_satype == *((u_int8_t *) satype_vp))
1008 0 : tdb_delete(tdb);
1009 0 : return (0);
1010 : }
1011 :
1012 : /*
1013 : * Convert between SATYPEs and IPsec protocols, taking into consideration
1014 : * sysctl variables enabling/disabling ESP/AH and the presence of the old
1015 : * IPsec transforms.
1016 : */
1017 : int
1018 0 : pfkeyv2_get_proto_alg(u_int8_t satype, u_int8_t *sproto, int *alg)
1019 : {
1020 0 : switch (satype) {
1021 : #ifdef IPSEC
1022 : case SADB_SATYPE_AH:
1023 0 : if (!ah_enable)
1024 0 : return (EOPNOTSUPP);
1025 :
1026 0 : *sproto = IPPROTO_AH;
1027 :
1028 0 : if(alg != NULL)
1029 0 : *alg = satype = XF_AH;
1030 :
1031 : break;
1032 :
1033 : case SADB_SATYPE_ESP:
1034 0 : if (!esp_enable)
1035 0 : return (EOPNOTSUPP);
1036 :
1037 0 : *sproto = IPPROTO_ESP;
1038 :
1039 0 : if(alg != NULL)
1040 0 : *alg = satype = XF_ESP;
1041 :
1042 : break;
1043 :
1044 : case SADB_X_SATYPE_IPIP:
1045 0 : *sproto = IPPROTO_IPIP;
1046 :
1047 0 : if (alg != NULL)
1048 0 : *alg = XF_IP4;
1049 :
1050 : break;
1051 :
1052 : case SADB_X_SATYPE_IPCOMP:
1053 0 : if (!ipcomp_enable)
1054 0 : return (EOPNOTSUPP);
1055 :
1056 0 : *sproto = IPPROTO_IPCOMP;
1057 :
1058 0 : if(alg != NULL)
1059 0 : *alg = satype = XF_IPCOMP;
1060 :
1061 : break;
1062 : #endif /* IPSEC */
1063 : #ifdef TCP_SIGNATURE
1064 : case SADB_X_SATYPE_TCPSIGNATURE:
1065 0 : *sproto = IPPROTO_TCP;
1066 :
1067 0 : if (alg != NULL)
1068 0 : *alg = XF_TCPSIGNATURE;
1069 :
1070 : break;
1071 : #endif /* TCP_SIGNATURE */
1072 :
1073 : default: /* Nothing else supported */
1074 0 : return (EOPNOTSUPP);
1075 : }
1076 :
1077 0 : return (0);
1078 0 : }
1079 :
1080 : /*
1081 : * Handle all messages from userland to kernel.
1082 : */
1083 : int
1084 0 : pfkeyv2_send(struct socket *so, void *message, int len)
1085 : {
1086 0 : int i, j, rval = 0, mode = PFKEYV2_SENDMESSAGE_BROADCAST;
1087 : int delflag = 0;
1088 0 : struct sockaddr_encap encapdst, encapnetmask;
1089 : struct ipsec_policy *ipo;
1090 : struct ipsec_acquire *ipa;
1091 : struct radix_node_head *rnh;
1092 : struct radix_node *rn = NULL;
1093 : struct pkpcb *kp, *bkp;
1094 0 : void *freeme = NULL, *bckptr = NULL;
1095 0 : void *headers[SADB_EXT_MAX + 1];
1096 : union sockaddr_union *sunionp;
1097 : struct tdb *sa1 = NULL, *sa2 = NULL;
1098 : struct sadb_msg *smsg;
1099 : struct sadb_spirange *sprng;
1100 : struct sadb_sa *ssa;
1101 : struct sadb_supported *ssup;
1102 : struct sadb_ident *sid, *did;
1103 0 : struct srp_ref sr;
1104 : u_int rdomain;
1105 : int promisc, s;
1106 :
1107 0 : mtx_enter(&pfkeyv2_mtx);
1108 0 : promisc = npromisc;
1109 0 : mtx_leave(&pfkeyv2_mtx);
1110 :
1111 : /* Verify that we received this over a legitimate pfkeyv2 socket */
1112 0 : bzero(headers, sizeof(headers));
1113 :
1114 0 : kp = sotokeycb(so);
1115 0 : if (!kp) {
1116 0 : rval = EINVAL;
1117 0 : goto ret;
1118 : }
1119 :
1120 0 : rdomain = kp->kcb_rdomain;
1121 :
1122 : /* If we have any promiscuous listeners, send them a copy of the message */
1123 0 : if (promisc) {
1124 0 : struct mbuf *packet;
1125 :
1126 0 : if (!(freeme = malloc(sizeof(struct sadb_msg) + len, M_PFKEY,
1127 : M_NOWAIT))) {
1128 0 : rval = ENOMEM;
1129 0 : goto ret;
1130 : }
1131 :
1132 : /* Initialize encapsulating header */
1133 0 : bzero(freeme, sizeof(struct sadb_msg));
1134 0 : smsg = (struct sadb_msg *) freeme;
1135 0 : smsg->sadb_msg_version = PF_KEY_V2;
1136 0 : smsg->sadb_msg_type = SADB_X_PROMISC;
1137 0 : smsg->sadb_msg_len = (sizeof(struct sadb_msg) + len) /
1138 : sizeof(uint64_t);
1139 0 : smsg->sadb_msg_seq = curproc->p_p->ps_pid;
1140 :
1141 0 : bcopy(message, freeme + sizeof(struct sadb_msg), len);
1142 :
1143 : /* Convert to mbuf chain */
1144 0 : if ((rval = pfdatatopacket(freeme,
1145 0 : sizeof(struct sadb_msg) + len, &packet)) != 0)
1146 0 : goto ret;
1147 :
1148 : /* Send to all promiscuous listeners */
1149 0 : SRPL_FOREACH(bkp, &sr, &pkptable.pkp_list, kcb_list) {
1150 0 : if (bkp->kcb_rdomain != rdomain)
1151 : continue;
1152 :
1153 0 : s = keylock(bkp);
1154 0 : if (bkp->kcb_flags & PFKEYV2_SOCKETFLAGS_PROMISC)
1155 0 : pfkey_sendup(bkp, packet, 1);
1156 0 : keyunlock(bkp, s);
1157 0 : }
1158 0 : SRPL_LEAVE(&sr);
1159 :
1160 0 : m_freem(packet);
1161 :
1162 : /* Paranoid */
1163 0 : explicit_bzero(freeme, sizeof(struct sadb_msg) + len);
1164 0 : free(freeme, M_PFKEY, 0);
1165 0 : freeme = NULL;
1166 0 : }
1167 :
1168 : /* Validate message format */
1169 0 : if ((rval = pfkeyv2_parsemessage(message, len, headers)) != 0)
1170 : goto ret;
1171 :
1172 0 : smsg = (struct sadb_msg *) headers[0];
1173 0 : switch (smsg->sadb_msg_type) {
1174 : case SADB_GETSPI: /* Reserve an SPI */
1175 0 : sa1 = malloc(sizeof (*sa1), M_PFKEY, M_NOWAIT | M_ZERO);
1176 0 : if (sa1 == NULL) {
1177 0 : rval = ENOMEM;
1178 0 : goto ret;
1179 : }
1180 :
1181 0 : sa1->tdb_satype = smsg->sadb_msg_satype;
1182 0 : if ((rval = pfkeyv2_get_proto_alg(sa1->tdb_satype,
1183 0 : &sa1->tdb_sproto, 0)))
1184 : goto ret;
1185 :
1186 0 : import_address(&sa1->tdb_src.sa, headers[SADB_EXT_ADDRESS_SRC]);
1187 0 : import_address(&sa1->tdb_dst.sa, headers[SADB_EXT_ADDRESS_DST]);
1188 :
1189 : /* Find an unused SA identifier */
1190 0 : sprng = (struct sadb_spirange *) headers[SADB_EXT_SPIRANGE];
1191 0 : NET_LOCK();
1192 0 : sa1->tdb_spi = reserve_spi(rdomain,
1193 0 : sprng->sadb_spirange_min, sprng->sadb_spirange_max,
1194 0 : &sa1->tdb_src, &sa1->tdb_dst, sa1->tdb_sproto, &rval);
1195 0 : if (sa1->tdb_spi == 0) {
1196 0 : NET_UNLOCK();
1197 0 : goto ret;
1198 : }
1199 :
1200 : /* Send a message back telling what the SA (the SPI really) is */
1201 0 : if (!(freeme = malloc(sizeof(struct sadb_sa), M_PFKEY,
1202 : M_NOWAIT | M_ZERO))) {
1203 0 : rval = ENOMEM;
1204 0 : NET_UNLOCK();
1205 0 : goto ret;
1206 : }
1207 :
1208 0 : headers[SADB_EXT_SPIRANGE] = NULL;
1209 0 : headers[SADB_EXT_SA] = freeme;
1210 0 : bckptr = freeme;
1211 :
1212 : /* We really only care about the SPI, but we'll export the SA */
1213 0 : export_sa((void **) &bckptr, sa1);
1214 0 : NET_UNLOCK();
1215 0 : break;
1216 :
1217 : case SADB_UPDATE:
1218 0 : ssa = (struct sadb_sa *) headers[SADB_EXT_SA];
1219 0 : sunionp = (union sockaddr_union *) (headers[SADB_EXT_ADDRESS_DST] +
1220 : sizeof(struct sadb_address));
1221 :
1222 : /* Either all or none of the flow must be included */
1223 0 : if ((headers[SADB_X_EXT_SRC_FLOW] ||
1224 0 : headers[SADB_X_EXT_PROTOCOL] ||
1225 0 : headers[SADB_X_EXT_FLOW_TYPE] ||
1226 0 : headers[SADB_X_EXT_DST_FLOW] ||
1227 0 : headers[SADB_X_EXT_SRC_MASK] ||
1228 0 : headers[SADB_X_EXT_DST_MASK]) &&
1229 0 : !(headers[SADB_X_EXT_SRC_FLOW] &&
1230 0 : headers[SADB_X_EXT_PROTOCOL] &&
1231 0 : headers[SADB_X_EXT_FLOW_TYPE] &&
1232 0 : headers[SADB_X_EXT_DST_FLOW] &&
1233 0 : headers[SADB_X_EXT_SRC_MASK] &&
1234 0 : headers[SADB_X_EXT_DST_MASK])) {
1235 0 : rval = EINVAL;
1236 0 : goto ret;
1237 : }
1238 : #ifdef IPSEC
1239 : /* UDP encap has to be enabled and is only supported for ESP */
1240 0 : if (headers[SADB_X_EXT_UDPENCAP] &&
1241 0 : (!udpencap_enable ||
1242 0 : smsg->sadb_msg_satype != SADB_SATYPE_ESP)) {
1243 0 : rval = EINVAL;
1244 0 : goto ret;
1245 : }
1246 : #endif /* IPSEC */
1247 :
1248 : /* Find TDB */
1249 0 : NET_LOCK();
1250 0 : sa2 = gettdb(rdomain, ssa->sadb_sa_spi, sunionp,
1251 0 : SADB_X_GETSPROTO(smsg->sadb_msg_satype));
1252 :
1253 : /* If there's no such SA, we're done */
1254 0 : if (sa2 == NULL) {
1255 0 : rval = ESRCH;
1256 0 : NET_UNLOCK();
1257 0 : goto ret;
1258 : }
1259 :
1260 : /* If this is a reserved SA */
1261 0 : if (sa2->tdb_flags & TDBF_INVALID) {
1262 : struct tdb *newsa;
1263 0 : struct ipsecinit ii;
1264 0 : int alg;
1265 :
1266 : /* Create new TDB */
1267 0 : freeme = tdb_alloc(rdomain);
1268 0 : bzero(&ii, sizeof(struct ipsecinit));
1269 :
1270 0 : newsa = (struct tdb *) freeme;
1271 0 : newsa->tdb_satype = smsg->sadb_msg_satype;
1272 :
1273 0 : if ((rval = pfkeyv2_get_proto_alg(newsa->tdb_satype,
1274 0 : &newsa->tdb_sproto, &alg))) {
1275 0 : tdb_free(freeme);
1276 0 : freeme = NULL;
1277 0 : NET_UNLOCK();
1278 0 : goto ret;
1279 : }
1280 :
1281 : /* Initialize SA */
1282 0 : import_sa(newsa, headers[SADB_EXT_SA], &ii);
1283 0 : import_address(&newsa->tdb_src.sa,
1284 0 : headers[SADB_EXT_ADDRESS_SRC]);
1285 0 : import_address(&newsa->tdb_dst.sa,
1286 0 : headers[SADB_EXT_ADDRESS_DST]);
1287 0 : import_lifetime(newsa,
1288 0 : headers[SADB_EXT_LIFETIME_CURRENT],
1289 : PFKEYV2_LIFETIME_CURRENT);
1290 0 : import_lifetime(newsa, headers[SADB_EXT_LIFETIME_SOFT],
1291 : PFKEYV2_LIFETIME_SOFT);
1292 0 : import_lifetime(newsa, headers[SADB_EXT_LIFETIME_HARD],
1293 : PFKEYV2_LIFETIME_HARD);
1294 0 : import_key(&ii, headers[SADB_EXT_KEY_AUTH],
1295 : PFKEYV2_AUTHENTICATION_KEY);
1296 0 : import_key(&ii, headers[SADB_EXT_KEY_ENCRYPT],
1297 : PFKEYV2_ENCRYPTION_KEY);
1298 0 : newsa->tdb_ids_swapped = 1; /* only on TDB_UPDATE */
1299 0 : import_identities(&newsa->tdb_ids,
1300 : newsa->tdb_ids_swapped,
1301 0 : headers[SADB_EXT_IDENTITY_SRC],
1302 0 : headers[SADB_EXT_IDENTITY_DST]);
1303 0 : import_flow(&newsa->tdb_filter, &newsa->tdb_filtermask,
1304 0 : headers[SADB_X_EXT_SRC_FLOW],
1305 0 : headers[SADB_X_EXT_SRC_MASK],
1306 0 : headers[SADB_X_EXT_DST_FLOW],
1307 0 : headers[SADB_X_EXT_DST_MASK],
1308 0 : headers[SADB_X_EXT_PROTOCOL],
1309 0 : headers[SADB_X_EXT_FLOW_TYPE]);
1310 0 : import_udpencap(newsa, headers[SADB_X_EXT_UDPENCAP]);
1311 : #if NPF > 0
1312 0 : import_tag(newsa, headers[SADB_X_EXT_TAG]);
1313 0 : import_tap(newsa, headers[SADB_X_EXT_TAP]);
1314 : #endif
1315 :
1316 : /* Exclude sensitive data from reply message. */
1317 0 : headers[SADB_EXT_KEY_AUTH] = NULL;
1318 0 : headers[SADB_EXT_KEY_ENCRYPT] = NULL;
1319 0 : headers[SADB_X_EXT_LOCAL_AUTH] = NULL;
1320 0 : headers[SADB_X_EXT_REMOTE_AUTH] = NULL;
1321 :
1322 0 : newsa->tdb_seq = smsg->sadb_msg_seq;
1323 :
1324 0 : rval = tdb_init(newsa, alg, &ii);
1325 0 : if (rval) {
1326 0 : rval = EINVAL;
1327 0 : tdb_free(freeme);
1328 0 : freeme = NULL;
1329 0 : NET_UNLOCK();
1330 0 : goto ret;
1331 : }
1332 :
1333 0 : newsa->tdb_cur_allocations = sa2->tdb_cur_allocations;
1334 :
1335 : /* Delete old version of the SA, insert new one */
1336 0 : tdb_delete(sa2);
1337 0 : puttdb((struct tdb *) freeme);
1338 0 : sa2 = freeme = NULL;
1339 0 : } else {
1340 : /*
1341 : * The SA is already initialized, so we're only allowed to
1342 : * change lifetimes and some other information; we're
1343 : * not allowed to change keys, addresses or identities.
1344 : */
1345 0 : if (headers[SADB_EXT_KEY_AUTH] ||
1346 0 : headers[SADB_EXT_KEY_ENCRYPT] ||
1347 0 : headers[SADB_EXT_IDENTITY_SRC] ||
1348 0 : headers[SADB_EXT_IDENTITY_DST] ||
1349 0 : headers[SADB_EXT_SENSITIVITY]) {
1350 0 : rval = EINVAL;
1351 0 : NET_UNLOCK();
1352 0 : goto ret;
1353 : }
1354 :
1355 0 : import_sa(sa2, headers[SADB_EXT_SA], NULL);
1356 0 : import_lifetime(sa2,
1357 0 : headers[SADB_EXT_LIFETIME_CURRENT],
1358 : PFKEYV2_LIFETIME_CURRENT);
1359 0 : import_lifetime(sa2, headers[SADB_EXT_LIFETIME_SOFT],
1360 : PFKEYV2_LIFETIME_SOFT);
1361 0 : import_lifetime(sa2, headers[SADB_EXT_LIFETIME_HARD],
1362 : PFKEYV2_LIFETIME_HARD);
1363 0 : import_udpencap(sa2, headers[SADB_X_EXT_UDPENCAP]);
1364 : #if NPF > 0
1365 0 : import_tag(sa2, headers[SADB_X_EXT_TAG]);
1366 0 : import_tap(sa2, headers[SADB_X_EXT_TAP]);
1367 : #endif
1368 0 : if (headers[SADB_EXT_ADDRESS_SRC] ||
1369 0 : headers[SADB_EXT_ADDRESS_PROXY]) {
1370 0 : tdb_unlink(sa2);
1371 0 : import_address((struct sockaddr *)&sa2->tdb_src,
1372 0 : headers[SADB_EXT_ADDRESS_SRC]);
1373 0 : import_address((struct sockaddr *)&sa2->tdb_dst,
1374 0 : headers[SADB_EXT_ADDRESS_PROXY]);
1375 0 : puttdb(sa2);
1376 0 : }
1377 : }
1378 0 : NET_UNLOCK();
1379 :
1380 0 : break;
1381 : case SADB_ADD:
1382 0 : ssa = (struct sadb_sa *) headers[SADB_EXT_SA];
1383 0 : sunionp = (union sockaddr_union *) (headers[SADB_EXT_ADDRESS_DST] +
1384 : sizeof(struct sadb_address));
1385 :
1386 : /* Either all or none of the flow must be included */
1387 0 : if ((headers[SADB_X_EXT_SRC_FLOW] ||
1388 0 : headers[SADB_X_EXT_PROTOCOL] ||
1389 0 : headers[SADB_X_EXT_FLOW_TYPE] ||
1390 0 : headers[SADB_X_EXT_DST_FLOW] ||
1391 0 : headers[SADB_X_EXT_SRC_MASK] ||
1392 0 : headers[SADB_X_EXT_DST_MASK]) &&
1393 0 : !(headers[SADB_X_EXT_SRC_FLOW] &&
1394 0 : headers[SADB_X_EXT_PROTOCOL] &&
1395 0 : headers[SADB_X_EXT_FLOW_TYPE] &&
1396 0 : headers[SADB_X_EXT_DST_FLOW] &&
1397 0 : headers[SADB_X_EXT_SRC_MASK] &&
1398 0 : headers[SADB_X_EXT_DST_MASK])) {
1399 0 : rval = EINVAL;
1400 0 : goto ret;
1401 : }
1402 : #ifdef IPSEC
1403 : /* UDP encap has to be enabled and is only supported for ESP */
1404 0 : if (headers[SADB_X_EXT_UDPENCAP] &&
1405 0 : (!udpencap_enable ||
1406 0 : smsg->sadb_msg_satype != SADB_SATYPE_ESP)) {
1407 0 : rval = EINVAL;
1408 0 : goto ret;
1409 : }
1410 : #endif /* IPSEC */
1411 :
1412 0 : NET_LOCK();
1413 0 : sa2 = gettdb(rdomain, ssa->sadb_sa_spi, sunionp,
1414 0 : SADB_X_GETSPROTO(smsg->sadb_msg_satype));
1415 :
1416 : /* We can't add an existing SA! */
1417 0 : if (sa2 != NULL) {
1418 0 : rval = EEXIST;
1419 0 : NET_UNLOCK();
1420 0 : goto ret;
1421 : }
1422 :
1423 : /* We can only add "mature" SAs */
1424 0 : if (ssa->sadb_sa_state != SADB_SASTATE_MATURE) {
1425 0 : rval = EINVAL;
1426 0 : NET_UNLOCK();
1427 0 : goto ret;
1428 : }
1429 :
1430 : /* Allocate and initialize new TDB */
1431 0 : freeme = tdb_alloc(rdomain);
1432 :
1433 : {
1434 : struct tdb *newsa = (struct tdb *) freeme;
1435 0 : struct ipsecinit ii;
1436 0 : int alg;
1437 :
1438 0 : bzero(&ii, sizeof(struct ipsecinit));
1439 :
1440 0 : newsa->tdb_satype = smsg->sadb_msg_satype;
1441 0 : if ((rval = pfkeyv2_get_proto_alg(newsa->tdb_satype,
1442 0 : &newsa->tdb_sproto, &alg))) {
1443 0 : tdb_free(freeme);
1444 0 : freeme = NULL;
1445 0 : NET_UNLOCK();
1446 0 : goto ret;
1447 : }
1448 :
1449 0 : import_sa(newsa, headers[SADB_EXT_SA], &ii);
1450 0 : import_address(&newsa->tdb_src.sa,
1451 0 : headers[SADB_EXT_ADDRESS_SRC]);
1452 0 : import_address(&newsa->tdb_dst.sa,
1453 0 : headers[SADB_EXT_ADDRESS_DST]);
1454 :
1455 0 : import_lifetime(newsa,
1456 0 : headers[SADB_EXT_LIFETIME_CURRENT],
1457 : PFKEYV2_LIFETIME_CURRENT);
1458 0 : import_lifetime(newsa, headers[SADB_EXT_LIFETIME_SOFT],
1459 : PFKEYV2_LIFETIME_SOFT);
1460 0 : import_lifetime(newsa, headers[SADB_EXT_LIFETIME_HARD],
1461 : PFKEYV2_LIFETIME_HARD);
1462 :
1463 0 : import_key(&ii, headers[SADB_EXT_KEY_AUTH],
1464 : PFKEYV2_AUTHENTICATION_KEY);
1465 0 : import_key(&ii, headers[SADB_EXT_KEY_ENCRYPT],
1466 : PFKEYV2_ENCRYPTION_KEY);
1467 :
1468 0 : import_identities(&newsa->tdb_ids,
1469 0 : newsa->tdb_ids_swapped,
1470 0 : headers[SADB_EXT_IDENTITY_SRC],
1471 0 : headers[SADB_EXT_IDENTITY_DST]);
1472 :
1473 0 : import_flow(&newsa->tdb_filter, &newsa->tdb_filtermask,
1474 0 : headers[SADB_X_EXT_SRC_FLOW],
1475 0 : headers[SADB_X_EXT_SRC_MASK],
1476 0 : headers[SADB_X_EXT_DST_FLOW],
1477 0 : headers[SADB_X_EXT_DST_MASK],
1478 0 : headers[SADB_X_EXT_PROTOCOL],
1479 0 : headers[SADB_X_EXT_FLOW_TYPE]);
1480 0 : import_udpencap(newsa, headers[SADB_X_EXT_UDPENCAP]);
1481 : #if NPF > 0
1482 0 : import_tag(newsa, headers[SADB_X_EXT_TAG]);
1483 0 : import_tap(newsa, headers[SADB_X_EXT_TAP]);
1484 : #endif
1485 :
1486 : /* Exclude sensitive data from reply message. */
1487 0 : headers[SADB_EXT_KEY_AUTH] = NULL;
1488 0 : headers[SADB_EXT_KEY_ENCRYPT] = NULL;
1489 0 : headers[SADB_X_EXT_LOCAL_AUTH] = NULL;
1490 0 : headers[SADB_X_EXT_REMOTE_AUTH] = NULL;
1491 :
1492 0 : newsa->tdb_seq = smsg->sadb_msg_seq;
1493 :
1494 0 : rval = tdb_init(newsa, alg, &ii);
1495 0 : if (rval) {
1496 0 : rval = EINVAL;
1497 0 : tdb_free(freeme);
1498 0 : freeme = NULL;
1499 0 : NET_UNLOCK();
1500 0 : goto ret;
1501 : }
1502 0 : }
1503 :
1504 : /* Add TDB in table */
1505 0 : puttdb((struct tdb *) freeme);
1506 0 : NET_UNLOCK();
1507 :
1508 0 : freeme = NULL;
1509 0 : break;
1510 :
1511 : case SADB_DELETE:
1512 0 : ssa = (struct sadb_sa *) headers[SADB_EXT_SA];
1513 : sunionp =
1514 0 : (union sockaddr_union *)(headers[SADB_EXT_ADDRESS_DST] +
1515 : sizeof(struct sadb_address));
1516 :
1517 0 : NET_LOCK();
1518 0 : sa2 = gettdb(rdomain, ssa->sadb_sa_spi, sunionp,
1519 0 : SADB_X_GETSPROTO(smsg->sadb_msg_satype));
1520 0 : if (sa2 == NULL) {
1521 0 : rval = ESRCH;
1522 0 : NET_UNLOCK();
1523 0 : goto ret;
1524 : }
1525 :
1526 0 : tdb_delete(sa2);
1527 0 : NET_UNLOCK();
1528 :
1529 : sa2 = NULL;
1530 0 : break;
1531 :
1532 : case SADB_X_ASKPOLICY:
1533 : /* Get the relevant policy */
1534 0 : NET_LOCK();
1535 0 : ipa = ipsec_get_acquire(((struct sadb_x_policy *) headers[SADB_X_EXT_POLICY])->sadb_x_policy_seq);
1536 0 : if (ipa == NULL) {
1537 0 : rval = ESRCH;
1538 0 : NET_UNLOCK();
1539 0 : goto ret;
1540 : }
1541 :
1542 0 : rval = pfkeyv2_policy(ipa, headers, &freeme);
1543 0 : NET_UNLOCK();
1544 0 : if (rval)
1545 0 : mode = PFKEYV2_SENDMESSAGE_UNICAST;
1546 :
1547 : break;
1548 :
1549 : case SADB_GET:
1550 0 : ssa = (struct sadb_sa *) headers[SADB_EXT_SA];
1551 : sunionp =
1552 0 : (union sockaddr_union *)(headers[SADB_EXT_ADDRESS_DST] +
1553 : sizeof(struct sadb_address));
1554 :
1555 0 : NET_LOCK();
1556 0 : sa2 = gettdb(rdomain, ssa->sadb_sa_spi, sunionp,
1557 0 : SADB_X_GETSPROTO(smsg->sadb_msg_satype));
1558 0 : if (sa2 == NULL) {
1559 0 : rval = ESRCH;
1560 0 : NET_UNLOCK();
1561 0 : goto ret;
1562 : }
1563 :
1564 0 : rval = pfkeyv2_get(sa2, headers, &freeme, NULL);
1565 0 : NET_UNLOCK();
1566 0 : if (rval)
1567 0 : mode = PFKEYV2_SENDMESSAGE_UNICAST;
1568 :
1569 : break;
1570 :
1571 : case SADB_REGISTER:
1572 0 : s = keylock(kp);
1573 0 : if (!(kp->kcb_flags & PFKEYV2_SOCKETFLAGS_REGISTERED)) {
1574 0 : kp->kcb_flags |= PFKEYV2_SOCKETFLAGS_REGISTERED;
1575 0 : mtx_enter(&pfkeyv2_mtx);
1576 0 : nregistered++;
1577 0 : mtx_leave(&pfkeyv2_mtx);
1578 0 : }
1579 0 : keyunlock(kp, s);
1580 :
1581 : i = sizeof(struct sadb_supported) + sizeof(ealgs);
1582 :
1583 0 : if (!(freeme = malloc(i, M_PFKEY, M_NOWAIT | M_ZERO))) {
1584 0 : rval = ENOMEM;
1585 0 : goto ret;
1586 : }
1587 :
1588 0 : ssup = (struct sadb_supported *) freeme;
1589 0 : ssup->sadb_supported_len = i / sizeof(uint64_t);
1590 :
1591 : {
1592 0 : void *p = freeme + sizeof(struct sadb_supported);
1593 :
1594 0 : bcopy(&ealgs[0], p, sizeof(ealgs));
1595 : }
1596 :
1597 0 : headers[SADB_EXT_SUPPORTED_ENCRYPT] = freeme;
1598 :
1599 : i = sizeof(struct sadb_supported) + sizeof(aalgs);
1600 :
1601 0 : if (!(freeme = malloc(i, M_PFKEY, M_NOWAIT | M_ZERO))) {
1602 0 : rval = ENOMEM;
1603 0 : goto ret;
1604 : }
1605 :
1606 : /* Keep track what this socket has registered for */
1607 0 : s = keylock(kp);
1608 0 : kp->kcb_reg |=
1609 0 : (1 << ((struct sadb_msg *)message)->sadb_msg_satype);
1610 0 : keyunlock(kp, s);
1611 :
1612 0 : ssup = (struct sadb_supported *) freeme;
1613 0 : ssup->sadb_supported_len = i / sizeof(uint64_t);
1614 :
1615 : {
1616 0 : void *p = freeme + sizeof(struct sadb_supported);
1617 :
1618 0 : bcopy(&aalgs[0], p, sizeof(aalgs));
1619 : }
1620 :
1621 0 : headers[SADB_EXT_SUPPORTED_AUTH] = freeme;
1622 :
1623 : i = sizeof(struct sadb_supported) + sizeof(calgs);
1624 :
1625 0 : if (!(freeme = malloc(i, M_PFKEY, M_NOWAIT | M_ZERO))) {
1626 0 : rval = ENOMEM;
1627 0 : goto ret;
1628 : }
1629 :
1630 0 : ssup = (struct sadb_supported *) freeme;
1631 0 : ssup->sadb_supported_len = i / sizeof(uint64_t);
1632 :
1633 : {
1634 0 : void *p = freeme + sizeof(struct sadb_supported);
1635 :
1636 0 : bcopy(&calgs[0], p, sizeof(calgs));
1637 : }
1638 :
1639 0 : headers[SADB_X_EXT_SUPPORTED_COMP] = freeme;
1640 :
1641 0 : break;
1642 :
1643 : case SADB_ACQUIRE:
1644 : case SADB_EXPIRE:
1645 : /* Nothing to handle */
1646 0 : rval = 0;
1647 0 : break;
1648 :
1649 : case SADB_FLUSH:
1650 0 : rval = 0;
1651 :
1652 0 : NET_LOCK();
1653 0 : switch (smsg->sadb_msg_satype) {
1654 : case SADB_SATYPE_UNSPEC:
1655 0 : spd_table_walk(rdomain, pfkeyv2_policy_flush, NULL);
1656 : /* FALLTHROUGH */
1657 : case SADB_SATYPE_AH:
1658 : case SADB_SATYPE_ESP:
1659 : case SADB_X_SATYPE_IPIP:
1660 : case SADB_X_SATYPE_IPCOMP:
1661 : #ifdef TCP_SIGNATURE
1662 : case SADB_X_SATYPE_TCPSIGNATURE:
1663 : #endif /* TCP_SIGNATURE */
1664 0 : tdb_walk(rdomain, pfkeyv2_sa_flush,
1665 : (u_int8_t *) &(smsg->sadb_msg_satype));
1666 :
1667 0 : break;
1668 :
1669 : default:
1670 0 : rval = EINVAL; /* Unknown/unsupported type */
1671 0 : }
1672 0 : NET_UNLOCK();
1673 :
1674 0 : break;
1675 :
1676 : case SADB_DUMP:
1677 : {
1678 0 : struct dump_state dump_state;
1679 0 : dump_state.sadb_msg = (struct sadb_msg *) headers[0];
1680 0 : dump_state.socket = so;
1681 :
1682 0 : NET_LOCK();
1683 0 : rval = tdb_walk(rdomain, pfkeyv2_dump_walker, &dump_state);
1684 0 : NET_UNLOCK();
1685 0 : if (!rval)
1686 0 : goto realret;
1687 0 : if ((rval == ENOMEM) || (rval == ENOBUFS))
1688 0 : rval = 0;
1689 0 : }
1690 : break;
1691 :
1692 : case SADB_X_GRPSPIS:
1693 : {
1694 : struct tdb *tdb1, *tdb2, *tdb3;
1695 : struct sadb_protocol *sa_proto;
1696 :
1697 0 : ssa = (struct sadb_sa *) headers[SADB_EXT_SA];
1698 0 : sunionp = (union sockaddr_union *) (headers[SADB_EXT_ADDRESS_DST] +
1699 : sizeof(struct sadb_address));
1700 :
1701 0 : NET_LOCK();
1702 0 : tdb1 = gettdb(rdomain, ssa->sadb_sa_spi, sunionp,
1703 0 : SADB_X_GETSPROTO(smsg->sadb_msg_satype));
1704 0 : if (tdb1 == NULL) {
1705 0 : rval = ESRCH;
1706 0 : NET_UNLOCK();
1707 0 : goto ret;
1708 : }
1709 :
1710 0 : ssa = (struct sadb_sa *) headers[SADB_X_EXT_SA2];
1711 0 : sunionp = (union sockaddr_union *) (headers[SADB_X_EXT_DST2] +
1712 : sizeof(struct sadb_address));
1713 0 : sa_proto = (struct sadb_protocol *) headers[SADB_X_EXT_SATYPE2];
1714 :
1715 0 : tdb2 = gettdb(rdomain, ssa->sadb_sa_spi, sunionp,
1716 0 : SADB_X_GETSPROTO(sa_proto->sadb_protocol_proto));
1717 0 : if (tdb2 == NULL) {
1718 0 : rval = ESRCH;
1719 0 : NET_UNLOCK();
1720 0 : goto ret;
1721 : }
1722 :
1723 : /* Detect cycles */
1724 0 : for (tdb3 = tdb2; tdb3; tdb3 = tdb3->tdb_onext)
1725 0 : if (tdb3 == tdb1) {
1726 0 : rval = ESRCH;
1727 0 : NET_UNLOCK();
1728 0 : goto ret;
1729 : }
1730 :
1731 : /* Maintenance */
1732 0 : if ((tdb1->tdb_onext) &&
1733 0 : (tdb1->tdb_onext->tdb_inext == tdb1))
1734 0 : tdb1->tdb_onext->tdb_inext = NULL;
1735 :
1736 0 : if ((tdb2->tdb_inext) &&
1737 0 : (tdb2->tdb_inext->tdb_onext == tdb2))
1738 0 : tdb2->tdb_inext->tdb_onext = NULL;
1739 :
1740 : /* Link them */
1741 0 : tdb1->tdb_onext = tdb2;
1742 0 : tdb2->tdb_inext = tdb1;
1743 0 : NET_UNLOCK();
1744 0 : }
1745 : break;
1746 :
1747 : case SADB_X_DELFLOW:
1748 0 : delflag = 1;
1749 : /*FALLTHROUGH*/
1750 : case SADB_X_ADDFLOW:
1751 : {
1752 : struct sadb_protocol *sab;
1753 : union sockaddr_union *ssrc;
1754 : int exists = 0;
1755 :
1756 0 : NET_LOCK();
1757 0 : if ((rnh = spd_table_add(rdomain)) == NULL) {
1758 0 : rval = ENOMEM;
1759 0 : NET_UNLOCK();
1760 0 : goto ret;
1761 : }
1762 :
1763 0 : sab = (struct sadb_protocol *) headers[SADB_X_EXT_FLOW_TYPE];
1764 :
1765 0 : if ((sab->sadb_protocol_direction != IPSP_DIRECTION_IN) &&
1766 0 : (sab->sadb_protocol_direction != IPSP_DIRECTION_OUT)) {
1767 0 : rval = EINVAL;
1768 0 : NET_UNLOCK();
1769 0 : goto ret;
1770 : }
1771 :
1772 : /* If the security protocol wasn't specified, pretend it was ESP */
1773 0 : if (smsg->sadb_msg_satype == 0)
1774 0 : smsg->sadb_msg_satype = SADB_SATYPE_ESP;
1775 :
1776 0 : if (headers[SADB_EXT_ADDRESS_DST])
1777 0 : sunionp = (union sockaddr_union *)
1778 0 : (headers[SADB_EXT_ADDRESS_DST] +
1779 : sizeof(struct sadb_address));
1780 : else
1781 : sunionp = NULL;
1782 :
1783 0 : if (headers[SADB_EXT_ADDRESS_SRC])
1784 0 : ssrc = (union sockaddr_union *)
1785 0 : (headers[SADB_EXT_ADDRESS_SRC] +
1786 : sizeof(struct sadb_address));
1787 : else
1788 : ssrc = NULL;
1789 :
1790 0 : import_flow(&encapdst, &encapnetmask,
1791 0 : headers[SADB_X_EXT_SRC_FLOW], headers[SADB_X_EXT_SRC_MASK],
1792 0 : headers[SADB_X_EXT_DST_FLOW], headers[SADB_X_EXT_DST_MASK],
1793 0 : headers[SADB_X_EXT_PROTOCOL], headers[SADB_X_EXT_FLOW_TYPE]);
1794 :
1795 : /* Determine whether the exact same SPD entry already exists. */
1796 0 : if ((rn = rn_match(&encapdst, rnh)) != NULL) {
1797 0 : ipo = (struct ipsec_policy *)rn;
1798 :
1799 : /* Verify that the entry is identical */
1800 0 : if (bcmp(&ipo->ipo_addr, &encapdst,
1801 0 : sizeof(struct sockaddr_encap)) ||
1802 0 : bcmp(&ipo->ipo_mask, &encapnetmask,
1803 : sizeof(struct sockaddr_encap)))
1804 0 : ipo = NULL; /* Fall through */
1805 : else
1806 : exists = 1;
1807 : } else
1808 : ipo = NULL;
1809 :
1810 : /*
1811 : * If the existing policy is static, only delete or update
1812 : * it if the new one is also static.
1813 : */
1814 0 : if (exists && (ipo->ipo_flags & IPSP_POLICY_STATIC)) {
1815 0 : if (!(sab->sadb_protocol_flags &
1816 : SADB_X_POLICYFLAGS_POLICY)) {
1817 0 : NET_UNLOCK();
1818 0 : goto ret;
1819 : }
1820 : }
1821 :
1822 : /* Delete ? */
1823 0 : if (delflag) {
1824 0 : if (exists) {
1825 0 : rval = ipsec_delete_policy(ipo);
1826 0 : NET_UNLOCK();
1827 0 : goto ret;
1828 : }
1829 :
1830 : /* If we were asked to delete something non-existent, error. */
1831 0 : rval = ESRCH;
1832 0 : NET_UNLOCK();
1833 0 : break;
1834 : }
1835 :
1836 0 : if (!exists) {
1837 0 : if (ipsec_policy_pool_initialized == 0) {
1838 0 : ipsec_policy_pool_initialized = 1;
1839 0 : pool_init(&ipsec_policy_pool,
1840 : sizeof(struct ipsec_policy), 0,
1841 : IPL_NONE, 0, "ipsec policy", NULL);
1842 0 : }
1843 :
1844 : /* Allocate policy entry */
1845 0 : ipo = pool_get(&ipsec_policy_pool, PR_NOWAIT|PR_ZERO);
1846 0 : if (ipo == NULL) {
1847 0 : rval = ENOMEM;
1848 0 : NET_UNLOCK();
1849 0 : goto ret;
1850 : }
1851 : }
1852 :
1853 0 : switch (sab->sadb_protocol_proto) {
1854 : case SADB_X_FLOW_TYPE_USE:
1855 0 : ipo->ipo_type = IPSP_IPSEC_USE;
1856 0 : break;
1857 :
1858 : case SADB_X_FLOW_TYPE_ACQUIRE:
1859 0 : ipo->ipo_type = IPSP_IPSEC_ACQUIRE;
1860 0 : break;
1861 :
1862 : case SADB_X_FLOW_TYPE_REQUIRE:
1863 0 : ipo->ipo_type = IPSP_IPSEC_REQUIRE;
1864 0 : break;
1865 :
1866 : case SADB_X_FLOW_TYPE_DENY:
1867 0 : ipo->ipo_type = IPSP_DENY;
1868 0 : break;
1869 :
1870 : case SADB_X_FLOW_TYPE_BYPASS:
1871 0 : ipo->ipo_type = IPSP_PERMIT;
1872 0 : break;
1873 :
1874 : case SADB_X_FLOW_TYPE_DONTACQ:
1875 0 : ipo->ipo_type = IPSP_IPSEC_DONTACQ;
1876 0 : break;
1877 :
1878 : default:
1879 0 : if (!exists)
1880 0 : pool_put(&ipsec_policy_pool, ipo);
1881 : else
1882 0 : ipsec_delete_policy(ipo);
1883 :
1884 0 : rval = EINVAL;
1885 0 : NET_UNLOCK();
1886 0 : goto ret;
1887 : }
1888 :
1889 0 : if (sab->sadb_protocol_flags & SADB_X_POLICYFLAGS_POLICY)
1890 0 : ipo->ipo_flags |= IPSP_POLICY_STATIC;
1891 :
1892 0 : if (sunionp)
1893 0 : bcopy(sunionp, &ipo->ipo_dst,
1894 : sizeof(union sockaddr_union));
1895 : else
1896 0 : bzero(&ipo->ipo_dst, sizeof(union sockaddr_union));
1897 :
1898 0 : if (ssrc)
1899 0 : bcopy(ssrc, &ipo->ipo_src,
1900 : sizeof(union sockaddr_union));
1901 : else
1902 0 : bzero(&ipo->ipo_src, sizeof(union sockaddr_union));
1903 :
1904 0 : ipo->ipo_sproto = SADB_X_GETSPROTO(smsg->sadb_msg_satype);
1905 :
1906 0 : if (ipo->ipo_ids) {
1907 0 : ipsp_ids_free(ipo->ipo_ids);
1908 0 : ipo->ipo_ids = NULL;
1909 0 : }
1910 :
1911 0 : if ((sid = headers[SADB_EXT_IDENTITY_SRC]) != NULL &&
1912 0 : (did = headers[SADB_EXT_IDENTITY_DST]) != NULL) {
1913 0 : import_identities(&ipo->ipo_ids, 0, sid, did);
1914 0 : if (ipo->ipo_ids == NULL) {
1915 0 : if (exists)
1916 0 : ipsec_delete_policy(ipo);
1917 : else
1918 0 : pool_put(&ipsec_policy_pool, ipo);
1919 0 : rval = ENOBUFS;
1920 0 : NET_UNLOCK();
1921 0 : goto ret;
1922 : }
1923 : }
1924 :
1925 : /* Flow type */
1926 0 : if (!exists) {
1927 : /* Initialize policy entry */
1928 0 : bcopy(&encapdst, &ipo->ipo_addr,
1929 : sizeof(struct sockaddr_encap));
1930 0 : bcopy(&encapnetmask, &ipo->ipo_mask,
1931 : sizeof(struct sockaddr_encap));
1932 :
1933 0 : TAILQ_INIT(&ipo->ipo_acquires);
1934 0 : ipo->ipo_rdomain = rdomain;
1935 0 : ipo->ipo_ref_count = 1;
1936 :
1937 : /* Add SPD entry */
1938 0 : if ((rnh = spd_table_get(rdomain)) == NULL ||
1939 0 : (rn = rn_addroute((caddr_t)&ipo->ipo_addr,
1940 : (caddr_t)&ipo->ipo_mask, rnh,
1941 0 : ipo->ipo_nodes, 0)) == NULL) {
1942 : /* Remove from linked list of policies on TDB */
1943 0 : if (ipo->ipo_tdb)
1944 0 : TAILQ_REMOVE(&ipo->ipo_tdb->tdb_policy_head,
1945 : ipo, ipo_tdb_next);
1946 :
1947 0 : if (ipo->ipo_ids)
1948 0 : ipsp_ids_free(ipo->ipo_ids);
1949 0 : pool_put(&ipsec_policy_pool, ipo);
1950 0 : NET_UNLOCK();
1951 0 : goto ret;
1952 : }
1953 0 : TAILQ_INSERT_HEAD(&ipsec_policy_head, ipo, ipo_list);
1954 0 : ipsec_in_use++;
1955 : /*
1956 : * XXXSMP IPsec data structures are not ready to be
1957 : * accessed by multiple Network threads in parallel,
1958 : * so force all packets to be processed by the first
1959 : * one.
1960 : */
1961 : extern int nettaskqs;
1962 0 : nettaskqs = 1;
1963 0 : } else {
1964 0 : ipo->ipo_last_searched = ipo->ipo_flags = 0;
1965 : }
1966 0 : NET_UNLOCK();
1967 0 : }
1968 : break;
1969 :
1970 : case SADB_X_PROMISC:
1971 0 : if (len >= 2 * sizeof(struct sadb_msg)) {
1972 0 : struct mbuf *packet;
1973 :
1974 0 : if ((rval = pfdatatopacket(message, len, &packet)) != 0)
1975 0 : goto ret;
1976 :
1977 0 : SRPL_FOREACH(bkp, &sr, &pkptable.pkp_list, kcb_list) {
1978 0 : if (bkp == kp || bkp->kcb_rdomain != rdomain)
1979 : continue;
1980 :
1981 0 : if (!smsg->sadb_msg_seq ||
1982 0 : (smsg->sadb_msg_seq == kp->kcb_pid)) {
1983 0 : s = keylock(bkp);
1984 0 : pfkey_sendup(bkp, packet, 1);
1985 0 : keyunlock(bkp, s);
1986 0 : }
1987 : }
1988 0 : SRPL_LEAVE(&sr);
1989 :
1990 0 : m_freem(packet);
1991 0 : } else {
1992 0 : if (len != sizeof(struct sadb_msg)) {
1993 0 : rval = EINVAL;
1994 0 : goto ret;
1995 : }
1996 :
1997 0 : s = keylock(kp);
1998 0 : i = (kp->kcb_flags &
1999 : PFKEYV2_SOCKETFLAGS_PROMISC) ? 1 : 0;
2000 0 : j = smsg->sadb_msg_satype ? 1 : 0;
2001 :
2002 0 : if (i ^ j) {
2003 0 : if (j) {
2004 0 : kp->kcb_flags |=
2005 : PFKEYV2_SOCKETFLAGS_PROMISC;
2006 0 : mtx_enter(&pfkeyv2_mtx);
2007 0 : npromisc++;
2008 0 : mtx_leave(&pfkeyv2_mtx);
2009 0 : } else {
2010 0 : kp->kcb_flags &=
2011 : ~PFKEYV2_SOCKETFLAGS_PROMISC;
2012 0 : mtx_enter(&pfkeyv2_mtx);
2013 0 : npromisc--;
2014 0 : mtx_leave(&pfkeyv2_mtx);
2015 : }
2016 : }
2017 0 : keyunlock(kp, s);
2018 : }
2019 :
2020 : break;
2021 :
2022 : default:
2023 0 : rval = EINVAL;
2024 0 : goto ret;
2025 : }
2026 :
2027 : ret:
2028 0 : if (rval) {
2029 0 : if ((rval == EINVAL) || (rval == ENOMEM) || (rval == ENOBUFS))
2030 : goto realret;
2031 :
2032 0 : for (i = 1; i <= SADB_EXT_MAX; i++)
2033 0 : headers[i] = NULL;
2034 :
2035 0 : smsg->sadb_msg_errno = abs(rval);
2036 0 : } else {
2037 : uint64_t seen = 0LL;
2038 :
2039 0 : for (i = 1; i <= SADB_EXT_MAX; i++)
2040 0 : if (headers[i])
2041 0 : seen |= (1LL << i);
2042 :
2043 0 : if ((seen & sadb_exts_allowed_out[smsg->sadb_msg_type])
2044 0 : != seen)
2045 0 : goto realret;
2046 :
2047 0 : if ((seen & sadb_exts_required_out[smsg->sadb_msg_type]) !=
2048 : sadb_exts_required_out[smsg->sadb_msg_type])
2049 0 : goto realret;
2050 0 : }
2051 :
2052 0 : rval = pfkeyv2_sendmessage(headers, mode, so, 0, 0, rdomain);
2053 :
2054 : realret:
2055 :
2056 0 : if (freeme)
2057 0 : free(freeme, M_PFKEY, 0);
2058 :
2059 0 : explicit_bzero(message, len);
2060 0 : free(message, M_PFKEY, 0);
2061 :
2062 0 : if (sa1)
2063 0 : free(sa1, M_PFKEY, 0);
2064 :
2065 0 : return (rval);
2066 0 : }
2067 :
2068 : /*
2069 : * Send an ACQUIRE message to key management, to get a new SA.
2070 : */
2071 : int
2072 0 : pfkeyv2_acquire(struct ipsec_policy *ipo, union sockaddr_union *gw,
2073 : union sockaddr_union *laddr, u_int32_t *seq, struct sockaddr_encap *ddst)
2074 : {
2075 0 : void *p, *headers[SADB_EXT_MAX + 1], *buffer = NULL;
2076 : struct sadb_comb *sadb_comb;
2077 : struct sadb_address *sadd;
2078 : struct sadb_prop *sa_prop;
2079 : struct sadb_msg *smsg;
2080 : int rval = 0;
2081 : int i, j, registered;
2082 :
2083 0 : mtx_enter(&pfkeyv2_mtx);
2084 0 : *seq = pfkeyv2_seq++;
2085 :
2086 0 : registered = nregistered;
2087 0 : mtx_leave(&pfkeyv2_mtx);
2088 :
2089 0 : if (!registered) {
2090 : rval = ESRCH;
2091 0 : goto ret;
2092 : }
2093 :
2094 : /* How large a buffer do we need... XXX we only do one proposal for now */
2095 0 : i = sizeof(struct sadb_msg) +
2096 0 : (laddr == NULL ? 0 : sizeof(struct sadb_address) +
2097 0 : PADUP(ipo->ipo_src.sa.sa_len)) +
2098 0 : sizeof(struct sadb_address) + PADUP(gw->sa.sa_len) +
2099 0 : sizeof(struct sadb_prop) + 1 * sizeof(struct sadb_comb);
2100 :
2101 0 : if (ipo->ipo_ids) {
2102 0 : i += sizeof(struct sadb_ident) + PADUP(ipo->ipo_ids->id_local->len);
2103 0 : i += sizeof(struct sadb_ident) + PADUP(ipo->ipo_ids->id_remote->len);
2104 0 : }
2105 :
2106 : /* Allocate */
2107 0 : if (!(p = malloc(i, M_PFKEY, M_NOWAIT | M_ZERO))) {
2108 : rval = ENOMEM;
2109 0 : goto ret;
2110 : }
2111 :
2112 0 : bzero(headers, sizeof(headers));
2113 :
2114 0 : buffer = p;
2115 :
2116 0 : headers[0] = p;
2117 0 : p += sizeof(struct sadb_msg);
2118 :
2119 0 : smsg = (struct sadb_msg *) headers[0];
2120 0 : smsg->sadb_msg_version = PF_KEY_V2;
2121 0 : smsg->sadb_msg_type = SADB_ACQUIRE;
2122 0 : smsg->sadb_msg_len = i / sizeof(uint64_t);
2123 0 : smsg->sadb_msg_seq = *seq;
2124 :
2125 0 : if (ipo->ipo_sproto == IPPROTO_ESP)
2126 0 : smsg->sadb_msg_satype = SADB_SATYPE_ESP;
2127 0 : else if (ipo->ipo_sproto == IPPROTO_AH)
2128 0 : smsg->sadb_msg_satype = SADB_SATYPE_AH;
2129 0 : else if (ipo->ipo_sproto == IPPROTO_IPCOMP)
2130 0 : smsg->sadb_msg_satype = SADB_X_SATYPE_IPCOMP;
2131 :
2132 0 : if (laddr) {
2133 0 : headers[SADB_EXT_ADDRESS_SRC] = p;
2134 0 : p += sizeof(struct sadb_address) + PADUP(laddr->sa.sa_len);
2135 0 : sadd = (struct sadb_address *) headers[SADB_EXT_ADDRESS_SRC];
2136 0 : sadd->sadb_address_len = (sizeof(struct sadb_address) +
2137 0 : laddr->sa.sa_len + sizeof(uint64_t) - 1) /
2138 : sizeof(uint64_t);
2139 0 : bcopy(laddr, headers[SADB_EXT_ADDRESS_SRC] +
2140 0 : sizeof(struct sadb_address), laddr->sa.sa_len);
2141 0 : }
2142 :
2143 0 : headers[SADB_EXT_ADDRESS_DST] = p;
2144 0 : p += sizeof(struct sadb_address) + PADUP(gw->sa.sa_len);
2145 0 : sadd = (struct sadb_address *) headers[SADB_EXT_ADDRESS_DST];
2146 0 : sadd->sadb_address_len = (sizeof(struct sadb_address) +
2147 0 : gw->sa.sa_len + sizeof(uint64_t) - 1) / sizeof(uint64_t);
2148 0 : bcopy(gw, headers[SADB_EXT_ADDRESS_DST] + sizeof(struct sadb_address),
2149 0 : gw->sa.sa_len);
2150 :
2151 0 : if (ipo->ipo_ids)
2152 0 : export_identities(&p, ipo->ipo_ids, 0, headers);
2153 :
2154 0 : headers[SADB_EXT_PROPOSAL] = p;
2155 0 : p += sizeof(struct sadb_prop);
2156 0 : sa_prop = (struct sadb_prop *) headers[SADB_EXT_PROPOSAL];
2157 0 : sa_prop->sadb_prop_num = 1; /* XXX One proposal only */
2158 0 : sa_prop->sadb_prop_len = (sizeof(struct sadb_prop) +
2159 : (sizeof(struct sadb_comb) * sa_prop->sadb_prop_num)) /
2160 : sizeof(uint64_t);
2161 :
2162 0 : sadb_comb = p;
2163 :
2164 : /* XXX Should actually ask the crypto layer what's supported */
2165 0 : for (j = 0; j < sa_prop->sadb_prop_num; j++) {
2166 0 : sadb_comb->sadb_comb_flags = 0;
2167 : #ifdef IPSEC
2168 0 : if (ipsec_require_pfs)
2169 0 : sadb_comb->sadb_comb_flags |= SADB_SAFLAGS_PFS;
2170 :
2171 : /* Set the encryption algorithm */
2172 0 : if (ipo->ipo_sproto == IPPROTO_ESP) {
2173 0 : if (!strncasecmp(ipsec_def_enc, "aes",
2174 : sizeof("aes"))) {
2175 0 : sadb_comb->sadb_comb_encrypt = SADB_X_EALG_AES;
2176 0 : sadb_comb->sadb_comb_encrypt_minbits = 128;
2177 0 : sadb_comb->sadb_comb_encrypt_maxbits = 256;
2178 0 : } else if (!strncasecmp(ipsec_def_enc, "aesctr",
2179 : sizeof("aesctr"))) {
2180 0 : sadb_comb->sadb_comb_encrypt = SADB_X_EALG_AESCTR;
2181 0 : sadb_comb->sadb_comb_encrypt_minbits = 128+32;
2182 0 : sadb_comb->sadb_comb_encrypt_maxbits = 256+32;
2183 0 : } else if (!strncasecmp(ipsec_def_enc, "3des",
2184 : sizeof("3des"))) {
2185 0 : sadb_comb->sadb_comb_encrypt = SADB_EALG_3DESCBC;
2186 0 : sadb_comb->sadb_comb_encrypt_minbits = 192;
2187 0 : sadb_comb->sadb_comb_encrypt_maxbits = 192;
2188 0 : } else if (!strncasecmp(ipsec_def_enc, "blowfish",
2189 : sizeof("blowfish"))) {
2190 0 : sadb_comb->sadb_comb_encrypt = SADB_X_EALG_BLF;
2191 0 : sadb_comb->sadb_comb_encrypt_minbits = 40;
2192 0 : sadb_comb->sadb_comb_encrypt_maxbits = BLF_MAXKEYLEN * 8;
2193 0 : } else if (!strncasecmp(ipsec_def_enc, "cast128",
2194 : sizeof("cast128"))) {
2195 0 : sadb_comb->sadb_comb_encrypt = SADB_X_EALG_CAST;
2196 0 : sadb_comb->sadb_comb_encrypt_minbits = 40;
2197 0 : sadb_comb->sadb_comb_encrypt_maxbits = 128;
2198 0 : }
2199 0 : } else if (ipo->ipo_sproto == IPPROTO_IPCOMP) {
2200 : /* Set the compression algorithm */
2201 0 : if (!strncasecmp(ipsec_def_comp, "deflate",
2202 : sizeof("deflate"))) {
2203 0 : sadb_comb->sadb_comb_encrypt = SADB_X_CALG_DEFLATE;
2204 0 : sadb_comb->sadb_comb_encrypt_minbits = 0;
2205 0 : sadb_comb->sadb_comb_encrypt_maxbits = 0;
2206 0 : } else if (!strncasecmp(ipsec_def_comp, "lzs",
2207 : sizeof("lzs"))) {
2208 0 : sadb_comb->sadb_comb_encrypt = SADB_X_CALG_LZS;
2209 0 : sadb_comb->sadb_comb_encrypt_minbits = 0;
2210 0 : sadb_comb->sadb_comb_encrypt_maxbits = 0;
2211 0 : }
2212 : }
2213 :
2214 : /* Set the authentication algorithm */
2215 0 : if (!strncasecmp(ipsec_def_auth, "hmac-sha1",
2216 : sizeof("hmac-sha1"))) {
2217 0 : sadb_comb->sadb_comb_auth = SADB_AALG_SHA1HMAC;
2218 0 : sadb_comb->sadb_comb_auth_minbits = 160;
2219 0 : sadb_comb->sadb_comb_auth_maxbits = 160;
2220 0 : } else if (!strncasecmp(ipsec_def_auth, "hmac-ripemd160",
2221 : sizeof("hmac_ripemd160"))) {
2222 0 : sadb_comb->sadb_comb_auth = SADB_X_AALG_RIPEMD160HMAC;
2223 0 : sadb_comb->sadb_comb_auth_minbits = 160;
2224 0 : sadb_comb->sadb_comb_auth_maxbits = 160;
2225 0 : } else if (!strncasecmp(ipsec_def_auth, "hmac-md5",
2226 : sizeof("hmac-md5"))) {
2227 0 : sadb_comb->sadb_comb_auth = SADB_AALG_MD5HMAC;
2228 0 : sadb_comb->sadb_comb_auth_minbits = 128;
2229 0 : sadb_comb->sadb_comb_auth_maxbits = 128;
2230 0 : } else if (!strncasecmp(ipsec_def_auth, "hmac-sha2-256",
2231 : sizeof("hmac-sha2-256"))) {
2232 0 : sadb_comb->sadb_comb_auth = SADB_X_AALG_SHA2_256;
2233 0 : sadb_comb->sadb_comb_auth_minbits = 256;
2234 0 : sadb_comb->sadb_comb_auth_maxbits = 256;
2235 0 : } else if (!strncasecmp(ipsec_def_auth, "hmac-sha2-384",
2236 : sizeof("hmac-sha2-384"))) {
2237 0 : sadb_comb->sadb_comb_auth = SADB_X_AALG_SHA2_384;
2238 0 : sadb_comb->sadb_comb_auth_minbits = 384;
2239 0 : sadb_comb->sadb_comb_auth_maxbits = 384;
2240 0 : } else if (!strncasecmp(ipsec_def_auth, "hmac-sha2-512",
2241 : sizeof("hmac-sha2-512"))) {
2242 0 : sadb_comb->sadb_comb_auth = SADB_X_AALG_SHA2_512;
2243 0 : sadb_comb->sadb_comb_auth_minbits = 512;
2244 0 : sadb_comb->sadb_comb_auth_maxbits = 512;
2245 0 : }
2246 :
2247 0 : sadb_comb->sadb_comb_soft_allocations = ipsec_soft_allocations;
2248 0 : sadb_comb->sadb_comb_hard_allocations = ipsec_exp_allocations;
2249 :
2250 0 : sadb_comb->sadb_comb_soft_bytes = ipsec_soft_bytes;
2251 0 : sadb_comb->sadb_comb_hard_bytes = ipsec_exp_bytes;
2252 :
2253 0 : sadb_comb->sadb_comb_soft_addtime = ipsec_soft_timeout;
2254 0 : sadb_comb->sadb_comb_hard_addtime = ipsec_exp_timeout;
2255 :
2256 0 : sadb_comb->sadb_comb_soft_usetime = ipsec_soft_first_use;
2257 0 : sadb_comb->sadb_comb_hard_usetime = ipsec_exp_first_use;
2258 : #endif
2259 0 : sadb_comb++;
2260 : }
2261 :
2262 : /* Send the ACQUIRE message to all compliant registered listeners. */
2263 0 : if ((rval = pfkeyv2_sendmessage(headers,
2264 0 : PFKEYV2_SENDMESSAGE_REGISTERED, NULL, smsg->sadb_msg_satype, 0,
2265 0 : ipo->ipo_rdomain)) != 0)
2266 : goto ret;
2267 :
2268 : rval = 0;
2269 : ret:
2270 0 : if (buffer != NULL) {
2271 0 : bzero(buffer, i);
2272 0 : free(buffer, M_PFKEY, 0);
2273 0 : }
2274 :
2275 0 : return (rval);
2276 0 : }
2277 :
2278 : /*
2279 : * Notify key management that an expiration went off. The second argument
2280 : * specifies the type of expiration (soft or hard).
2281 : */
2282 : int
2283 0 : pfkeyv2_expire(struct tdb *tdb, u_int16_t type)
2284 : {
2285 0 : void *p, *headers[SADB_EXT_MAX+1], *buffer = NULL;
2286 : struct sadb_msg *smsg;
2287 : int rval = 0;
2288 : int i;
2289 :
2290 0 : switch (tdb->tdb_sproto) {
2291 : case IPPROTO_AH:
2292 : case IPPROTO_ESP:
2293 : case IPPROTO_IPIP:
2294 : case IPPROTO_IPCOMP:
2295 : #ifdef TCP_SIGNATURE
2296 : case IPPROTO_TCP:
2297 : #endif /* TCP_SIGNATURE */
2298 : break;
2299 :
2300 : default:
2301 : rval = EOPNOTSUPP;
2302 0 : goto ret;
2303 : }
2304 :
2305 0 : i = sizeof(struct sadb_msg) + sizeof(struct sadb_sa) +
2306 : 2 * sizeof(struct sadb_lifetime) +
2307 0 : sizeof(struct sadb_address) + PADUP(tdb->tdb_src.sa.sa_len) +
2308 0 : sizeof(struct sadb_address) + PADUP(tdb->tdb_dst.sa.sa_len);
2309 :
2310 0 : if (!(p = malloc(i, M_PFKEY, M_NOWAIT | M_ZERO))) {
2311 : rval = ENOMEM;
2312 0 : goto ret;
2313 : }
2314 :
2315 0 : bzero(headers, sizeof(headers));
2316 :
2317 0 : buffer = p;
2318 :
2319 0 : headers[0] = p;
2320 0 : p += sizeof(struct sadb_msg);
2321 :
2322 0 : smsg = (struct sadb_msg *) headers[0];
2323 0 : smsg->sadb_msg_version = PF_KEY_V2;
2324 0 : smsg->sadb_msg_type = SADB_EXPIRE;
2325 0 : smsg->sadb_msg_satype = tdb->tdb_satype;
2326 0 : smsg->sadb_msg_len = i / sizeof(uint64_t);
2327 :
2328 0 : mtx_enter(&pfkeyv2_mtx);
2329 0 : smsg->sadb_msg_seq = pfkeyv2_seq++;
2330 0 : mtx_leave(&pfkeyv2_mtx);
2331 :
2332 0 : headers[SADB_EXT_SA] = p;
2333 0 : export_sa(&p, tdb);
2334 :
2335 0 : headers[SADB_EXT_LIFETIME_CURRENT] = p;
2336 0 : export_lifetime(&p, tdb, 2);
2337 :
2338 0 : headers[type] = p;
2339 0 : export_lifetime(&p, tdb, type == SADB_EXT_LIFETIME_SOFT ?
2340 : PFKEYV2_LIFETIME_SOFT : PFKEYV2_LIFETIME_HARD);
2341 :
2342 0 : headers[SADB_EXT_ADDRESS_SRC] = p;
2343 0 : export_address(&p, &tdb->tdb_src.sa);
2344 :
2345 0 : headers[SADB_EXT_ADDRESS_DST] = p;
2346 0 : export_address(&p, &tdb->tdb_dst.sa);
2347 :
2348 0 : if ((rval = pfkeyv2_sendmessage(headers, PFKEYV2_SENDMESSAGE_BROADCAST,
2349 0 : NULL, 0, 0, tdb->tdb_rdomain)) != 0)
2350 : goto ret;
2351 :
2352 : rval = 0;
2353 :
2354 : ret:
2355 0 : if (buffer != NULL) {
2356 0 : bzero(buffer, i);
2357 0 : free(buffer, M_PFKEY, 0);
2358 0 : }
2359 :
2360 0 : return (rval);
2361 0 : }
2362 :
2363 : struct pfkeyv2_sysctl_walk {
2364 : void *w_where;
2365 : size_t w_len;
2366 : int w_op;
2367 : u_int8_t w_satype;
2368 : };
2369 :
2370 : int
2371 0 : pfkeyv2_sysctl_walker(struct tdb *tdb, void *arg, int last)
2372 : {
2373 0 : struct pfkeyv2_sysctl_walk *w = (struct pfkeyv2_sysctl_walk *)arg;
2374 0 : void *buffer = NULL;
2375 : int error = 0;
2376 0 : int buflen, i;
2377 :
2378 0 : if (w->w_satype != SADB_SATYPE_UNSPEC &&
2379 0 : w->w_satype != tdb->tdb_satype)
2380 0 : return (0);
2381 :
2382 0 : if (w->w_where) {
2383 0 : void *headers[SADB_EXT_MAX+1];
2384 0 : struct sadb_msg msg;
2385 :
2386 0 : bzero(headers, sizeof(headers));
2387 0 : if ((error = pfkeyv2_get(tdb, headers, &buffer, &buflen)) != 0)
2388 0 : goto done;
2389 0 : if (w->w_len < sizeof(msg) + buflen) {
2390 : error = ENOMEM;
2391 0 : goto done;
2392 : }
2393 : /* prepend header */
2394 0 : bzero(&msg, sizeof(msg));
2395 0 : msg.sadb_msg_version = PF_KEY_V2;
2396 0 : msg.sadb_msg_satype = tdb->tdb_satype;
2397 0 : msg.sadb_msg_type = SADB_DUMP;
2398 0 : msg.sadb_msg_len = (sizeof(msg) + buflen) / sizeof(uint64_t);
2399 0 : if ((error = copyout(&msg, w->w_where, sizeof(msg))) != 0)
2400 0 : goto done;
2401 0 : w->w_where += sizeof(msg);
2402 0 : w->w_len -= sizeof(msg);
2403 : /* set extension type */
2404 0 : for (i = 1; i <= SADB_EXT_MAX; i++)
2405 0 : if (headers[i])
2406 0 : ((struct sadb_ext *)
2407 0 : headers[i])->sadb_ext_type = i;
2408 0 : if ((error = copyout(buffer, w->w_where, buflen)) != 0)
2409 0 : goto done;
2410 0 : w->w_where += buflen;
2411 0 : w->w_len -= buflen;
2412 0 : } else {
2413 0 : if ((error = pfkeyv2_get(tdb, NULL, NULL, &buflen)) != 0)
2414 0 : return (error);
2415 0 : w->w_len += buflen;
2416 0 : w->w_len += sizeof(struct sadb_msg);
2417 : }
2418 :
2419 : done:
2420 0 : if (buffer)
2421 0 : free(buffer, M_PFKEY, 0);
2422 0 : return (error);
2423 0 : }
2424 :
2425 : int
2426 0 : pfkeyv2_dump_policy(struct ipsec_policy *ipo, void **headers, void **buffer,
2427 : int *lenp)
2428 : {
2429 : int i, rval, perm;
2430 0 : void *p;
2431 :
2432 : /* Find how much space we need. */
2433 : i = 2 * sizeof(struct sadb_protocol);
2434 :
2435 : /* We'll need four of them: src, src mask, dst, dst mask. */
2436 0 : switch (ipo->ipo_addr.sen_type) {
2437 : case SENT_IP4:
2438 : i += 4 * PADUP(sizeof(struct sockaddr_in));
2439 : i += 4 * sizeof(struct sadb_address);
2440 0 : break;
2441 : #ifdef INET6
2442 : case SENT_IP6:
2443 : i += 4 * PADUP(sizeof(struct sockaddr_in6));
2444 : i += 4 * sizeof(struct sadb_address);
2445 0 : break;
2446 : #endif /* INET6 */
2447 : default:
2448 0 : return (EINVAL);
2449 : }
2450 :
2451 : /* Local address, might be zeroed. */
2452 0 : switch (ipo->ipo_src.sa.sa_family) {
2453 : case 0:
2454 : break;
2455 : case AF_INET:
2456 0 : i += PADUP(sizeof(struct sockaddr_in));
2457 0 : i += sizeof(struct sadb_address);
2458 0 : break;
2459 : #ifdef INET6
2460 : case AF_INET6:
2461 0 : i += PADUP(sizeof(struct sockaddr_in6));
2462 0 : i += sizeof(struct sadb_address);
2463 0 : break;
2464 : #endif /* INET6 */
2465 : default:
2466 0 : return (EINVAL);
2467 : }
2468 :
2469 : /* Remote address, might be zeroed. XXX ??? */
2470 0 : switch (ipo->ipo_dst.sa.sa_family) {
2471 : case 0:
2472 : break;
2473 : case AF_INET:
2474 0 : i += PADUP(sizeof(struct sockaddr_in));
2475 0 : i += sizeof(struct sadb_address);
2476 0 : break;
2477 : #ifdef INET6
2478 : case AF_INET6:
2479 0 : i += PADUP(sizeof(struct sockaddr_in6));
2480 0 : i += sizeof(struct sadb_address);
2481 0 : break;
2482 : #endif /* INET6 */
2483 : default:
2484 0 : return (EINVAL);
2485 : }
2486 :
2487 0 : if (ipo->ipo_ids) {
2488 0 : i += sizeof(struct sadb_ident) + PADUP(ipo->ipo_ids->id_local->len);
2489 0 : i += sizeof(struct sadb_ident) + PADUP(ipo->ipo_ids->id_remote->len);
2490 0 : }
2491 :
2492 0 : if (lenp)
2493 0 : *lenp = i;
2494 :
2495 0 : if (buffer == NULL) {
2496 : rval = 0;
2497 0 : goto ret;
2498 : }
2499 :
2500 0 : if (!(p = malloc(i, M_PFKEY, M_NOWAIT | M_ZERO))) {
2501 : rval = ENOMEM;
2502 0 : goto ret;
2503 : } else
2504 0 : *buffer = p;
2505 :
2506 : /* Local address. */
2507 0 : if (ipo->ipo_src.sa.sa_family) {
2508 0 : headers[SADB_EXT_ADDRESS_SRC] = p;
2509 0 : export_address(&p, &ipo->ipo_src.sa);
2510 0 : }
2511 :
2512 : /* Remote address. */
2513 0 : if (ipo->ipo_dst.sa.sa_family) {
2514 0 : headers[SADB_EXT_ADDRESS_DST] = p;
2515 0 : export_address(&p, &ipo->ipo_dst.sa);
2516 0 : }
2517 :
2518 : /* Get actual flow. */
2519 0 : export_flow(&p, ipo->ipo_type, &ipo->ipo_addr, &ipo->ipo_mask,
2520 : headers);
2521 :
2522 : /* Add ids only when we are root. */
2523 0 : perm = suser(curproc);
2524 0 : if (perm == 0 && ipo->ipo_ids)
2525 0 : export_identities(&p, ipo->ipo_ids, 0, headers);
2526 :
2527 0 : rval = 0;
2528 : ret:
2529 0 : return (rval);
2530 0 : }
2531 :
2532 : int
2533 0 : pfkeyv2_sysctl_policydumper(struct ipsec_policy *ipo, void *arg,
2534 : unsigned int tableid)
2535 : {
2536 0 : struct pfkeyv2_sysctl_walk *w = (struct pfkeyv2_sysctl_walk *)arg;
2537 0 : void *buffer = 0;
2538 0 : int i, buflen, error = 0;
2539 :
2540 0 : if (w->w_where) {
2541 0 : void *headers[SADB_EXT_MAX + 1];
2542 0 : struct sadb_msg msg;
2543 :
2544 0 : bzero(headers, sizeof(headers));
2545 0 : if ((error = pfkeyv2_dump_policy(ipo, headers, &buffer,
2546 0 : &buflen)) != 0)
2547 0 : goto done;
2548 0 : if (w->w_len < buflen) {
2549 : error = ENOMEM;
2550 0 : goto done;
2551 : }
2552 : /* prepend header */
2553 0 : bzero(&msg, sizeof(msg));
2554 0 : msg.sadb_msg_version = PF_KEY_V2;
2555 0 : if (ipo->ipo_sproto == IPPROTO_ESP)
2556 0 : msg.sadb_msg_satype = SADB_SATYPE_ESP;
2557 0 : else if (ipo->ipo_sproto == IPPROTO_AH)
2558 0 : msg.sadb_msg_satype = SADB_SATYPE_AH;
2559 0 : else if (ipo->ipo_sproto == IPPROTO_IPCOMP)
2560 0 : msg.sadb_msg_satype = SADB_X_SATYPE_IPCOMP;
2561 0 : else if (ipo->ipo_sproto == IPPROTO_IPIP)
2562 0 : msg.sadb_msg_satype = SADB_X_SATYPE_IPIP;
2563 0 : msg.sadb_msg_type = SADB_X_SPDDUMP;
2564 0 : msg.sadb_msg_len = (sizeof(msg) + buflen) / sizeof(uint64_t);
2565 0 : if ((error = copyout(&msg, w->w_where, sizeof(msg))) != 0)
2566 0 : goto done;
2567 0 : w->w_where += sizeof(msg);
2568 0 : w->w_len -= sizeof(msg);
2569 : /* set extension type */
2570 0 : for (i = 1; i < SADB_EXT_MAX; i++)
2571 0 : if (headers[i])
2572 0 : ((struct sadb_ext *)
2573 0 : headers[i])->sadb_ext_type = i;
2574 0 : if ((error = copyout(buffer, w->w_where, buflen)) != 0)
2575 0 : goto done;
2576 0 : w->w_where += buflen;
2577 0 : w->w_len -= buflen;
2578 0 : } else {
2579 0 : if ((error = pfkeyv2_dump_policy(ipo, NULL, NULL,
2580 0 : &buflen)) != 0)
2581 : goto done;
2582 0 : w->w_len += buflen;
2583 0 : w->w_len += sizeof(struct sadb_msg);
2584 : }
2585 :
2586 : done:
2587 0 : if (buffer)
2588 0 : free(buffer, M_PFKEY, 0);
2589 0 : return (error);
2590 0 : }
2591 :
2592 : int
2593 0 : pfkeyv2_policy_flush(struct ipsec_policy *ipo, void *arg, unsigned int tableid)
2594 : {
2595 : int error;
2596 :
2597 0 : error = ipsec_delete_policy(ipo);
2598 0 : if (error == 0)
2599 : error = EAGAIN;
2600 :
2601 0 : return (error);
2602 : }
2603 :
2604 : int
2605 0 : pfkeyv2_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
2606 : void *new, size_t newlen)
2607 : {
2608 0 : struct pfkeyv2_sysctl_walk w;
2609 : int error = EINVAL;
2610 : u_int rdomain;
2611 :
2612 0 : if (new)
2613 0 : return (EPERM);
2614 0 : if (namelen < 1)
2615 0 : return (EINVAL);
2616 0 : w.w_op = name[0];
2617 0 : w.w_satype = name[1];
2618 0 : w.w_where = oldp;
2619 0 : w.w_len = oldp ? *oldlenp : 0;
2620 :
2621 0 : rdomain = rtable_l2(curproc->p_p->ps_rtableid);
2622 :
2623 0 : switch(w.w_op) {
2624 : case NET_KEY_SADB_DUMP:
2625 0 : if ((error = suser(curproc)) != 0)
2626 0 : return (error);
2627 0 : NET_LOCK();
2628 0 : error = tdb_walk(rdomain, pfkeyv2_sysctl_walker, &w);
2629 0 : NET_UNLOCK();
2630 0 : if (oldp)
2631 0 : *oldlenp = w.w_where - oldp;
2632 : else
2633 0 : *oldlenp = w.w_len;
2634 : break;
2635 :
2636 : case NET_KEY_SPD_DUMP:
2637 0 : NET_LOCK();
2638 0 : error = spd_table_walk(rdomain,
2639 : pfkeyv2_sysctl_policydumper, &w);
2640 0 : NET_UNLOCK();
2641 0 : if (oldp)
2642 0 : *oldlenp = w.w_where - oldp;
2643 : else
2644 0 : *oldlenp = w.w_len;
2645 : break;
2646 : }
2647 :
2648 0 : return (error);
2649 0 : }
|