1 /* $OpenBSD: pfkeyv2_parsemessage.c,v 1.49 2015/04/14 12:22:15 mikeb 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 <netinet/ip_var.h> 80 #include <net/pfkeyv2.h> 81 82 #if NPF > 0 83 #include <net/if.h> 84 #include <net/pfvar.h> 85 #endif 86 87 #ifdef ENCDEBUG 88 #define DPRINTF(x) if (encdebug) printf x 89 #else 90 #define DPRINTF(x) 91 #endif 92 93 #define BITMAP_SA (1LL << SADB_EXT_SA) 94 #define BITMAP_LIFETIME_CURRENT (1LL << SADB_EXT_LIFETIME_CURRENT) 95 #define BITMAP_LIFETIME_HARD (1LL << SADB_EXT_LIFETIME_HARD) 96 #define BITMAP_LIFETIME_SOFT (1LL << SADB_EXT_LIFETIME_SOFT) 97 #define BITMAP_ADDRESS_SRC (1LL << SADB_EXT_ADDRESS_SRC) 98 #define BITMAP_ADDRESS_DST (1LL << SADB_EXT_ADDRESS_DST) 99 #define BITMAP_KEY_AUTH (1LL << SADB_EXT_KEY_AUTH) 100 #define BITMAP_KEY_ENCRYPT (1LL << SADB_EXT_KEY_ENCRYPT) 101 #define BITMAP_IDENTITY_SRC (1LL << SADB_EXT_IDENTITY_SRC) 102 #define BITMAP_IDENTITY_DST (1LL << SADB_EXT_IDENTITY_DST) 103 #define BITMAP_SENSITIVITY (1LL << SADB_EXT_SENSITIVITY) 104 #define BITMAP_PROPOSAL (1LL << SADB_EXT_PROPOSAL) 105 #define BITMAP_SUPPORTED_AUTH (1LL << SADB_EXT_SUPPORTED_AUTH) 106 #define BITMAP_SUPPORTED_ENCRYPT (1LL << SADB_EXT_SUPPORTED_ENCRYPT) 107 #define BITMAP_SPIRANGE (1LL << SADB_EXT_SPIRANGE) 108 #define BITMAP_LIFETIME (BITMAP_LIFETIME_CURRENT | BITMAP_LIFETIME_HARD | BITMAP_LIFETIME_SOFT) 109 #define BITMAP_ADDRESS (BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST) 110 #define BITMAP_KEY (BITMAP_KEY_AUTH | BITMAP_KEY_ENCRYPT) 111 #define BITMAP_IDENTITY (BITMAP_IDENTITY_SRC | BITMAP_IDENTITY_DST) 112 #define BITMAP_MSG 1 113 #define BITMAP_X_SRC_MASK (1LL << SADB_X_EXT_SRC_MASK) 114 #define BITMAP_X_DST_MASK (1LL << SADB_X_EXT_DST_MASK) 115 #define BITMAP_X_PROTOCOL (1LL << SADB_X_EXT_PROTOCOL) 116 #define BITMAP_X_SRC_FLOW (1LL << SADB_X_EXT_SRC_FLOW) 117 #define BITMAP_X_DST_FLOW (1LL << SADB_X_EXT_DST_FLOW) 118 #define BITMAP_X_FLOW_TYPE (1LL << SADB_X_EXT_FLOW_TYPE) 119 #define BITMAP_X_SA2 (1LL << SADB_X_EXT_SA2) 120 #define BITMAP_X_DST2 (1LL << SADB_X_EXT_DST2) 121 #define BITMAP_X_POLICY (1LL << SADB_X_EXT_POLICY) 122 #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) 123 #define BITMAP_X_SUPPORTED_COMP (1LL << SADB_X_EXT_SUPPORTED_COMP) 124 #define BITMAP_X_UDPENCAP (1LL << SADB_X_EXT_UDPENCAP) 125 #define BITMAP_X_LIFETIME_LASTUSE (1LL << SADB_X_EXT_LIFETIME_LASTUSE) 126 #define BITMAP_X_TAG (1LL << SADB_X_EXT_TAG) 127 #define BITMAP_X_TAP (1LL << SADB_X_EXT_TAP) 128 129 uint64_t sadb_exts_allowed_in[SADB_MAX+1] = 130 { 131 /* RESERVED */ 132 ~0, 133 /* GETSPI */ 134 BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_SPIRANGE, 135 /* UPDATE */ 136 BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS | BITMAP_KEY | BITMAP_IDENTITY | BITMAP_X_FLOW | BITMAP_X_UDPENCAP | BITMAP_X_TAG | BITMAP_X_TAP, 137 /* ADD */ 138 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, 139 /* DELETE */ 140 BITMAP_SA | BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST, 141 /* GET */ 142 BITMAP_SA | BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST, 143 /* ACQUIRE */ 144 BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_IDENTITY | BITMAP_PROPOSAL, 145 /* REGISTER */ 146 0, 147 /* EXPIRE */ 148 BITMAP_SA | BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST, 149 /* FLUSH */ 150 0, 151 /* DUMP */ 152 0, 153 /* X_PROMISC */ 154 0, 155 /* X_ADDFLOW */ 156 BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_IDENTITY_SRC | BITMAP_IDENTITY_DST | BITMAP_X_FLOW, 157 /* X_DELFLOW */ 158 BITMAP_X_FLOW, 159 /* X_GRPSPIS */ 160 BITMAP_SA | BITMAP_X_SA2 | BITMAP_X_DST2 | BITMAP_ADDRESS_DST | BITMAP_X_PROTOCOL, 161 /* X_ASKPOLICY */ 162 BITMAP_X_POLICY, 163 }; 164 165 uint64_t sadb_exts_required_in[SADB_MAX+1] = 166 { 167 /* RESERVED */ 168 0, 169 /* GETSPI */ 170 BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_SPIRANGE, 171 /* UPDATE */ 172 BITMAP_SA | BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST, 173 /* ADD */ 174 BITMAP_SA | BITMAP_ADDRESS_DST, 175 /* DELETE */ 176 BITMAP_SA | BITMAP_ADDRESS_DST, 177 /* GET */ 178 BITMAP_SA | BITMAP_ADDRESS_DST, 179 /* ACQUIRE */ 180 0, 181 /* REGISTER */ 182 0, 183 /* EXPIRE */ 184 BITMAP_SA | BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST, 185 /* FLUSH */ 186 0, 187 /* DUMP */ 188 0, 189 /* X_PROMISC */ 190 0, 191 /* X_ADDFLOW */ 192 BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_FLOW_TYPE, 193 /* X_DELFLOW */ 194 BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_FLOW_TYPE, 195 /* X_GRPSPIS */ 196 BITMAP_SA | BITMAP_X_SA2 | BITMAP_X_DST2 | BITMAP_ADDRESS_DST | BITMAP_X_PROTOCOL, 197 /* X_ASKPOLICY */ 198 BITMAP_X_POLICY, 199 }; 200 201 uint64_t sadb_exts_allowed_out[SADB_MAX+1] = 202 { 203 /* RESERVED */ 204 ~0, 205 /* GETSPI */ 206 BITMAP_SA | BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST, 207 /* UPDATE */ 208 BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS | BITMAP_IDENTITY | BITMAP_X_FLOW | BITMAP_X_UDPENCAP | BITMAP_X_TAG | BITMAP_X_TAP, 209 /* ADD */ 210 BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS | BITMAP_IDENTITY | BITMAP_X_FLOW | BITMAP_X_UDPENCAP | BITMAP_X_TAG | BITMAP_X_TAP, 211 /* DELETE */ 212 BITMAP_SA | BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST, 213 /* GET */ 214 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, 215 /* ACQUIRE */ 216 BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_IDENTITY | BITMAP_PROPOSAL, 217 /* REGISTER */ 218 BITMAP_SUPPORTED_AUTH | BITMAP_SUPPORTED_ENCRYPT | BITMAP_X_SUPPORTED_COMP, 219 /* EXPIRE */ 220 BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS, 221 /* FLUSH */ 222 0, 223 /* DUMP */ 224 BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS | BITMAP_IDENTITY, 225 /* X_PROMISC */ 226 0, 227 /* X_ADDFLOW */ 228 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, 229 /* X_DELFLOW */ 230 BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_PROTOCOL | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_FLOW_TYPE, 231 /* X_GRPSPIS */ 232 BITMAP_SA | BITMAP_X_SA2 | BITMAP_X_DST2 | BITMAP_ADDRESS_DST | BITMAP_X_PROTOCOL, 233 /* X_ASKPOLICY */ 234 BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_FLOW_TYPE | BITMAP_X_POLICY, 235 }; 236 237 uint64_t sadb_exts_required_out[SADB_MAX+1] = 238 { 239 /* RESERVED */ 240 0, 241 /* GETSPI */ 242 BITMAP_SA | BITMAP_ADDRESS_DST, 243 /* UPDATE */ 244 BITMAP_SA | BITMAP_ADDRESS_DST, 245 /* ADD */ 246 BITMAP_SA | BITMAP_ADDRESS_DST, 247 /* DELETE */ 248 BITMAP_SA | BITMAP_ADDRESS_DST, 249 /* GET */ 250 BITMAP_SA | BITMAP_LIFETIME_CURRENT | BITMAP_ADDRESS_DST, 251 /* ACQUIRE */ 252 0, 253 /* REGISTER */ 254 BITMAP_SUPPORTED_AUTH | BITMAP_SUPPORTED_ENCRYPT | BITMAP_X_SUPPORTED_COMP, 255 /* EXPIRE */ 256 BITMAP_SA | BITMAP_ADDRESS_DST, 257 /* FLUSH */ 258 0, 259 /* DUMP */ 260 0, 261 /* X_PROMISC */ 262 0, 263 /* X_ADDFLOW */ 264 BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_FLOW_TYPE, 265 /* X_DELFLOW */ 266 BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_FLOW_TYPE, 267 /* X_GRPSPIS */ 268 BITMAP_SA | BITMAP_X_SA2 | BITMAP_X_DST2 | BITMAP_ADDRESS_DST | BITMAP_X_PROTOCOL, 269 /* X_REPPOLICY */ 270 BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_FLOW_TYPE, 271 }; 272 273 int pfkeyv2_parsemessage(void *, int, void **); 274 275 #define RETURN_EINVAL(line) goto einval; 276 277 int 278 pfkeyv2_parsemessage(void *p, int len, void **headers) 279 { 280 struct sadb_ext *sadb_ext; 281 int i, left = len; 282 uint64_t allow, seen = 1; 283 struct sadb_msg *sadb_msg = (struct sadb_msg *) p; 284 285 bzero(headers, (SADB_EXT_MAX + 1) * sizeof(void *)); 286 287 if (left < sizeof(struct sadb_msg)) { 288 DPRINTF(("pfkeyv2_parsemessage: message too short\n")); 289 return (EINVAL); 290 } 291 292 headers[0] = p; 293 294 if (sadb_msg->sadb_msg_len * sizeof(uint64_t) != left) { 295 DPRINTF(("pfkeyv2_parsemessage: length not a multiple of 64\n")); 296 return (EINVAL); 297 } 298 299 p += sizeof(struct sadb_msg); 300 left -= sizeof(struct sadb_msg); 301 302 if (sadb_msg->sadb_msg_reserved) { 303 DPRINTF(("pfkeyv2_parsemessage: message header reserved " 304 "field set\n")); 305 return (EINVAL); 306 } 307 308 if (sadb_msg->sadb_msg_type > SADB_MAX) { 309 DPRINTF(("pfkeyv2_parsemessage: message type > %d\n", 310 SADB_MAX)); 311 return (EINVAL); 312 } 313 314 if (!sadb_msg->sadb_msg_type) { 315 DPRINTF(("pfkeyv2_parsemessage: message type unset\n")); 316 return (EINVAL); 317 } 318 319 if (sadb_msg->sadb_msg_pid != curproc->p_p->ps_pid) { 320 DPRINTF(("pfkeyv2_parsemessage: bad PID value\n")); 321 return (EINVAL); 322 } 323 324 if (sadb_msg->sadb_msg_errno) { 325 if (left) { 326 DPRINTF(("pfkeyv2_parsemessage: too-large error message\n")); 327 return (EINVAL); 328 } 329 return (0); 330 } 331 332 if (sadb_msg->sadb_msg_type == SADB_X_PROMISC) { 333 DPRINTF(("pfkeyv2_parsemessage: message type promiscuous\n")); 334 return (0); 335 } 336 337 allow = sadb_exts_allowed_in[sadb_msg->sadb_msg_type]; 338 339 while (left > 0) { 340 sadb_ext = (struct sadb_ext *)p; 341 if (left < sizeof(struct sadb_ext)) { 342 DPRINTF(("pfkeyv2_parsemessage: extension header too " 343 "short\n")); 344 return (EINVAL); 345 } 346 347 i = sadb_ext->sadb_ext_len * sizeof(uint64_t); 348 if (left < i) { 349 DPRINTF(("pfkeyv2_parsemessage: extension header " 350 "exceeds message length\n")); 351 return (EINVAL); 352 } 353 354 if (sadb_ext->sadb_ext_type > SADB_EXT_MAX) { 355 DPRINTF(("pfkeyv2_parsemessage: unknown extension " 356 "header %d\n", sadb_ext->sadb_ext_type)); 357 return (EINVAL); 358 } 359 360 if (!sadb_ext->sadb_ext_type) { 361 DPRINTF(("pfkeyv2_parsemessage: unset extension " 362 "header\n")); 363 return (EINVAL); 364 } 365 366 if (!(allow & (1LL << sadb_ext->sadb_ext_type))) { 367 DPRINTF(("pfkeyv2_parsemessage: extension header %d " 368 "not permitted on message type %d\n", 369 sadb_ext->sadb_ext_type, sadb_msg->sadb_msg_type)); 370 return (EINVAL); 371 } 372 373 if (headers[sadb_ext->sadb_ext_type]) { 374 DPRINTF(("pfkeyv2_parsemessage: duplicate extension " 375 "header %d\n", sadb_ext->sadb_ext_type)); 376 return (EINVAL); 377 } 378 379 seen |= (1LL << sadb_ext->sadb_ext_type); 380 381 switch (sadb_ext->sadb_ext_type) { 382 case SADB_EXT_SA: 383 case SADB_X_EXT_SA2: 384 { 385 struct sadb_sa *sadb_sa = (struct sadb_sa *)p; 386 387 if (i != sizeof(struct sadb_sa)) { 388 DPRINTF(("pfkeyv2_parsemessage: bad header " 389 "length for SA extension header %d\n", 390 sadb_ext->sadb_ext_type)); 391 return (EINVAL); 392 } 393 394 if (sadb_sa->sadb_sa_state > SADB_SASTATE_MAX) { 395 DPRINTF(("pfkeyv2_parsemessage: unknown SA " 396 "state %d in SA extension header %d\n", 397 sadb_sa->sadb_sa_state, 398 sadb_ext->sadb_ext_type)); 399 return (EINVAL); 400 } 401 402 if (sadb_sa->sadb_sa_state == SADB_SASTATE_DEAD) { 403 DPRINTF(("pfkeyv2_parsemessage: cannot set SA " 404 "state to dead, SA extension header %d\n", 405 sadb_ext->sadb_ext_type)); 406 return (EINVAL); 407 } 408 409 if (sadb_sa->sadb_sa_encrypt > SADB_EALG_MAX) { 410 DPRINTF(("pfkeyv2_parsemessage: unknown " 411 "encryption algorithm %d in SA extension " 412 "header %d\n", sadb_sa->sadb_sa_encrypt, 413 sadb_ext->sadb_ext_type)); 414 return (EINVAL); 415 } 416 417 if (sadb_sa->sadb_sa_auth > SADB_AALG_MAX) { 418 DPRINTF(("pfkeyv2_parsemessage: unknown " 419 "authentication algorithm %d in SA " 420 "extension header %d\n", 421 sadb_sa->sadb_sa_auth, 422 sadb_ext->sadb_ext_type)); 423 return (EINVAL); 424 } 425 426 if (sadb_sa->sadb_sa_replay > 64) { 427 DPRINTF(("pfkeyv2_parsemessage: unsupported " 428 "replay window size %d in SA extension " 429 "header %d\n", sadb_sa->sadb_sa_replay, 430 sadb_ext->sadb_ext_type)); 431 return (EINVAL); 432 } 433 } 434 break; 435 case SADB_X_EXT_PROTOCOL: 436 case SADB_X_EXT_FLOW_TYPE: 437 if (i != sizeof(struct sadb_protocol)) { 438 DPRINTF(("pfkeyv2_parsemessage: bad " 439 "PROTOCOL/FLOW header length in extension " 440 "header %d\n", sadb_ext->sadb_ext_type)); 441 return (EINVAL); 442 } 443 break; 444 case SADB_X_EXT_POLICY: 445 if (i != sizeof(struct sadb_x_policy)) { 446 DPRINTF(("pfkeyv2_parsemessage: bad POLICY " 447 "header length\n")); 448 return (EINVAL); 449 } 450 break; 451 case SADB_EXT_LIFETIME_CURRENT: 452 case SADB_EXT_LIFETIME_HARD: 453 case SADB_EXT_LIFETIME_SOFT: 454 case SADB_X_EXT_LIFETIME_LASTUSE: 455 if (i != sizeof(struct sadb_lifetime)) { 456 DPRINTF(("pfkeyv2_parsemessage: bad header " 457 "length for LIFETIME extension header " 458 "%d\n", sadb_ext->sadb_ext_type)); 459 return (EINVAL); 460 } 461 break; 462 case SADB_EXT_ADDRESS_SRC: 463 case SADB_EXT_ADDRESS_DST: 464 case SADB_X_EXT_SRC_MASK: 465 case SADB_X_EXT_DST_MASK: 466 case SADB_X_EXT_SRC_FLOW: 467 case SADB_X_EXT_DST_FLOW: 468 case SADB_X_EXT_DST2: 469 { 470 struct sadb_address *sadb_address = 471 (struct sadb_address *)p; 472 struct sockaddr *sa = (struct sockaddr *)(p + 473 sizeof(struct sadb_address)); 474 475 if (i < sizeof(struct sadb_address) + 476 sizeof(struct sockaddr)) { 477 DPRINTF(("pfkeyv2_parsemessage: bad ADDRESS " 478 "extension header %d length\n", 479 sadb_ext->sadb_ext_type)); 480 return (EINVAL); 481 } 482 483 if (sadb_address->sadb_address_reserved) { 484 DPRINTF(("pfkeyv2_parsemessage: ADDRESS " 485 "extension header %d reserved field set\n", 486 sadb_ext->sadb_ext_type)); 487 return (EINVAL); 488 } 489 if (sa->sa_len && 490 (i != sizeof(struct sadb_address) + 491 PADUP(sa->sa_len))) { 492 DPRINTF(("pfkeyv2_parsemessage: bad sockaddr " 493 "length field in ADDRESS extension " 494 "header %d\n", sadb_ext->sadb_ext_type)); 495 return (EINVAL); 496 } 497 498 switch (sa->sa_family) { 499 case AF_INET: 500 if (sizeof(struct sadb_address) + 501 PADUP(sizeof(struct sockaddr_in)) != i) { 502 DPRINTF(("pfkeyv2_parsemessage: " 503 "invalid ADDRESS extension header " 504 "%d length\n", 505 sadb_ext->sadb_ext_type)); 506 return (EINVAL); 507 } 508 509 if (sa->sa_len != sizeof(struct sockaddr_in)) { 510 DPRINTF(("pfkeyv2_parsemessage: bad " 511 "sockaddr_in length in ADDRESS " 512 "extension header %d\n", 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(("pfkeyv2_parsemessage" 529 ": port field set in " 530 "sockaddr_in of ADDRESS " 531 "extension header %d\n", 532 sadb_ext->sadb_ext_type)); 533 return (EINVAL); 534 } 535 break; 536 } 537 538 { 539 char zero[sizeof(((struct sockaddr_in *)sa)->sin_zero)]; 540 bzero(zero, sizeof(zero)); 541 542 if (bcmp(&((struct sockaddr_in *)sa)->sin_zero, zero, sizeof(zero))) { 543 DPRINTF(("pfkeyv2_parsemessage" 544 ": reserved sockaddr_in " 545 "field non-zero'ed in " 546 "ADDRESS extension header " 547 "%d\n", 548 sadb_ext->sadb_ext_type)); 549 return (EINVAL); 550 } 551 } 552 break; 553 #ifdef INET6 554 case AF_INET6: 555 if (i != sizeof(struct sadb_address) + 556 PADUP(sizeof(struct sockaddr_in6))) { 557 DPRINTF(("pfkeyv2_parsemessage: " 558 "invalid sockaddr_in6 length in " 559 "ADDRESS extension header %d\n", 560 sadb_ext->sadb_ext_type)); 561 return (EINVAL); 562 } 563 564 if (sa->sa_len != 565 sizeof(struct sockaddr_in6)) { 566 DPRINTF(("pfkeyv2_parsemessage: bad " 567 "sockaddr_in6 length in ADDRESS " 568 "extension header %d\n", 569 sadb_ext->sadb_ext_type)); 570 return (EINVAL); 571 } 572 573 if (((struct sockaddr_in6 *)sa)->sin6_flowinfo) { 574 DPRINTF(("pfkeyv2_parsemessage: " 575 "flowinfo field set in " 576 "sockaddr_in6 of ADDRESS " 577 "extension header %d\n", 578 sadb_ext->sadb_ext_type)); 579 return (EINVAL); 580 } 581 582 /* Only check the right pieces */ 583 switch (sadb_ext->sadb_ext_type) 584 { 585 case SADB_X_EXT_SRC_MASK: 586 case SADB_X_EXT_DST_MASK: 587 case SADB_X_EXT_SRC_FLOW: 588 case SADB_X_EXT_DST_FLOW: 589 break; 590 591 default: 592 if (((struct sockaddr_in6 *)sa)->sin6_port) { 593 DPRINTF(("pfkeyv2_parsemessage" 594 ": port field set in " 595 "sockaddr_in6 of ADDRESS " 596 "extension header %d\n", 597 sadb_ext->sadb_ext_type)); 598 return (EINVAL); 599 } 600 break; 601 } 602 break; 603 #endif /* INET6 */ 604 default: 605 if (sadb_msg->sadb_msg_satype == 606 SADB_X_SATYPE_TCPSIGNATURE && 607 sa->sa_family == 0) 608 break; 609 DPRINTF(("pfkeyv2_parsemessage: unknown " 610 "address family %d in ADDRESS extension " 611 "header %d\n", 612 sa->sa_family, sadb_ext->sadb_ext_type)); 613 return (EINVAL); 614 } 615 } 616 break; 617 case SADB_EXT_KEY_AUTH: 618 case SADB_EXT_KEY_ENCRYPT: 619 { 620 struct sadb_key *sadb_key = (struct sadb_key *)p; 621 622 if (i < sizeof(struct sadb_key)) { 623 DPRINTF(("pfkeyv2_parsemessage: bad header " 624 "length in KEY extension header %d\n", 625 sadb_ext->sadb_ext_type)); 626 return (EINVAL); 627 } 628 629 if (!sadb_key->sadb_key_bits) { 630 DPRINTF(("pfkeyv2_parsemessage: key length " 631 "unset in KEY extension header %d\n", 632 sadb_ext->sadb_ext_type)); 633 return (EINVAL); 634 } 635 636 if (((sadb_key->sadb_key_bits + 63) / 64) * sizeof(uint64_t) != i - sizeof(struct sadb_key)) { 637 DPRINTF(("pfkeyv2_parsemessage: invalid key " 638 "length in KEY extension header %d\n", 639 sadb_ext->sadb_ext_type)); 640 return (EINVAL); 641 } 642 643 if (sadb_key->sadb_key_reserved) { 644 DPRINTF(("pfkeyv2_parsemessage: reserved field" 645 " set in KEY extension header %d\n", 646 sadb_ext->sadb_ext_type)); 647 return (EINVAL); 648 } 649 } 650 break; 651 case SADB_EXT_IDENTITY_SRC: 652 case SADB_EXT_IDENTITY_DST: 653 { 654 struct sadb_ident *sadb_ident = (struct sadb_ident *)p; 655 656 if (i < sizeof(struct sadb_ident)) { 657 DPRINTF(("pfkeyv2_parsemessage: bad header " 658 "length of IDENTITY extension header %d\n", 659 sadb_ext->sadb_ext_type)); 660 return (EINVAL); 661 } 662 663 if (sadb_ident->sadb_ident_type > SADB_IDENTTYPE_MAX) { 664 DPRINTF(("pfkeyv2_parsemessage: unknown " 665 "identity type %d in IDENTITY extension " 666 "header %d\n", 667 sadb_ident->sadb_ident_type, 668 sadb_ext->sadb_ext_type)); 669 return (EINVAL); 670 } 671 672 if (sadb_ident->sadb_ident_reserved) { 673 DPRINTF(("pfkeyv2_parsemessage: reserved " 674 "field set in IDENTITY extension header " 675 "%d\n", sadb_ext->sadb_ext_type)); 676 return (EINVAL); 677 } 678 679 if (i > sizeof(struct sadb_ident)) { 680 char *c = 681 (char *)(p + sizeof(struct sadb_ident)); 682 int j; 683 684 if (*(char *)(p + i - 1)) { 685 DPRINTF(("pfkeyv2_parsemessage: non " 686 "NUL-terminated identity in " 687 "IDENTITY extension header %d\n", 688 sadb_ext->sadb_ext_type)); 689 return (EINVAL); 690 } 691 692 j = PADUP(strlen(c) + 1) + 693 sizeof(struct sadb_ident); 694 695 if (i != j) { 696 DPRINTF(("pfkeyv2_parsemessage: actual" 697 " identity length does not match " 698 "expected length in identity " 699 "extension header %d\n", 700 sadb_ext->sadb_ext_type)); 701 return (EINVAL); 702 } 703 } 704 } 705 break; 706 case SADB_EXT_SENSITIVITY: 707 { 708 struct sadb_sens *sadb_sens = (struct sadb_sens *)p; 709 710 if (i < sizeof(struct sadb_sens)) { 711 DPRINTF(("pfkeyv2_parsemessage: bad header " 712 "length for SENSITIVITY extension " 713 "header\n")); 714 return (EINVAL); 715 } 716 717 if (i != (sadb_sens->sadb_sens_sens_len + 718 sadb_sens->sadb_sens_integ_len) * 719 sizeof(uint64_t) + 720 sizeof(struct sadb_sens)) { 721 DPRINTF(("pfkeyv2_parsemessage: bad payload " 722 "length for SENSITIVITY extension " 723 "header\n")); 724 return (EINVAL); 725 } 726 } 727 break; 728 case SADB_EXT_PROPOSAL: 729 { 730 struct sadb_prop *sadb_prop = (struct sadb_prop *)p; 731 732 if (i < sizeof(struct sadb_prop)) { 733 DPRINTF(("pfkeyv2_parsemessage: bad PROPOSAL " 734 "header length\n")); 735 return (EINVAL); 736 } 737 738 if (sadb_prop->sadb_prop_reserved) { 739 DPRINTF(("pfkeyv2_parsemessage: reserved field" 740 "set in PROPOSAL extension header\n")); 741 return (EINVAL); 742 } 743 744 if ((i - sizeof(struct sadb_prop)) % 745 sizeof(struct sadb_comb)) { 746 DPRINTF(("pfkeyv2_parsemessage: bad proposal " 747 "length\n")); 748 return (EINVAL); 749 } 750 751 { 752 struct sadb_comb *sadb_comb = 753 (struct sadb_comb *)(p + 754 sizeof(struct sadb_prop)); 755 int j; 756 757 for (j = 0; 758 j < (i - sizeof(struct sadb_prop))/ 759 sizeof(struct sadb_comb); 760 j++) { 761 if (sadb_comb->sadb_comb_auth > 762 SADB_AALG_MAX) { 763 DPRINTF(("pfkeyv2_parsemessage" 764 ": unknown authentication " 765 "algorithm %d in " 766 "PROPOSAL\n", 767 sadb_comb->sadb_comb_auth)); 768 return (EINVAL); 769 } 770 771 if (sadb_comb->sadb_comb_encrypt > 772 SADB_EALG_MAX) { 773 DPRINTF(("pfkeyv2_parsemessage" 774 ": unknown encryption " 775 "algorithm %d in " 776 "PROPOSAL\n", 777 sadb_comb->sadb_comb_encrypt)); 778 return (EINVAL); 779 } 780 781 if (sadb_comb->sadb_comb_reserved) { 782 DPRINTF(("pfkeyv2_parsemessage" 783 ": reserved field set in " 784 "COMB header\n")); 785 return (EINVAL); 786 } 787 } 788 } 789 } 790 break; 791 case SADB_EXT_SUPPORTED_AUTH: 792 case SADB_EXT_SUPPORTED_ENCRYPT: 793 case SADB_X_EXT_SUPPORTED_COMP: 794 { 795 struct sadb_supported *sadb_supported = 796 (struct sadb_supported *)p; 797 int j; 798 799 if (i < sizeof(struct sadb_supported)) { 800 DPRINTF(("pfkeyv2_parsemessage: bad header " 801 "length for SUPPORTED extension header " 802 "%d\n", sadb_ext->sadb_ext_type)); 803 return (EINVAL); 804 } 805 806 if (sadb_supported->sadb_supported_reserved) { 807 DPRINTF(("pfkeyv2_parsemessage: reserved " 808 "field set in SUPPORTED extension " 809 "header %d\n", sadb_ext->sadb_ext_type)); 810 return (EINVAL); 811 } 812 813 { 814 struct sadb_alg *sadb_alg = 815 (struct sadb_alg *)(p + 816 sizeof(struct sadb_supported)); 817 int max_alg; 818 819 max_alg = sadb_ext->sadb_ext_type == 820 SADB_EXT_SUPPORTED_AUTH ? 821 SADB_AALG_MAX : SADB_EXT_SUPPORTED_ENCRYPT ? 822 SADB_EALG_MAX : SADB_X_CALG_MAX; 823 824 for (j = 0; 825 j < sadb_supported->sadb_supported_len - 1; 826 j++) { 827 if (sadb_alg->sadb_alg_id > max_alg) { 828 DPRINTF(("pfkeyv2_parsemessage" 829 ": unknown algorithm %d " 830 "in SUPPORTED extension " 831 "header %d\n", 832 sadb_alg->sadb_alg_id, 833 sadb_ext->sadb_ext_type)); 834 return (EINVAL); 835 } 836 837 if (sadb_alg->sadb_alg_reserved) { 838 DPRINTF(("pfkeyv2_parsemessage" 839 ": reserved field set in " 840 "supported algorithms " 841 "header inside SUPPORTED " 842 "extension header %d\n", 843 sadb_ext->sadb_ext_type)); 844 return (EINVAL); 845 } 846 847 sadb_alg++; 848 } 849 } 850 } 851 break; 852 case SADB_EXT_SPIRANGE: 853 { 854 struct sadb_spirange *sadb_spirange = 855 (struct sadb_spirange *)p; 856 857 if (i != sizeof(struct sadb_spirange)) { 858 DPRINTF(("pfkeyv2_parsemessage: bad header " 859 "length of SPIRANGE extension header\n")); 860 return (EINVAL); 861 } 862 863 if (sadb_spirange->sadb_spirange_min > 864 sadb_spirange->sadb_spirange_max) { 865 DPRINTF(("pfkeyv2_parsemessage: bad SPI " 866 "range\n")); 867 return (EINVAL); 868 } 869 } 870 break; 871 case SADB_X_EXT_UDPENCAP: 872 if (i != sizeof(struct sadb_x_udpencap)) { 873 DPRINTF(("pfkeyv2_parsemessage: bad UDPENCAP " 874 "header length\n")); 875 return (EINVAL); 876 } 877 break; 878 #if NPF > 0 879 case SADB_X_EXT_TAG: 880 if (i < sizeof(struct sadb_x_tag)) { 881 DPRINTF(("pfkeyv2_parsemessage: " 882 "TAG extension header too small")); 883 return (EINVAL); 884 } 885 if (i > (sizeof(struct sadb_x_tag) + 886 PF_TAG_NAME_SIZE)) { 887 DPRINTF(("pfkeyv2_parsemessage: " 888 "TAG extension header too long")); 889 return (EINVAL); 890 } 891 break; 892 case SADB_X_EXT_TAP: 893 if (i < sizeof(struct sadb_x_tap)) { 894 DPRINTF(("pfkeyv2_parsemessage: " 895 "TAP extension header too small")); 896 return (EINVAL); 897 } 898 if (i > sizeof(struct sadb_x_tap)) { 899 DPRINTF(("pfkeyv2_parsemessage: " 900 "TAP extension header too long")); 901 return (EINVAL); 902 } 903 break; 904 #endif 905 default: 906 DPRINTF(("pfkeyv2_parsemessage: unknown extension " 907 "header type %d\n", 908 sadb_ext->sadb_ext_type)); 909 return (EINVAL); 910 } 911 912 headers[sadb_ext->sadb_ext_type] = p; 913 p += i; 914 left -= i; 915 } 916 917 if (left) { 918 DPRINTF(("pfkeyv2_parsemessage: message too long\n")); 919 return (EINVAL); 920 } 921 922 { 923 uint64_t required; 924 925 required = sadb_exts_required_in[sadb_msg->sadb_msg_type]; 926 927 if ((seen & required) != required) { 928 DPRINTF(("pfkeyv2_parsemessage: required fields " 929 "missing\n")); 930 return (EINVAL); 931 } 932 } 933 934 switch (((struct sadb_msg *)headers[0])->sadb_msg_type) { 935 case SADB_UPDATE: 936 if (((struct sadb_sa *)headers[SADB_EXT_SA])->sadb_sa_state != 937 SADB_SASTATE_MATURE) { 938 DPRINTF(("pfkeyv2_parsemessage: updating non-mature " 939 "SA prohibited\n")); 940 return (EINVAL); 941 } 942 break; 943 case SADB_ADD: 944 if (((struct sadb_sa *)headers[SADB_EXT_SA])->sadb_sa_state != 945 SADB_SASTATE_MATURE) { 946 DPRINTF(("pfkeyv2_parsemessage: adding non-mature " 947 "SA prohibited\n")); 948 return (EINVAL); 949 } 950 break; 951 } 952 953 return (0); 954 } 955