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