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