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