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 53 MALLOC_DEFINE(M_IPSEC_INPCB, "inpcbpolicy", "inpcb-resident ipsec policy"); 54 55 static void 56 ipsec_setsockaddrs_inpcb(struct inpcb *inp, union sockaddr_union *src, 57 union sockaddr_union *dst, u_int dir) 58 { 59 60 #ifdef INET6 61 if (inp->inp_vflag & INP_IPV6) { 62 struct sockaddr_in6 *sin6; 63 64 bzero(&src->sin6, sizeof(src->sin6)); 65 bzero(&dst->sin6, sizeof(dst->sin6)); 66 src->sin6.sin6_family = AF_INET6; 67 src->sin6.sin6_len = sizeof(struct sockaddr_in6); 68 dst->sin6.sin6_family = AF_INET6; 69 dst->sin6.sin6_len = sizeof(struct sockaddr_in6); 70 71 if (dir == IPSEC_DIR_OUTBOUND) 72 sin6 = &src->sin6; 73 else 74 sin6 = &dst->sin6; 75 sin6->sin6_addr = inp->in6p_laddr; 76 sin6->sin6_port = inp->inp_lport; 77 if (IN6_IS_SCOPE_LINKLOCAL(&inp->in6p_laddr)) { 78 /* XXXAE: use in6p_zoneid */ 79 sin6->sin6_addr.s6_addr16[1] = 0; 80 sin6->sin6_scope_id = ntohs( 81 inp->in6p_laddr.s6_addr16[1]); 82 } 83 84 if (dir == IPSEC_DIR_OUTBOUND) 85 sin6 = &dst->sin6; 86 else 87 sin6 = &src->sin6; 88 sin6->sin6_addr = inp->in6p_faddr; 89 sin6->sin6_port = inp->inp_fport; 90 if (IN6_IS_SCOPE_LINKLOCAL(&inp->in6p_faddr)) { 91 /* XXXAE: use in6p_zoneid */ 92 sin6->sin6_addr.s6_addr16[1] = 0; 93 sin6->sin6_scope_id = ntohs( 94 inp->in6p_faddr.s6_addr16[1]); 95 } 96 } 97 #endif 98 #ifdef INET 99 if (inp->inp_vflag & INP_IPV4) { 100 struct sockaddr_in *sin; 101 102 bzero(&src->sin, sizeof(src->sin)); 103 bzero(&dst->sin, sizeof(dst->sin)); 104 src->sin.sin_family = AF_INET; 105 src->sin.sin_len = sizeof(struct sockaddr_in); 106 dst->sin.sin_family = AF_INET; 107 dst->sin.sin_len = sizeof(struct sockaddr_in); 108 109 if (dir == IPSEC_DIR_OUTBOUND) 110 sin = &src->sin; 111 else 112 sin = &dst->sin; 113 sin->sin_addr = inp->inp_laddr; 114 sin->sin_port = inp->inp_lport; 115 116 if (dir == IPSEC_DIR_OUTBOUND) 117 sin = &dst->sin; 118 else 119 sin = &src->sin; 120 sin->sin_addr = inp->inp_faddr; 121 sin->sin_port = inp->inp_fport; 122 } 123 #endif 124 } 125 126 void 127 ipsec_setspidx_inpcb(struct inpcb *inp, struct secpolicyindex *spidx, 128 u_int dir) 129 { 130 131 ipsec_setsockaddrs_inpcb(inp, &spidx->src, &spidx->dst, dir); 132 #ifdef INET6 133 if (inp->inp_vflag & INP_IPV6) { 134 spidx->prefs = sizeof(struct in6_addr) << 3; 135 spidx->prefd = sizeof(struct in6_addr) << 3; 136 } 137 #endif 138 #ifdef INET 139 if (inp->inp_vflag & INP_IPV4) { 140 spidx->prefs = sizeof(struct in_addr) << 3; 141 spidx->prefd = sizeof(struct in_addr) << 3; 142 } 143 #endif 144 spidx->ul_proto = IPPROTO_TCP; /* XXX: currently only TCP uses this */ 145 spidx->dir = dir; 146 KEYDBG(IPSEC_DUMP, 147 printf("%s: ", __func__); kdebug_secpolicyindex(spidx, NULL)); 148 } 149 150 /* Initialize PCB policy. */ 151 int 152 ipsec_init_pcbpolicy(struct inpcb *inp) 153 { 154 155 IPSEC_ASSERT(inp != NULL, ("null inp")); 156 IPSEC_ASSERT(inp->inp_sp == NULL, ("inp_sp already initialized")); 157 158 inp->inp_sp = malloc(sizeof(struct inpcbpolicy), M_IPSEC_INPCB, 159 M_NOWAIT | M_ZERO); 160 if (inp->inp_sp == NULL) 161 return (ENOBUFS); 162 return (0); 163 } 164 165 /* Delete PCB policy. */ 166 int 167 ipsec_delete_pcbpolicy(struct inpcb *inp) 168 { 169 170 if (inp->inp_sp == NULL) 171 return (0); 172 173 if (inp->inp_sp->sp_in != NULL) 174 key_freesp(&inp->inp_sp->sp_in); 175 176 if (inp->inp_sp->sp_out != NULL) 177 key_freesp(&inp->inp_sp->sp_out); 178 179 free(inp->inp_sp, M_IPSEC_INPCB); 180 inp->inp_sp = NULL; 181 return (0); 182 } 183 184 /* Deep-copy a policy in PCB. */ 185 static struct secpolicy * 186 ipsec_deepcopy_pcbpolicy(struct secpolicy *src) 187 { 188 struct secpolicy *dst; 189 int i; 190 191 if (src == NULL) 192 return (NULL); 193 194 IPSEC_ASSERT(src->state == IPSEC_SPSTATE_PCB, ("SP isn't PCB")); 195 196 dst = key_newsp(); 197 if (dst == NULL) 198 return (NULL); 199 200 /* spidx is not copied here */ 201 dst->policy = src->policy; 202 dst->state = src->state; 203 dst->priority = src->priority; 204 /* Do not touch the refcnt field. */ 205 206 /* Copy IPsec request chain. */ 207 for (i = 0; i < src->tcount; i++) { 208 dst->req[i] = ipsec_newisr(); 209 if (dst->req[i] == NULL) { 210 key_freesp(&dst); 211 return (NULL); 212 } 213 bcopy(src->req[i], dst->req[i], sizeof(struct ipsecrequest)); 214 dst->tcount++; 215 } 216 KEYDBG(IPSEC_DUMP, 217 printf("%s: copied SP(%p) -> SP(%p)\n", __func__, src, dst); 218 kdebug_secpolicy(dst)); 219 return (dst); 220 } 221 222 /* 223 * Copy IPsec policy from old INPCB into new. 224 * It is expected that new INPCB has not configured policies. 225 */ 226 int 227 ipsec_copy_pcbpolicy(struct inpcb *old, struct inpcb *new) 228 { 229 struct secpolicy *sp; 230 231 /* 232 * old->inp_sp can be NULL if PCB was created when an IPsec 233 * support was unavailable. This is not an error, we don't have 234 * policies in this PCB, so nothing to copy. 235 */ 236 if (old->inp_sp == NULL) 237 return (0); 238 239 IPSEC_ASSERT(new->inp_sp != NULL, ("new inp_sp is NULL")); 240 IPSEC_ASSERT((new->inp_sp->flags & ( 241 INP_INBOUND_POLICY | INP_OUTBOUND_POLICY)) == 0, 242 ("new PCB already has configured policies")); 243 INP_WLOCK_ASSERT(new); 244 INP_LOCK_ASSERT(old); 245 246 if (old->inp_sp->flags & INP_INBOUND_POLICY) { 247 sp = ipsec_deepcopy_pcbpolicy(old->inp_sp->sp_in); 248 if (sp == NULL) 249 return (ENOBUFS); 250 ipsec_setspidx_inpcb(new, &sp->spidx, IPSEC_DIR_INBOUND); 251 if (new->inp_sp->sp_in != NULL) 252 key_freesp(&new->inp_sp->sp_in); 253 new->inp_sp->sp_in = sp; 254 new->inp_sp->flags |= INP_INBOUND_POLICY; 255 } 256 if (old->inp_sp->flags & INP_OUTBOUND_POLICY) { 257 sp = ipsec_deepcopy_pcbpolicy(old->inp_sp->sp_out); 258 if (sp == NULL) 259 return (ENOBUFS); 260 ipsec_setspidx_inpcb(new, &sp->spidx, IPSEC_DIR_OUTBOUND); 261 if (new->inp_sp->sp_out != NULL) 262 key_freesp(&new->inp_sp->sp_out); 263 new->inp_sp->sp_out = sp; 264 new->inp_sp->flags |= INP_OUTBOUND_POLICY; 265 } 266 return (0); 267 } 268 269 static int 270 ipsec_set_pcbpolicy(struct inpcb *inp, struct ucred *cred, 271 void *request, size_t len) 272 { 273 struct sadb_x_policy *xpl; 274 struct secpolicy **spp, *newsp; 275 int error, flags; 276 277 xpl = (struct sadb_x_policy *)request; 278 /* Select direction. */ 279 switch (xpl->sadb_x_policy_dir) { 280 case IPSEC_DIR_INBOUND: 281 case IPSEC_DIR_OUTBOUND: 282 break; 283 default: 284 ipseclog((LOG_ERR, "%s: invalid direction=%u\n", __func__, 285 xpl->sadb_x_policy_dir)); 286 return (EINVAL); 287 } 288 /* 289 * Privileged sockets are allowed to set own security policy 290 * and configure IPsec bypass. Unprivileged sockets only can 291 * have ENTRUST policy. 292 */ 293 switch (xpl->sadb_x_policy_type) { 294 case IPSEC_POLICY_IPSEC: 295 case IPSEC_POLICY_BYPASS: 296 if (cred != NULL && 297 priv_check_cred(cred, PRIV_NETINET_IPSEC) != 0) 298 return (EACCES); 299 /* Allocate new SP entry. */ 300 newsp = key_msg2sp(xpl, len, &error); 301 if (newsp == NULL) 302 return (error); 303 newsp->state = IPSEC_SPSTATE_PCB; 304 newsp->spidx.ul_proto = IPSEC_ULPROTO_ANY; 305 #ifdef INET 306 if (inp->inp_vflag & INP_IPV4) { 307 newsp->spidx.src.sin.sin_family = 308 newsp->spidx.dst.sin.sin_family = AF_INET; 309 newsp->spidx.src.sin.sin_len = 310 newsp->spidx.dst.sin.sin_len = 311 sizeof(struct sockaddr_in); 312 } 313 #endif 314 #ifdef INET6 315 if (inp->inp_vflag & INP_IPV6) { 316 newsp->spidx.src.sin6.sin6_family = 317 newsp->spidx.dst.sin6.sin6_family = AF_INET6; 318 newsp->spidx.src.sin6.sin6_len = 319 newsp->spidx.dst.sin6.sin6_len = 320 sizeof(struct sockaddr_in6); 321 } 322 #endif 323 break; 324 case IPSEC_POLICY_ENTRUST: 325 /* We just use NULL pointer for ENTRUST policy */ 326 newsp = NULL; 327 break; 328 default: 329 /* Other security policy types aren't allowed for PCB */ 330 return (EINVAL); 331 } 332 333 INP_WLOCK(inp); 334 if (xpl->sadb_x_policy_dir == IPSEC_DIR_INBOUND) { 335 spp = &inp->inp_sp->sp_in; 336 flags = INP_INBOUND_POLICY; 337 } else { 338 spp = &inp->inp_sp->sp_out; 339 flags = INP_OUTBOUND_POLICY; 340 } 341 /* Clear old SP and set new SP. */ 342 if (*spp != NULL) 343 key_freesp(spp); 344 *spp = newsp; 345 KEYDBG(IPSEC_DUMP, 346 printf("%s: new SP(%p)\n", __func__, newsp)); 347 if (newsp == NULL) 348 inp->inp_sp->flags &= ~flags; 349 else { 350 inp->inp_sp->flags |= flags; 351 KEYDBG(IPSEC_DUMP, kdebug_secpolicy(newsp)); 352 } 353 INP_WUNLOCK(inp); 354 return (0); 355 } 356 357 static int 358 ipsec_get_pcbpolicy(struct inpcb *inp, void *request, size_t *len) 359 { 360 struct sadb_x_policy *xpl; 361 struct secpolicy *sp; 362 int error, flags; 363 364 xpl = (struct sadb_x_policy *)request; 365 366 INP_RLOCK(inp); 367 flags = inp->inp_sp->flags; 368 /* Select direction. */ 369 switch (xpl->sadb_x_policy_dir) { 370 case IPSEC_DIR_INBOUND: 371 sp = inp->inp_sp->sp_in; 372 flags &= INP_INBOUND_POLICY; 373 break; 374 case IPSEC_DIR_OUTBOUND: 375 sp = inp->inp_sp->sp_out; 376 flags &= INP_OUTBOUND_POLICY; 377 break; 378 default: 379 INP_RUNLOCK(inp); 380 ipseclog((LOG_ERR, "%s: invalid direction=%u\n", __func__, 381 xpl->sadb_x_policy_dir)); 382 return (EINVAL); 383 } 384 385 if (flags == 0) { 386 /* Return ENTRUST policy */ 387 INP_RUNLOCK(inp); 388 xpl->sadb_x_policy_exttype = SADB_X_EXT_POLICY; 389 xpl->sadb_x_policy_type = IPSEC_POLICY_ENTRUST; 390 xpl->sadb_x_policy_id = 0; 391 xpl->sadb_x_policy_priority = 0; 392 xpl->sadb_x_policy_len = PFKEY_UNIT64(sizeof(*xpl)); 393 *len = sizeof(*xpl); 394 return (0); 395 } 396 397 IPSEC_ASSERT(sp != NULL, 398 ("sp is NULL, but flags is 0x%04x", inp->inp_sp->flags)); 399 400 key_addref(sp); 401 INP_RUNLOCK(inp); 402 error = key_sp2msg(sp, request, len); 403 key_freesp(&sp); 404 if (error == EINVAL) 405 return (error); 406 /* 407 * We return "success", but user should check *len. 408 * *len will be set to size of valid data and 409 * sadb_x_policy_len will contain needed size. 410 */ 411 return (0); 412 } 413 414 /* Handle socket option control request for PCB */ 415 static int 416 ipsec_control_pcbpolicy(struct inpcb *inp, struct sockopt *sopt) 417 { 418 void *optdata; 419 size_t optlen; 420 int error; 421 422 if (inp->inp_sp == NULL) 423 return (ENOPROTOOPT); 424 425 /* Limit maximum request size to PAGE_SIZE */ 426 optlen = sopt->sopt_valsize; 427 if (optlen < sizeof(struct sadb_x_policy) || optlen > PAGE_SIZE) 428 return (EINVAL); 429 430 optdata = malloc(optlen, M_TEMP, sopt->sopt_td ? M_WAITOK: M_NOWAIT); 431 if (optdata == NULL) 432 return (ENOBUFS); 433 /* 434 * We need a hint from the user, what policy is requested - input 435 * or output? User should specify it in the buffer, even for 436 * setsockopt(). 437 */ 438 error = sooptcopyin(sopt, optdata, optlen, optlen); 439 if (error == 0) { 440 if (sopt->sopt_dir == SOPT_SET) 441 error = ipsec_set_pcbpolicy(inp, 442 sopt->sopt_td ? sopt->sopt_td->td_ucred: NULL, 443 optdata, optlen); 444 else { 445 error = ipsec_get_pcbpolicy(inp, optdata, &optlen); 446 if (error == 0) 447 error = sooptcopyout(sopt, optdata, optlen); 448 } 449 } 450 free(optdata, M_TEMP); 451 return (error); 452 } 453 454 #ifdef INET 455 /* 456 * IPSEC_PCBCTL() method implementation for IPv4. 457 */ 458 int 459 ipsec4_pcbctl(struct inpcb *inp, struct sockopt *sopt) 460 { 461 462 if (sopt->sopt_name != IP_IPSEC_POLICY) 463 return (ENOPROTOOPT); 464 return (ipsec_control_pcbpolicy(inp, sopt)); 465 } 466 #endif 467 468 #ifdef INET6 469 /* 470 * IPSEC_PCBCTL() method implementation for IPv6. 471 */ 472 int 473 ipsec6_pcbctl(struct inpcb *inp, struct sockopt *sopt) 474 { 475 476 if (sopt->sopt_name != IPV6_IPSEC_POLICY) 477 return (ENOPROTOOPT); 478 return (ipsec_control_pcbpolicy(inp, sopt)); 479 } 480 #endif 481