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