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