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