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