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