2 * Copyright (c) 2016 Andrey V. Elsukov <ae@FreeBSD.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
31 #include "opt_inet6.h"
32 #include "opt_ipsec.h"
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/kernel.h>
38 #include <sys/malloc.h>
41 #include <sys/socket.h>
42 #include <sys/sockopt.h>
43 #include <sys/syslog.h>
46 #include <netinet/in.h>
47 #include <netinet/in_pcb.h>
49 #include <netipsec/ipsec.h>
50 #include <netipsec/ipsec6.h>
51 #include <netipsec/ipsec_support.h>
52 #include <netipsec/key.h>
53 #include <netipsec/key_debug.h>
55 MALLOC_DEFINE(M_IPSEC_INPCB, "inpcbpolicy", "inpcb-resident ipsec policy");
58 ipsec_setsockaddrs_inpcb(struct inpcb *inp, union sockaddr_union *src,
59 union sockaddr_union *dst, u_int dir)
63 if (inp->inp_vflag & INP_IPV6) {
64 struct sockaddr_in6 *sin6;
66 bzero(&src->sin6, sizeof(src->sin6));
67 bzero(&dst->sin6, sizeof(dst->sin6));
68 src->sin6.sin6_family = AF_INET6;
69 src->sin6.sin6_len = sizeof(struct sockaddr_in6);
70 dst->sin6.sin6_family = AF_INET6;
71 dst->sin6.sin6_len = sizeof(struct sockaddr_in6);
73 if (dir == IPSEC_DIR_OUTBOUND)
77 sin6->sin6_addr = inp->in6p_laddr;
78 sin6->sin6_port = inp->inp_lport;
79 if (IN6_IS_SCOPE_LINKLOCAL(&inp->in6p_laddr)) {
80 /* XXXAE: use in6p_zoneid */
81 sin6->sin6_addr.s6_addr16[1] = 0;
82 sin6->sin6_scope_id = ntohs(
83 inp->in6p_laddr.s6_addr16[1]);
86 if (dir == IPSEC_DIR_OUTBOUND)
90 sin6->sin6_addr = inp->in6p_faddr;
91 sin6->sin6_port = inp->inp_fport;
92 if (IN6_IS_SCOPE_LINKLOCAL(&inp->in6p_faddr)) {
93 /* XXXAE: use in6p_zoneid */
94 sin6->sin6_addr.s6_addr16[1] = 0;
95 sin6->sin6_scope_id = ntohs(
96 inp->in6p_faddr.s6_addr16[1]);
101 if (inp->inp_vflag & INP_IPV4) {
102 struct sockaddr_in *sin;
104 bzero(&src->sin, sizeof(src->sin));
105 bzero(&dst->sin, sizeof(dst->sin));
106 src->sin.sin_family = AF_INET;
107 src->sin.sin_len = sizeof(struct sockaddr_in);
108 dst->sin.sin_family = AF_INET;
109 dst->sin.sin_len = sizeof(struct sockaddr_in);
111 if (dir == IPSEC_DIR_OUTBOUND)
115 sin->sin_addr = inp->inp_laddr;
116 sin->sin_port = inp->inp_lport;
118 if (dir == IPSEC_DIR_OUTBOUND)
122 sin->sin_addr = inp->inp_faddr;
123 sin->sin_port = inp->inp_fport;
129 ipsec_setspidx_inpcb(struct inpcb *inp, struct secpolicyindex *spidx,
133 ipsec_setsockaddrs_inpcb(inp, &spidx->src, &spidx->dst, dir);
135 if (inp->inp_vflag & INP_IPV6) {
136 spidx->prefs = sizeof(struct in6_addr) << 3;
137 spidx->prefd = sizeof(struct in6_addr) << 3;
141 if (inp->inp_vflag & INP_IPV4) {
142 spidx->prefs = sizeof(struct in_addr) << 3;
143 spidx->prefd = sizeof(struct in_addr) << 3;
146 spidx->ul_proto = IPPROTO_TCP; /* XXX: currently only TCP uses this */
149 printf("%s: ", __func__); kdebug_secpolicyindex(spidx, NULL));
152 /* Initialize PCB policy. */
154 ipsec_init_pcbpolicy(struct inpcb *inp)
157 IPSEC_ASSERT(inp != NULL, ("null inp"));
158 IPSEC_ASSERT(inp->inp_sp == NULL, ("inp_sp already initialized"));
160 inp->inp_sp = malloc(sizeof(struct inpcbpolicy), M_IPSEC_INPCB,
162 if (inp->inp_sp == NULL)
167 /* Delete PCB policy. */
169 ipsec_delete_pcbpolicy(struct inpcb *inp)
172 if (inp->inp_sp == NULL)
175 if (inp->inp_sp->sp_in != NULL)
176 key_freesp(&inp->inp_sp->sp_in);
178 if (inp->inp_sp->sp_out != NULL)
179 key_freesp(&inp->inp_sp->sp_out);
181 free(inp->inp_sp, M_IPSEC_INPCB);
186 /* Deep-copy a policy in PCB. */
187 static struct secpolicy *
188 ipsec_deepcopy_pcbpolicy(struct secpolicy *src)
190 struct secpolicy *dst;
196 IPSEC_ASSERT(src->state == IPSEC_SPSTATE_PCB, ("SP isn't PCB"));
202 /* spidx is not copied here */
203 dst->policy = src->policy;
204 dst->state = src->state;
205 dst->priority = src->priority;
206 /* Do not touch the refcnt field. */
208 /* Copy IPsec request chain. */
209 for (i = 0; i < src->tcount; i++) {
210 dst->req[i] = ipsec_newisr();
211 if (dst->req[i] == NULL) {
215 bcopy(src->req[i], dst->req[i], sizeof(struct ipsecrequest));
219 printf("%s: copied SP(%p) -> SP(%p)\n", __func__, src, dst);
220 kdebug_secpolicy(dst));
225 * Copy IPsec policy from old INPCB into new.
226 * It is expected that new INPCB has not configured policies.
229 ipsec_copy_pcbpolicy(struct inpcb *old, struct inpcb *new)
231 struct secpolicy *sp;
234 * old->inp_sp can be NULL if PCB was created when an IPsec
235 * support was unavailable. This is not an error, we don't have
236 * policies in this PCB, so nothing to copy.
238 if (old->inp_sp == NULL)
241 IPSEC_ASSERT(new->inp_sp != NULL, ("new inp_sp is NULL"));
242 IPSEC_ASSERT((new->inp_sp->flags & (
243 INP_INBOUND_POLICY | INP_OUTBOUND_POLICY)) == 0,
244 ("new PCB already has configured policies"));
245 INP_WLOCK_ASSERT(new);
246 INP_LOCK_ASSERT(old);
248 if (old->inp_sp->flags & INP_INBOUND_POLICY) {
249 sp = ipsec_deepcopy_pcbpolicy(old->inp_sp->sp_in);
252 ipsec_setspidx_inpcb(new, &sp->spidx, IPSEC_DIR_INBOUND);
253 if (new->inp_sp->sp_in != NULL)
254 key_freesp(&new->inp_sp->sp_in);
255 new->inp_sp->sp_in = sp;
256 new->inp_sp->flags |= INP_INBOUND_POLICY;
258 if (old->inp_sp->flags & INP_OUTBOUND_POLICY) {
259 sp = ipsec_deepcopy_pcbpolicy(old->inp_sp->sp_out);
262 ipsec_setspidx_inpcb(new, &sp->spidx, IPSEC_DIR_OUTBOUND);
263 if (new->inp_sp->sp_out != NULL)
264 key_freesp(&new->inp_sp->sp_out);
265 new->inp_sp->sp_out = sp;
266 new->inp_sp->flags |= INP_OUTBOUND_POLICY;
272 ipsec_set_pcbpolicy(struct inpcb *inp, struct ucred *cred,
273 void *request, size_t len)
275 struct sadb_x_policy *xpl;
276 struct secpolicy **spp, *newsp;
279 xpl = (struct sadb_x_policy *)request;
280 /* Select direction. */
281 switch (xpl->sadb_x_policy_dir) {
282 case IPSEC_DIR_INBOUND:
283 case IPSEC_DIR_OUTBOUND:
286 ipseclog((LOG_ERR, "%s: invalid direction=%u\n", __func__,
287 xpl->sadb_x_policy_dir));
291 * Privileged sockets are allowed to set own security policy
292 * and configure IPsec bypass. Unprivileged sockets only can
293 * have ENTRUST policy.
295 switch (xpl->sadb_x_policy_type) {
296 case IPSEC_POLICY_IPSEC:
297 case IPSEC_POLICY_BYPASS:
299 priv_check_cred(cred, PRIV_NETINET_IPSEC, 0) != 0)
301 /* Allocate new SP entry. */
302 newsp = key_msg2sp(xpl, len, &error);
305 newsp->state = IPSEC_SPSTATE_PCB;
306 newsp->spidx.ul_proto = IPSEC_ULPROTO_ANY;
308 if (inp->inp_vflag & INP_IPV4) {
309 newsp->spidx.src.sin.sin_family =
310 newsp->spidx.dst.sin.sin_family = AF_INET;
311 newsp->spidx.src.sin.sin_len =
312 newsp->spidx.dst.sin.sin_len =
313 sizeof(struct sockaddr_in);
317 if (inp->inp_vflag & INP_IPV6) {
318 newsp->spidx.src.sin6.sin6_family =
319 newsp->spidx.dst.sin6.sin6_family = AF_INET6;
320 newsp->spidx.src.sin6.sin6_len =
321 newsp->spidx.dst.sin6.sin6_len =
322 sizeof(struct sockaddr_in6);
326 case IPSEC_POLICY_ENTRUST:
327 /* We just use NULL pointer for ENTRUST policy */
331 /* Other security policy types aren't allowed for PCB */
336 if (xpl->sadb_x_policy_dir == IPSEC_DIR_INBOUND) {
337 spp = &inp->inp_sp->sp_in;
338 flags = INP_INBOUND_POLICY;
340 spp = &inp->inp_sp->sp_out;
341 flags = INP_OUTBOUND_POLICY;
343 /* Clear old SP and set new SP. */
348 printf("%s: new SP(%p)\n", __func__, newsp));
350 inp->inp_sp->flags &= ~flags;
352 inp->inp_sp->flags |= flags;
353 KEYDBG(IPSEC_DUMP, kdebug_secpolicy(newsp));
360 ipsec_get_pcbpolicy(struct inpcb *inp, void *request, size_t *len)
362 struct sadb_x_policy *xpl;
363 struct secpolicy *sp;
366 xpl = (struct sadb_x_policy *)request;
369 flags = inp->inp_sp->flags;
370 /* Select direction. */
371 switch (xpl->sadb_x_policy_dir) {
372 case IPSEC_DIR_INBOUND:
373 sp = inp->inp_sp->sp_in;
374 flags &= INP_INBOUND_POLICY;
376 case IPSEC_DIR_OUTBOUND:
377 sp = inp->inp_sp->sp_out;
378 flags &= INP_OUTBOUND_POLICY;
382 ipseclog((LOG_ERR, "%s: invalid direction=%u\n", __func__,
383 xpl->sadb_x_policy_dir));
388 /* Return ENTRUST policy */
390 xpl->sadb_x_policy_exttype = SADB_X_EXT_POLICY;
391 xpl->sadb_x_policy_type = IPSEC_POLICY_ENTRUST;
392 xpl->sadb_x_policy_id = 0;
393 xpl->sadb_x_policy_priority = 0;
394 xpl->sadb_x_policy_len = PFKEY_UNIT64(sizeof(*xpl));
399 IPSEC_ASSERT(sp != NULL,
400 ("sp is NULL, but flags is 0x%04x", inp->inp_sp->flags));
404 error = key_sp2msg(sp, request, len);
409 * We return "success", but user should check *len.
410 * *len will be set to size of valid data and
411 * sadb_x_policy_len will contain needed size.
416 /* Handle socket option control request for PCB */
418 ipsec_control_pcbpolicy(struct inpcb *inp, struct sockopt *sopt)
424 if (inp->inp_sp == NULL)
425 return (ENOPROTOOPT);
427 /* Limit maximum request size to PAGE_SIZE */
428 optlen = sopt->sopt_valsize;
429 if (optlen < sizeof(struct sadb_x_policy) || optlen > PAGE_SIZE)
432 optdata = malloc(optlen, M_TEMP, sopt->sopt_td ? M_WAITOK: M_NOWAIT);
436 * We need a hint from the user, what policy is requested - input
437 * or output? User should specify it in the buffer, even for
440 error = sooptcopyin(sopt, optdata, optlen, optlen);
442 if (sopt->sopt_dir == SOPT_SET)
443 error = ipsec_set_pcbpolicy(inp,
444 sopt->sopt_td ? sopt->sopt_td->td_ucred: NULL,
447 error = ipsec_get_pcbpolicy(inp, optdata, &optlen);
449 error = sooptcopyout(sopt, optdata, optlen);
452 free(optdata, M_TEMP);
458 * IPSEC_PCBCTL() method implementation for IPv4.
461 ipsec4_pcbctl(struct inpcb *inp, struct sockopt *sopt)
464 if (sopt->sopt_name != IP_IPSEC_POLICY)
465 return (ENOPROTOOPT);
466 return (ipsec_control_pcbpolicy(inp, sopt));
472 * IPSEC_PCBCTL() method implementation for IPv6.
475 ipsec6_pcbctl(struct inpcb *inp, struct sockopt *sopt)
478 if (sopt->sopt_name != IPV6_IPSEC_POLICY)
479 return (ENOPROTOOPT);
480 return (ipsec_control_pcbpolicy(inp, sopt));