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