1 /* $OpenBSD: pfkey.c,v 1.12 2019/01/23 02:02:04 dlg 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 ldp_auth *); 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 freezero(data, len); 313 return (-1); 314 } 315 316 if (hdr.sadb_msg_type == SADB_GETSPI) { 317 if (spip == NULL) { 318 freezero(data, len); 319 return (0); 320 } 321 322 msg = (struct sadb_msg *)data; 323 for (ext = (struct sadb_ext *)(msg + 1); 324 (size_t)((uint8_t *)ext - (uint8_t *)msg) < 325 msg->sadb_msg_len * PFKEY2_CHUNK; 326 ext = (struct sadb_ext *)((uint8_t *)ext + 327 ext->sadb_ext_len * PFKEY2_CHUNK)) { 328 if (ext->sadb_ext_type == SADB_EXT_SA) { 329 sa = (struct sadb_sa *) ext; 330 *spip = sa->sadb_sa_spi; 331 break; 332 } 333 } 334 } 335 freezero(data, len); 336 return (0); 337 } 338 339 static int 340 pfkey_sa_add(int af, union ldpd_addr *src, union ldpd_addr *dst, uint8_t keylen, 341 char *key, uint32_t *spi) 342 { 343 if (pfkey_send(fd, SADB_X_SATYPE_TCPSIGNATURE, SADB_GETSPI, 0, 344 af, src, dst, 0, 0, 0, NULL, 0, 0, NULL, 0, 0) < 0) 345 return (-1); 346 if (pfkey_reply(fd, spi) < 0) 347 return (-1); 348 if (pfkey_send(fd, SADB_X_SATYPE_TCPSIGNATURE, SADB_UPDATE, 0, 349 af, src, dst, *spi, 0, keylen, key, 0, 0, NULL, 0, 0) < 0) 350 return (-1); 351 if (pfkey_reply(fd, NULL) < 0) 352 return (-1); 353 return (0); 354 } 355 356 static int 357 pfkey_sa_remove(int af, union ldpd_addr *src, union ldpd_addr *dst, 358 uint32_t *spi) 359 { 360 if (pfkey_send(fd, SADB_X_SATYPE_TCPSIGNATURE, SADB_DELETE, 0, 361 af, src, dst, *spi, 0, 0, NULL, 0, 0, NULL, 0, 0) < 0) 362 return (-1); 363 if (pfkey_reply(fd, NULL) < 0) 364 return (-1); 365 *spi = 0; 366 return (0); 367 } 368 369 static int 370 pfkey_md5sig_establish(struct nbr *nbr, struct ldp_auth *auth) 371 { 372 sleep(1); 373 374 pfkey_md5sig_remove(nbr); 375 376 if (pfkey_sa_add(nbr->af, &nbr->laddr, &nbr->raddr, 377 auth->md5key_len, auth->md5key, &nbr->auth_spi_out) == -1) 378 return (-1); 379 380 if (pfkey_sa_add(nbr->af, &nbr->raddr, &nbr->laddr, 381 auth->md5key_len, auth->md5key, &nbr->auth_spi_in) == -1) 382 return (-1); 383 384 nbr->auth_established = 1; 385 386 return (0); 387 } 388 389 static int 390 pfkey_md5sig_remove(struct nbr *nbr) 391 { 392 if (nbr->auth_spi_out) { 393 if (pfkey_sa_remove(nbr->af, &nbr->laddr, &nbr->raddr, 394 &nbr->auth_spi_out) == -1) 395 return (-1); 396 } 397 if (nbr->auth_spi_in) { 398 if (pfkey_sa_remove(nbr->af, &nbr->raddr, &nbr->laddr, 399 &nbr->auth_spi_in) == -1) 400 return (-1); 401 } 402 403 nbr->auth_established = 0; 404 nbr->auth_spi_in = 0; 405 nbr->auth_spi_out = 0; 406 407 return (0); 408 } 409 410 static struct ldp_auth * 411 pfkey_find_auth(struct ldpd_conf *conf, struct nbr *nbr) 412 { 413 struct ldp_auth *auth, *match = NULL; 414 415 LIST_FOREACH(auth, &conf->auth_list, entry) { 416 in_addr_t mask = prefixlen2mask(auth->idlen); 417 if ((auth->id.s_addr & mask) != (nbr->id.s_addr & mask)) 418 continue; 419 420 if (match == NULL || 421 match->idlen < auth->idlen) 422 match = auth; 423 } 424 425 return (match); 426 } 427 428 int 429 pfkey_establish(struct ldpd_conf *conf, struct nbr *nbr) 430 { 431 struct ldp_auth *auth = NULL; 432 433 auth = pfkey_find_auth(conf, nbr); 434 if (auth == NULL || /* no policy */ 435 auth->md5key_len == 0) /* "no tcpmd5 sig" */ 436 return (0); 437 438 return (pfkey_md5sig_establish(nbr, auth)); 439 } 440 441 int 442 pfkey_remove(struct nbr *nbr) 443 { 444 return (pfkey_md5sig_remove(nbr)); 445 } 446 447 int 448 pfkey_init(void) 449 { 450 if ((fd = socket(PF_KEY, SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK, 451 PF_KEY_V2)) == -1) { 452 if (errno == EPROTONOSUPPORT) { 453 log_warnx("PF_KEY not available"); 454 sysdep.no_pfkey = 1; 455 return (-1); 456 } else 457 fatal("pfkey setup failed"); 458 } 459 return (fd); 460 } 461