1 /* $OpenBSD: pfkey.c,v 1.10 2016/05/23 19:11:42 renato Exp $ */ 2 3 /* 4 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> 5 * Copyright (c) 2003, 2004 Markus Friedl <markus@openbsd.org> 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 #include <sys/types.h> 21 #include <errno.h> 22 #include <stdlib.h> 23 #include <string.h> 24 #include <unistd.h> 25 26 #include "ldpd.h" 27 #include "ldpe.h" 28 #include "log.h" 29 30 static int pfkey_send(int, uint8_t, uint8_t, uint8_t, 31 int, union ldpd_addr *, union ldpd_addr *, 32 uint32_t, uint8_t, int, char *, uint8_t, int, char *, 33 uint16_t, uint16_t); 34 static int pfkey_reply(int, uint32_t *); 35 static int pfkey_sa_add(int, union ldpd_addr *, union ldpd_addr *, 36 uint8_t, char *, uint32_t *); 37 static int pfkey_sa_remove(int, union ldpd_addr *, union ldpd_addr *, 38 uint32_t *); 39 static int pfkey_md5sig_establish(struct nbr *, struct nbr_params *nbrp); 40 static int pfkey_md5sig_remove(struct nbr *); 41 42 #define PFKEY2_CHUNK sizeof(uint64_t) 43 #define ROUNDUP(x) (((x) + (PFKEY2_CHUNK - 1)) & ~(PFKEY2_CHUNK - 1)) 44 #define IOV_CNT 20 45 46 static uint32_t sadb_msg_seq; 47 static uint32_t pid; /* should pid_t but pfkey needs uint32_t */ 48 static int fd; 49 50 static int 51 pfkey_send(int sd, uint8_t satype, uint8_t mtype, uint8_t dir, 52 int af, union ldpd_addr *src, union ldpd_addr *dst, uint32_t spi, 53 uint8_t aalg, int alen, char *akey, uint8_t ealg, int elen, char *ekey, 54 uint16_t sport, uint16_t dport) 55 { 56 struct sadb_msg smsg; 57 struct sadb_sa sa; 58 struct sadb_address sa_src, sa_dst; 59 struct sadb_key sa_akey, sa_ekey; 60 struct sadb_spirange sa_spirange; 61 struct iovec iov[IOV_CNT]; 62 ssize_t n; 63 int len = 0; 64 int iov_cnt; 65 struct sockaddr_storage ssrc, sdst, smask, dmask; 66 struct sockaddr *saptr; 67 68 if (!pid) 69 pid = getpid(); 70 71 /* we need clean sockaddr... no ports set */ 72 memset(&ssrc, 0, sizeof(ssrc)); 73 memset(&smask, 0, sizeof(smask)); 74 if ((saptr = addr2sa(af, src, 0))) 75 memcpy(&ssrc, saptr, sizeof(ssrc)); 76 switch (af) { 77 case AF_INET: 78 memset(&((struct sockaddr_in *)&smask)->sin_addr, 0xff, 32/8); 79 break; 80 case AF_INET6: 81 memset(&((struct sockaddr_in6 *)&smask)->sin6_addr, 0xff, 82 128/8); 83 break; 84 default: 85 return (-1); 86 } 87 smask.ss_family = ssrc.ss_family; 88 smask.ss_len = ssrc.ss_len; 89 90 memset(&sdst, 0, sizeof(sdst)); 91 memset(&dmask, 0, sizeof(dmask)); 92 if ((saptr = addr2sa(af, dst, 0))) 93 memcpy(&sdst, saptr, sizeof(sdst)); 94 switch (af) { 95 case AF_INET: 96 memset(&((struct sockaddr_in *)&dmask)->sin_addr, 0xff, 32/8); 97 break; 98 case AF_INET6: 99 memset(&((struct sockaddr_in6 *)&dmask)->sin6_addr, 0xff, 100 128/8); 101 break; 102 default: 103 return (-1); 104 } 105 dmask.ss_family = sdst.ss_family; 106 dmask.ss_len = sdst.ss_len; 107 108 memset(&smsg, 0, sizeof(smsg)); 109 smsg.sadb_msg_version = PF_KEY_V2; 110 smsg.sadb_msg_seq = ++sadb_msg_seq; 111 smsg.sadb_msg_pid = pid; 112 smsg.sadb_msg_len = sizeof(smsg) / 8; 113 smsg.sadb_msg_type = mtype; 114 smsg.sadb_msg_satype = satype; 115 116 switch (mtype) { 117 case SADB_GETSPI: 118 memset(&sa_spirange, 0, sizeof(sa_spirange)); 119 sa_spirange.sadb_spirange_exttype = SADB_EXT_SPIRANGE; 120 sa_spirange.sadb_spirange_len = sizeof(sa_spirange) / 8; 121 sa_spirange.sadb_spirange_min = 0x100; 122 sa_spirange.sadb_spirange_max = 0xffffffff; 123 sa_spirange.sadb_spirange_reserved = 0; 124 break; 125 case SADB_ADD: 126 case SADB_UPDATE: 127 case SADB_DELETE: 128 memset(&sa, 0, sizeof(sa)); 129 sa.sadb_sa_exttype = SADB_EXT_SA; 130 sa.sadb_sa_len = sizeof(sa) / 8; 131 sa.sadb_sa_replay = 0; 132 sa.sadb_sa_spi = spi; 133 sa.sadb_sa_state = SADB_SASTATE_MATURE; 134 break; 135 } 136 137 memset(&sa_src, 0, sizeof(sa_src)); 138 sa_src.sadb_address_exttype = SADB_EXT_ADDRESS_SRC; 139 sa_src.sadb_address_len = (sizeof(sa_src) + ROUNDUP(ssrc.ss_len)) / 8; 140 141 memset(&sa_dst, 0, sizeof(sa_dst)); 142 sa_dst.sadb_address_exttype = SADB_EXT_ADDRESS_DST; 143 sa_dst.sadb_address_len = (sizeof(sa_dst) + ROUNDUP(sdst.ss_len)) / 8; 144 145 sa.sadb_sa_auth = aalg; 146 sa.sadb_sa_encrypt = SADB_X_EALG_AES; /* XXX */ 147 148 switch (mtype) { 149 case SADB_ADD: 150 case SADB_UPDATE: 151 memset(&sa_akey, 0, sizeof(sa_akey)); 152 sa_akey.sadb_key_exttype = SADB_EXT_KEY_AUTH; 153 sa_akey.sadb_key_len = (sizeof(sa_akey) + 154 ((alen + 7) / 8) * 8) / 8; 155 sa_akey.sadb_key_bits = 8 * alen; 156 157 memset(&sa_ekey, 0, sizeof(sa_ekey)); 158 sa_ekey.sadb_key_exttype = SADB_EXT_KEY_ENCRYPT; 159 sa_ekey.sadb_key_len = (sizeof(sa_ekey) + 160 ((elen + 7) / 8) * 8) / 8; 161 sa_ekey.sadb_key_bits = 8 * elen; 162 163 break; 164 } 165 166 iov_cnt = 0; 167 168 /* msghdr */ 169 iov[iov_cnt].iov_base = &smsg; 170 iov[iov_cnt].iov_len = sizeof(smsg); 171 iov_cnt++; 172 173 switch (mtype) { 174 case SADB_ADD: 175 case SADB_UPDATE: 176 case SADB_DELETE: 177 /* SA hdr */ 178 iov[iov_cnt].iov_base = &sa; 179 iov[iov_cnt].iov_len = sizeof(sa); 180 smsg.sadb_msg_len += sa.sadb_sa_len; 181 iov_cnt++; 182 break; 183 case SADB_GETSPI: 184 /* SPI range */ 185 iov[iov_cnt].iov_base = &sa_spirange; 186 iov[iov_cnt].iov_len = sizeof(sa_spirange); 187 smsg.sadb_msg_len += sa_spirange.sadb_spirange_len; 188 iov_cnt++; 189 break; 190 } 191 192 /* dest addr */ 193 iov[iov_cnt].iov_base = &sa_dst; 194 iov[iov_cnt].iov_len = sizeof(sa_dst); 195 iov_cnt++; 196 iov[iov_cnt].iov_base = &sdst; 197 iov[iov_cnt].iov_len = ROUNDUP(sdst.ss_len); 198 smsg.sadb_msg_len += sa_dst.sadb_address_len; 199 iov_cnt++; 200 201 /* src addr */ 202 iov[iov_cnt].iov_base = &sa_src; 203 iov[iov_cnt].iov_len = sizeof(sa_src); 204 iov_cnt++; 205 iov[iov_cnt].iov_base = &ssrc; 206 iov[iov_cnt].iov_len = ROUNDUP(ssrc.ss_len); 207 smsg.sadb_msg_len += sa_src.sadb_address_len; 208 iov_cnt++; 209 210 switch (mtype) { 211 case SADB_ADD: 212 case SADB_UPDATE: 213 if (alen) { 214 /* auth key */ 215 iov[iov_cnt].iov_base = &sa_akey; 216 iov[iov_cnt].iov_len = sizeof(sa_akey); 217 iov_cnt++; 218 iov[iov_cnt].iov_base = akey; 219 iov[iov_cnt].iov_len = ((alen + 7) / 8) * 8; 220 smsg.sadb_msg_len += sa_akey.sadb_key_len; 221 iov_cnt++; 222 } 223 if (elen) { 224 /* encryption key */ 225 iov[iov_cnt].iov_base = &sa_ekey; 226 iov[iov_cnt].iov_len = sizeof(sa_ekey); 227 iov_cnt++; 228 iov[iov_cnt].iov_base = ekey; 229 iov[iov_cnt].iov_len = ((elen + 7) / 8) * 8; 230 smsg.sadb_msg_len += sa_ekey.sadb_key_len; 231 iov_cnt++; 232 } 233 break; 234 } 235 236 len = smsg.sadb_msg_len * 8; 237 do { 238 n = writev(sd, iov, iov_cnt); 239 } while (n == -1 && (errno == EAGAIN || errno == EINTR)); 240 241 if (n == -1) { 242 log_warn("writev (%d/%d)", iov_cnt, len); 243 return (-1); 244 } 245 246 return (0); 247 } 248 249 int 250 pfkey_read(int sd, struct sadb_msg *h) 251 { 252 struct sadb_msg hdr; 253 254 if (recv(sd, &hdr, sizeof(hdr), MSG_PEEK) != sizeof(hdr)) { 255 if (errno == EAGAIN || errno == EINTR) 256 return (0); 257 log_warn("pfkey peek"); 258 return (-1); 259 } 260 261 /* XXX: Only one message can be outstanding. */ 262 if (hdr.sadb_msg_seq == sadb_msg_seq && 263 hdr.sadb_msg_pid == pid) { 264 if (h) 265 *h = hdr; 266 return (0); 267 } 268 269 /* not ours, discard */ 270 if (read(sd, &hdr, sizeof(hdr)) == -1) { 271 if (errno == EAGAIN || errno == EINTR) 272 return (0); 273 log_warn("pfkey read"); 274 return (-1); 275 } 276 277 return (1); 278 } 279 280 static int 281 pfkey_reply(int sd, uint32_t *spip) 282 { 283 struct sadb_msg hdr, *msg; 284 struct sadb_ext *ext; 285 struct sadb_sa *sa; 286 uint8_t *data; 287 ssize_t len; 288 int rv; 289 290 do { 291 rv = pfkey_read(sd, &hdr); 292 if (rv == -1) 293 return (-1); 294 } while (rv); 295 296 if (hdr.sadb_msg_errno != 0) { 297 errno = hdr.sadb_msg_errno; 298 if (errno == ESRCH) 299 return (0); 300 else { 301 log_warn("pfkey"); 302 return (-1); 303 } 304 } 305 if ((data = reallocarray(NULL, hdr.sadb_msg_len, PFKEY2_CHUNK)) == NULL) { 306 log_warn("pfkey malloc"); 307 return (-1); 308 } 309 len = hdr.sadb_msg_len * PFKEY2_CHUNK; 310 if (read(sd, data, len) != len) { 311 log_warn("pfkey read"); 312 explicit_bzero(data, len); 313 free(data); 314 return (-1); 315 } 316 317 if (hdr.sadb_msg_type == SADB_GETSPI) { 318 if (spip == NULL) { 319 explicit_bzero(data, len); 320 free(data); 321 return (0); 322 } 323 324 msg = (struct sadb_msg *)data; 325 for (ext = (struct sadb_ext *)(msg + 1); 326 (size_t)((uint8_t *)ext - (uint8_t *)msg) < 327 msg->sadb_msg_len * PFKEY2_CHUNK; 328 ext = (struct sadb_ext *)((uint8_t *)ext + 329 ext->sadb_ext_len * PFKEY2_CHUNK)) { 330 if (ext->sadb_ext_type == SADB_EXT_SA) { 331 sa = (struct sadb_sa *) ext; 332 *spip = sa->sadb_sa_spi; 333 break; 334 } 335 } 336 } 337 explicit_bzero(data, len); 338 free(data); 339 return (0); 340 } 341 342 static int 343 pfkey_sa_add(int af, union ldpd_addr *src, union ldpd_addr *dst, uint8_t keylen, 344 char *key, uint32_t *spi) 345 { 346 if (pfkey_send(fd, SADB_X_SATYPE_TCPSIGNATURE, SADB_GETSPI, 0, 347 af, src, dst, 0, 0, 0, NULL, 0, 0, NULL, 0, 0) < 0) 348 return (-1); 349 if (pfkey_reply(fd, spi) < 0) 350 return (-1); 351 if (pfkey_send(fd, SADB_X_SATYPE_TCPSIGNATURE, SADB_UPDATE, 0, 352 af, src, dst, *spi, 0, keylen, key, 0, 0, NULL, 0, 0) < 0) 353 return (-1); 354 if (pfkey_reply(fd, NULL) < 0) 355 return (-1); 356 return (0); 357 } 358 359 static int 360 pfkey_sa_remove(int af, union ldpd_addr *src, union ldpd_addr *dst, 361 uint32_t *spi) 362 { 363 if (pfkey_send(fd, SADB_X_SATYPE_TCPSIGNATURE, SADB_DELETE, 0, 364 af, src, dst, *spi, 0, 0, NULL, 0, 0, NULL, 0, 0) < 0) 365 return (-1); 366 if (pfkey_reply(fd, NULL) < 0) 367 return (-1); 368 *spi = 0; 369 return (0); 370 } 371 372 static int 373 pfkey_md5sig_establish(struct nbr *nbr, struct nbr_params *nbrp) 374 { 375 sleep(1); 376 377 if (!nbr->auth.spi_out) 378 if (pfkey_sa_add(nbr->af, &nbr->laddr, &nbr->raddr, 379 nbrp->auth.md5key_len, nbrp->auth.md5key, 380 &nbr->auth.spi_out) == -1) 381 return (-1); 382 if (!nbr->auth.spi_in) 383 if (pfkey_sa_add(nbr->af, &nbr->raddr, &nbr->laddr, 384 nbrp->auth.md5key_len, nbrp->auth.md5key, 385 &nbr->auth.spi_in) == -1) 386 return (-1); 387 388 nbr->auth.established = 1; 389 return (0); 390 } 391 392 static int 393 pfkey_md5sig_remove(struct nbr *nbr) 394 { 395 if (nbr->auth.spi_out) 396 if (pfkey_sa_remove(nbr->af, &nbr->laddr, &nbr->raddr, 397 &nbr->auth.spi_out) == -1) 398 return (-1); 399 if (nbr->auth.spi_in) 400 if (pfkey_sa_remove(nbr->af, &nbr->raddr, &nbr->laddr, 401 &nbr->auth.spi_in) == -1) 402 return (-1); 403 404 nbr->auth.established = 0; 405 nbr->auth.spi_in = 0; 406 nbr->auth.spi_out = 0; 407 nbr->auth.method = AUTH_NONE; 408 memset(nbr->auth.md5key, 0, sizeof(nbr->auth.md5key)); 409 410 return (0); 411 } 412 413 int 414 pfkey_establish(struct nbr *nbr, struct nbr_params *nbrp) 415 { 416 if (nbrp->auth.method == AUTH_NONE) 417 return (0); 418 419 /* 420 * make sure we keep copies of everything we need to 421 * remove SAs and flows later again. 422 */ 423 nbr->auth.method = nbrp->auth.method; 424 425 switch (nbr->auth.method) { 426 case AUTH_MD5SIG: 427 strlcpy(nbr->auth.md5key, nbrp->auth.md5key, 428 sizeof(nbr->auth.md5key)); 429 return (pfkey_md5sig_establish(nbr, nbrp)); 430 default: 431 break; 432 } 433 434 return (0); 435 } 436 437 int 438 pfkey_remove(struct nbr *nbr) 439 { 440 if (nbr->auth.method == AUTH_NONE || !nbr->auth.established) 441 return (0); 442 443 switch (nbr->auth.method) { 444 case AUTH_MD5SIG: 445 return (pfkey_md5sig_remove(nbr)); 446 default: 447 break; 448 } 449 450 return (0); 451 } 452 453 int 454 pfkey_init(void) 455 { 456 if ((fd = socket(PF_KEY, SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK, 457 PF_KEY_V2)) == -1) { 458 if (errno == EPROTONOSUPPORT) { 459 log_warnx("PF_KEY not available"); 460 sysdep.no_pfkey = 1; 461 return (-1); 462 } else 463 fatal("pfkey setup failed"); 464 } 465 return (fd); 466 } 467