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