xref: /freebsd/sys/netipsec/ipsec_pcb.c (revision ef2a572bf6bdcac97ef29ce631d2f50f938e1ec8)
1 /*-
2  * Copyright (c) 2016 Andrey V. Elsukov <ae@FreeBSD.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26 
27 #include <sys/cdefs.h>
28 #include "opt_inet.h"
29 #include "opt_inet6.h"
30 #include "opt_ipsec.h"
31 
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/kernel.h>
35 #include <sys/lock.h>
36 #include <sys/malloc.h>
37 #include <sys/mbuf.h>
38 #include <sys/priv.h>
39 #include <sys/socket.h>
40 #include <sys/sockopt.h>
41 #include <sys/syslog.h>
42 #include <sys/proc.h>
43 
44 #include <netinet/in.h>
45 #include <netinet/in_pcb.h>
46 
47 #include <netipsec/ipsec.h>
48 #include <netipsec/ipsec6.h>
49 #include <netipsec/ipsec_support.h>
50 #include <netipsec/key.h>
51 #include <netipsec/key_debug.h>
52 #include <netipsec/ipsec_offload.h>
53 
54 MALLOC_DEFINE(M_IPSEC_INPCB, "inpcbpolicy", "inpcb-resident ipsec policy");
55 
56 static void
57 ipsec_setsockaddrs_inpcb(struct inpcb *inp, union sockaddr_union *src,
58     union sockaddr_union *dst, u_int dir)
59 {
60 
61 #ifdef INET6
62 	if (inp->inp_vflag & INP_IPV6) {
63 		struct sockaddr_in6 *sin6;
64 
65 		bzero(&src->sin6, sizeof(src->sin6));
66 		bzero(&dst->sin6, sizeof(dst->sin6));
67 		src->sin6.sin6_family = AF_INET6;
68 		src->sin6.sin6_len = sizeof(struct sockaddr_in6);
69 		dst->sin6.sin6_family = AF_INET6;
70 		dst->sin6.sin6_len = sizeof(struct sockaddr_in6);
71 
72 		if (dir == IPSEC_DIR_OUTBOUND)
73 			sin6 = &src->sin6;
74 		else
75 			sin6 = &dst->sin6;
76 		sin6->sin6_addr = inp->in6p_laddr;
77 		sin6->sin6_port = inp->inp_lport;
78 		if (IN6_IS_SCOPE_LINKLOCAL(&inp->in6p_laddr)) {
79 			/* XXXAE: use in6p_zoneid */
80 			sin6->sin6_addr.s6_addr16[1] = 0;
81 			sin6->sin6_scope_id = ntohs(
82 			    inp->in6p_laddr.s6_addr16[1]);
83 		}
84 
85 		if (dir == IPSEC_DIR_OUTBOUND)
86 			sin6 = &dst->sin6;
87 		else
88 			sin6 = &src->sin6;
89 		sin6->sin6_addr = inp->in6p_faddr;
90 		sin6->sin6_port = inp->inp_fport;
91 		if (IN6_IS_SCOPE_LINKLOCAL(&inp->in6p_faddr)) {
92 			/* XXXAE: use in6p_zoneid */
93 			sin6->sin6_addr.s6_addr16[1] = 0;
94 			sin6->sin6_scope_id = ntohs(
95 			    inp->in6p_faddr.s6_addr16[1]);
96 		}
97 	}
98 #endif
99 #ifdef INET
100 	if (inp->inp_vflag & INP_IPV4) {
101 		struct sockaddr_in *sin;
102 
103 		bzero(&src->sin, sizeof(src->sin));
104 		bzero(&dst->sin, sizeof(dst->sin));
105 		src->sin.sin_family = AF_INET;
106 		src->sin.sin_len = sizeof(struct sockaddr_in);
107 		dst->sin.sin_family = AF_INET;
108 		dst->sin.sin_len = sizeof(struct sockaddr_in);
109 
110 		if (dir == IPSEC_DIR_OUTBOUND)
111 			sin = &src->sin;
112 		else
113 			sin = &dst->sin;
114 		sin->sin_addr = inp->inp_laddr;
115 		sin->sin_port = inp->inp_lport;
116 
117 		if (dir == IPSEC_DIR_OUTBOUND)
118 			sin = &dst->sin;
119 		else
120 			sin = &src->sin;
121 		sin->sin_addr = inp->inp_faddr;
122 		sin->sin_port = inp->inp_fport;
123 	}
124 #endif
125 }
126 
127 void
128 ipsec_setspidx_inpcb(struct inpcb *inp, struct secpolicyindex *spidx,
129     u_int dir)
130 {
131 
132 	ipsec_setsockaddrs_inpcb(inp, &spidx->src, &spidx->dst, dir);
133 #ifdef INET6
134 	if (inp->inp_vflag & INP_IPV6) {
135 		spidx->prefs = sizeof(struct in6_addr) << 3;
136 		spidx->prefd = sizeof(struct in6_addr) << 3;
137 	}
138 #endif
139 #ifdef INET
140 	if (inp->inp_vflag & INP_IPV4) {
141 		spidx->prefs = sizeof(struct in_addr) << 3;
142 		spidx->prefd = sizeof(struct in_addr) << 3;
143 	}
144 #endif
145 	spidx->ul_proto = IPPROTO_TCP; /* XXX: currently only TCP uses this */
146 	spidx->dir = dir;
147 	KEYDBG(IPSEC_DUMP,
148 	    printf("%s: ", __func__); kdebug_secpolicyindex(spidx, NULL));
149 }
150 
151 /* Initialize PCB policy. */
152 int
153 ipsec_init_pcbpolicy(struct inpcb *inp)
154 {
155 
156 	IPSEC_ASSERT(inp != NULL, ("null inp"));
157 	IPSEC_ASSERT(inp->inp_sp == NULL, ("inp_sp already initialized"));
158 
159 	inp->inp_sp = malloc(sizeof(struct inpcbpolicy), M_IPSEC_INPCB,
160 	    M_NOWAIT | M_ZERO);
161 	if (inp->inp_sp == NULL)
162 		return (ENOBUFS);
163 	return (0);
164 }
165 
166 /* Delete PCB policy. */
167 int
168 ipsec_delete_pcbpolicy(struct inpcb *inp)
169 {
170 	struct inpcbpolicy *inp_sp;
171 
172 	inp_sp = inp->inp_sp;
173 	if (inp_sp == NULL)
174 		return (0);
175 	inp->inp_sp = NULL;
176 
177 	if (inp_sp->sp_in != NULL) {
178 		if ((inp_sp->flags & INP_INBOUND_POLICY) != 0)
179 			ipsec_accel_spddel(inp_sp->sp_in);
180 		key_freesp(&inp_sp->sp_in);
181 	}
182 
183 	if (inp_sp->sp_out != NULL) {
184 		if ((inp_sp->flags & INP_OUTBOUND_POLICY) != 0)
185 			ipsec_accel_spddel(inp_sp->sp_out);
186 		key_freesp(&inp_sp->sp_out);
187 	}
188 
189 	free(inp_sp, M_IPSEC_INPCB);
190 	return (0);
191 }
192 
193 /* Deep-copy a policy in PCB. */
194 static struct secpolicy *
195 ipsec_deepcopy_pcbpolicy(struct secpolicy *src)
196 {
197 	struct secpolicy *dst;
198 	int i;
199 
200 	if (src == NULL)
201 		return (NULL);
202 
203 	IPSEC_ASSERT(src->state == IPSEC_SPSTATE_PCB, ("SP isn't PCB"));
204 
205 	dst = key_newsp();
206 	if (dst == NULL)
207 		return (NULL);
208 
209 	/* spidx is not copied here */
210 	dst->policy = src->policy;
211 	dst->state = src->state;
212 	dst->priority = src->priority;
213 	/* Do not touch the refcnt field. */
214 
215 	/* Copy IPsec request chain. */
216 	for (i = 0; i < src->tcount; i++) {
217 		dst->req[i] = ipsec_newisr();
218 		if (dst->req[i] == NULL) {
219 			key_freesp(&dst);
220 			return (NULL);
221 		}
222 		bcopy(src->req[i], dst->req[i], sizeof(struct ipsecrequest));
223 		dst->tcount++;
224 	}
225 	KEYDBG(IPSEC_DUMP,
226 	    printf("%s: copied SP(%p) -> SP(%p)\n", __func__, src, dst);
227 	    kdebug_secpolicy(dst));
228 	return (dst);
229 }
230 
231 /*
232  * Copy IPsec policy from old INPCB into new.
233  * It is expected that new INPCB has not configured policies.
234  */
235 int
236 ipsec_copy_pcbpolicy(struct inpcb *old, struct inpcb *new)
237 {
238 	struct secpolicy *sp;
239 
240 	/*
241 	 * old->inp_sp can be NULL if PCB was created when an IPsec
242 	 * support was unavailable. This is not an error, we don't have
243 	 * policies in this PCB, so nothing to copy.
244 	 */
245 	if (old->inp_sp == NULL)
246 		return (0);
247 
248 	IPSEC_ASSERT(new->inp_sp != NULL, ("new inp_sp is NULL"));
249 	IPSEC_ASSERT((new->inp_sp->flags & (
250 	    INP_INBOUND_POLICY | INP_OUTBOUND_POLICY)) == 0,
251 	    ("new PCB already has configured policies"));
252 	INP_WLOCK_ASSERT(new);
253 	INP_LOCK_ASSERT(old);
254 
255 	if (old->inp_sp->flags & INP_INBOUND_POLICY) {
256 		sp = ipsec_deepcopy_pcbpolicy(old->inp_sp->sp_in);
257 		if (sp == NULL)
258 			return (ENOBUFS);
259 		ipsec_setspidx_inpcb(new, &sp->spidx, IPSEC_DIR_INBOUND);
260 		if (new->inp_sp->sp_in != NULL) {
261 			ipsec_accel_spddel(new->inp_sp->sp_in);
262 			key_freesp(&new->inp_sp->sp_in);
263 		}
264 		new->inp_sp->sp_in = sp;
265 		new->inp_sp->flags |= INP_INBOUND_POLICY;
266 		ipsec_accel_spdadd(sp, new);
267 	}
268 	if (old->inp_sp->flags & INP_OUTBOUND_POLICY) {
269 		sp = ipsec_deepcopy_pcbpolicy(old->inp_sp->sp_out);
270 		if (sp == NULL)
271 			return (ENOBUFS);
272 		ipsec_setspidx_inpcb(new, &sp->spidx, IPSEC_DIR_OUTBOUND);
273 		if (new->inp_sp->sp_out != NULL) {
274 			ipsec_accel_spddel(new->inp_sp->sp_out);
275 			key_freesp(&new->inp_sp->sp_out);
276 		}
277 		new->inp_sp->sp_out = sp;
278 		new->inp_sp->flags |= INP_OUTBOUND_POLICY;
279 		ipsec_accel_spdadd(sp, new);
280 	}
281 	return (0);
282 }
283 
284 static int
285 ipsec_set_pcbpolicy(struct inpcb *inp, struct ucred *cred,
286     void *request, size_t len)
287 {
288 	struct sadb_x_policy *xpl;
289 	struct secpolicy **spp, *newsp;
290 	int error, flags;
291 
292 	xpl = (struct sadb_x_policy *)request;
293 	/* Select direction. */
294 	switch (xpl->sadb_x_policy_dir) {
295 	case IPSEC_DIR_INBOUND:
296 	case IPSEC_DIR_OUTBOUND:
297 		break;
298 	default:
299 		ipseclog((LOG_ERR, "%s: invalid direction=%u\n", __func__,
300 			xpl->sadb_x_policy_dir));
301 		return (EINVAL);
302 	}
303 	/*
304 	 * Privileged sockets are allowed to set own security policy
305 	 * and configure IPsec bypass. Unprivileged sockets only can
306 	 * have ENTRUST policy.
307 	 */
308 	switch (xpl->sadb_x_policy_type) {
309 	case IPSEC_POLICY_IPSEC:
310 	case IPSEC_POLICY_BYPASS:
311 		if (cred != NULL &&
312 		    priv_check_cred(cred, PRIV_NETINET_IPSEC) != 0)
313 			return (EACCES);
314 		/* Allocate new SP entry. */
315 		newsp = key_msg2sp(xpl, len, &error);
316 		if (newsp == NULL)
317 			return (error);
318 		newsp->state = IPSEC_SPSTATE_PCB;
319 		newsp->spidx.ul_proto = IPSEC_ULPROTO_ANY;
320 #ifdef INET
321 		if (inp->inp_vflag & INP_IPV4) {
322 			newsp->spidx.src.sin.sin_family =
323 			    newsp->spidx.dst.sin.sin_family = AF_INET;
324 			newsp->spidx.src.sin.sin_len =
325 			    newsp->spidx.dst.sin.sin_len =
326 			    sizeof(struct sockaddr_in);
327 		}
328 #endif
329 #ifdef INET6
330 		if (inp->inp_vflag & INP_IPV6) {
331 			newsp->spidx.src.sin6.sin6_family =
332 			    newsp->spidx.dst.sin6.sin6_family = AF_INET6;
333 			newsp->spidx.src.sin6.sin6_len =
334 			    newsp->spidx.dst.sin6.sin6_len =
335 			    sizeof(struct sockaddr_in6);
336 		}
337 #endif
338 		break;
339 	case IPSEC_POLICY_ENTRUST:
340 		/* We just use NULL pointer for ENTRUST policy */
341 		newsp = NULL;
342 		break;
343 	default:
344 		/* Other security policy types aren't allowed for PCB */
345 		return (EINVAL);
346 	}
347 
348 	INP_WLOCK(inp);
349 	if (xpl->sadb_x_policy_dir == IPSEC_DIR_INBOUND) {
350 		spp = &inp->inp_sp->sp_in;
351 		flags = INP_INBOUND_POLICY;
352 	} else {
353 		spp = &inp->inp_sp->sp_out;
354 		flags = INP_OUTBOUND_POLICY;
355 	}
356 	/* Clear old SP and set new SP. */
357 	if (*spp != NULL) {
358 		ipsec_accel_spddel(*spp);
359 		key_freesp(spp);
360 	}
361 	*spp = newsp;
362 	KEYDBG(IPSEC_DUMP,
363 	    printf("%s: new SP(%p)\n", __func__, newsp));
364 	if (newsp == NULL)
365 		inp->inp_sp->flags &= ~flags;
366 	else {
367 		inp->inp_sp->flags |= flags;
368 		ipsec_accel_spdadd(newsp, inp);
369 		KEYDBG(IPSEC_DUMP, kdebug_secpolicy(newsp));
370 	}
371 	INP_WUNLOCK(inp);
372 	return (0);
373 }
374 
375 static int
376 ipsec_get_pcbpolicy(struct inpcb *inp, void *request, size_t *len)
377 {
378 	struct sadb_x_policy *xpl;
379 	struct secpolicy *sp;
380 	int error, flags;
381 
382 	xpl = (struct sadb_x_policy *)request;
383 
384 	INP_RLOCK(inp);
385 	flags = inp->inp_sp->flags;
386 	/* Select direction. */
387 	switch (xpl->sadb_x_policy_dir) {
388 	case IPSEC_DIR_INBOUND:
389 		sp = inp->inp_sp->sp_in;
390 		flags &= INP_INBOUND_POLICY;
391 		break;
392 	case IPSEC_DIR_OUTBOUND:
393 		sp = inp->inp_sp->sp_out;
394 		flags &= INP_OUTBOUND_POLICY;
395 		break;
396 	default:
397 		INP_RUNLOCK(inp);
398 		ipseclog((LOG_ERR, "%s: invalid direction=%u\n", __func__,
399 			xpl->sadb_x_policy_dir));
400 		return (EINVAL);
401 	}
402 
403 	if (flags == 0) {
404 		/* Return ENTRUST policy */
405 		INP_RUNLOCK(inp);
406 		xpl->sadb_x_policy_exttype = SADB_X_EXT_POLICY;
407 		xpl->sadb_x_policy_type = IPSEC_POLICY_ENTRUST;
408 		xpl->sadb_x_policy_id = 0;
409 		xpl->sadb_x_policy_priority = 0;
410 		xpl->sadb_x_policy_len = PFKEY_UNIT64(sizeof(*xpl));
411 		*len = sizeof(*xpl);
412 		return (0);
413 	}
414 
415 	IPSEC_ASSERT(sp != NULL,
416 	    ("sp is NULL, but flags is 0x%04x", inp->inp_sp->flags));
417 
418 	key_addref(sp);
419 	INP_RUNLOCK(inp);
420 	error = key_sp2msg(sp, request, len);
421 	key_freesp(&sp);
422 	if (error == EINVAL)
423 		return (error);
424 	/*
425 	 * We return "success", but user should check *len.
426 	 * *len will be set to size of valid data and
427 	 * sadb_x_policy_len will contain needed size.
428 	 */
429 	return (0);
430 }
431 
432 /* Handle socket option control request for PCB */
433 static int
434 ipsec_control_pcbpolicy(struct inpcb *inp, struct sockopt *sopt)
435 {
436 	void *optdata;
437 	size_t optlen;
438 	int error;
439 
440 	if (inp->inp_sp == NULL)
441 		return (ENOPROTOOPT);
442 
443 	/* Limit maximum request size to PAGE_SIZE */
444 	optlen = sopt->sopt_valsize;
445 	if (optlen < sizeof(struct sadb_x_policy) || optlen > PAGE_SIZE)
446 		return (EINVAL);
447 
448 	optdata = malloc(optlen, M_TEMP, sopt->sopt_td ? M_WAITOK: M_NOWAIT);
449 	if (optdata == NULL)
450 		return (ENOBUFS);
451 	/*
452 	 * We need a hint from the user, what policy is requested - input
453 	 * or output? User should specify it in the buffer, even for
454 	 * setsockopt().
455 	 */
456 	error = sooptcopyin(sopt, optdata, optlen, optlen);
457 	if (error == 0) {
458 		if (sopt->sopt_dir == SOPT_SET)
459 			error = ipsec_set_pcbpolicy(inp,
460 			    sopt->sopt_td ? sopt->sopt_td->td_ucred: NULL,
461 			    optdata, optlen);
462 		else {
463 			error = ipsec_get_pcbpolicy(inp, optdata, &optlen);
464 			if (error == 0)
465 				error = sooptcopyout(sopt, optdata, optlen);
466 		}
467 	}
468 	free(optdata, M_TEMP);
469 	return (error);
470 }
471 
472 #ifdef INET
473 /*
474  * IPSEC_PCBCTL() method implementation for IPv4.
475  */
476 int
477 ipsec4_pcbctl(struct inpcb *inp, struct sockopt *sopt)
478 {
479 
480 	if (sopt->sopt_name != IP_IPSEC_POLICY)
481 		return (ENOPROTOOPT);
482 	return (ipsec_control_pcbpolicy(inp, sopt));
483 }
484 #endif
485 
486 #ifdef INET6
487 /*
488  * IPSEC_PCBCTL() method implementation for IPv6.
489  */
490 int
491 ipsec6_pcbctl(struct inpcb *inp, struct sockopt *sopt)
492 {
493 
494 	if (sopt->sopt_name != IPV6_IPSEC_POLICY)
495 		return (ENOPROTOOPT);
496 	return (ipsec_control_pcbpolicy(inp, sopt));
497 }
498 #endif
499