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