1 /* $OpenBSD: pfkey.c,v 1.29 2018/06/28 02:37:26 gsoares Exp $ */ 2 3 /* 4 * Copyright (c) 2005 H�kan Olsson. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 /* 29 * This code was written under funding by Multicom Security AB. 30 */ 31 32 33 #include <sys/types.h> 34 #include <sys/ioctl.h> 35 #include <sys/select.h> 36 #include <sys/socket.h> 37 #include <sys/queue.h> 38 #include <sys/sysctl.h> 39 #include <net/pfkeyv2.h> 40 #include <netinet/ip_ipsp.h> 41 42 #include <errno.h> 43 #include <stdio.h> 44 #include <stdlib.h> 45 #include <string.h> 46 #include <unistd.h> 47 48 #include "sasyncd.h" 49 #include "monitor.h" 50 #include "net.h" 51 52 struct pfkey_msg 53 { 54 SIMPLEQ_ENTRY(pfkey_msg) next; 55 56 u_int8_t *buf; 57 u_int32_t len; 58 }; 59 60 SIMPLEQ_HEAD(, pfkey_msg) pfkey_msglist; 61 62 static const char *msgtypes[] = { 63 "RESERVED", "GETSPI", "UPDATE", "ADD", "DELETE", "GET", "ACQUIRE", 64 "REGISTER", "EXPIRE", "FLUSH", "DUMP", "X_PROMISC", "X_ADDFLOW", 65 "X_DELFLOW", "X_GRPSPIS", "X_ASKPOLICY", "X_SPDDUMP" 66 }; 67 68 #define CHUNK sizeof(u_int64_t) 69 70 static const char *pfkey_print_type(struct sadb_msg *); 71 72 static int 73 pfkey_write(u_int8_t *buf, ssize_t len) 74 { 75 struct sadb_msg *msg = (struct sadb_msg *)buf; 76 ssize_t n; 77 78 if (cfgstate.pfkey_socket == -1) 79 return 0; 80 81 do { 82 n = write(cfgstate.pfkey_socket, buf, len); 83 } while (n == -1 && (errno == EAGAIN || errno == EINTR)); 84 if (n == -1) { 85 log_err("pfkey: msg %s write() failed on socket %d", 86 pfkey_print_type(msg), cfgstate.pfkey_socket); 87 return -1; 88 } 89 90 return 0; 91 } 92 93 int 94 pfkey_set_promisc(void) 95 { 96 struct sadb_msg msg; 97 static u_int32_t seq = 1; 98 99 memset(&msg, 0, sizeof msg); 100 msg.sadb_msg_version = PF_KEY_V2; 101 msg.sadb_msg_seq = seq++; 102 msg.sadb_msg_satype = 1; /* Special; 1 to enable, 0 to disable */ 103 msg.sadb_msg_type = SADB_X_PROMISC; 104 msg.sadb_msg_pid = getpid(); 105 msg.sadb_msg_len = sizeof msg / CHUNK; 106 107 return pfkey_write((u_int8_t *)&msg, sizeof msg); 108 } 109 110 /* Send a SADB_FLUSH PFKEY message to peer 'p' */ 111 static void 112 pfkey_send_flush(struct syncpeer *p) 113 { 114 struct sadb_msg *m = calloc(1, sizeof *m); 115 static u_int32_t seq = 1; 116 117 if (m) { 118 m->sadb_msg_version = PF_KEY_V2; 119 m->sadb_msg_seq = seq++; 120 m->sadb_msg_type = SADB_FLUSH; 121 m->sadb_msg_satype = SADB_SATYPE_UNSPEC; 122 m->sadb_msg_pid = getpid(); 123 m->sadb_msg_len = sizeof *m / CHUNK; 124 125 log_msg(2, "pfkey_send_flush: sending FLUSH to peer %s", 126 p->name); 127 net_queue(p, MSG_PFKEYDATA, (u_int8_t *)m, sizeof *m); 128 } 129 } 130 131 static const char * 132 pfkey_print_type(struct sadb_msg *msg) 133 { 134 static char uk[20]; 135 136 if (msg->sadb_msg_type < sizeof msgtypes / sizeof msgtypes[0]) 137 return msgtypes[msg->sadb_msg_type]; 138 else { 139 snprintf(uk, sizeof uk, "<unknown(%d)>", msg->sadb_msg_type); 140 return uk; 141 } 142 } 143 144 static struct sadb_ext * 145 pfkey_find_ext(struct sadb_msg *msg, u_int16_t type) 146 { 147 struct sadb_ext *ext; 148 u_int8_t *e; 149 150 for (e = (u_int8_t *)msg + sizeof *msg; 151 e < (u_int8_t *)msg + msg->sadb_msg_len * CHUNK; 152 e += ext->sadb_ext_len * CHUNK) { 153 ext = (struct sadb_ext *)e; 154 if (ext->sadb_ext_len == 0) 155 break; 156 if (ext->sadb_ext_type != type) 157 continue; 158 return ext; 159 } 160 return NULL; 161 } 162 163 /* Return: 0 means ok to sync msg, 1 means to skip it */ 164 static int 165 pfkey_msg_filter(struct sadb_msg *msg) 166 { 167 struct sockaddr *src = 0, *dst = 0; 168 struct syncpeer *p; 169 struct sadb_ext *ext; 170 u_int8_t *max; 171 172 switch (msg->sadb_msg_type) { 173 case SADB_X_PROMISC: 174 case SADB_DUMP: 175 case SADB_GET: 176 case SADB_GETSPI: 177 case SADB_ACQUIRE: 178 case SADB_X_ASKPOLICY: 179 case SADB_REGISTER: 180 /* Some messages should not be synced. */ 181 return 1; 182 183 case SADB_ADD: 184 /* No point in syncing LARVAL SAs */ 185 if (pfkey_find_ext(msg, SADB_EXT_KEY_ENCRYPT) == 0) 186 return 1; 187 case SADB_DELETE: 188 case SADB_X_ADDFLOW: 189 case SADB_X_DELFLOW: 190 case SADB_EXPIRE: 191 /* Continue below */ 192 break; 193 case SADB_FLUSH: 194 if ((cfgstate.flags & FM_MASK) == FM_NEVER) 195 return 1; 196 break; 197 default: 198 return 0; 199 } 200 201 if ((cfgstate.flags & SKIP_LOCAL_SAS) == 0) 202 return 0; 203 204 /* SRC or DST address of this msg must not be one of our peers. */ 205 ext = pfkey_find_ext(msg, SADB_EXT_ADDRESS_SRC); 206 if (ext) 207 src = (struct sockaddr *)((struct sadb_address *)ext + 1); 208 ext = pfkey_find_ext(msg, SADB_EXT_ADDRESS_DST); 209 if (ext) 210 dst = (struct sockaddr *)((struct sadb_address *)ext + 1); 211 if (!src && !dst) 212 return 0; 213 214 max = (u_int8_t *)msg + msg->sadb_msg_len * CHUNK; 215 if (src && ((u_int8_t *)src + src->sa_len) > max) 216 return 1; 217 if (dst && ((u_int8_t *)dst + dst->sa_len) > max) 218 return 1; 219 220 /* Found SRC or DST, check it against our peers */ 221 for (p = LIST_FIRST(&cfgstate.peerlist); p; p = LIST_NEXT(p, link)) { 222 if (p->socket < 0 || p->sa->sa_family != 223 (src ? src->sa_family : dst->sa_family)) 224 continue; 225 226 switch (p->sa->sa_family) { 227 case AF_INET: 228 if (src && memcmp( 229 &((struct sockaddr_in *)p->sa)->sin_addr.s_addr, 230 &((struct sockaddr_in *)src)->sin_addr.s_addr, 231 sizeof(struct in_addr)) == 0) 232 return 1; 233 if (dst && memcmp( 234 &((struct sockaddr_in *)p->sa)->sin_addr.s_addr, 235 &((struct sockaddr_in *)dst)->sin_addr.s_addr, 236 sizeof(struct in_addr)) == 0) 237 return 1; 238 break; 239 case AF_INET6: 240 if (src && 241 memcmp(&((struct sockaddr_in6 *)p->sa)->sin6_addr, 242 &((struct sockaddr_in6 *)src)->sin6_addr, 243 sizeof(struct in_addr)) == 0) 244 return 1; 245 if (dst && 246 memcmp(&((struct sockaddr_in6 *)p->sa)->sin6_addr, 247 &((struct sockaddr_in6 *)dst)->sin6_addr, 248 sizeof(struct in_addr)) == 0) 249 return 1; 250 break; 251 } 252 } 253 return 0; 254 } 255 256 static int 257 pfkey_handle_message(struct sadb_msg *m) 258 { 259 struct sadb_msg *msg = m; 260 261 /* 262 * Report errors, but ignore for DELETE (both isakmpd and kernel will 263 * expire the SA, if the kernel is first, DELETE returns failure). 264 */ 265 if (msg->sadb_msg_errno && msg->sadb_msg_type != SADB_DELETE && 266 msg->sadb_msg_pid == (u_int32_t)getpid()) { 267 errno = msg->sadb_msg_errno; 268 log_msg(1, "pfkey error (%s)", pfkey_print_type(msg)); 269 } 270 271 /* We only want promiscuous messages here, skip all others. */ 272 if (msg->sadb_msg_type != SADB_X_PROMISC || 273 (msg->sadb_msg_len * CHUNK) < 2 * sizeof *msg) { 274 free(m); 275 return 0; 276 } 277 /* Move next msg to start of the buffer. */ 278 msg++; 279 280 /* 281 * We should not listen to PFKEY messages when we are not running 282 * as MASTER, or the pid is our own. 283 */ 284 if (cfgstate.runstate != MASTER || 285 msg->sadb_msg_pid == (u_int32_t)getpid()) { 286 free(m); 287 return 0; 288 } 289 290 if (pfkey_msg_filter(msg)) { 291 free(m); 292 return 0; 293 } 294 295 switch (msg->sadb_msg_type) { 296 case SADB_UPDATE: 297 /* 298 * Tweak -- the peers do not have a larval SA to update, so 299 * instead we ADD it here. 300 */ 301 msg->sadb_msg_type = SADB_ADD; 302 /* FALLTHROUGH */ 303 304 default: 305 /* Pass the rest along to our peers. */ 306 memmove(m, msg, msg->sadb_msg_len * CHUNK); /* for realloc */ 307 return net_queue(NULL, MSG_PFKEYDATA, (u_int8_t *)m, 308 m->sadb_msg_len * CHUNK); 309 } 310 311 return 0; 312 } 313 314 static int 315 pfkey_read(void) 316 { 317 struct sadb_msg hdr, *msg; 318 u_int8_t *data; 319 ssize_t datalen; 320 int fd = cfgstate.pfkey_socket; 321 322 if (recv(fd, &hdr, sizeof hdr, MSG_PEEK) != sizeof hdr) { 323 log_err("pfkey_read: recv() failed"); 324 return -1; 325 } 326 datalen = hdr.sadb_msg_len * CHUNK; 327 data = reallocarray(NULL, hdr.sadb_msg_len, CHUNK); 328 if (!data) { 329 log_err("pfkey_read: malloc(%lu) failed", datalen); 330 return -1; 331 } 332 msg = (struct sadb_msg *)data; 333 334 if (read(fd, data, datalen) != datalen) { 335 log_err("pfkey_read: read() failed, %lu bytes", datalen); 336 free(data); 337 return -1; 338 } 339 340 return pfkey_handle_message(msg); 341 } 342 343 int 344 pfkey_init(int reinit) 345 { 346 int fd; 347 348 fd = socket(PF_KEY, SOCK_RAW, PF_KEY_V2); 349 if (fd == -1) { 350 perror("failed to open PF_KEY socket"); 351 return -1; 352 } 353 cfgstate.pfkey_socket = fd; 354 355 if (cfgstate.runstate == MASTER) 356 pfkey_set_promisc(); 357 358 if (reinit) 359 return (fd > -1 ? 0 : -1); 360 361 SIMPLEQ_INIT(&pfkey_msglist); 362 return 0; 363 } 364 365 void 366 pfkey_set_rfd(fd_set *fds) 367 { 368 if (cfgstate.pfkey_socket != -1) 369 FD_SET(cfgstate.pfkey_socket, fds); 370 } 371 372 void 373 pfkey_set_pending_wfd(fd_set *fds) 374 { 375 if (cfgstate.pfkey_socket != -1 && SIMPLEQ_FIRST(&pfkey_msglist)) 376 FD_SET(cfgstate.pfkey_socket, fds); 377 } 378 379 void 380 pfkey_read_message(fd_set *fds) 381 { 382 if (cfgstate.pfkey_socket != -1) 383 if (FD_ISSET(cfgstate.pfkey_socket, fds)) 384 (void)pfkey_read(); 385 } 386 387 void 388 pfkey_send_message(fd_set *fds) 389 { 390 struct pfkey_msg *pmsg = SIMPLEQ_FIRST(&pfkey_msglist); 391 392 if (!pmsg || !FD_ISSET(cfgstate.pfkey_socket, fds)) 393 return; 394 395 if (cfgstate.pfkey_socket == -1) 396 if (pfkey_init(1)) /* Reinit socket */ 397 return; 398 399 (void)pfkey_write(pmsg->buf, pmsg->len); 400 401 SIMPLEQ_REMOVE_HEAD(&pfkey_msglist, next); 402 free(pmsg->buf); 403 free(pmsg); 404 405 return; 406 } 407 408 int 409 pfkey_queue_message(u_int8_t *data, u_int32_t datalen) 410 { 411 struct pfkey_msg *pmsg; 412 struct sadb_msg *sadb = (struct sadb_msg *)data; 413 static u_int32_t seq = 1; 414 415 pmsg = malloc(sizeof *pmsg); 416 if (!pmsg) { 417 log_err("malloc()"); 418 return -1; 419 } 420 memset(pmsg, 0, sizeof *pmsg); 421 422 pmsg->buf = data; 423 pmsg->len = datalen; 424 425 sadb->sadb_msg_pid = getpid(); 426 sadb->sadb_msg_seq = seq++; 427 log_msg(2, "pfkey_queue_message: pfkey %s len %zu seq %u", 428 pfkey_print_type(sadb), sadb->sadb_msg_len * CHUNK, 429 sadb->sadb_msg_seq); 430 431 SIMPLEQ_INSERT_TAIL(&pfkey_msglist, pmsg, next); 432 return 0; 433 } 434 435 void 436 pfkey_shutdown(void) 437 { 438 struct pfkey_msg *p = SIMPLEQ_FIRST(&pfkey_msglist); 439 440 while ((p = SIMPLEQ_FIRST(&pfkey_msglist))) { 441 SIMPLEQ_REMOVE_HEAD(&pfkey_msglist, next); 442 free(p->buf); 443 free(p); 444 } 445 446 if (cfgstate.pfkey_socket > -1) 447 close(cfgstate.pfkey_socket); 448 } 449 450 /* ------------------------------------------------------------------------- */ 451 452 void 453 pfkey_snapshot(void *v) 454 { 455 struct syncpeer *p = (struct syncpeer *)v; 456 struct sadb_msg *m; 457 u_int8_t *sadb, *spd, *max, *next, *sendbuf; 458 u_int32_t sadbsz, spdsz; 459 460 if (!p) 461 return; 462 463 if (monitor_get_pfkey_snap(&sadb, &sadbsz, &spd, &spdsz)) { 464 log_msg(0, "pfkey_snapshot: failed to get pfkey snapshot"); 465 return; 466 } 467 468 /* XXX needs moving if snapshot is called more than once per peer */ 469 if ((cfgstate.flags & FM_MASK) == FM_STARTUP) 470 pfkey_send_flush(p); 471 472 /* Parse SADB data */ 473 if (sadbsz && sadb) { 474 dump_buf(2, sadb, sadbsz, "pfkey_snapshot: SADB data"); 475 max = sadb + sadbsz; 476 for (next = sadb; next < max; 477 next += m->sadb_msg_len * CHUNK) { 478 m = (struct sadb_msg *)next; 479 if (m->sadb_msg_len == 0) 480 break; 481 482 /* Tweak and send this SA to the peer. */ 483 m->sadb_msg_type = SADB_ADD; 484 485 if (pfkey_msg_filter(m)) 486 continue; 487 488 /* Allocate msgbuffer, net_queue() will free it. */ 489 sendbuf = calloc(m->sadb_msg_len, CHUNK); 490 if (sendbuf) { 491 memcpy(sendbuf, m, m->sadb_msg_len * CHUNK); 492 net_queue(p, MSG_PFKEYDATA, sendbuf, 493 m->sadb_msg_len * CHUNK); 494 log_msg(2, "pfkey_snapshot: sync SA %p len %zu " 495 "to peer %s", m, 496 m->sadb_msg_len * CHUNK, p->name); 497 } 498 } 499 freezero(sadb, sadbsz); 500 } 501 502 /* Parse SPD data */ 503 if (spdsz && spd) { 504 dump_buf(2, spd, spdsz, "pfkey_snapshot: SPD data"); 505 max = spd + spdsz; 506 for (next = spd; next < max; next += m->sadb_msg_len * CHUNK) { 507 m = (struct sadb_msg *)next; 508 if (m->sadb_msg_len == 0) 509 break; 510 511 /* Tweak msg type. */ 512 m->sadb_msg_type = SADB_X_ADDFLOW; 513 514 if (pfkey_msg_filter(m)) 515 continue; 516 517 /* Allocate msgbuffer, freed by net_queue(). */ 518 sendbuf = calloc(m->sadb_msg_len, CHUNK); 519 if (sendbuf) { 520 memcpy(sendbuf, m, m->sadb_msg_len * CHUNK); 521 net_queue(p, MSG_PFKEYDATA, sendbuf, 522 m->sadb_msg_len * CHUNK); 523 log_msg(2, "pfkey_snapshot: sync FLOW %p len " 524 "%zu to peer %s", m, 525 m->sadb_msg_len * CHUNK, p->name); 526 } 527 } 528 /* Cleanup. */ 529 freezero(spd, spdsz); 530 } 531 532 net_ctl_send_endsnap(p); 533 return; 534 } 535