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