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