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