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