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