1 /* $OpenBSD: pfkey.c,v 1.20 2010/06/29 18:10:04 kjell 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/param.h> 34 #include <sys/types.h> 35 #include <sys/ioctl.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 = (struct sadb_msg *)calloc(1, sizeof *m); 115 static u_int32_t seq = 1; 116 117 if (m) { 118 memset(m, 0, sizeof *m); 119 m->sadb_msg_version = PF_KEY_V2; 120 m->sadb_msg_seq = seq++; 121 m->sadb_msg_type = SADB_FLUSH; 122 m->sadb_msg_satype = SADB_SATYPE_UNSPEC; 123 m->sadb_msg_pid = getpid(); 124 m->sadb_msg_len = sizeof *m / CHUNK; 125 126 log_msg(2, "pfkey_send_flush: sending FLUSH to peer %s", 127 p->name); 128 net_queue(p, MSG_PFKEYDATA, (u_int8_t *)m, sizeof *m); 129 } 130 } 131 132 static const char * 133 pfkey_print_type(struct sadb_msg *msg) 134 { 135 static char uk[20]; 136 137 if (msg->sadb_msg_type < sizeof msgtypes / sizeof msgtypes[0]) 138 return msgtypes[msg->sadb_msg_type]; 139 else { 140 snprintf(uk, sizeof uk, "<unknown(%d)>", msg->sadb_msg_type); 141 return uk; 142 } 143 } 144 145 static struct sadb_ext * 146 pfkey_find_ext(struct sadb_msg *msg, u_int16_t type) 147 { 148 struct sadb_ext *ext; 149 u_int8_t *e; 150 151 for (e = (u_int8_t *)msg + sizeof *msg; 152 e < (u_int8_t *)msg + msg->sadb_msg_len * CHUNK; 153 e += ext->sadb_ext_len * CHUNK) { 154 ext = (struct sadb_ext *)e; 155 if (ext->sadb_ext_len == 0) 156 break; 157 if (ext->sadb_ext_type != type) 158 continue; 159 return ext; 160 } 161 return NULL; 162 } 163 164 /* Return: 0 means ok to sync msg, 1 means to skip it */ 165 static int 166 pfkey_msg_filter(struct sadb_msg *msg) 167 { 168 struct sockaddr *src = 0, *dst = 0; 169 struct syncpeer *p; 170 struct sadb_ext *ext; 171 u_int8_t *max; 172 173 switch (msg->sadb_msg_type) { 174 case SADB_X_PROMISC: 175 case SADB_DUMP: 176 case SADB_GET: 177 case SADB_GETSPI: 178 case SADB_ACQUIRE: 179 case SADB_X_ASKPOLICY: 180 case SADB_REGISTER: 181 /* Some messages should not be synced. */ 182 return 1; 183 184 case SADB_ADD: 185 /* No point in syncing LARVAL SAs */ 186 if (pfkey_find_ext(msg, SADB_EXT_KEY_ENCRYPT) == 0) 187 return 1; 188 case SADB_DELETE: 189 case SADB_X_ADDFLOW: 190 case SADB_X_DELFLOW: 191 case SADB_EXPIRE: 192 /* Continue below */ 193 break; 194 case SADB_FLUSH: 195 if ((cfgstate.flags & FM_MASK) == FM_NEVER) 196 return 1; 197 break; 198 default: 199 return 0; 200 } 201 202 if ((cfgstate.flags & SKIP_LOCAL_SAS) == 0) 203 return 0; 204 205 /* SRC or DST address of this msg must not be one of our peers. */ 206 ext = pfkey_find_ext(msg, SADB_EXT_ADDRESS_SRC); 207 if (ext) 208 src = (struct sockaddr *)((struct sadb_address *)ext + 1); 209 ext = pfkey_find_ext(msg, SADB_EXT_ADDRESS_DST); 210 if (ext) 211 dst = (struct sockaddr *)((struct sadb_address *)ext + 1); 212 if (!src && !dst) 213 return 0; 214 215 max = (u_int8_t *)msg + msg->sadb_msg_len * CHUNK; 216 if (src && ((u_int8_t *)src + src->sa_len) > max) 217 return 1; 218 if (dst && ((u_int8_t *)dst + dst->sa_len) > max) 219 return 1; 220 221 /* Found SRC or DST, check it against our peers */ 222 for (p = LIST_FIRST(&cfgstate.peerlist); p; p = LIST_NEXT(p, link)) { 223 if (p->socket < 0 || p->sa->sa_family != 224 (src ? src->sa_family : dst->sa_family)) 225 continue; 226 227 switch (p->sa->sa_family) { 228 case AF_INET: 229 if (src && memcmp( 230 &((struct sockaddr_in *)p->sa)->sin_addr.s_addr, 231 &((struct sockaddr_in *)src)->sin_addr.s_addr, 232 sizeof(struct in_addr)) == 0) 233 return 1; 234 if (dst && memcmp( 235 &((struct sockaddr_in *)p->sa)->sin_addr.s_addr, 236 &((struct sockaddr_in *)dst)->sin_addr.s_addr, 237 sizeof(struct in_addr)) == 0) 238 return 1; 239 break; 240 case AF_INET6: 241 if (src && 242 memcmp(&((struct sockaddr_in6 *)p->sa)->sin6_addr, 243 &((struct sockaddr_in6 *)src)->sin6_addr, 244 sizeof(struct in_addr)) == 0) 245 return 1; 246 if (dst && 247 memcmp(&((struct sockaddr_in6 *)p->sa)->sin6_addr, 248 &((struct sockaddr_in6 *)dst)->sin6_addr, 249 sizeof(struct in_addr)) == 0) 250 return 1; 251 break; 252 } 253 } 254 return 0; 255 } 256 257 static int 258 pfkey_handle_message(struct sadb_msg *m) 259 { 260 struct sadb_msg *msg = m; 261 262 /* 263 * Report errors, but ignore for DELETE (both isakmpd and kernel will 264 * expire the SA, if the kernel is first, DELETE returns failure). 265 */ 266 if (msg->sadb_msg_errno && msg->sadb_msg_type != SADB_DELETE && 267 msg->sadb_msg_pid == (u_int32_t)getpid()) { 268 errno = msg->sadb_msg_errno; 269 log_msg(1, "pfkey error (%s)", pfkey_print_type(msg)); 270 } 271 272 /* We only want promiscuous messages here, skip all others. */ 273 if (msg->sadb_msg_type != SADB_X_PROMISC || 274 (msg->sadb_msg_len * CHUNK) < 2 * sizeof *msg) { 275 free(m); 276 return 0; 277 } 278 /* Move next msg to start of the buffer. */ 279 msg++; 280 281 /* 282 * We should not listen to PFKEY messages when we are not running 283 * as MASTER, or the pid is our own. 284 */ 285 if (cfgstate.runstate != MASTER || 286 msg->sadb_msg_pid == (u_int32_t)getpid()) { 287 free(m); 288 return 0; 289 } 290 291 if (pfkey_msg_filter(msg)) { 292 free(m); 293 return 0; 294 } 295 296 switch (msg->sadb_msg_type) { 297 case SADB_UPDATE: 298 /* 299 * Tweak -- the peers do not have a larval SA to update, so 300 * instead we ADD it here. 301 */ 302 msg->sadb_msg_type = SADB_ADD; 303 /* FALLTHROUGH */ 304 305 default: 306 /* Pass the rest along to our peers. */ 307 memmove(m, msg, msg->sadb_msg_len * CHUNK); /* for realloc */ 308 return net_queue(NULL, MSG_PFKEYDATA, (u_int8_t *)m, 309 m->sadb_msg_len * CHUNK); 310 } 311 312 return 0; 313 } 314 315 static int 316 pfkey_read(void) 317 { 318 struct sadb_msg hdr, *msg; 319 u_int8_t *data; 320 ssize_t datalen; 321 int fd = cfgstate.pfkey_socket; 322 323 if (recv(fd, &hdr, sizeof hdr, MSG_PEEK) != sizeof hdr) { 324 log_err("pfkey_read: recv() failed"); 325 return -1; 326 } 327 datalen = hdr.sadb_msg_len * CHUNK; 328 data = (u_int8_t *)malloc(datalen); 329 if (!data) { 330 log_err("pfkey_read: malloc(%lu) failed", datalen); 331 return -1; 332 } 333 msg = (struct sadb_msg *)data; 334 335 if (read(fd, data, datalen) != datalen) { 336 log_err("pfkey_read: read() failed, %lu bytes", datalen); 337 free(data); 338 return -1; 339 } 340 341 return pfkey_handle_message(msg); 342 } 343 344 int 345 pfkey_init(int reinit) 346 { 347 int fd; 348 349 fd = socket(PF_KEY, SOCK_RAW, PF_KEY_V2); 350 if (fd == -1) { 351 perror("failed to open PF_KEY socket"); 352 return -1; 353 } 354 cfgstate.pfkey_socket = fd; 355 356 if (cfgstate.runstate == MASTER) 357 pfkey_set_promisc(); 358 359 if (reinit) 360 return (fd > -1 ? 0 : -1); 361 362 SIMPLEQ_INIT(&pfkey_msglist); 363 return 0; 364 } 365 366 void 367 pfkey_set_rfd(fd_set *fds) 368 { 369 if (cfgstate.pfkey_socket != -1) 370 FD_SET(cfgstate.pfkey_socket, fds); 371 } 372 373 void 374 pfkey_set_pending_wfd(fd_set *fds) 375 { 376 if (cfgstate.pfkey_socket != -1 && SIMPLEQ_FIRST(&pfkey_msglist)) 377 FD_SET(cfgstate.pfkey_socket, fds); 378 } 379 380 void 381 pfkey_read_message(fd_set *fds) 382 { 383 if (cfgstate.pfkey_socket != -1) 384 if (FD_ISSET(cfgstate.pfkey_socket, fds)) 385 (void)pfkey_read(); 386 } 387 388 void 389 pfkey_send_message(fd_set *fds) 390 { 391 struct pfkey_msg *pmsg = SIMPLEQ_FIRST(&pfkey_msglist); 392 393 if (!pmsg || !FD_ISSET(cfgstate.pfkey_socket, fds)) 394 return; 395 396 if (cfgstate.pfkey_socket == -1) 397 if (pfkey_init(1)) /* Reinit socket */ 398 return; 399 400 (void)pfkey_write(pmsg->buf, pmsg->len); 401 402 SIMPLEQ_REMOVE_HEAD(&pfkey_msglist, next); 403 free(pmsg->buf); 404 free(pmsg); 405 406 return; 407 } 408 409 int 410 pfkey_queue_message(u_int8_t *data, u_int32_t datalen) 411 { 412 struct pfkey_msg *pmsg; 413 struct sadb_msg *sadb = (struct sadb_msg *)data; 414 static u_int32_t seq = 1; 415 416 pmsg = (struct pfkey_msg *)malloc(sizeof *pmsg); 417 if (!pmsg) { 418 log_err("malloc()"); 419 return -1; 420 } 421 memset(pmsg, 0, sizeof *pmsg); 422 423 pmsg->buf = data; 424 pmsg->len = datalen; 425 426 sadb->sadb_msg_pid = getpid(); 427 sadb->sadb_msg_seq = seq++; 428 log_msg(2, "pfkey_queue_message: pfkey %s len %u seq %u", 429 pfkey_print_type(sadb), sadb->sadb_msg_len * CHUNK, 430 sadb->sadb_msg_seq); 431 432 SIMPLEQ_INSERT_TAIL(&pfkey_msglist, pmsg, next); 433 return 0; 434 } 435 436 void 437 pfkey_shutdown(void) 438 { 439 struct pfkey_msg *p = SIMPLEQ_FIRST(&pfkey_msglist); 440 441 while ((p = SIMPLEQ_FIRST(&pfkey_msglist))) { 442 SIMPLEQ_REMOVE_HEAD(&pfkey_msglist, next); 443 free(p->buf); 444 free(p); 445 } 446 447 if (cfgstate.pfkey_socket > -1) 448 close(cfgstate.pfkey_socket); 449 } 450 451 /* ------------------------------------------------------------------------- */ 452 453 void 454 pfkey_snapshot(void *v) 455 { 456 struct syncpeer *p = (struct syncpeer *)v; 457 struct sadb_msg *m; 458 u_int8_t *sadb, *spd, *max, *next, *sendbuf; 459 u_int32_t sadbsz, spdsz; 460 461 if (!p) 462 return; 463 464 if (monitor_get_pfkey_snap(&sadb, &sadbsz, &spd, &spdsz)) { 465 log_msg(0, "pfkey_snapshot: failed to get pfkey snapshot"); 466 return; 467 } 468 469 /* XXX needs moving if snapshot is called more than once per peer */ 470 if ((cfgstate.flags & FM_MASK) == FM_STARTUP) 471 pfkey_send_flush(p); 472 473 /* Parse SADB data */ 474 if (sadbsz && sadb) { 475 dump_buf(2, sadb, sadbsz, "pfkey_snapshot: SADB data"); 476 max = sadb + sadbsz; 477 for (next = sadb; next < max; 478 next += m->sadb_msg_len * CHUNK) { 479 m = (struct sadb_msg *)next; 480 if (m->sadb_msg_len == 0) 481 break; 482 483 /* Tweak and send this SA to the peer. */ 484 m->sadb_msg_type = SADB_ADD; 485 486 if (pfkey_msg_filter(m)) 487 continue; 488 489 /* Allocate msgbuffer, net_queue() will free it. */ 490 sendbuf = (u_int8_t *)calloc(m->sadb_msg_len, CHUNK); 491 if (sendbuf) { 492 memcpy(sendbuf, m, m->sadb_msg_len * CHUNK); 493 net_queue(p, MSG_PFKEYDATA, sendbuf, 494 m->sadb_msg_len * CHUNK); 495 log_msg(2, "pfkey_snapshot: sync SA %p len %u " 496 "to peer %s", m, 497 m->sadb_msg_len * CHUNK, p->name); 498 } 499 } 500 memset(sadb, 0, sadbsz); 501 free(sadb); 502 } 503 504 /* Parse SPD data */ 505 if (spdsz && spd) { 506 dump_buf(2, spd, spdsz, "pfkey_snapshot: SPD data"); 507 max = spd + spdsz; 508 for (next = spd; next < max; next += m->sadb_msg_len * CHUNK) { 509 m = (struct sadb_msg *)next; 510 if (m->sadb_msg_len == 0) 511 break; 512 513 /* Tweak msg type. */ 514 m->sadb_msg_type = SADB_X_ADDFLOW; 515 516 if (pfkey_msg_filter(m)) 517 continue; 518 519 /* Allocate msgbuffer, freed by net_queue(). */ 520 sendbuf = (u_int8_t *)calloc(m->sadb_msg_len, CHUNK); 521 if (sendbuf) { 522 memcpy(sendbuf, m, m->sadb_msg_len * CHUNK); 523 net_queue(p, MSG_PFKEYDATA, sendbuf, 524 m->sadb_msg_len * CHUNK); 525 log_msg(2, "pfkey_snapshot: sync FLOW %p len " 526 "%u to peer %s", m, 527 m->sadb_msg_len * CHUNK, p->name); 528 } 529 } 530 /* Cleanup. */ 531 memset(spd, 0, spdsz); 532 free(spd); 533 } 534 535 net_ctl_send_endsnap(p); 536 return; 537 } 538