1 /* $OpenBSD: pfkeyv2_parsemessage.c,v 1.61 2023/08/07 03:35:06 dlg Exp $ */ 2 3 /* 4 * @(#)COPYRIGHT 1.1 (NRL) 17 January 1995 5 * 6 * NRL grants permission for redistribution and use in source and binary 7 * forms, with or without modification, of the software and documentation 8 * created at NRL provided that the following conditions 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 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgements: 17 * This product includes software developed by the University of 18 * California, Berkeley and its contributors. 19 * This product includes software developed at the Information 20 * Technology Division, US Naval Research Laboratory. 21 * 4. Neither the name of the NRL nor the names of its contributors 22 * may be used to endorse or promote products derived from this software 23 * without specific prior written permission. 24 * 25 * THE SOFTWARE PROVIDED BY NRL IS PROVIDED BY NRL AND CONTRIBUTORS ``AS 26 * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 28 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NRL OR 29 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 30 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 31 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 32 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 33 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 34 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 35 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 * 37 * The views and conclusions contained in the software and documentation 38 * are those of the authors and should not be interpreted as representing 39 * official policies, either expressed or implied, of the US Naval 40 * Research Laboratory (NRL). 41 */ 42 43 /* 44 * Copyright (c) 1995, 1996, 1997, 1998, 1999 Craig Metz. All rights reserved. 45 * 46 * Redistribution and use in source and binary forms, with or without 47 * modification, are permitted provided that the following conditions 48 * are met: 49 * 1. Redistributions of source code must retain the above copyright 50 * notice, this list of conditions and the following disclaimer. 51 * 2. Redistributions in binary form must reproduce the above copyright 52 * notice, this list of conditions and the following disclaimer in the 53 * documentation and/or other materials provided with the distribution. 54 * 3. Neither the name of the author nor the names of any contributors 55 * may be used to endorse or promote products derived from this software 56 * without specific prior written permission. 57 * 58 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 59 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 60 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 61 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 62 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 63 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 64 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 65 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 66 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 67 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 68 * SUCH DAMAGE. 69 */ 70 71 #include "pf.h" 72 73 #include <sys/param.h> 74 #include <sys/systm.h> 75 #include <sys/socket.h> 76 #include <sys/mbuf.h> 77 #include <sys/proc.h> 78 #include <netinet/ip_ipsp.h> 79 #include <net/pfkeyv2.h> 80 81 #if NPF > 0 82 #include <net/if.h> 83 #include <net/pfvar.h> 84 #endif 85 86 #ifdef ENCDEBUG 87 #define DPRINTF(fmt, args...) \ 88 do { \ 89 if (encdebug) \ 90 printf("%s: " fmt "\n", __func__, ## args); \ 91 } while (0) 92 #else 93 #define DPRINTF(fmt, args...) \ 94 do { } while (0) 95 #endif 96 97 #define BITMAP_SA (1LL << SADB_EXT_SA) 98 #define BITMAP_LIFETIME_CURRENT (1LL << SADB_EXT_LIFETIME_CURRENT) 99 #define BITMAP_LIFETIME_HARD (1LL << SADB_EXT_LIFETIME_HARD) 100 #define BITMAP_LIFETIME_SOFT (1LL << SADB_EXT_LIFETIME_SOFT) 101 #define BITMAP_ADDRESS_SRC (1LL << SADB_EXT_ADDRESS_SRC) 102 #define BITMAP_ADDRESS_DST (1LL << SADB_EXT_ADDRESS_DST) 103 #define BITMAP_ADDRESS_PROXY (1LL << SADB_EXT_ADDRESS_PROXY) 104 #define BITMAP_KEY_AUTH (1LL << SADB_EXT_KEY_AUTH) 105 #define BITMAP_KEY_ENCRYPT (1LL << SADB_EXT_KEY_ENCRYPT) 106 #define BITMAP_IDENTITY_SRC (1LL << SADB_EXT_IDENTITY_SRC) 107 #define BITMAP_IDENTITY_DST (1LL << SADB_EXT_IDENTITY_DST) 108 #define BITMAP_SENSITIVITY (1LL << SADB_EXT_SENSITIVITY) 109 #define BITMAP_PROPOSAL (1LL << SADB_EXT_PROPOSAL) 110 #define BITMAP_SUPPORTED_AUTH (1LL << SADB_EXT_SUPPORTED_AUTH) 111 #define BITMAP_SUPPORTED_ENCRYPT (1LL << SADB_EXT_SUPPORTED_ENCRYPT) 112 #define BITMAP_SPIRANGE (1LL << SADB_EXT_SPIRANGE) 113 #define BITMAP_LIFETIME (BITMAP_LIFETIME_CURRENT | BITMAP_LIFETIME_HARD | BITMAP_LIFETIME_SOFT) 114 #define BITMAP_ADDRESS (BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST) 115 #define BITMAP_KEY (BITMAP_KEY_AUTH | BITMAP_KEY_ENCRYPT) 116 #define BITMAP_IDENTITY (BITMAP_IDENTITY_SRC | BITMAP_IDENTITY_DST) 117 #define BITMAP_MSG 1 118 #define BITMAP_X_SRC_MASK (1LL << SADB_X_EXT_SRC_MASK) 119 #define BITMAP_X_DST_MASK (1LL << SADB_X_EXT_DST_MASK) 120 #define BITMAP_X_PROTOCOL (1LL << SADB_X_EXT_PROTOCOL) 121 #define BITMAP_X_SRC_FLOW (1LL << SADB_X_EXT_SRC_FLOW) 122 #define BITMAP_X_DST_FLOW (1LL << SADB_X_EXT_DST_FLOW) 123 #define BITMAP_X_FLOW_TYPE (1LL << SADB_X_EXT_FLOW_TYPE) 124 #define BITMAP_X_SA2 (1LL << SADB_X_EXT_SA2) 125 #define BITMAP_X_DST2 (1LL << SADB_X_EXT_DST2) 126 #define BITMAP_X_POLICY (1LL << SADB_X_EXT_POLICY) 127 #define BITMAP_X_FLOW (BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_PROTOCOL | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_FLOW_TYPE) 128 #define BITMAP_X_SUPPORTED_COMP (1LL << SADB_X_EXT_SUPPORTED_COMP) 129 #define BITMAP_X_UDPENCAP (1LL << SADB_X_EXT_UDPENCAP) 130 #define BITMAP_X_LIFETIME_LASTUSE (1LL << SADB_X_EXT_LIFETIME_LASTUSE) 131 #define BITMAP_X_TAG (1LL << SADB_X_EXT_TAG) 132 #define BITMAP_X_TAP (1LL << SADB_X_EXT_TAP) 133 #define BITMAP_X_SATYPE2 (1LL << SADB_X_EXT_SATYPE2) 134 #define BITMAP_X_RDOMAIN (1LL << SADB_X_EXT_RDOMAIN) 135 #define BITMAP_X_COUNTER (1LL << SADB_X_EXT_COUNTER) 136 #define BITMAP_X_MTU (1LL << SADB_X_EXT_MTU) 137 #define BITMAP_X_REPLAY (1LL << SADB_X_EXT_REPLAY) 138 #define BITMAP_X_IFACE (1LL << SADB_X_EXT_IFACE) 139 140 uint64_t sadb_exts_allowed_in[SADB_MAX+1] = 141 { 142 /* RESERVED */ 143 ~0, 144 /* GETSPI */ 145 BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_SPIRANGE, 146 /* UPDATE */ 147 BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS | BITMAP_ADDRESS_PROXY | BITMAP_KEY | BITMAP_IDENTITY | BITMAP_X_FLOW | BITMAP_X_UDPENCAP | BITMAP_X_TAG | BITMAP_X_TAP | BITMAP_X_RDOMAIN | BITMAP_X_IFACE, 148 /* ADD */ 149 BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS | BITMAP_KEY | BITMAP_IDENTITY | BITMAP_X_FLOW | BITMAP_X_UDPENCAP | BITMAP_X_LIFETIME_LASTUSE | BITMAP_X_TAG | BITMAP_X_TAP | BITMAP_X_RDOMAIN | BITMAP_X_IFACE, 150 /* DELETE */ 151 BITMAP_SA | BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_X_RDOMAIN, 152 /* GET */ 153 BITMAP_SA | BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_X_RDOMAIN, 154 /* ACQUIRE */ 155 BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_IDENTITY | BITMAP_PROPOSAL, 156 /* REGISTER */ 157 0, 158 /* EXPIRE */ 159 BITMAP_SA | BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST, 160 /* FLUSH */ 161 0, 162 /* DUMP */ 163 0, 164 /* X_PROMISC */ 165 0, 166 /* X_ADDFLOW */ 167 BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_IDENTITY_SRC | BITMAP_IDENTITY_DST | BITMAP_X_FLOW | BITMAP_X_RDOMAIN, 168 /* X_DELFLOW */ 169 BITMAP_X_FLOW | BITMAP_X_RDOMAIN, 170 /* X_GRPSPIS */ 171 BITMAP_SA | BITMAP_X_SA2 | BITMAP_X_DST2 | BITMAP_ADDRESS_DST | BITMAP_X_SATYPE2 | BITMAP_X_RDOMAIN, 172 /* X_ASKPOLICY */ 173 BITMAP_X_POLICY, 174 }; 175 176 uint64_t sadb_exts_required_in[SADB_MAX+1] = 177 { 178 /* RESERVED */ 179 0, 180 /* GETSPI */ 181 BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_SPIRANGE, 182 /* UPDATE */ 183 BITMAP_SA | BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST, 184 /* ADD */ 185 BITMAP_SA | BITMAP_ADDRESS_DST, 186 /* DELETE */ 187 BITMAP_SA | BITMAP_ADDRESS_DST, 188 /* GET */ 189 BITMAP_SA | BITMAP_ADDRESS_DST, 190 /* ACQUIRE */ 191 0, 192 /* REGISTER */ 193 0, 194 /* EXPIRE */ 195 BITMAP_SA | BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST, 196 /* FLUSH */ 197 0, 198 /* DUMP */ 199 0, 200 /* X_PROMISC */ 201 0, 202 /* X_ADDFLOW */ 203 BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_FLOW_TYPE, 204 /* X_DELFLOW */ 205 BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_FLOW_TYPE, 206 /* X_GRPSPIS */ 207 BITMAP_SA | BITMAP_X_SA2 | BITMAP_X_DST2 | BITMAP_ADDRESS_DST | BITMAP_X_SATYPE2, 208 /* X_ASKPOLICY */ 209 BITMAP_X_POLICY, 210 }; 211 212 const uint64_t sadb_exts_allowed_out[SADB_MAX+1] = 213 { 214 /* RESERVED */ 215 ~0, 216 /* GETSPI */ 217 BITMAP_SA | BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST, 218 /* UPDATE */ 219 BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS | BITMAP_ADDRESS_PROXY | BITMAP_IDENTITY | BITMAP_X_FLOW | BITMAP_X_UDPENCAP | BITMAP_X_TAG | BITMAP_X_TAP | BITMAP_X_RDOMAIN | BITMAP_X_IFACE, 220 /* ADD */ 221 BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS | BITMAP_IDENTITY | BITMAP_X_FLOW | BITMAP_X_UDPENCAP | BITMAP_X_TAG | BITMAP_X_TAP | BITMAP_X_RDOMAIN | BITMAP_X_IFACE, 222 /* DELETE */ 223 BITMAP_SA | BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_X_RDOMAIN, 224 /* GET */ 225 BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS | BITMAP_KEY | BITMAP_IDENTITY | BITMAP_X_UDPENCAP | BITMAP_X_LIFETIME_LASTUSE | BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_PROTOCOL | BITMAP_X_FLOW_TYPE | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_TAG | BITMAP_X_TAP | BITMAP_X_COUNTER | BITMAP_X_RDOMAIN | BITMAP_X_MTU | BITMAP_X_REPLAY | BITMAP_X_IFACE, 226 /* ACQUIRE */ 227 BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_IDENTITY | BITMAP_PROPOSAL, 228 /* REGISTER */ 229 BITMAP_SUPPORTED_AUTH | BITMAP_SUPPORTED_ENCRYPT | BITMAP_X_SUPPORTED_COMP, 230 /* EXPIRE */ 231 BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS, 232 /* FLUSH */ 233 0, 234 /* DUMP */ 235 BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS | BITMAP_IDENTITY, 236 /* X_PROMISC */ 237 0, 238 /* X_ADDFLOW */ 239 BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_PROTOCOL | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_FLOW_TYPE | BITMAP_IDENTITY_SRC | BITMAP_IDENTITY_DST | BITMAP_X_RDOMAIN, 240 /* X_DELFLOW */ 241 BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_PROTOCOL | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_FLOW_TYPE | BITMAP_X_RDOMAIN, 242 /* X_GRPSPIS */ 243 BITMAP_SA | BITMAP_X_SA2 | BITMAP_X_DST2 | BITMAP_ADDRESS_DST | BITMAP_X_SATYPE2 | BITMAP_X_RDOMAIN, 244 /* X_ASKPOLICY */ 245 BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_FLOW_TYPE | BITMAP_X_POLICY, 246 }; 247 248 const uint64_t sadb_exts_required_out[SADB_MAX+1] = 249 { 250 /* RESERVED */ 251 0, 252 /* GETSPI */ 253 BITMAP_SA | BITMAP_ADDRESS_DST, 254 /* UPDATE */ 255 BITMAP_SA | BITMAP_ADDRESS_DST, 256 /* ADD */ 257 BITMAP_SA | BITMAP_ADDRESS_DST, 258 /* DELETE */ 259 BITMAP_SA | BITMAP_ADDRESS_DST, 260 /* GET */ 261 BITMAP_SA | BITMAP_LIFETIME_CURRENT | BITMAP_ADDRESS_DST, 262 /* ACQUIRE */ 263 0, 264 /* REGISTER */ 265 BITMAP_SUPPORTED_AUTH | BITMAP_SUPPORTED_ENCRYPT | BITMAP_X_SUPPORTED_COMP, 266 /* EXPIRE */ 267 BITMAP_SA | BITMAP_ADDRESS_DST, 268 /* FLUSH */ 269 0, 270 /* DUMP */ 271 0, 272 /* X_PROMISC */ 273 0, 274 /* X_ADDFLOW */ 275 BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_FLOW_TYPE, 276 /* X_DELFLOW */ 277 BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_FLOW_TYPE, 278 /* X_GRPSPIS */ 279 BITMAP_SA | BITMAP_X_SA2 | BITMAP_X_DST2 | BITMAP_ADDRESS_DST | BITMAP_X_SATYPE2, 280 /* X_REPPOLICY */ 281 BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_FLOW_TYPE, 282 }; 283 284 int 285 pfkeyv2_parsemessage(void *p, int len, void **headers) 286 { 287 struct sadb_ext *sadb_ext; 288 int i, left = len; 289 uint64_t allow, seen = 1; 290 struct sadb_msg *sadb_msg = (struct sadb_msg *) p; 291 292 bzero(headers, (SADB_EXT_MAX + 1) * sizeof(void *)); 293 294 if (left < sizeof(struct sadb_msg)) { 295 DPRINTF("message too short"); 296 return (EINVAL); 297 } 298 299 headers[0] = p; 300 301 if (sadb_msg->sadb_msg_len * sizeof(uint64_t) != left) { 302 DPRINTF("length not a multiple of 64"); 303 return (EINVAL); 304 } 305 306 p += sizeof(struct sadb_msg); 307 left -= sizeof(struct sadb_msg); 308 309 if (sadb_msg->sadb_msg_reserved) { 310 DPRINTF("message header reserved field set"); 311 return (EINVAL); 312 } 313 314 if (sadb_msg->sadb_msg_type > SADB_MAX) { 315 DPRINTF("message type > %d", SADB_MAX); 316 return (EINVAL); 317 } 318 319 if (!sadb_msg->sadb_msg_type) { 320 DPRINTF("message type unset"); 321 return (EINVAL); 322 } 323 324 if (sadb_msg->sadb_msg_pid != curproc->p_p->ps_pid) { 325 DPRINTF("bad PID value"); 326 return (EINVAL); 327 } 328 329 if (sadb_msg->sadb_msg_errno) { 330 if (left) { 331 DPRINTF("too-large error message"); 332 return (EINVAL); 333 } 334 return (0); 335 } 336 337 if (sadb_msg->sadb_msg_type == SADB_X_PROMISC) { 338 DPRINTF("message type promiscuous"); 339 return (0); 340 } 341 342 allow = sadb_exts_allowed_in[sadb_msg->sadb_msg_type]; 343 344 while (left > 0) { 345 sadb_ext = (struct sadb_ext *)p; 346 if (left < sizeof(struct sadb_ext)) { 347 DPRINTF("extension header too short"); 348 return (EINVAL); 349 } 350 351 i = sadb_ext->sadb_ext_len * sizeof(uint64_t); 352 if (left < i) { 353 DPRINTF("extension header exceeds message length"); 354 return (EINVAL); 355 } 356 357 if (sadb_ext->sadb_ext_type > SADB_EXT_MAX) { 358 DPRINTF("unknown extension header %d", 359 sadb_ext->sadb_ext_type); 360 return (EINVAL); 361 } 362 363 if (!sadb_ext->sadb_ext_type) { 364 DPRINTF("unset extension header"); 365 return (EINVAL); 366 } 367 368 if (!(allow & (1LL << sadb_ext->sadb_ext_type))) { 369 DPRINTF("extension header %d not permitted on message " 370 "type %d", 371 sadb_ext->sadb_ext_type, sadb_msg->sadb_msg_type); 372 return (EINVAL); 373 } 374 375 if (headers[sadb_ext->sadb_ext_type]) { 376 DPRINTF("duplicate extension header %d", 377 sadb_ext->sadb_ext_type); 378 return (EINVAL); 379 } 380 381 seen |= (1LL << sadb_ext->sadb_ext_type); 382 383 switch (sadb_ext->sadb_ext_type) { 384 case SADB_EXT_SA: 385 case SADB_X_EXT_SA2: 386 { 387 struct sadb_sa *sadb_sa = (struct sadb_sa *)p; 388 389 if (i != sizeof(struct sadb_sa)) { 390 DPRINTF("bad header length for SA extension " 391 "header %d", 392 sadb_ext->sadb_ext_type); 393 return (EINVAL); 394 } 395 396 if (sadb_sa->sadb_sa_state > SADB_SASTATE_MAX) { 397 DPRINTF("unknown SA state %d in SA extension " 398 "header %d", 399 sadb_sa->sadb_sa_state, 400 sadb_ext->sadb_ext_type); 401 return (EINVAL); 402 } 403 404 if (sadb_sa->sadb_sa_state == SADB_SASTATE_DEAD) { 405 DPRINTF("cannot set SA state to dead, " 406 "SA extension header %d", 407 sadb_ext->sadb_ext_type); 408 return (EINVAL); 409 } 410 411 if (sadb_sa->sadb_sa_encrypt > SADB_EALG_MAX) { 412 DPRINTF("unknown encryption algorithm %d " 413 "in SA extension header %d", 414 sadb_sa->sadb_sa_encrypt, 415 sadb_ext->sadb_ext_type); 416 return (EINVAL); 417 } 418 419 if (sadb_sa->sadb_sa_auth > SADB_AALG_MAX) { 420 DPRINTF("unknown authentication algorithm %d " 421 "in SA extension header %d", 422 sadb_sa->sadb_sa_auth, 423 sadb_ext->sadb_ext_type); 424 return (EINVAL); 425 } 426 427 if (sadb_sa->sadb_sa_replay > 64) { 428 DPRINTF("unsupported replay window size %d " 429 "in SA extension header %d", 430 sadb_sa->sadb_sa_replay, 431 sadb_ext->sadb_ext_type); 432 return (EINVAL); 433 } 434 } 435 break; 436 case SADB_X_EXT_PROTOCOL: 437 case SADB_X_EXT_FLOW_TYPE: 438 case SADB_X_EXT_SATYPE2: 439 if (i != sizeof(struct sadb_protocol)) { 440 DPRINTF("bad PROTOCOL/FLOW/SATYPE2 header " 441 "length in extension header %d", 442 sadb_ext->sadb_ext_type); 443 return (EINVAL); 444 } 445 break; 446 case SADB_X_EXT_POLICY: 447 if (i != sizeof(struct sadb_x_policy)) { 448 DPRINTF("bad POLICY header length"); 449 return (EINVAL); 450 } 451 break; 452 case SADB_EXT_LIFETIME_CURRENT: 453 case SADB_EXT_LIFETIME_HARD: 454 case SADB_EXT_LIFETIME_SOFT: 455 case SADB_X_EXT_LIFETIME_LASTUSE: 456 if (i != sizeof(struct sadb_lifetime)) { 457 DPRINTF("bad header length for LIFETIME " 458 "extension header %d", 459 sadb_ext->sadb_ext_type); 460 return (EINVAL); 461 } 462 break; 463 case SADB_EXT_ADDRESS_SRC: 464 case SADB_EXT_ADDRESS_DST: 465 case SADB_EXT_ADDRESS_PROXY: 466 case SADB_X_EXT_SRC_MASK: 467 case SADB_X_EXT_DST_MASK: 468 case SADB_X_EXT_SRC_FLOW: 469 case SADB_X_EXT_DST_FLOW: 470 case SADB_X_EXT_DST2: 471 { 472 struct sadb_address *sadb_address = 473 (struct sadb_address *)p; 474 struct sockaddr *sa = (struct sockaddr *)(p + 475 sizeof(struct sadb_address)); 476 477 if (i < sizeof(struct sadb_address) + 478 sizeof(struct sockaddr)) { 479 DPRINTF("bad ADDRESS extension header %d " 480 "length", 481 sadb_ext->sadb_ext_type); 482 return (EINVAL); 483 } 484 485 if (sadb_address->sadb_address_reserved) { 486 DPRINTF("ADDRESS extension header %d reserved " 487 "field set", 488 sadb_ext->sadb_ext_type); 489 return (EINVAL); 490 } 491 if (sa->sa_len && 492 (i != sizeof(struct sadb_address) + 493 PADUP(sa->sa_len))) { 494 DPRINTF("bad sockaddr length field in ADDRESS " 495 "extension header %d", 496 sadb_ext->sadb_ext_type); 497 return (EINVAL); 498 } 499 500 switch (sa->sa_family) { 501 case AF_INET: 502 if (sizeof(struct sadb_address) + 503 PADUP(sizeof(struct sockaddr_in)) != i) { 504 DPRINTF("invalid ADDRESS extension " 505 "header %d length", 506 sadb_ext->sadb_ext_type); 507 return (EINVAL); 508 } 509 510 if (sa->sa_len != sizeof(struct sockaddr_in)) { 511 DPRINTF("bad sockaddr_in length in " 512 "ADDRESS extension header %d", 513 sadb_ext->sadb_ext_type); 514 return (EINVAL); 515 } 516 517 /* Only check the right pieces */ 518 switch (sadb_ext->sadb_ext_type) 519 { 520 case SADB_X_EXT_SRC_MASK: 521 case SADB_X_EXT_DST_MASK: 522 case SADB_X_EXT_SRC_FLOW: 523 case SADB_X_EXT_DST_FLOW: 524 break; 525 526 default: 527 if (((struct sockaddr_in *)sa)->sin_port) { 528 DPRINTF("port field set in " 529 "sockaddr_in of ADDRESS " 530 "extension header %d", 531 sadb_ext->sadb_ext_type); 532 return (EINVAL); 533 } 534 break; 535 } 536 537 { 538 char zero[sizeof(((struct sockaddr_in *)sa)->sin_zero)]; 539 bzero(zero, sizeof(zero)); 540 541 if (bcmp(&((struct sockaddr_in *)sa)->sin_zero, zero, sizeof(zero))) { 542 DPRINTF("reserved sockaddr_in " 543 "field non-zero'ed in " 544 "ADDRESS extension header " 545 "%d", 546 sadb_ext->sadb_ext_type); 547 return (EINVAL); 548 } 549 } 550 break; 551 #ifdef INET6 552 case AF_INET6: 553 if (i != sizeof(struct sadb_address) + 554 PADUP(sizeof(struct sockaddr_in6))) { 555 DPRINTF("invalid sockaddr_in6 length " 556 "in ADDRESS extension header %d", 557 sadb_ext->sadb_ext_type); 558 return (EINVAL); 559 } 560 561 if (sa->sa_len != 562 sizeof(struct sockaddr_in6)) { 563 DPRINTF("bad sockaddr_in6 length in " 564 "ADDRESS extension header %d", 565 sadb_ext->sadb_ext_type); 566 return (EINVAL); 567 } 568 569 if (((struct sockaddr_in6 *)sa)->sin6_flowinfo) { 570 DPRINTF("flowinfo field set in " 571 "sockaddr_in6 of ADDRESS " 572 "extension header %d", 573 sadb_ext->sadb_ext_type); 574 return (EINVAL); 575 } 576 577 /* Only check the right pieces */ 578 switch (sadb_ext->sadb_ext_type) 579 { 580 case SADB_X_EXT_SRC_MASK: 581 case SADB_X_EXT_DST_MASK: 582 case SADB_X_EXT_SRC_FLOW: 583 case SADB_X_EXT_DST_FLOW: 584 break; 585 586 default: 587 if (((struct sockaddr_in6 *)sa)->sin6_port) { 588 DPRINTF("port field set in " 589 "sockaddr_in6 of ADDRESS " 590 "extension header %d", 591 sadb_ext->sadb_ext_type); 592 return (EINVAL); 593 } 594 break; 595 } 596 break; 597 #endif /* INET6 */ 598 default: 599 if (sadb_msg->sadb_msg_satype == 600 SADB_X_SATYPE_TCPSIGNATURE && 601 sa->sa_family == 0) 602 break; 603 DPRINTF("unknown address family %d in ADDRESS " 604 "extension header %d", 605 sa->sa_family, sadb_ext->sadb_ext_type); 606 return (EINVAL); 607 } 608 } 609 break; 610 case SADB_EXT_KEY_AUTH: 611 case SADB_EXT_KEY_ENCRYPT: 612 { 613 struct sadb_key *sadb_key = (struct sadb_key *)p; 614 615 if (i < sizeof(struct sadb_key)) { 616 DPRINTF("bad header length in KEY extension " 617 "header %d", 618 sadb_ext->sadb_ext_type); 619 return (EINVAL); 620 } 621 622 if (!sadb_key->sadb_key_bits) { 623 DPRINTF("key length unset in KEY extension " 624 "header %d", 625 sadb_ext->sadb_ext_type); 626 return (EINVAL); 627 } 628 629 if (((sadb_key->sadb_key_bits + 63) / 64) * sizeof(uint64_t) != i - sizeof(struct sadb_key)) { 630 DPRINTF("invalid key length in KEY extension " 631 "header %d", 632 sadb_ext->sadb_ext_type); 633 return (EINVAL); 634 } 635 636 if (sadb_key->sadb_key_reserved) { 637 DPRINTF("reserved field set in KEY extension " 638 "header %d", 639 sadb_ext->sadb_ext_type); 640 return (EINVAL); 641 } 642 } 643 break; 644 case SADB_EXT_IDENTITY_SRC: 645 case SADB_EXT_IDENTITY_DST: 646 { 647 struct sadb_ident *sadb_ident = (struct sadb_ident *)p; 648 649 if (i < sizeof(struct sadb_ident)) { 650 DPRINTF("bad header length of IDENTITY " 651 "extension header %d", 652 sadb_ext->sadb_ext_type); 653 return (EINVAL); 654 } 655 656 if (sadb_ident->sadb_ident_type > SADB_IDENTTYPE_MAX) { 657 DPRINTF("unknown identity type %d in IDENTITY " 658 "extension header %d", 659 sadb_ident->sadb_ident_type, 660 sadb_ext->sadb_ext_type); 661 return (EINVAL); 662 } 663 664 if (sadb_ident->sadb_ident_reserved) { 665 DPRINTF("reserved field set in IDENTITY " 666 "extension header %d", 667 sadb_ext->sadb_ext_type); 668 return (EINVAL); 669 } 670 671 if (i > sizeof(struct sadb_ident)) { 672 char *c = 673 (char *)(p + sizeof(struct sadb_ident)); 674 int j; 675 676 if (*(char *)(p + i - 1)) { 677 DPRINTF("non NUL-terminated identity " 678 "in IDENTITY extension header %d", 679 sadb_ext->sadb_ext_type); 680 return (EINVAL); 681 } 682 683 j = PADUP(strlen(c) + 1) + 684 sizeof(struct sadb_ident); 685 686 if (i != j) { 687 DPRINTF("actual identity length does " 688 "not match expected length in " 689 "identity extension header %d", 690 sadb_ext->sadb_ext_type); 691 return (EINVAL); 692 } 693 } 694 } 695 break; 696 case SADB_EXT_SENSITIVITY: 697 { 698 struct sadb_sens *sadb_sens = (struct sadb_sens *)p; 699 700 if (i < sizeof(struct sadb_sens)) { 701 DPRINTF("bad header length for SENSITIVITY " 702 "extension header"); 703 return (EINVAL); 704 } 705 706 if (i != (sadb_sens->sadb_sens_sens_len + 707 sadb_sens->sadb_sens_integ_len) * 708 sizeof(uint64_t) + 709 sizeof(struct sadb_sens)) { 710 DPRINTF("bad payload length for SENSITIVITY " 711 "extension header"); 712 return (EINVAL); 713 } 714 } 715 break; 716 case SADB_EXT_PROPOSAL: 717 { 718 struct sadb_prop *sadb_prop = (struct sadb_prop *)p; 719 720 if (i < sizeof(struct sadb_prop)) { 721 DPRINTF("bad PROPOSAL header length"); 722 return (EINVAL); 723 } 724 725 if (sadb_prop->sadb_prop_reserved) { 726 DPRINTF("reserved fieldset in PROPOSAL " 727 "extension header"); 728 return (EINVAL); 729 } 730 731 if ((i - sizeof(struct sadb_prop)) % 732 sizeof(struct sadb_comb)) { 733 DPRINTF("bad proposal length"); 734 return (EINVAL); 735 } 736 737 { 738 struct sadb_comb *sadb_comb = 739 (struct sadb_comb *)(p + 740 sizeof(struct sadb_prop)); 741 int j; 742 743 for (j = 0; 744 j < (i - sizeof(struct sadb_prop))/ 745 sizeof(struct sadb_comb); 746 j++) { 747 if (sadb_comb->sadb_comb_auth > 748 SADB_AALG_MAX) { 749 DPRINTF("unknown " 750 "authentication algorithm " 751 "%d in PROPOSAL", 752 sadb_comb->sadb_comb_auth); 753 return (EINVAL); 754 } 755 756 if (sadb_comb->sadb_comb_encrypt > 757 SADB_EALG_MAX) { 758 DPRINTF("unknown encryption " 759 "algorithm %d in PROPOSAL", 760 sadb_comb-> 761 sadb_comb_encrypt); 762 return (EINVAL); 763 } 764 765 if (sadb_comb->sadb_comb_reserved) { 766 DPRINTF("reserved field set " 767 "in COMB header"); 768 return (EINVAL); 769 } 770 } 771 } 772 } 773 break; 774 case SADB_EXT_SUPPORTED_AUTH: 775 case SADB_EXT_SUPPORTED_ENCRYPT: 776 case SADB_X_EXT_SUPPORTED_COMP: 777 { 778 struct sadb_supported *sadb_supported = 779 (struct sadb_supported *)p; 780 int j; 781 782 if (i < sizeof(struct sadb_supported)) { 783 DPRINTF("bad header length for SUPPORTED " "extension header %d", 784 sadb_ext->sadb_ext_type); 785 return (EINVAL); 786 } 787 788 if (sadb_supported->sadb_supported_reserved) { 789 DPRINTF("reserved field set in SUPPORTED " 790 "extension header %d", 791 sadb_ext->sadb_ext_type); 792 return (EINVAL); 793 } 794 795 { 796 struct sadb_alg *sadb_alg = 797 (struct sadb_alg *)(p + 798 sizeof(struct sadb_supported)); 799 int max_alg; 800 801 max_alg = sadb_ext->sadb_ext_type == 802 SADB_EXT_SUPPORTED_AUTH ? 803 SADB_AALG_MAX : SADB_EXT_SUPPORTED_ENCRYPT ? 804 SADB_EALG_MAX : SADB_X_CALG_MAX; 805 806 for (j = 0; 807 j < sadb_supported->sadb_supported_len - 1; 808 j++) { 809 if (sadb_alg->sadb_alg_id > max_alg) { 810 DPRINTF("unknown algorithm %d " 811 "in SUPPORTED extension " 812 "header %d", 813 sadb_alg->sadb_alg_id, 814 sadb_ext->sadb_ext_type); 815 return (EINVAL); 816 } 817 818 if (sadb_alg->sadb_alg_reserved) { 819 DPRINTF("reserved field set " 820 "in supported algorithms " 821 "header inside SUPPORTED " 822 "extension header %d", 823 sadb_ext->sadb_ext_type); 824 return (EINVAL); 825 } 826 827 sadb_alg++; 828 } 829 } 830 } 831 break; 832 case SADB_EXT_SPIRANGE: 833 { 834 struct sadb_spirange *sadb_spirange = 835 (struct sadb_spirange *)p; 836 837 if (i != sizeof(struct sadb_spirange)) { 838 DPRINTF("bad header length of SPIRANGE " 839 "extension header"); 840 return (EINVAL); 841 } 842 843 if (sadb_spirange->sadb_spirange_min > 844 sadb_spirange->sadb_spirange_max) { 845 DPRINTF("bad SPI range"); 846 return (EINVAL); 847 } 848 } 849 break; 850 case SADB_X_EXT_UDPENCAP: 851 if (i != sizeof(struct sadb_x_udpencap)) { 852 DPRINTF("bad UDPENCAP header length"); 853 return (EINVAL); 854 } 855 break; 856 case SADB_X_EXT_RDOMAIN: 857 if (i != sizeof(struct sadb_x_rdomain)) { 858 DPRINTF("bad RDOMAIN header length"); 859 return (EINVAL); 860 } 861 break; 862 #if NPF > 0 863 case SADB_X_EXT_TAG: 864 if (i < sizeof(struct sadb_x_tag)) { 865 DPRINTF("TAG extension header too small"); 866 return (EINVAL); 867 } 868 if (i > (sizeof(struct sadb_x_tag) + 869 PF_TAG_NAME_SIZE)) { 870 DPRINTF("TAG extension header too long"); 871 return (EINVAL); 872 } 873 break; 874 case SADB_X_EXT_TAP: 875 if (i < sizeof(struct sadb_x_tap)) { 876 DPRINTF("TAP extension header too small"); 877 return (EINVAL); 878 } 879 if (i > sizeof(struct sadb_x_tap)) { 880 DPRINTF("TAP extension header too long"); 881 return (EINVAL); 882 } 883 break; 884 #endif 885 case SADB_X_EXT_IFACE: 886 if (i != sizeof(struct sadb_x_iface)) { 887 DPRINTF("bad IFACE header length"); 888 return (EINVAL); 889 } 890 break; 891 default: 892 DPRINTF("unknown extension header type %d", 893 sadb_ext->sadb_ext_type); 894 return (EINVAL); 895 } 896 897 headers[sadb_ext->sadb_ext_type] = p; 898 p += i; 899 left -= i; 900 } 901 902 if (left) { 903 DPRINTF("message too long"); 904 return (EINVAL); 905 } 906 907 { 908 uint64_t required; 909 910 required = sadb_exts_required_in[sadb_msg->sadb_msg_type]; 911 912 if ((seen & required) != required) { 913 DPRINTF("required fields missing"); 914 return (EINVAL); 915 } 916 } 917 918 switch (((struct sadb_msg *)headers[0])->sadb_msg_type) { 919 case SADB_UPDATE: 920 if (((struct sadb_sa *)headers[SADB_EXT_SA])->sadb_sa_state != 921 SADB_SASTATE_MATURE) { 922 DPRINTF("updating non-mature SA prohibited"); 923 return (EINVAL); 924 } 925 break; 926 case SADB_ADD: 927 if (((struct sadb_sa *)headers[SADB_EXT_SA])->sadb_sa_state != 928 SADB_SASTATE_MATURE) { 929 DPRINTF("adding non-mature SA prohibited"); 930 return (EINVAL); 931 } 932 break; 933 } 934 935 return (0); 936 } 937