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