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