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