1 | /* |
2 | * Copyright (c) 2008-2016 Apple Inc. All rights reserved. |
3 | * |
4 | * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ |
5 | * |
6 | * This file contains Original Code and/or Modifications of Original Code |
7 | * as defined in and that are subject to the Apple Public Source License |
8 | * Version 2.0 (the 'License'). You may not use this file except in |
9 | * compliance with the License. The rights granted to you under the License |
10 | * may not be used to create, or enable the creation or redistribution of, |
11 | * unlawful or unlicensed copies of an Apple operating system, or to |
12 | * circumvent, violate, or enable the circumvention or violation of, any |
13 | * terms of an Apple operating system software license agreement. |
14 | * |
15 | * Please obtain a copy of the License at |
16 | * http://www.opensource.apple.com/apsl/ and read it before using this file. |
17 | * |
18 | * The Original Code and all software distributed under the License are |
19 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER |
20 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, |
21 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, |
22 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. |
23 | * Please see the License for the specific language governing rights and |
24 | * limitations under the License. |
25 | * |
26 | * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ |
27 | */ |
28 | |
29 | /* $FreeBSD: src/sys/netkey/key.c,v 1.16.2.13 2002/07/24 18:17:40 ume Exp $ */ |
30 | /* $KAME: key.c,v 1.191 2001/06/27 10:46:49 sakane Exp $ */ |
31 | |
32 | /* |
33 | * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. |
34 | * All rights reserved. |
35 | * |
36 | * Redistribution and use in source and binary forms, with or without |
37 | * modification, are permitted provided that the following conditions |
38 | * are met: |
39 | * 1. Redistributions of source code must retain the above copyright |
40 | * notice, this list of conditions and the following disclaimer. |
41 | * 2. Redistributions in binary form must reproduce the above copyright |
42 | * notice, this list of conditions and the following disclaimer in the |
43 | * documentation and/or other materials provided with the distribution. |
44 | * 3. Neither the name of the project nor the names of its contributors |
45 | * may be used to endorse or promote products derived from this software |
46 | * without specific prior written permission. |
47 | * |
48 | * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND |
49 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
50 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
51 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE |
52 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
53 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
54 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
55 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
56 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
57 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
58 | * SUCH DAMAGE. |
59 | */ |
60 | |
61 | /* |
62 | * This code is referd to RFC 2367 |
63 | */ |
64 | |
65 | #include <machine/endian.h> |
66 | #include <sys/types.h> |
67 | #include <sys/param.h> |
68 | #include <sys/systm.h> |
69 | #include <sys/kernel.h> |
70 | #include <sys/mbuf.h> |
71 | #include <sys/domain.h> |
72 | #include <sys/protosw.h> |
73 | #include <sys/malloc.h> |
74 | #include <sys/socket.h> |
75 | #include <sys/socketvar.h> |
76 | #include <sys/sysctl.h> |
77 | #include <sys/errno.h> |
78 | #include <sys/proc.h> |
79 | #include <sys/queue.h> |
80 | #include <sys/syslog.h> |
81 | #include <sys/mcache.h> |
82 | |
83 | #include <kern/locks.h> |
84 | |
85 | #include <net/if.h> |
86 | #include <net/route.h> |
87 | #include <net/raw_cb.h> |
88 | |
89 | #include <netinet/in.h> |
90 | #include <netinet/in_systm.h> |
91 | #include <netinet/ip.h> |
92 | #include <netinet/in_var.h> |
93 | |
94 | #if INET6 |
95 | #include <netinet/ip6.h> |
96 | #include <netinet6/in6_var.h> |
97 | #include <netinet6/ip6_var.h> |
98 | #endif /* INET6 */ |
99 | |
100 | #include <net/pfkeyv2.h> |
101 | #include <netkey/keydb.h> |
102 | #include <netkey/key.h> |
103 | #include <netkey/keysock.h> |
104 | #include <netkey/key_debug.h> |
105 | #include <stdarg.h> |
106 | #include <libkern/crypto/rand.h> |
107 | |
108 | #include <netinet6/ipsec.h> |
109 | #if INET6 |
110 | #include <netinet6/ipsec6.h> |
111 | #endif |
112 | #include <netinet6/ah.h> |
113 | #if INET6 |
114 | #include <netinet6/ah6.h> |
115 | #endif |
116 | #if IPSEC_ESP |
117 | #include <netinet6/esp.h> |
118 | #if INET6 |
119 | #include <netinet6/esp6.h> |
120 | #endif |
121 | #endif |
122 | #include <netinet6/ipcomp.h> |
123 | #if INET6 |
124 | #include <netinet6/ipcomp6.h> |
125 | #endif |
126 | |
127 | |
128 | /* randomness */ |
129 | #include <sys/random.h> |
130 | |
131 | #include <net/net_osdep.h> |
132 | |
133 | #define FULLMASK 0xff |
134 | |
135 | lck_grp_t *sadb_mutex_grp; |
136 | lck_grp_attr_t *sadb_mutex_grp_attr; |
137 | lck_attr_t *sadb_mutex_attr; |
138 | decl_lck_mtx_data(, sadb_mutex_data); |
139 | lck_mtx_t *sadb_mutex = &sadb_mutex_data; |
140 | |
141 | lck_grp_t *pfkey_stat_mutex_grp; |
142 | lck_grp_attr_t *pfkey_stat_mutex_grp_attr; |
143 | lck_attr_t *pfkey_stat_mutex_attr; |
144 | decl_lck_mtx_data(, pfkey_stat_mutex_data); |
145 | lck_mtx_t *pfkey_stat_mutex = &pfkey_stat_mutex_data; |
146 | |
147 | /* |
148 | * Note on SA reference counting: |
149 | * - SAs that are not in DEAD state will have (total external reference + 1) |
150 | * following value in reference count field. they cannot be freed and are |
151 | * referenced from SA header. |
152 | * - SAs that are in DEAD state will have (total external reference) |
153 | * in reference count field. they are ready to be freed. reference from |
154 | * SA header will be removed in key_delsav(), when the reference count |
155 | * field hits 0 (= no external reference other than from SA header. |
156 | */ |
157 | |
158 | u_int32_t key_debug_level = 0; //### our sysctl is not dynamic |
159 | static int key_timehandler_running = 0; |
160 | static u_int key_spi_trycnt = 1000; |
161 | static u_int32_t key_spi_minval = 0x100; |
162 | static u_int32_t key_spi_maxval = 0x0fffffff; /* XXX */ |
163 | static u_int32_t policy_id = 0; |
164 | static u_int key_int_random = 60; /*interval to initialize randseed,1(m)*/ |
165 | static u_int key_larval_lifetime = 30; /* interval to expire acquiring, 30(s)*/ |
166 | static int key_blockacq_count = 10; /* counter for blocking SADB_ACQUIRE.*/ |
167 | static int key_blockacq_lifetime = 20; /* lifetime for blocking SADB_ACQUIRE.*/ |
168 | static int key_preferred_oldsa = 0; /* preferred old sa rather than new sa.*/ |
169 | __private_extern__ int natt_keepalive_interval = 20; /* interval between natt keepalives.*/ |
170 | __private_extern__ int ipsec_policy_count = 0; |
171 | static int ipsec_sav_count = 0; |
172 | |
173 | static u_int32_t acq_seq = 0; |
174 | static int key_tick_init_random = 0; |
175 | static u_int64_t up_time = 0; |
176 | __private_extern__ u_int64_t natt_now = 0; |
177 | |
178 | static LIST_HEAD(_sptree, secpolicy) sptree[IPSEC_DIR_MAX]; /* SPD */ |
179 | static LIST_HEAD(_sahtree, secashead) sahtree; /* SAD */ |
180 | static LIST_HEAD(_regtree, secreg) regtree[SADB_SATYPE_MAX + 1]; |
181 | /* registed list */ |
182 | |
183 | #define SPIHASHSIZE 128 |
184 | #define SPIHASH(x) (((x) ^ ((x) >> 16)) % SPIHASHSIZE) |
185 | static LIST_HEAD(_spihash, secasvar) spihash[SPIHASHSIZE]; |
186 | |
187 | #ifndef IPSEC_NONBLOCK_ACQUIRE |
188 | static LIST_HEAD(_acqtree, secacq) acqtree; /* acquiring list */ |
189 | #endif |
190 | static LIST_HEAD(_spacqtree, secspacq) spacqtree; /* SP acquiring list */ |
191 | |
192 | struct key_cb key_cb; |
193 | |
194 | /* search order for SAs */ |
195 | static const u_int saorder_state_valid_prefer_old[] = { |
196 | SADB_SASTATE_DYING, SADB_SASTATE_MATURE, |
197 | }; |
198 | static const u_int saorder_state_valid_prefer_new[] = { |
199 | SADB_SASTATE_MATURE, SADB_SASTATE_DYING, |
200 | }; |
201 | static const u_int saorder_state_alive[] = { |
202 | /* except DEAD */ |
203 | SADB_SASTATE_MATURE, SADB_SASTATE_DYING, SADB_SASTATE_LARVAL |
204 | }; |
205 | static const u_int saorder_state_any[] = { |
206 | SADB_SASTATE_MATURE, SADB_SASTATE_DYING, |
207 | SADB_SASTATE_LARVAL, SADB_SASTATE_DEAD |
208 | }; |
209 | |
210 | static const int minsize[] = { |
211 | sizeof(struct sadb_msg), /* SADB_EXT_RESERVED */ |
212 | sizeof(struct sadb_sa), /* SADB_EXT_SA */ |
213 | sizeof(struct sadb_lifetime), /* SADB_EXT_LIFETIME_CURRENT */ |
214 | sizeof(struct sadb_lifetime), /* SADB_EXT_LIFETIME_HARD */ |
215 | sizeof(struct sadb_lifetime), /* SADB_EXT_LIFETIME_SOFT */ |
216 | sizeof(struct sadb_address), /* SADB_EXT_ADDRESS_SRC */ |
217 | sizeof(struct sadb_address), /* SADB_EXT_ADDRESS_DST */ |
218 | sizeof(struct sadb_address), /* SADB_EXT_ADDRESS_PROXY */ |
219 | sizeof(struct sadb_key), /* SADB_EXT_KEY_AUTH */ |
220 | sizeof(struct sadb_key), /* SADB_EXT_KEY_ENCRYPT */ |
221 | sizeof(struct sadb_ident), /* SADB_EXT_IDENTITY_SRC */ |
222 | sizeof(struct sadb_ident), /* SADB_EXT_IDENTITY_DST */ |
223 | sizeof(struct sadb_sens), /* SADB_EXT_SENSITIVITY */ |
224 | sizeof(struct sadb_prop), /* SADB_EXT_PROPOSAL */ |
225 | sizeof(struct sadb_supported), /* SADB_EXT_SUPPORTED_AUTH */ |
226 | sizeof(struct sadb_supported), /* SADB_EXT_SUPPORTED_ENCRYPT */ |
227 | sizeof(struct sadb_spirange), /* SADB_EXT_SPIRANGE */ |
228 | 0, /* SADB_X_EXT_KMPRIVATE */ |
229 | sizeof(struct sadb_x_policy), /* SADB_X_EXT_POLICY */ |
230 | sizeof(struct sadb_x_sa2), /* SADB_X_SA2 */ |
231 | sizeof(struct sadb_session_id), /* SADB_EXT_SESSION_ID */ |
232 | sizeof(struct sadb_sastat), /* SADB_EXT_SASTAT */ |
233 | sizeof(struct sadb_x_ipsecif), /* SADB_X_EXT_IPSECIF */ |
234 | sizeof(struct sadb_address), /* SADB_X_EXT_ADDR_RANGE_SRC_START */ |
235 | sizeof(struct sadb_address), /* SADB_X_EXT_ADDR_RANGE_SRC_END */ |
236 | sizeof(struct sadb_address), /* SADB_X_EXT_ADDR_RANGE_DST_START */ |
237 | sizeof(struct sadb_address), /* SADB_X_EXT_ADDR_RANGE_DST_END */ |
238 | sizeof(struct sadb_address), /* SADB_EXT_MIGRATE_ADDRESS_SRC */ |
239 | sizeof(struct sadb_address), /* SADB_EXT_MIGRATE_ADDRESS_DST */ |
240 | sizeof(struct sadb_x_ipsecif), /* SADB_X_EXT_MIGRATE_IPSECIF */ |
241 | }; |
242 | static const int maxsize[] = { |
243 | sizeof(struct sadb_msg), /* SADB_EXT_RESERVED */ |
244 | sizeof(struct sadb_sa_2), /* SADB_EXT_SA */ |
245 | sizeof(struct sadb_lifetime), /* SADB_EXT_LIFETIME_CURRENT */ |
246 | sizeof(struct sadb_lifetime), /* SADB_EXT_LIFETIME_HARD */ |
247 | sizeof(struct sadb_lifetime), /* SADB_EXT_LIFETIME_SOFT */ |
248 | 0, /* SADB_EXT_ADDRESS_SRC */ |
249 | 0, /* SADB_EXT_ADDRESS_DST */ |
250 | 0, /* SADB_EXT_ADDRESS_PROXY */ |
251 | 0, /* SADB_EXT_KEY_AUTH */ |
252 | 0, /* SADB_EXT_KEY_ENCRYPT */ |
253 | 0, /* SADB_EXT_IDENTITY_SRC */ |
254 | 0, /* SADB_EXT_IDENTITY_DST */ |
255 | 0, /* SADB_EXT_SENSITIVITY */ |
256 | 0, /* SADB_EXT_PROPOSAL */ |
257 | 0, /* SADB_EXT_SUPPORTED_AUTH */ |
258 | 0, /* SADB_EXT_SUPPORTED_ENCRYPT */ |
259 | sizeof(struct sadb_spirange), /* SADB_EXT_SPIRANGE */ |
260 | 0, /* SADB_X_EXT_KMPRIVATE */ |
261 | 0, /* SADB_X_EXT_POLICY */ |
262 | sizeof(struct sadb_x_sa2), /* SADB_X_SA2 */ |
263 | 0, /* SADB_EXT_SESSION_ID */ |
264 | 0, /* SADB_EXT_SASTAT */ |
265 | sizeof(struct sadb_x_ipsecif), /* SADB_X_EXT_IPSECIF */ |
266 | 0, /* SADB_X_EXT_ADDR_RANGE_SRC_START */ |
267 | 0, /* SADB_X_EXT_ADDR_RANGE_SRC_END */ |
268 | 0, /* SADB_X_EXT_ADDR_RANGE_DST_START */ |
269 | 0, /* SADB_X_EXT_ADDR_RANGE_DST_END */ |
270 | 0, /* SADB_EXT_MIGRATE_ADDRESS_SRC */ |
271 | 0, /* SADB_EXT_MIGRATE_ADDRESS_DST */ |
272 | sizeof(struct sadb_x_ipsecif), /* SADB_X_EXT_MIGRATE_IPSECIF */ |
273 | }; |
274 | |
275 | static int ipsec_esp_keymin = 256; |
276 | static int ipsec_esp_auth = 0; |
277 | static int ipsec_ah_keymin = 128; |
278 | |
279 | SYSCTL_DECL(_net_key); |
280 | /* Thread safe: no accumulated state */ |
281 | SYSCTL_INT(_net_key, KEYCTL_DEBUG_LEVEL, debug, CTLFLAG_RW | CTLFLAG_LOCKED, \ |
282 | &key_debug_level, 0, "" ); |
283 | |
284 | |
285 | /* max count of trial for the decision of spi value */ |
286 | SYSCTL_INT(_net_key, KEYCTL_SPI_TRY, spi_trycnt, CTLFLAG_RW | CTLFLAG_LOCKED, \ |
287 | &key_spi_trycnt, 0, "" ); |
288 | |
289 | /* minimum spi value to allocate automatically. */ |
290 | SYSCTL_INT(_net_key, KEYCTL_SPI_MIN_VALUE, spi_minval, CTLFLAG_RW | CTLFLAG_LOCKED, \ |
291 | &key_spi_minval, 0, "" ); |
292 | |
293 | /* maximun spi value to allocate automatically. */ |
294 | SYSCTL_INT(_net_key, KEYCTL_SPI_MAX_VALUE, spi_maxval, CTLFLAG_RW | CTLFLAG_LOCKED, \ |
295 | &key_spi_maxval, 0, "" ); |
296 | |
297 | /* interval to initialize randseed */ |
298 | SYSCTL_INT(_net_key, KEYCTL_RANDOM_INT, int_random, CTLFLAG_RW | CTLFLAG_LOCKED, \ |
299 | &key_int_random, 0, "" ); |
300 | |
301 | /* lifetime for larval SA; thread safe due to > compare */ |
302 | SYSCTL_INT(_net_key, KEYCTL_LARVAL_LIFETIME, larval_lifetime, CTLFLAG_RW | CTLFLAG_LOCKED, \ |
303 | &key_larval_lifetime, 0, "" ); |
304 | |
305 | /* counter for blocking to send SADB_ACQUIRE to IKEd */ |
306 | SYSCTL_INT(_net_key, KEYCTL_BLOCKACQ_COUNT, blockacq_count, CTLFLAG_RW | CTLFLAG_LOCKED, \ |
307 | &key_blockacq_count, 0, "" ); |
308 | |
309 | /* lifetime for blocking to send SADB_ACQUIRE to IKEd: Thread safe, > compare */ |
310 | SYSCTL_INT(_net_key, KEYCTL_BLOCKACQ_LIFETIME, blockacq_lifetime, CTLFLAG_RW | CTLFLAG_LOCKED, \ |
311 | &key_blockacq_lifetime, 0, "" ); |
312 | |
313 | /* ESP auth */ |
314 | SYSCTL_INT(_net_key, KEYCTL_ESP_AUTH, esp_auth, CTLFLAG_RW | CTLFLAG_LOCKED, \ |
315 | &ipsec_esp_auth, 0, "" ); |
316 | |
317 | /* minimum ESP key length */ |
318 | SYSCTL_INT(_net_key, KEYCTL_ESP_KEYMIN, esp_keymin, CTLFLAG_RW | CTLFLAG_LOCKED, \ |
319 | &ipsec_esp_keymin, 0, "" ); |
320 | |
321 | /* minimum AH key length */ |
322 | SYSCTL_INT(_net_key, KEYCTL_AH_KEYMIN, ah_keymin, CTLFLAG_RW | CTLFLAG_LOCKED, \ |
323 | &ipsec_ah_keymin, 0, "" ); |
324 | |
325 | /* perfered old SA rather than new SA */ |
326 | SYSCTL_INT(_net_key, KEYCTL_PREFERED_OLDSA, prefered_oldsa, CTLFLAG_RW | CTLFLAG_LOCKED,\ |
327 | &key_preferred_oldsa, 0, "" ); |
328 | |
329 | /* time between NATT keepalives in seconds, 0 disabled */ |
330 | SYSCTL_INT(_net_key, KEYCTL_NATT_KEEPALIVE_INTERVAL, natt_keepalive_interval, CTLFLAG_RW | CTLFLAG_LOCKED,\ |
331 | &natt_keepalive_interval, 0, "" ); |
332 | |
333 | /* PF_KEY statistics */ |
334 | SYSCTL_STRUCT(_net_key, KEYCTL_PFKEYSTAT, pfkeystat, CTLFLAG_RD | CTLFLAG_LOCKED,\ |
335 | &pfkeystat, pfkeystat, "" ); |
336 | |
337 | #ifndef LIST_FOREACH |
338 | #define LIST_FOREACH(elm, head, field) \ |
339 | for (elm = LIST_FIRST(head); elm; elm = LIST_NEXT(elm, field)) |
340 | #endif |
341 | #define __LIST_CHAINED(elm) \ |
342 | (!((elm)->chain.le_next == NULL && (elm)->chain.le_prev == NULL)) |
343 | #define LIST_INSERT_TAIL(head, elm, type, field) \ |
344 | do {\ |
345 | struct type *curelm = LIST_FIRST(head); \ |
346 | if (curelm == NULL) {\ |
347 | LIST_INSERT_HEAD(head, elm, field); \ |
348 | } else { \ |
349 | while (LIST_NEXT(curelm, field)) \ |
350 | curelm = LIST_NEXT(curelm, field);\ |
351 | LIST_INSERT_AFTER(curelm, elm, field);\ |
352 | }\ |
353 | } while (0) |
354 | |
355 | #define KEY_CHKSASTATE(head, sav, name) \ |
356 | do { \ |
357 | if ((head) != (sav)) { \ |
358 | ipseclog((LOG_DEBUG, "%s: state mismatched (TREE=%d SA=%d)\n", \ |
359 | (name), (head), (sav))); \ |
360 | continue; \ |
361 | } \ |
362 | } while (0) |
363 | |
364 | #define KEY_CHKSPDIR(head, sp, name) \ |
365 | do { \ |
366 | if ((head) != (sp)) { \ |
367 | ipseclog((LOG_DEBUG, "%s: direction mismatched (TREE=%d SP=%d), " \ |
368 | "anyway continue.\n", \ |
369 | (name), (head), (sp))); \ |
370 | } \ |
371 | } while (0) |
372 | |
373 | #if 1 |
374 | #define KMALLOC_WAIT(p, t, n) \ |
375 | ((p) = (t) _MALLOC((u_int32_t)(n), M_SECA, M_WAITOK)) |
376 | #define KMALLOC_NOWAIT(p, t, n) \ |
377 | ((p) = (t) _MALLOC((u_int32_t)(n), M_SECA, M_NOWAIT)) |
378 | #define KFREE(p) \ |
379 | _FREE((caddr_t)(p), M_SECA); |
380 | #else |
381 | #define KMALLOC_WAIT(p, t, n) \ |
382 | do { \ |
383 | ((p) = (t)_MALLOC((u_int32_t)(n), M_SECA, M_WAITOK)); \ |
384 | printf("%s %d: %p <- KMALLOC_WAIT(%s, %d)\n", \ |
385 | __FILE__, __LINE__, (p), #t, n); \ |
386 | } while (0) |
387 | #define KMALLOC_NOWAIT(p, t, n) \ |
388 | do { \ |
389 | ((p) = (t)_MALLOC((u_int32_t)(n), M_SECA, M_NOWAIT)); \ |
390 | printf("%s %d: %p <- KMALLOC_NOWAIT(%s, %d)\n", \ |
391 | __FILE__, __LINE__, (p), #t, n); \ |
392 | } while (0) |
393 | |
394 | #define KFREE(p) \ |
395 | do { \ |
396 | printf("%s %d: %p -> KFREE()\n", __FILE__, __LINE__, (p)); \ |
397 | _FREE((caddr_t)(p), M_SECA); \ |
398 | } while (0) |
399 | #endif |
400 | |
401 | /* |
402 | * set parameters into secpolicyindex buffer. |
403 | * Must allocate secpolicyindex buffer passed to this function. |
404 | */ |
405 | #define KEY_SETSECSPIDX(_dir, s, d, ps, pd, ulp, ifp, s_s, s_e, d_s, d_e, idx) \ |
406 | do { \ |
407 | bzero((idx), sizeof(struct secpolicyindex)); \ |
408 | (idx)->dir = (_dir); \ |
409 | (idx)->prefs = (ps); \ |
410 | (idx)->prefd = (pd); \ |
411 | (idx)->ul_proto = (ulp); \ |
412 | (idx)->internal_if = (ifp); \ |
413 | if (s) bcopy((s), &(idx)->src, ((struct sockaddr *)(s))->sa_len); \ |
414 | if (d) bcopy((d), &(idx)->dst, ((struct sockaddr *)(d))->sa_len); \ |
415 | if (s_s) bcopy((s_s), &(idx)->src_range.start, ((struct sockaddr *)(s_s))->sa_len); \ |
416 | if (s_e) bcopy((s_e), &(idx)->src_range.end, ((struct sockaddr *)(s_e))->sa_len); \ |
417 | if (d_s) bcopy((d_s), &(idx)->dst_range.start, ((struct sockaddr *)(d_s))->sa_len); \ |
418 | if (d_e) bcopy((d_e), &(idx)->dst_range.end, ((struct sockaddr *)(d_e))->sa_len); \ |
419 | } while (0) |
420 | |
421 | /* |
422 | * set parameters into secasindex buffer. |
423 | * Must allocate secasindex buffer before calling this function. |
424 | */ |
425 | #define KEY_SETSECASIDX(p, m, r, s, d, ifi, idx) \ |
426 | do { \ |
427 | bzero((idx), sizeof(struct secasindex)); \ |
428 | (idx)->proto = (p); \ |
429 | (idx)->mode = (m); \ |
430 | (idx)->reqid = (r); \ |
431 | bcopy((s), &(idx)->src, ((const struct sockaddr *)(s))->sa_len); \ |
432 | bcopy((d), &(idx)->dst, ((const struct sockaddr *)(d))->sa_len); \ |
433 | (idx)->ipsec_ifindex = (ifi); \ |
434 | } while (0) |
435 | |
436 | /* key statistics */ |
437 | struct _keystat { |
438 | u_int32_t getspi_count; /* the avarage of count to try to get new SPI */ |
439 | } keystat; |
440 | |
441 | struct sadb_msghdr { |
442 | struct sadb_msg *msg; |
443 | struct sadb_ext *ext[SADB_EXT_MAX + 1]; |
444 | int extoff[SADB_EXT_MAX + 1]; |
445 | int extlen[SADB_EXT_MAX + 1]; |
446 | }; |
447 | |
448 | static struct secpolicy *__key_getspbyid(u_int32_t id); |
449 | static struct secasvar *key_do_allocsa_policy(struct secashead *, u_int, u_int16_t); |
450 | static int key_do_get_translated_port(struct secashead *, struct secasvar *, u_int); |
451 | static void key_delsp(struct secpolicy *); |
452 | static struct secpolicy *key_getsp(struct secpolicyindex *); |
453 | static u_int32_t key_newreqid(void); |
454 | static struct mbuf *key_gather_mbuf(struct mbuf *, |
455 | const struct sadb_msghdr *, int, int, int *); |
456 | static int key_spdadd(struct socket *, struct mbuf *, |
457 | const struct sadb_msghdr *); |
458 | static u_int32_t key_getnewspid(void); |
459 | static int key_spddelete(struct socket *, struct mbuf *, |
460 | const struct sadb_msghdr *); |
461 | static int key_spddelete2(struct socket *, struct mbuf *, |
462 | const struct sadb_msghdr *); |
463 | static int key_spdenable(struct socket *, struct mbuf *, |
464 | const struct sadb_msghdr *); |
465 | static int key_spddisable(struct socket *, struct mbuf *, |
466 | const struct sadb_msghdr *); |
467 | static int key_spdget(struct socket *, struct mbuf *, |
468 | const struct sadb_msghdr *); |
469 | static int key_spdflush(struct socket *, struct mbuf *, |
470 | const struct sadb_msghdr *); |
471 | static int key_spddump(struct socket *, struct mbuf *, |
472 | const struct sadb_msghdr *); |
473 | static struct mbuf *key_setdumpsp(struct secpolicy *, |
474 | u_int8_t, u_int32_t, u_int32_t); |
475 | static u_int key_getspreqmsglen(struct secpolicy *); |
476 | static int key_spdexpire(struct secpolicy *); |
477 | static struct secashead *key_newsah(struct secasindex *, ifnet_t, u_int, u_int8_t); |
478 | static struct secasvar *key_newsav(struct mbuf *, |
479 | const struct sadb_msghdr *, struct secashead *, int *, |
480 | struct socket *); |
481 | static struct secashead *key_getsah(struct secasindex *); |
482 | static struct secasvar *key_checkspidup(struct secasindex *, u_int32_t); |
483 | static void key_setspi __P((struct secasvar *, u_int32_t)); |
484 | static struct secasvar *key_getsavbyspi(struct secashead *, u_int32_t); |
485 | static int key_setsaval(struct secasvar *, struct mbuf *, |
486 | const struct sadb_msghdr *); |
487 | static int key_mature(struct secasvar *); |
488 | static struct mbuf *key_setdumpsa(struct secasvar *, u_int8_t, |
489 | u_int8_t, u_int32_t, u_int32_t); |
490 | static struct mbuf *key_setsadbmsg(u_int8_t, u_int16_t, u_int8_t, |
491 | u_int32_t, pid_t, u_int16_t); |
492 | static struct mbuf *key_setsadbsa(struct secasvar *); |
493 | static struct mbuf *key_setsadbaddr(u_int16_t, |
494 | struct sockaddr *, u_int8_t, u_int16_t); |
495 | static struct mbuf *key_setsadbipsecif(ifnet_t, ifnet_t, ifnet_t, int); |
496 | #if 0 |
497 | static struct mbuf *key_setsadbident(u_int16_t, u_int16_t, caddr_t, |
498 | int, u_int64_t); |
499 | #endif |
500 | static struct mbuf *key_setsadbxsa2(u_int8_t, u_int32_t, u_int32_t, u_int16_t); |
501 | static struct mbuf *key_setsadbxpolicy(u_int16_t, u_int8_t, |
502 | u_int32_t); |
503 | static void *key_newbuf(const void *, u_int); |
504 | #if INET6 |
505 | static int key_ismyaddr6(struct sockaddr_in6 *); |
506 | #endif |
507 | static void key_update_natt_keepalive_timestamp(struct secasvar *, struct secasvar *); |
508 | |
509 | /* flags for key_cmpsaidx() */ |
510 | #define CMP_HEAD 0x1 /* protocol, addresses. */ |
511 | #define CMP_PORT 0x2 /* additionally HEAD, reqid, mode. */ |
512 | #define CMP_REQID 0x4 /* additionally HEAD, reqid. */ |
513 | #define CMP_MODE 0x8 /* additionally mode. */ |
514 | #define CMP_EXACTLY 0xF /* all elements. */ |
515 | static int key_cmpsaidx(struct secasindex *, struct secasindex *, int); |
516 | |
517 | static int key_cmpspidx_exactly(struct secpolicyindex *, |
518 | struct secpolicyindex *); |
519 | static int key_cmpspidx_withmask(struct secpolicyindex *, |
520 | struct secpolicyindex *); |
521 | static int key_sockaddrcmp(struct sockaddr *, struct sockaddr *, int); |
522 | static int key_is_addr_in_range(struct sockaddr_storage *, struct secpolicyaddrrange *); |
523 | static int key_bbcmp(caddr_t, caddr_t, u_int); |
524 | static void key_srandom(void); |
525 | static u_int16_t key_satype2proto(u_int8_t); |
526 | static u_int8_t key_proto2satype(u_int16_t); |
527 | |
528 | static int key_getspi(struct socket *, struct mbuf *, |
529 | const struct sadb_msghdr *); |
530 | static u_int32_t key_do_getnewspi(struct sadb_spirange *, struct secasindex *); |
531 | static int key_update(struct socket *, struct mbuf *, |
532 | const struct sadb_msghdr *); |
533 | #if IPSEC_DOSEQCHECK |
534 | static struct secasvar *key_getsavbyseq(struct secashead *, u_int32_t); |
535 | #endif |
536 | static int key_add(struct socket *, struct mbuf *, const struct sadb_msghdr *); |
537 | static int key_setident(struct secashead *, struct mbuf *, |
538 | const struct sadb_msghdr *); |
539 | static struct mbuf *key_getmsgbuf_x1(struct mbuf *, const struct sadb_msghdr *); |
540 | static int key_delete(struct socket *, struct mbuf *, |
541 | const struct sadb_msghdr *); |
542 | static int key_get(struct socket *, struct mbuf *, const struct sadb_msghdr *); |
543 | |
544 | static void key_getcomb_setlifetime(struct sadb_comb *); |
545 | #if IPSEC_ESP |
546 | static struct mbuf *key_getcomb_esp(void); |
547 | #endif |
548 | static struct mbuf *key_getcomb_ah(void); |
549 | static struct mbuf *key_getcomb_ipcomp(void); |
550 | static struct mbuf *key_getprop(const struct secasindex *); |
551 | |
552 | static int key_acquire(struct secasindex *, struct secpolicy *); |
553 | #ifndef IPSEC_NONBLOCK_ACQUIRE |
554 | static struct secacq *key_newacq(struct secasindex *); |
555 | static struct secacq *key_getacq(struct secasindex *); |
556 | static struct secacq *key_getacqbyseq(u_int32_t); |
557 | #endif |
558 | static struct secspacq *key_newspacq(struct secpolicyindex *); |
559 | static struct secspacq *key_getspacq(struct secpolicyindex *); |
560 | static int key_acquire2(struct socket *, struct mbuf *, |
561 | const struct sadb_msghdr *); |
562 | static int key_register(struct socket *, struct mbuf *, |
563 | const struct sadb_msghdr *); |
564 | static int key_expire(struct secasvar *); |
565 | static int key_flush(struct socket *, struct mbuf *, |
566 | const struct sadb_msghdr *); |
567 | static int key_dump(struct socket *, struct mbuf *, const struct sadb_msghdr *); |
568 | static int key_promisc(struct socket *, struct mbuf *, |
569 | const struct sadb_msghdr *); |
570 | static int key_senderror(struct socket *, struct mbuf *, int); |
571 | static int key_validate_ext(const struct sadb_ext *, int); |
572 | static int key_align(struct mbuf *, struct sadb_msghdr *); |
573 | static struct mbuf *key_alloc_mbuf(int); |
574 | static int key_getsastat (struct socket *, struct mbuf *, const struct sadb_msghdr *); |
575 | static int key_migrate (struct socket *, struct mbuf *, const struct sadb_msghdr *); |
576 | static int key_setsaval2(struct secasvar *sav, |
577 | u_int8_t satype, |
578 | u_int8_t alg_auth, |
579 | u_int8_t alg_enc, |
580 | u_int32_t flags, |
581 | u_int8_t replay, |
582 | struct sadb_key *key_auth, |
583 | u_int16_t key_auth_len, |
584 | struct sadb_key *key_enc, |
585 | u_int16_t key_enc_len, |
586 | u_int16_t natt_port, |
587 | u_int32_t seq, |
588 | u_int32_t spi, |
589 | u_int32_t pid, |
590 | struct sadb_lifetime *lifetime_hard, |
591 | struct sadb_lifetime *lifetime_soft); |
592 | static void bzero_keys(const struct sadb_msghdr *); |
593 | |
594 | extern int ipsec_bypass; |
595 | extern int esp_udp_encap_port; |
596 | int ipsec_send_natt_keepalive(struct secasvar *sav); |
597 | bool ipsec_fill_offload_frame(ifnet_t ifp, struct secasvar *sav, struct ifnet_keepalive_offload_frame *frame, size_t frame_data_offset); |
598 | |
599 | void key_init(struct protosw *, struct domain *); |
600 | |
601 | /* |
602 | * PF_KEY init |
603 | * setup locks, call raw_init(), and then init timer and associated data |
604 | * |
605 | */ |
606 | void |
607 | key_init(struct protosw *pp, struct domain *dp) |
608 | { |
609 | static int key_initialized = 0; |
610 | int i; |
611 | |
612 | VERIFY((pp->pr_flags & (PR_INITIALIZED|PR_ATTACHED)) == PR_ATTACHED); |
613 | |
614 | _CASSERT(PFKEY_ALIGN8(sizeof(struct sadb_msg)) <= _MHLEN); |
615 | |
616 | if (key_initialized) |
617 | return; |
618 | key_initialized = 1; |
619 | |
620 | sadb_mutex_grp_attr = lck_grp_attr_alloc_init(); |
621 | sadb_mutex_grp = lck_grp_alloc_init("sadb" , sadb_mutex_grp_attr); |
622 | sadb_mutex_attr = lck_attr_alloc_init(); |
623 | |
624 | lck_mtx_init(sadb_mutex, sadb_mutex_grp, sadb_mutex_attr); |
625 | |
626 | pfkey_stat_mutex_grp_attr = lck_grp_attr_alloc_init(); |
627 | pfkey_stat_mutex_grp = lck_grp_alloc_init("pfkey_stat" , pfkey_stat_mutex_grp_attr); |
628 | pfkey_stat_mutex_attr = lck_attr_alloc_init(); |
629 | |
630 | lck_mtx_init(pfkey_stat_mutex, pfkey_stat_mutex_grp, pfkey_stat_mutex_attr); |
631 | |
632 | for (i = 0; i < SPIHASHSIZE; i++) |
633 | LIST_INIT(&spihash[i]); |
634 | |
635 | raw_init(pp, dp); |
636 | |
637 | bzero((caddr_t)&key_cb, sizeof(key_cb)); |
638 | |
639 | for (i = 0; i < IPSEC_DIR_MAX; i++) { |
640 | LIST_INIT(&sptree[i]); |
641 | } |
642 | ipsec_policy_count = 0; |
643 | |
644 | LIST_INIT(&sahtree); |
645 | |
646 | for (i = 0; i <= SADB_SATYPE_MAX; i++) { |
647 | LIST_INIT(®tree[i]); |
648 | } |
649 | ipsec_sav_count = 0; |
650 | |
651 | #ifndef IPSEC_NONBLOCK_ACQUIRE |
652 | LIST_INIT(&acqtree); |
653 | #endif |
654 | LIST_INIT(&spacqtree); |
655 | |
656 | /* system default */ |
657 | #if INET |
658 | ip4_def_policy.policy = IPSEC_POLICY_NONE; |
659 | ip4_def_policy.refcnt++; /*never reclaim this*/ |
660 | #endif |
661 | #if INET6 |
662 | ip6_def_policy.policy = IPSEC_POLICY_NONE; |
663 | ip6_def_policy.refcnt++; /*never reclaim this*/ |
664 | #endif |
665 | |
666 | key_timehandler_running = 0; |
667 | |
668 | /* initialize key statistics */ |
669 | keystat.getspi_count = 1; |
670 | |
671 | #ifndef __APPLE__ |
672 | printf("IPsec: Initialized Security Association Processing.\n" ); |
673 | #endif |
674 | } |
675 | |
676 | static void |
677 | key_start_timehandler(void) |
678 | { |
679 | /* must be called while locked */ |
680 | LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_OWNED); |
681 | if (key_timehandler_running == 0) { |
682 | key_timehandler_running = 1; |
683 | (void)timeout((void *)key_timehandler, (void *)0, hz); |
684 | } |
685 | |
686 | /* Turn off the ipsec bypass */ |
687 | if (ipsec_bypass != 0) |
688 | ipsec_bypass = 0; |
689 | } |
690 | |
691 | /* %%% IPsec policy management */ |
692 | /* |
693 | * allocating a SP for OUTBOUND or INBOUND packet. |
694 | * Must call key_freesp() later. |
695 | * OUT: NULL: not found |
696 | * others: found and return the pointer. |
697 | */ |
698 | struct secpolicy * |
699 | key_allocsp( |
700 | struct secpolicyindex *spidx, |
701 | u_int dir) |
702 | { |
703 | struct secpolicy *sp; |
704 | struct timeval tv; |
705 | |
706 | LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED); |
707 | /* sanity check */ |
708 | if (spidx == NULL) |
709 | panic("key_allocsp: NULL pointer is passed.\n" ); |
710 | |
711 | /* check direction */ |
712 | switch (dir) { |
713 | case IPSEC_DIR_INBOUND: |
714 | case IPSEC_DIR_OUTBOUND: |
715 | break; |
716 | default: |
717 | panic("key_allocsp: Invalid direction is passed.\n" ); |
718 | } |
719 | |
720 | /* get a SP entry */ |
721 | KEYDEBUG(KEYDEBUG_IPSEC_DATA, |
722 | printf("*** objects\n" ); |
723 | kdebug_secpolicyindex(spidx)); |
724 | |
725 | lck_mtx_lock(sadb_mutex); |
726 | LIST_FOREACH(sp, &sptree[dir], chain) { |
727 | KEYDEBUG(KEYDEBUG_IPSEC_DATA, |
728 | printf("*** in SPD\n" ); |
729 | kdebug_secpolicyindex(&sp->spidx)); |
730 | |
731 | if (sp->state == IPSEC_SPSTATE_DEAD) |
732 | continue; |
733 | |
734 | /* If the policy is disabled, skip */ |
735 | if (sp->disabled > 0) |
736 | continue; |
737 | |
738 | /* If the incoming spidx specifies bound if, |
739 | ignore unbound policies*/ |
740 | if (spidx->internal_if != NULL |
741 | && (sp->spidx.internal_if == NULL || sp->ipsec_if == NULL)) |
742 | continue; |
743 | |
744 | if (key_cmpspidx_withmask(&sp->spidx, spidx)) |
745 | goto found; |
746 | } |
747 | lck_mtx_unlock(sadb_mutex); |
748 | return NULL; |
749 | |
750 | found: |
751 | |
752 | /* found a SPD entry */ |
753 | microtime(&tv); |
754 | sp->lastused = tv.tv_sec; |
755 | sp->refcnt++; |
756 | lck_mtx_unlock(sadb_mutex); |
757 | |
758 | /* sanity check */ |
759 | KEY_CHKSPDIR(sp->spidx.dir, dir, "key_allocsp" ); |
760 | KEYDEBUG(KEYDEBUG_IPSEC_STAMP, |
761 | printf("DP key_allocsp cause refcnt++:%d SP:0x%llx\n" , |
762 | sp->refcnt, (uint64_t)VM_KERNEL_ADDRPERM(sp))); |
763 | return sp; |
764 | } |
765 | |
766 | /* |
767 | * return a policy that matches this particular inbound packet. |
768 | * XXX slow |
769 | */ |
770 | struct secpolicy * |
771 | key_gettunnel( |
772 | struct sockaddr *osrc, |
773 | struct sockaddr *odst, |
774 | struct sockaddr *isrc, |
775 | struct sockaddr *idst) |
776 | { |
777 | struct secpolicy *sp; |
778 | const int dir = IPSEC_DIR_INBOUND; |
779 | struct timeval tv; |
780 | struct ipsecrequest *r1, *r2, *p; |
781 | struct sockaddr *os, *od, *is, *id; |
782 | struct secpolicyindex spidx; |
783 | |
784 | if (isrc->sa_family != idst->sa_family) { |
785 | ipseclog((LOG_ERR, "protocol family mismatched %d != %d\n." , |
786 | isrc->sa_family, idst->sa_family)); |
787 | return NULL; |
788 | } |
789 | |
790 | lck_mtx_lock(sadb_mutex); |
791 | LIST_FOREACH(sp, &sptree[dir], chain) { |
792 | if (sp->state == IPSEC_SPSTATE_DEAD) |
793 | continue; |
794 | |
795 | r1 = r2 = NULL; |
796 | for (p = sp->req; p; p = p->next) { |
797 | if (p->saidx.mode != IPSEC_MODE_TUNNEL) |
798 | continue; |
799 | |
800 | r1 = r2; |
801 | r2 = p; |
802 | |
803 | if (!r1) { |
804 | /* here we look at address matches only */ |
805 | spidx = sp->spidx; |
806 | if (isrc->sa_len > sizeof(spidx.src) || |
807 | idst->sa_len > sizeof(spidx.dst)) |
808 | continue; |
809 | bcopy(isrc, &spidx.src, isrc->sa_len); |
810 | bcopy(idst, &spidx.dst, idst->sa_len); |
811 | if (!key_cmpspidx_withmask(&sp->spidx, &spidx)) |
812 | continue; |
813 | } else { |
814 | is = (struct sockaddr *)&r1->saidx.src; |
815 | id = (struct sockaddr *)&r1->saidx.dst; |
816 | if (key_sockaddrcmp(is, isrc, 0) || |
817 | key_sockaddrcmp(id, idst, 0)) |
818 | continue; |
819 | } |
820 | |
821 | os = (struct sockaddr *)&r2->saidx.src; |
822 | od = (struct sockaddr *)&r2->saidx.dst; |
823 | if (key_sockaddrcmp(os, osrc, 0) || |
824 | key_sockaddrcmp(od, odst, 0)) |
825 | continue; |
826 | |
827 | goto found; |
828 | } |
829 | } |
830 | lck_mtx_unlock(sadb_mutex); |
831 | return NULL; |
832 | |
833 | found: |
834 | microtime(&tv); |
835 | sp->lastused = tv.tv_sec; |
836 | sp->refcnt++; |
837 | lck_mtx_unlock(sadb_mutex); |
838 | return sp; |
839 | } |
840 | |
841 | struct secasvar *key_alloc_outbound_sav_for_interface(ifnet_t interface, int family, |
842 | struct sockaddr *src, |
843 | struct sockaddr *dst) |
844 | { |
845 | struct secashead *sah; |
846 | struct secasvar *sav; |
847 | u_int stateidx; |
848 | u_int state; |
849 | const u_int *saorder_state_valid; |
850 | int arraysize; |
851 | struct sockaddr_in *sin; |
852 | u_int16_t dstport; |
853 | bool strict = true; |
854 | |
855 | if (interface == NULL) { |
856 | return NULL; |
857 | } |
858 | |
859 | LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED); |
860 | |
861 | lck_mtx_lock(sadb_mutex); |
862 | |
863 | do { |
864 | LIST_FOREACH(sah, &sahtree, chain) { |
865 | if (sah->state == SADB_SASTATE_DEAD) { |
866 | continue; |
867 | } |
868 | if (sah->ipsec_if == interface && |
869 | (family == AF_INET6 || family == AF_INET) && |
870 | sah->dir == IPSEC_DIR_OUTBOUND) { |
871 | |
872 | if (strict && |
873 | sah->saidx.mode == IPSEC_MODE_TRANSPORT && |
874 | src != NULL && dst != NULL) { |
875 | // Validate addresses for transport mode |
876 | if (key_sockaddrcmp((struct sockaddr *)&sah->saidx.src, src, 0) != 0) { |
877 | // Source doesn't match |
878 | continue; |
879 | } |
880 | |
881 | if (key_sockaddrcmp((struct sockaddr *)&sah->saidx.dst, dst, 0) != 0) { |
882 | // Destination doesn't match |
883 | continue; |
884 | } |
885 | } |
886 | |
887 | /* This SAH is linked to the IPSec interface, and the right family. We found it! */ |
888 | if (key_preferred_oldsa) { |
889 | saorder_state_valid = saorder_state_valid_prefer_old; |
890 | arraysize = _ARRAYLEN(saorder_state_valid_prefer_old); |
891 | } else { |
892 | saorder_state_valid = saorder_state_valid_prefer_new; |
893 | arraysize = _ARRAYLEN(saorder_state_valid_prefer_new); |
894 | } |
895 | |
896 | sin = (struct sockaddr_in *)&sah->saidx.dst; |
897 | dstport = sin->sin_port; |
898 | if (sah->saidx.mode == IPSEC_MODE_TRANSPORT) { |
899 | sin->sin_port = IPSEC_PORT_ANY; |
900 | } |
901 | |
902 | for (stateidx = 0; stateidx < arraysize; stateidx++) { |
903 | state = saorder_state_valid[stateidx]; |
904 | sav = key_do_allocsa_policy(sah, state, dstport); |
905 | if (sav != NULL) { |
906 | lck_mtx_unlock(sadb_mutex); |
907 | return sav; |
908 | } |
909 | } |
910 | |
911 | break; |
912 | } |
913 | } |
914 | if (strict) { |
915 | // If we didn't find anything, try again without strict |
916 | strict = false; |
917 | } else { |
918 | // We already were on the second try, bail |
919 | break; |
920 | } |
921 | } while (true); |
922 | |
923 | lck_mtx_unlock(sadb_mutex); |
924 | return NULL; |
925 | } |
926 | |
927 | /* |
928 | * allocating an SA entry for an *OUTBOUND* packet. |
929 | * checking each request entries in SP, and acquire an SA if need. |
930 | * OUT: 0: there are valid requests. |
931 | * ENOENT: policy may be valid, but SA with REQUIRE is on acquiring. |
932 | */ |
933 | int |
934 | key_checkrequest( |
935 | struct ipsecrequest *isr, |
936 | struct secasindex *saidx, |
937 | struct secasvar **sav) |
938 | { |
939 | u_int level; |
940 | int error; |
941 | struct sockaddr_in *sin; |
942 | |
943 | LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED); |
944 | |
945 | *sav = NULL; |
946 | |
947 | /* sanity check */ |
948 | if (isr == NULL || saidx == NULL) |
949 | panic("key_checkrequest: NULL pointer is passed.\n" ); |
950 | |
951 | /* check mode */ |
952 | switch (saidx->mode) { |
953 | case IPSEC_MODE_TRANSPORT: |
954 | case IPSEC_MODE_TUNNEL: |
955 | break; |
956 | case IPSEC_MODE_ANY: |
957 | default: |
958 | panic("key_checkrequest: Invalid policy defined.\n" ); |
959 | } |
960 | |
961 | /* get current level */ |
962 | level = ipsec_get_reqlevel(isr); |
963 | |
964 | |
965 | /* |
966 | * key_allocsa_policy should allocate the oldest SA available. |
967 | * See key_do_allocsa_policy(), and draft-jenkins-ipsec-rekeying-03.txt. |
968 | */ |
969 | if (*sav == NULL) |
970 | *sav = key_allocsa_policy(saidx); |
971 | |
972 | /* When there is SA. */ |
973 | if (*sav != NULL) |
974 | return 0; |
975 | |
976 | /* There is no SA. |
977 | * |
978 | * Remove dst port - used for special natt support - don't call |
979 | * key_acquire with it. |
980 | */ |
981 | if (saidx->mode == IPSEC_MODE_TRANSPORT) { |
982 | sin = (struct sockaddr_in *)&saidx->dst; |
983 | sin->sin_port = IPSEC_PORT_ANY; |
984 | } |
985 | if ((error = key_acquire(saidx, isr->sp)) != 0) { |
986 | /* XXX What should I do ? */ |
987 | ipseclog((LOG_DEBUG, "key_checkrequest: error %d returned " |
988 | "from key_acquire.\n" , error)); |
989 | return error; |
990 | } |
991 | |
992 | return level == IPSEC_LEVEL_REQUIRE ? ENOENT : 0; |
993 | } |
994 | |
995 | /* |
996 | * allocating a SA for policy entry from SAD. |
997 | * NOTE: searching SAD of aliving state. |
998 | * OUT: NULL: not found. |
999 | * others: found and return the pointer. |
1000 | */ |
1001 | u_int32_t sah_search_calls = 0; |
1002 | u_int32_t sah_search_count = 0; |
1003 | struct secasvar * |
1004 | key_allocsa_policy( |
1005 | struct secasindex *saidx) |
1006 | { |
1007 | struct secashead *sah; |
1008 | struct secasvar *sav; |
1009 | u_int stateidx, state; |
1010 | const u_int *saorder_state_valid; |
1011 | int arraysize; |
1012 | struct sockaddr_in *sin; |
1013 | u_int16_t dstport; |
1014 | |
1015 | lck_mtx_lock(sadb_mutex); |
1016 | sah_search_calls++; |
1017 | LIST_FOREACH(sah, &sahtree, chain) { |
1018 | sah_search_count++; |
1019 | if (sah->state == SADB_SASTATE_DEAD) |
1020 | continue; |
1021 | if (key_cmpsaidx(&sah->saidx, saidx, CMP_MODE | CMP_REQID)) |
1022 | goto found; |
1023 | } |
1024 | lck_mtx_unlock(sadb_mutex); |
1025 | return NULL; |
1026 | |
1027 | found: |
1028 | |
1029 | /* |
1030 | * search a valid state list for outbound packet. |
1031 | * This search order is important. |
1032 | */ |
1033 | if (key_preferred_oldsa) { |
1034 | saorder_state_valid = saorder_state_valid_prefer_old; |
1035 | arraysize = _ARRAYLEN(saorder_state_valid_prefer_old); |
1036 | } else { |
1037 | saorder_state_valid = saorder_state_valid_prefer_new; |
1038 | arraysize = _ARRAYLEN(saorder_state_valid_prefer_new); |
1039 | } |
1040 | |
1041 | |
1042 | sin = (struct sockaddr_in *)&saidx->dst; |
1043 | dstport = sin->sin_port; |
1044 | if (saidx->mode == IPSEC_MODE_TRANSPORT) |
1045 | sin->sin_port = IPSEC_PORT_ANY; |
1046 | |
1047 | for (stateidx = 0; stateidx < arraysize; stateidx++) { |
1048 | |
1049 | state = saorder_state_valid[stateidx]; |
1050 | |
1051 | sav = key_do_allocsa_policy(sah, state, dstport); |
1052 | if (sav != NULL) { |
1053 | lck_mtx_unlock(sadb_mutex); |
1054 | return sav; |
1055 | } |
1056 | } |
1057 | lck_mtx_unlock(sadb_mutex); |
1058 | return NULL; |
1059 | } |
1060 | |
1061 | static void |
1062 | key_send_delete (struct secasvar *sav) |
1063 | { |
1064 | struct mbuf *m, *result; |
1065 | u_int8_t satype; |
1066 | |
1067 | key_sa_chgstate(sav, SADB_SASTATE_DEAD); |
1068 | |
1069 | if ((satype = key_proto2satype(sav->sah->saidx.proto)) == 0) |
1070 | panic("key_do_allocsa_policy: invalid proto is passed.\n" ); |
1071 | |
1072 | m = key_setsadbmsg(SADB_DELETE, 0, |
1073 | satype, 0, 0, sav->refcnt - 1); |
1074 | if (!m) |
1075 | goto msgfail; |
1076 | result = m; |
1077 | |
1078 | /* set sadb_address for saidx's. */ |
1079 | m = key_setsadbaddr(SADB_EXT_ADDRESS_SRC, |
1080 | (struct sockaddr *)&sav->sah->saidx.src, |
1081 | sav->sah->saidx.src.ss_len << 3, |
1082 | IPSEC_ULPROTO_ANY); |
1083 | if (!m) |
1084 | goto msgfail; |
1085 | m_cat(result, m); |
1086 | |
1087 | /* set sadb_address for saidx's. */ |
1088 | m = key_setsadbaddr(SADB_EXT_ADDRESS_DST, |
1089 | (struct sockaddr *)&sav->sah->saidx.dst, |
1090 | sav->sah->saidx.src.ss_len << 3, |
1091 | IPSEC_ULPROTO_ANY); |
1092 | if (!m) |
1093 | goto msgfail; |
1094 | m_cat(result, m); |
1095 | |
1096 | /* create SA extension */ |
1097 | m = key_setsadbsa(sav); |
1098 | if (!m) |
1099 | goto msgfail; |
1100 | m_cat(result, m); |
1101 | |
1102 | if (result->m_len < sizeof(struct sadb_msg)) { |
1103 | result = m_pullup(result, |
1104 | sizeof(struct sadb_msg)); |
1105 | if (result == NULL) |
1106 | goto msgfail; |
1107 | } |
1108 | |
1109 | result->m_pkthdr.len = 0; |
1110 | for (m = result; m; m = m->m_next) |
1111 | result->m_pkthdr.len += m->m_len; |
1112 | mtod(result, struct sadb_msg *)->sadb_msg_len = |
1113 | PFKEY_UNIT64(result->m_pkthdr.len); |
1114 | |
1115 | if (key_sendup_mbuf(NULL, result, |
1116 | KEY_SENDUP_REGISTERED)) |
1117 | goto msgfail; |
1118 | msgfail: |
1119 | key_freesav(sav, KEY_SADB_LOCKED); |
1120 | } |
1121 | |
1122 | /* |
1123 | * searching SAD with direction, protocol, mode and state. |
1124 | * called by key_allocsa_policy(). |
1125 | * OUT: |
1126 | * NULL : not found |
1127 | * others : found, pointer to a SA. |
1128 | */ |
1129 | static struct secasvar * |
1130 | key_do_allocsa_policy( |
1131 | struct secashead *sah, |
1132 | u_int state, |
1133 | u_int16_t dstport) |
1134 | { |
1135 | struct secasvar *sav, *nextsav, *candidate, *natt_candidate, *no_natt_candidate, *d; |
1136 | |
1137 | LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_OWNED); |
1138 | |
1139 | /* initialize */ |
1140 | candidate = NULL; |
1141 | natt_candidate = NULL; |
1142 | no_natt_candidate = NULL; |
1143 | |
1144 | for (sav = LIST_FIRST(&sah->savtree[state]); |
1145 | sav != NULL; |
1146 | sav = nextsav) { |
1147 | |
1148 | nextsav = LIST_NEXT(sav, chain); |
1149 | |
1150 | /* sanity check */ |
1151 | KEY_CHKSASTATE(sav->state, state, "key_do_allocsa_policy" ); |
1152 | |
1153 | if (sah->saidx.mode == IPSEC_MODE_TUNNEL && dstport && |
1154 | ((sav->flags & SADB_X_EXT_NATT) != 0) && |
1155 | ntohs(dstport) != sav->remote_ike_port) |
1156 | continue; |
1157 | |
1158 | if (sah->saidx.mode == IPSEC_MODE_TRANSPORT && |
1159 | ((sav->flags & SADB_X_EXT_NATT_MULTIPLEUSERS) != 0) && |
1160 | ntohs(dstport) != sav->remote_ike_port) |
1161 | continue; /* skip this one - not a match - or not UDP */ |
1162 | |
1163 | if ((sah->saidx.mode == IPSEC_MODE_TUNNEL && |
1164 | ((sav->flags & SADB_X_EXT_NATT) != 0)) || |
1165 | (sah->saidx.mode == IPSEC_MODE_TRANSPORT && |
1166 | ((sav->flags & SADB_X_EXT_NATT_MULTIPLEUSERS) != 0))) { |
1167 | if (natt_candidate == NULL) { |
1168 | natt_candidate = sav; |
1169 | continue; |
1170 | } else |
1171 | candidate = natt_candidate; |
1172 | } else { |
1173 | if (no_natt_candidate == NULL) { |
1174 | no_natt_candidate = sav; |
1175 | continue; |
1176 | } else |
1177 | candidate = no_natt_candidate; |
1178 | } |
1179 | |
1180 | /* Which SA is the better ? */ |
1181 | |
1182 | /* sanity check 2 */ |
1183 | if (candidate->lft_c == NULL || sav->lft_c == NULL) |
1184 | panic("key_do_allocsa_policy: " |
1185 | "lifetime_current is NULL.\n" ); |
1186 | |
1187 | /* What the best method is to compare ? */ |
1188 | if (key_preferred_oldsa) { |
1189 | if (candidate->lft_c->sadb_lifetime_addtime > |
1190 | sav->lft_c->sadb_lifetime_addtime) { |
1191 | if ((sav->flags & SADB_X_EXT_NATT_MULTIPLEUSERS) != 0) |
1192 | natt_candidate = sav; |
1193 | else |
1194 | no_natt_candidate = sav; |
1195 | } |
1196 | continue; |
1197 | /*NOTREACHED*/ |
1198 | } |
1199 | |
1200 | /* prefered new sa rather than old sa */ |
1201 | if (candidate->lft_c->sadb_lifetime_addtime < |
1202 | sav->lft_c->sadb_lifetime_addtime) { |
1203 | d = candidate; |
1204 | if ((sah->saidx.mode == IPSEC_MODE_TUNNEL && |
1205 | ((sav->flags & SADB_X_EXT_NATT) != 0)) || |
1206 | (sah->saidx.mode == IPSEC_MODE_TRANSPORT && |
1207 | ((sav->flags & SADB_X_EXT_NATT_MULTIPLEUSERS) != 0))) { |
1208 | natt_candidate = sav; |
1209 | } else { |
1210 | no_natt_candidate = sav; |
1211 | } |
1212 | } else { |
1213 | d = sav; |
1214 | } |
1215 | |
1216 | /* |
1217 | * prepared to delete the SA when there is more |
1218 | * suitable candidate and the lifetime of the SA is not |
1219 | * permanent. |
1220 | */ |
1221 | if (d->lft_c->sadb_lifetime_addtime != 0) { |
1222 | key_send_delete(d); |
1223 | } |
1224 | } |
1225 | |
1226 | /* choose latest if both types present */ |
1227 | if (natt_candidate == NULL) |
1228 | candidate = no_natt_candidate; |
1229 | else if (no_natt_candidate == NULL) |
1230 | candidate = natt_candidate; |
1231 | else if (sah->saidx.mode == IPSEC_MODE_TUNNEL && dstport) |
1232 | candidate = natt_candidate; |
1233 | else if (natt_candidate->lft_c->sadb_lifetime_addtime > |
1234 | no_natt_candidate->lft_c->sadb_lifetime_addtime) |
1235 | candidate = natt_candidate; |
1236 | else |
1237 | candidate = no_natt_candidate; |
1238 | |
1239 | if (candidate) { |
1240 | candidate->refcnt++; |
1241 | KEYDEBUG(KEYDEBUG_IPSEC_STAMP, |
1242 | printf("DP allocsa_policy cause " |
1243 | "refcnt++:%d SA:0x%llx\n" , candidate->refcnt, |
1244 | (uint64_t)VM_KERNEL_ADDRPERM(candidate))); |
1245 | } |
1246 | return candidate; |
1247 | } |
1248 | |
1249 | /* |
1250 | * allocating a SA entry for a *INBOUND* packet. |
1251 | * Must call key_freesav() later. |
1252 | * OUT: positive: pointer to a sav. |
1253 | * NULL: not found, or error occurred. |
1254 | * |
1255 | * In the comparison, source address will be ignored for RFC2401 conformance. |
1256 | * To quote, from section 4.1: |
1257 | * A security association is uniquely identified by a triple consisting |
1258 | * of a Security Parameter Index (SPI), an IP Destination Address, and a |
1259 | * security protocol (AH or ESP) identifier. |
1260 | * Note that, however, we do need to keep source address in IPsec SA. |
1261 | * IKE specification and PF_KEY specification do assume that we |
1262 | * keep source address in IPsec SA. We see a tricky situation here. |
1263 | */ |
1264 | struct secasvar * |
1265 | key_allocsa( |
1266 | u_int family, |
1267 | caddr_t src, |
1268 | caddr_t dst, |
1269 | u_int proto, |
1270 | u_int32_t spi) |
1271 | { |
1272 | return key_allocsa_extended(family, src, dst, proto, spi, NULL); |
1273 | } |
1274 | |
1275 | struct secasvar * |
1276 | key_allocsa_extended(u_int family, |
1277 | caddr_t src, |
1278 | caddr_t dst, |
1279 | u_int proto, |
1280 | u_int32_t spi, |
1281 | ifnet_t interface) |
1282 | { |
1283 | struct secasvar *sav, *match; |
1284 | u_int stateidx, state, tmpidx, matchidx; |
1285 | struct sockaddr_in sin; |
1286 | struct sockaddr_in6 sin6; |
1287 | const u_int *saorder_state_valid; |
1288 | int arraysize; |
1289 | |
1290 | LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED); |
1291 | |
1292 | /* sanity check */ |
1293 | if (src == NULL || dst == NULL) |
1294 | panic("key_allocsa: NULL pointer is passed.\n" ); |
1295 | |
1296 | /* |
1297 | * when both systems employ similar strategy to use a SA. |
1298 | * the search order is important even in the inbound case. |
1299 | */ |
1300 | if (key_preferred_oldsa) { |
1301 | saorder_state_valid = saorder_state_valid_prefer_old; |
1302 | arraysize = _ARRAYLEN(saorder_state_valid_prefer_old); |
1303 | } else { |
1304 | saorder_state_valid = saorder_state_valid_prefer_new; |
1305 | arraysize = _ARRAYLEN(saorder_state_valid_prefer_new); |
1306 | } |
1307 | |
1308 | /* |
1309 | * searching SAD. |
1310 | * XXX: to be checked internal IP header somewhere. Also when |
1311 | * IPsec tunnel packet is received. But ESP tunnel mode is |
1312 | * encrypted so we can't check internal IP header. |
1313 | */ |
1314 | /* |
1315 | * search a valid state list for inbound packet. |
1316 | * the search order is not important. |
1317 | */ |
1318 | match = NULL; |
1319 | matchidx = arraysize; |
1320 | lck_mtx_lock(sadb_mutex); |
1321 | LIST_FOREACH(sav, &spihash[SPIHASH(spi)], spihash) { |
1322 | if (sav->spi != spi) |
1323 | continue; |
1324 | if (interface != NULL && |
1325 | sav->sah->ipsec_if != interface) { |
1326 | continue; |
1327 | } |
1328 | if (proto != sav->sah->saidx.proto) |
1329 | continue; |
1330 | if (family != sav->sah->saidx.src.ss_family || |
1331 | family != sav->sah->saidx.dst.ss_family) |
1332 | continue; |
1333 | tmpidx = arraysize; |
1334 | for (stateidx = 0; stateidx < matchidx; stateidx++) { |
1335 | state = saorder_state_valid[stateidx]; |
1336 | if (sav->state == state) { |
1337 | tmpidx = stateidx; |
1338 | break; |
1339 | } |
1340 | } |
1341 | if (tmpidx >= matchidx) |
1342 | continue; |
1343 | |
1344 | #if 0 /* don't check src */ |
1345 | /* check src address */ |
1346 | switch (family) { |
1347 | case AF_INET: |
1348 | bzero(&sin, sizeof(sin)); |
1349 | sin.sin_family = AF_INET; |
1350 | sin.sin_len = sizeof(sin); |
1351 | bcopy(src, &sin.sin_addr, |
1352 | sizeof(sin.sin_addr)); |
1353 | if (key_sockaddrcmp((struct sockaddr*)&sin, |
1354 | (struct sockaddr *)&sav->sah->saidx.src, 0) != 0) |
1355 | continue; |
1356 | break; |
1357 | case AF_INET6: |
1358 | bzero(&sin6, sizeof(sin6)); |
1359 | sin6.sin6_family = AF_INET6; |
1360 | sin6.sin6_len = sizeof(sin6); |
1361 | bcopy(src, &sin6.sin6_addr, |
1362 | sizeof(sin6.sin6_addr)); |
1363 | if (IN6_IS_SCOPE_LINKLOCAL(&sin6.sin6_addr)) { |
1364 | /* kame fake scopeid */ |
1365 | sin6.sin6_scope_id = |
1366 | ntohs(sin6.sin6_addr.s6_addr16[1]); |
1367 | sin6.sin6_addr.s6_addr16[1] = 0; |
1368 | } |
1369 | if (key_sockaddrcmp((struct sockaddr*)&sin6, |
1370 | (struct sockaddr *)&sav->sah->saidx.src, 0) != 0) |
1371 | continue; |
1372 | break; |
1373 | default: |
1374 | ipseclog((LOG_DEBUG, "key_allocsa: " |
1375 | "unknown address family=%d.\n" , |
1376 | family)); |
1377 | continue; |
1378 | } |
1379 | |
1380 | #endif |
1381 | /* check dst address */ |
1382 | switch (family) { |
1383 | case AF_INET: |
1384 | bzero(&sin, sizeof(sin)); |
1385 | sin.sin_family = AF_INET; |
1386 | sin.sin_len = sizeof(sin); |
1387 | bcopy(dst, &sin.sin_addr, |
1388 | sizeof(sin.sin_addr)); |
1389 | if (key_sockaddrcmp((struct sockaddr*)&sin, |
1390 | (struct sockaddr *)&sav->sah->saidx.dst, 0) != 0) |
1391 | continue; |
1392 | |
1393 | break; |
1394 | case AF_INET6: |
1395 | bzero(&sin6, sizeof(sin6)); |
1396 | sin6.sin6_family = AF_INET6; |
1397 | sin6.sin6_len = sizeof(sin6); |
1398 | bcopy(dst, &sin6.sin6_addr, |
1399 | sizeof(sin6.sin6_addr)); |
1400 | if (IN6_IS_SCOPE_LINKLOCAL(&sin6.sin6_addr)) { |
1401 | /* kame fake scopeid */ |
1402 | sin6.sin6_scope_id = |
1403 | ntohs(sin6.sin6_addr.s6_addr16[1]); |
1404 | sin6.sin6_addr.s6_addr16[1] = 0; |
1405 | } |
1406 | if (key_sockaddrcmp((struct sockaddr*)&sin6, |
1407 | (struct sockaddr *)&sav->sah->saidx.dst, 0) != 0) |
1408 | continue; |
1409 | break; |
1410 | default: |
1411 | ipseclog((LOG_DEBUG, "key_allocsa: " |
1412 | "unknown address family=%d.\n" , family)); |
1413 | continue; |
1414 | } |
1415 | |
1416 | match = sav; |
1417 | matchidx = tmpidx; |
1418 | } |
1419 | if (match) |
1420 | goto found; |
1421 | |
1422 | /* not found */ |
1423 | lck_mtx_unlock(sadb_mutex); |
1424 | return NULL; |
1425 | |
1426 | found: |
1427 | match->refcnt++; |
1428 | lck_mtx_unlock(sadb_mutex); |
1429 | KEYDEBUG(KEYDEBUG_IPSEC_STAMP, |
1430 | printf("DP allocsa cause refcnt++:%d SA:0x%llx\n" , |
1431 | match->refcnt, (uint64_t)VM_KERNEL_ADDRPERM(match))); |
1432 | return match; |
1433 | } |
1434 | |
1435 | u_int16_t |
1436 | key_natt_get_translated_port( |
1437 | struct secasvar *outsav) |
1438 | { |
1439 | |
1440 | struct secasindex saidx; |
1441 | struct secashead *sah; |
1442 | u_int stateidx, state; |
1443 | const u_int *saorder_state_valid; |
1444 | int arraysize; |
1445 | |
1446 | /* get sa for incoming */ |
1447 | saidx.mode = outsav->sah->saidx.mode; |
1448 | saidx.reqid = 0; |
1449 | saidx.proto = outsav->sah->saidx.proto; |
1450 | bcopy(&outsav->sah->saidx.src, &saidx.dst, sizeof(struct sockaddr_in)); |
1451 | bcopy(&outsav->sah->saidx.dst, &saidx.src, sizeof(struct sockaddr_in)); |
1452 | |
1453 | lck_mtx_lock(sadb_mutex); |
1454 | LIST_FOREACH(sah, &sahtree, chain) { |
1455 | if (sah->state == SADB_SASTATE_DEAD) |
1456 | continue; |
1457 | if (key_cmpsaidx(&sah->saidx, &saidx, CMP_MODE)) |
1458 | goto found; |
1459 | } |
1460 | lck_mtx_unlock(sadb_mutex); |
1461 | return 0; |
1462 | |
1463 | found: |
1464 | /* |
1465 | * Found sah - now go thru list of SAs and find |
1466 | * matching remote ike port. If found - set |
1467 | * sav->natt_encapsulated_src_port and return the port. |
1468 | */ |
1469 | /* |
1470 | * search a valid state list for outbound packet. |
1471 | * This search order is important. |
1472 | */ |
1473 | if (key_preferred_oldsa) { |
1474 | saorder_state_valid = saorder_state_valid_prefer_old; |
1475 | arraysize = _ARRAYLEN(saorder_state_valid_prefer_old); |
1476 | } else { |
1477 | saorder_state_valid = saorder_state_valid_prefer_new; |
1478 | arraysize = _ARRAYLEN(saorder_state_valid_prefer_new); |
1479 | } |
1480 | |
1481 | for (stateidx = 0; stateidx < arraysize; stateidx++) { |
1482 | state = saorder_state_valid[stateidx]; |
1483 | if (key_do_get_translated_port(sah, outsav, state)) { |
1484 | lck_mtx_unlock(sadb_mutex); |
1485 | return outsav->natt_encapsulated_src_port; |
1486 | } |
1487 | } |
1488 | lck_mtx_unlock(sadb_mutex); |
1489 | return 0; |
1490 | } |
1491 | |
1492 | static int |
1493 | key_do_get_translated_port( |
1494 | struct secashead *sah, |
1495 | struct secasvar *outsav, |
1496 | u_int state) |
1497 | { |
1498 | struct secasvar *currsav, *nextsav, *candidate; |
1499 | |
1500 | |
1501 | LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_OWNED); |
1502 | |
1503 | /* initilize */ |
1504 | candidate = NULL; |
1505 | |
1506 | for (currsav = LIST_FIRST(&sah->savtree[state]); |
1507 | currsav != NULL; |
1508 | currsav = nextsav) { |
1509 | |
1510 | nextsav = LIST_NEXT(currsav, chain); |
1511 | |
1512 | /* sanity check */ |
1513 | KEY_CHKSASTATE(currsav->state, state, "key_do_get_translated_port" ); |
1514 | |
1515 | if ((currsav->flags & SADB_X_EXT_NATT_MULTIPLEUSERS) == 0 || |
1516 | currsav->remote_ike_port != outsav->remote_ike_port) |
1517 | continue; |
1518 | |
1519 | if (candidate == NULL) { |
1520 | candidate = currsav; |
1521 | continue; |
1522 | } |
1523 | |
1524 | /* Which SA is the better ? */ |
1525 | |
1526 | /* sanity check 2 */ |
1527 | if (candidate->lft_c == NULL || currsav->lft_c == NULL) |
1528 | panic("key_do_get_translated_port: " |
1529 | "lifetime_current is NULL.\n" ); |
1530 | |
1531 | /* What the best method is to compare ? */ |
1532 | if (key_preferred_oldsa) { |
1533 | if (candidate->lft_c->sadb_lifetime_addtime > |
1534 | currsav->lft_c->sadb_lifetime_addtime) { |
1535 | candidate = currsav; |
1536 | } |
1537 | continue; |
1538 | /*NOTREACHED*/ |
1539 | } |
1540 | |
1541 | /* prefered new sa rather than old sa */ |
1542 | if (candidate->lft_c->sadb_lifetime_addtime < |
1543 | currsav->lft_c->sadb_lifetime_addtime) |
1544 | candidate = currsav; |
1545 | } |
1546 | |
1547 | if (candidate) { |
1548 | outsav->natt_encapsulated_src_port = candidate->natt_encapsulated_src_port; |
1549 | return 1; |
1550 | } |
1551 | |
1552 | return 0; |
1553 | } |
1554 | |
1555 | /* |
1556 | * Must be called after calling key_allocsp(). |
1557 | */ |
1558 | void |
1559 | key_freesp( |
1560 | struct secpolicy *sp, |
1561 | int locked) |
1562 | { |
1563 | |
1564 | /* sanity check */ |
1565 | if (sp == NULL) |
1566 | panic("key_freesp: NULL pointer is passed.\n" ); |
1567 | |
1568 | if (!locked) |
1569 | lck_mtx_lock(sadb_mutex); |
1570 | else |
1571 | LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_OWNED); |
1572 | sp->refcnt--; |
1573 | KEYDEBUG(KEYDEBUG_IPSEC_STAMP, |
1574 | printf("DP freesp cause refcnt--:%d SP:0x%llx\n" , |
1575 | sp->refcnt, (uint64_t)VM_KERNEL_ADDRPERM(sp))); |
1576 | |
1577 | if (sp->refcnt == 0) |
1578 | key_delsp(sp); |
1579 | if (!locked) |
1580 | lck_mtx_unlock(sadb_mutex); |
1581 | return; |
1582 | } |
1583 | |
1584 | /* |
1585 | * Must be called after calling key_allocsa(). |
1586 | * This function is called by key_freesp() to free some SA allocated |
1587 | * for a policy. |
1588 | */ |
1589 | void |
1590 | key_freesav( |
1591 | struct secasvar *sav, |
1592 | int locked) |
1593 | { |
1594 | |
1595 | /* sanity check */ |
1596 | if (sav == NULL) |
1597 | panic("key_freesav: NULL pointer is passed.\n" ); |
1598 | |
1599 | if (!locked) |
1600 | lck_mtx_lock(sadb_mutex); |
1601 | else |
1602 | LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_OWNED); |
1603 | sav->refcnt--; |
1604 | KEYDEBUG(KEYDEBUG_IPSEC_STAMP, |
1605 | printf("DP freesav cause refcnt--:%d SA:0x%llx SPI %u\n" , |
1606 | sav->refcnt, (uint64_t)VM_KERNEL_ADDRPERM(sav), |
1607 | (u_int32_t)ntohl(sav->spi))); |
1608 | |
1609 | if (sav->refcnt == 0) |
1610 | key_delsav(sav); |
1611 | if (!locked) |
1612 | lck_mtx_unlock(sadb_mutex); |
1613 | return; |
1614 | } |
1615 | |
1616 | /* %%% SPD management */ |
1617 | /* |
1618 | * free security policy entry. |
1619 | */ |
1620 | static void |
1621 | key_delsp( |
1622 | struct secpolicy *sp) |
1623 | { |
1624 | |
1625 | /* sanity check */ |
1626 | if (sp == NULL) |
1627 | panic("key_delsp: NULL pointer is passed.\n" ); |
1628 | |
1629 | LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_OWNED); |
1630 | sp->state = IPSEC_SPSTATE_DEAD; |
1631 | |
1632 | if (sp->refcnt > 0) |
1633 | return; /* can't free */ |
1634 | |
1635 | /* remove from SP index */ |
1636 | if (__LIST_CHAINED(sp)) { |
1637 | LIST_REMOVE(sp, chain); |
1638 | ipsec_policy_count--; |
1639 | } |
1640 | |
1641 | if (sp->spidx.internal_if) { |
1642 | ifnet_release(sp->spidx.internal_if); |
1643 | sp->spidx.internal_if = NULL; |
1644 | } |
1645 | |
1646 | if (sp->ipsec_if) { |
1647 | ifnet_release(sp->ipsec_if); |
1648 | sp->ipsec_if = NULL; |
1649 | } |
1650 | |
1651 | if (sp->outgoing_if) { |
1652 | ifnet_release(sp->outgoing_if); |
1653 | sp->outgoing_if = NULL; |
1654 | } |
1655 | |
1656 | { |
1657 | struct ipsecrequest *isr = sp->req, *nextisr; |
1658 | |
1659 | while (isr != NULL) { |
1660 | nextisr = isr->next; |
1661 | KFREE(isr); |
1662 | isr = nextisr; |
1663 | } |
1664 | } |
1665 | keydb_delsecpolicy(sp); |
1666 | |
1667 | return; |
1668 | } |
1669 | |
1670 | /* |
1671 | * search SPD |
1672 | * OUT: NULL : not found |
1673 | * others : found, pointer to a SP. |
1674 | */ |
1675 | static struct secpolicy * |
1676 | key_getsp( |
1677 | struct secpolicyindex *spidx) |
1678 | { |
1679 | struct secpolicy *sp; |
1680 | |
1681 | LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_OWNED); |
1682 | |
1683 | /* sanity check */ |
1684 | if (spidx == NULL) |
1685 | panic("key_getsp: NULL pointer is passed.\n" ); |
1686 | |
1687 | LIST_FOREACH(sp, &sptree[spidx->dir], chain) { |
1688 | if (sp->state == IPSEC_SPSTATE_DEAD) |
1689 | continue; |
1690 | if (key_cmpspidx_exactly(spidx, &sp->spidx)) { |
1691 | sp->refcnt++; |
1692 | return sp; |
1693 | } |
1694 | } |
1695 | |
1696 | return NULL; |
1697 | } |
1698 | |
1699 | /* |
1700 | * get SP by index. |
1701 | * OUT: NULL : not found |
1702 | * others : found, pointer to a SP. |
1703 | */ |
1704 | struct secpolicy * |
1705 | key_getspbyid( |
1706 | u_int32_t id) |
1707 | { |
1708 | struct secpolicy *sp; |
1709 | |
1710 | LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED); |
1711 | |
1712 | lck_mtx_lock(sadb_mutex); |
1713 | sp = __key_getspbyid(id); |
1714 | lck_mtx_unlock(sadb_mutex); |
1715 | |
1716 | return sp; |
1717 | } |
1718 | |
1719 | static struct secpolicy * |
1720 | __key_getspbyid(u_int32_t id) |
1721 | { |
1722 | struct secpolicy *sp; |
1723 | |
1724 | LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_OWNED); |
1725 | |
1726 | LIST_FOREACH(sp, &sptree[IPSEC_DIR_INBOUND], chain) { |
1727 | if (sp->state == IPSEC_SPSTATE_DEAD) |
1728 | continue; |
1729 | if (sp->id == id) { |
1730 | sp->refcnt++; |
1731 | return sp; |
1732 | } |
1733 | } |
1734 | |
1735 | LIST_FOREACH(sp, &sptree[IPSEC_DIR_OUTBOUND], chain) { |
1736 | if (sp->state == IPSEC_SPSTATE_DEAD) |
1737 | continue; |
1738 | if (sp->id == id) { |
1739 | sp->refcnt++; |
1740 | return sp; |
1741 | } |
1742 | } |
1743 | |
1744 | return NULL; |
1745 | } |
1746 | |
1747 | struct secpolicy * |
1748 | key_newsp(void) |
1749 | { |
1750 | struct secpolicy *newsp = NULL; |
1751 | |
1752 | LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED); |
1753 | newsp = keydb_newsecpolicy(); |
1754 | if (!newsp) |
1755 | return newsp; |
1756 | |
1757 | newsp->refcnt = 1; |
1758 | newsp->req = NULL; |
1759 | |
1760 | return newsp; |
1761 | } |
1762 | |
1763 | /* |
1764 | * create secpolicy structure from sadb_x_policy structure. |
1765 | * NOTE: `state', `secpolicyindex' in secpolicy structure are not set, |
1766 | * so must be set properly later. |
1767 | */ |
1768 | struct secpolicy * |
1769 | key_msg2sp( |
1770 | struct sadb_x_policy *xpl0, |
1771 | size_t len, |
1772 | int *error) |
1773 | { |
1774 | struct secpolicy *newsp; |
1775 | |
1776 | LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED); |
1777 | |
1778 | /* sanity check */ |
1779 | if (xpl0 == NULL) |
1780 | panic("key_msg2sp: NULL pointer was passed.\n" ); |
1781 | if (len < sizeof(*xpl0)) |
1782 | panic("key_msg2sp: invalid length.\n" ); |
1783 | if (len != PFKEY_EXTLEN(xpl0)) { |
1784 | ipseclog((LOG_DEBUG, "key_msg2sp: Invalid msg length.\n" )); |
1785 | *error = EINVAL; |
1786 | return NULL; |
1787 | } |
1788 | |
1789 | if ((newsp = key_newsp()) == NULL) { |
1790 | *error = ENOBUFS; |
1791 | return NULL; |
1792 | } |
1793 | |
1794 | newsp->spidx.dir = xpl0->sadb_x_policy_dir; |
1795 | newsp->policy = xpl0->sadb_x_policy_type; |
1796 | |
1797 | /* check policy */ |
1798 | switch (xpl0->sadb_x_policy_type) { |
1799 | case IPSEC_POLICY_DISCARD: |
1800 | case IPSEC_POLICY_GENERATE: |
1801 | case IPSEC_POLICY_NONE: |
1802 | case IPSEC_POLICY_ENTRUST: |
1803 | case IPSEC_POLICY_BYPASS: |
1804 | newsp->req = NULL; |
1805 | break; |
1806 | |
1807 | case IPSEC_POLICY_IPSEC: |
1808 | { |
1809 | int tlen; |
1810 | struct sadb_x_ipsecrequest *xisr; |
1811 | struct ipsecrequest **p_isr = &newsp->req; |
1812 | |
1813 | /* validity check */ |
1814 | if (PFKEY_EXTLEN(xpl0) < sizeof(*xpl0)) { |
1815 | ipseclog((LOG_DEBUG, |
1816 | "key_msg2sp: Invalid msg length.\n" )); |
1817 | key_freesp(newsp, KEY_SADB_UNLOCKED); |
1818 | *error = EINVAL; |
1819 | return NULL; |
1820 | } |
1821 | |
1822 | tlen = PFKEY_EXTLEN(xpl0) - sizeof(*xpl0); |
1823 | xisr = (struct sadb_x_ipsecrequest *)(xpl0 + 1); |
1824 | |
1825 | while (tlen > 0) { |
1826 | if (tlen < sizeof(*xisr)) { |
1827 | ipseclog((LOG_DEBUG, "key_msg2sp: " |
1828 | "invalid ipsecrequest.\n" )); |
1829 | key_freesp(newsp, KEY_SADB_UNLOCKED); |
1830 | *error = EINVAL; |
1831 | return NULL; |
1832 | } |
1833 | |
1834 | /* length check */ |
1835 | if (xisr->sadb_x_ipsecrequest_len < sizeof(*xisr)) { |
1836 | ipseclog((LOG_DEBUG, "key_msg2sp: " |
1837 | "invalid ipsecrequest length.\n" )); |
1838 | key_freesp(newsp, KEY_SADB_UNLOCKED); |
1839 | *error = EINVAL; |
1840 | return NULL; |
1841 | } |
1842 | |
1843 | /* allocate request buffer */ |
1844 | KMALLOC_WAIT(*p_isr, struct ipsecrequest *, sizeof(**p_isr)); |
1845 | if ((*p_isr) == NULL) { |
1846 | ipseclog((LOG_DEBUG, |
1847 | "key_msg2sp: No more memory.\n" )); |
1848 | key_freesp(newsp, KEY_SADB_UNLOCKED); |
1849 | *error = ENOBUFS; |
1850 | return NULL; |
1851 | } |
1852 | bzero(*p_isr, sizeof(**p_isr)); |
1853 | |
1854 | /* set values */ |
1855 | (*p_isr)->next = NULL; |
1856 | |
1857 | switch (xisr->sadb_x_ipsecrequest_proto) { |
1858 | case IPPROTO_ESP: |
1859 | case IPPROTO_AH: |
1860 | case IPPROTO_IPCOMP: |
1861 | break; |
1862 | default: |
1863 | ipseclog((LOG_DEBUG, |
1864 | "key_msg2sp: invalid proto type=%u\n" , |
1865 | xisr->sadb_x_ipsecrequest_proto)); |
1866 | key_freesp(newsp, KEY_SADB_UNLOCKED); |
1867 | *error = EPROTONOSUPPORT; |
1868 | return NULL; |
1869 | } |
1870 | (*p_isr)->saidx.proto = xisr->sadb_x_ipsecrequest_proto; |
1871 | |
1872 | switch (xisr->sadb_x_ipsecrequest_mode) { |
1873 | case IPSEC_MODE_TRANSPORT: |
1874 | case IPSEC_MODE_TUNNEL: |
1875 | break; |
1876 | case IPSEC_MODE_ANY: |
1877 | default: |
1878 | ipseclog((LOG_DEBUG, |
1879 | "key_msg2sp: invalid mode=%u\n" , |
1880 | xisr->sadb_x_ipsecrequest_mode)); |
1881 | key_freesp(newsp, KEY_SADB_UNLOCKED); |
1882 | *error = EINVAL; |
1883 | return NULL; |
1884 | } |
1885 | (*p_isr)->saidx.mode = xisr->sadb_x_ipsecrequest_mode; |
1886 | |
1887 | switch (xisr->sadb_x_ipsecrequest_level) { |
1888 | case IPSEC_LEVEL_DEFAULT: |
1889 | case IPSEC_LEVEL_USE: |
1890 | case IPSEC_LEVEL_REQUIRE: |
1891 | break; |
1892 | case IPSEC_LEVEL_UNIQUE: |
1893 | /* validity check */ |
1894 | /* |
1895 | * If range violation of reqid, kernel will |
1896 | * update it, don't refuse it. |
1897 | */ |
1898 | if (xisr->sadb_x_ipsecrequest_reqid |
1899 | > IPSEC_MANUAL_REQID_MAX) { |
1900 | ipseclog((LOG_DEBUG, |
1901 | "key_msg2sp: reqid=%d range " |
1902 | "violation, updated by kernel.\n" , |
1903 | xisr->sadb_x_ipsecrequest_reqid)); |
1904 | xisr->sadb_x_ipsecrequest_reqid = 0; |
1905 | } |
1906 | |
1907 | /* allocate new reqid id if reqid is zero. */ |
1908 | if (xisr->sadb_x_ipsecrequest_reqid == 0) { |
1909 | u_int32_t reqid; |
1910 | if ((reqid = key_newreqid()) == 0) { |
1911 | key_freesp(newsp, KEY_SADB_UNLOCKED); |
1912 | *error = ENOBUFS; |
1913 | return NULL; |
1914 | } |
1915 | (*p_isr)->saidx.reqid = reqid; |
1916 | xisr->sadb_x_ipsecrequest_reqid = reqid; |
1917 | } else { |
1918 | /* set it for manual keying. */ |
1919 | (*p_isr)->saidx.reqid = |
1920 | xisr->sadb_x_ipsecrequest_reqid; |
1921 | } |
1922 | break; |
1923 | |
1924 | default: |
1925 | ipseclog((LOG_DEBUG, "key_msg2sp: invalid level=%u\n" , |
1926 | xisr->sadb_x_ipsecrequest_level)); |
1927 | key_freesp(newsp, KEY_SADB_UNLOCKED); |
1928 | *error = EINVAL; |
1929 | return NULL; |
1930 | } |
1931 | (*p_isr)->level = xisr->sadb_x_ipsecrequest_level; |
1932 | |
1933 | /* set IP addresses if there */ |
1934 | if (xisr->sadb_x_ipsecrequest_len > sizeof(*xisr)) { |
1935 | struct sockaddr *paddr; |
1936 | |
1937 | if (tlen < xisr->sadb_x_ipsecrequest_len) { |
1938 | ipseclog((LOG_DEBUG, "key_msg2sp: invalid request " |
1939 | "address length.\n" )); |
1940 | key_freesp(newsp, KEY_SADB_UNLOCKED); |
1941 | *error = EINVAL; |
1942 | return NULL; |
1943 | } |
1944 | |
1945 | paddr = (struct sockaddr *)(xisr + 1); |
1946 | uint8_t src_len = paddr->sa_len; |
1947 | |
1948 | if (xisr->sadb_x_ipsecrequest_len < src_len) { |
1949 | ipseclog((LOG_DEBUG, "key_msg2sp: invalid request " |
1950 | "invalid source address length.\n" )); |
1951 | key_freesp(newsp, KEY_SADB_UNLOCKED); |
1952 | *error = EINVAL; |
1953 | return NULL; |
1954 | } |
1955 | |
1956 | /* validity check */ |
1957 | if (paddr->sa_len |
1958 | > sizeof((*p_isr)->saidx.src)) { |
1959 | ipseclog((LOG_DEBUG, "key_msg2sp: invalid request " |
1960 | "address length.\n" )); |
1961 | key_freesp(newsp, KEY_SADB_UNLOCKED); |
1962 | *error = EINVAL; |
1963 | return NULL; |
1964 | } |
1965 | |
1966 | bcopy(paddr, &(*p_isr)->saidx.src, |
1967 | MIN(paddr->sa_len, sizeof((*p_isr)->saidx.src))); |
1968 | |
1969 | paddr = (struct sockaddr *)((caddr_t)paddr + paddr->sa_len); |
1970 | uint8_t dst_len = paddr->sa_len; |
1971 | |
1972 | if (xisr->sadb_x_ipsecrequest_len < (src_len + dst_len)) { |
1973 | ipseclog((LOG_DEBUG, "key_msg2sp: invalid request " |
1974 | "invalid dest address length.\n" )); |
1975 | key_freesp(newsp, KEY_SADB_UNLOCKED); |
1976 | *error = EINVAL; |
1977 | return NULL; |
1978 | } |
1979 | |
1980 | /* validity check */ |
1981 | if (paddr->sa_len |
1982 | > sizeof((*p_isr)->saidx.dst)) { |
1983 | ipseclog((LOG_DEBUG, "key_msg2sp: invalid request " |
1984 | "address length.\n" )); |
1985 | key_freesp(newsp, KEY_SADB_UNLOCKED); |
1986 | *error = EINVAL; |
1987 | return NULL; |
1988 | } |
1989 | |
1990 | bcopy(paddr, &(*p_isr)->saidx.dst, |
1991 | MIN(paddr->sa_len, sizeof((*p_isr)->saidx.dst))); |
1992 | } |
1993 | |
1994 | (*p_isr)->sp = newsp; |
1995 | |
1996 | /* initialization for the next. */ |
1997 | p_isr = &(*p_isr)->next; |
1998 | tlen -= xisr->sadb_x_ipsecrequest_len; |
1999 | |
2000 | /* validity check */ |
2001 | if (tlen < 0) { |
2002 | ipseclog((LOG_DEBUG, "key_msg2sp: becoming tlen < 0.\n" )); |
2003 | key_freesp(newsp, KEY_SADB_UNLOCKED); |
2004 | *error = EINVAL; |
2005 | return NULL; |
2006 | } |
2007 | |
2008 | xisr = (struct sadb_x_ipsecrequest *)(void *) |
2009 | ((caddr_t)xisr + xisr->sadb_x_ipsecrequest_len); |
2010 | } |
2011 | } |
2012 | break; |
2013 | default: |
2014 | ipseclog((LOG_DEBUG, "key_msg2sp: invalid policy type.\n" )); |
2015 | key_freesp(newsp, KEY_SADB_UNLOCKED); |
2016 | *error = EINVAL; |
2017 | return NULL; |
2018 | } |
2019 | |
2020 | *error = 0; |
2021 | return newsp; |
2022 | } |
2023 | |
2024 | static u_int32_t |
2025 | key_newreqid(void) |
2026 | { |
2027 | lck_mtx_lock(sadb_mutex); |
2028 | static u_int32_t auto_reqid = IPSEC_MANUAL_REQID_MAX + 1; |
2029 | int done = 0; |
2030 | |
2031 | /* The reqid must be limited to 16 bits because the PF_KEY message format only uses |
2032 | 16 bits for this field. Once it becomes larger than 16 bits - ipsec fails to |
2033 | work anymore. Changing the PF_KEY message format would introduce compatibility |
2034 | issues. This code now tests to see if the tentative reqid is in use */ |
2035 | |
2036 | while (!done) { |
2037 | struct secpolicy *sp; |
2038 | struct ipsecrequest *isr; |
2039 | int dir; |
2040 | |
2041 | auto_reqid = (auto_reqid == 0xFFFF |
2042 | ? IPSEC_MANUAL_REQID_MAX + 1 : auto_reqid + 1); |
2043 | |
2044 | /* check for uniqueness */ |
2045 | done = 1; |
2046 | for (dir = 0; dir < IPSEC_DIR_MAX; dir++) { |
2047 | LIST_FOREACH(sp, &sptree[dir], chain) { |
2048 | for (isr = sp->req; isr != NULL; isr = isr->next) { |
2049 | if (isr->saidx.reqid == auto_reqid) { |
2050 | done = 0; |
2051 | break; |
2052 | } |
2053 | } |
2054 | if (done == 0) |
2055 | break; |
2056 | } |
2057 | if (done == 0) |
2058 | break; |
2059 | } |
2060 | } |
2061 | |
2062 | lck_mtx_unlock(sadb_mutex); |
2063 | return auto_reqid; |
2064 | } |
2065 | |
2066 | /* |
2067 | * copy secpolicy struct to sadb_x_policy structure indicated. |
2068 | */ |
2069 | struct mbuf * |
2070 | key_sp2msg( |
2071 | struct secpolicy *sp) |
2072 | { |
2073 | struct sadb_x_policy *xpl; |
2074 | int tlen; |
2075 | caddr_t p; |
2076 | struct mbuf *m; |
2077 | |
2078 | /* sanity check. */ |
2079 | if (sp == NULL) |
2080 | panic("key_sp2msg: NULL pointer was passed.\n" ); |
2081 | |
2082 | tlen = key_getspreqmsglen(sp); |
2083 | |
2084 | m = key_alloc_mbuf(tlen); |
2085 | if (!m || m->m_next) { /*XXX*/ |
2086 | if (m) |
2087 | m_freem(m); |
2088 | return NULL; |
2089 | } |
2090 | |
2091 | m->m_len = tlen; |
2092 | m->m_next = NULL; |
2093 | xpl = mtod(m, struct sadb_x_policy *); |
2094 | bzero(xpl, tlen); |
2095 | |
2096 | xpl->sadb_x_policy_len = PFKEY_UNIT64(tlen); |
2097 | xpl->sadb_x_policy_exttype = SADB_X_EXT_POLICY; |
2098 | xpl->sadb_x_policy_type = sp->policy; |
2099 | xpl->sadb_x_policy_dir = sp->spidx.dir; |
2100 | xpl->sadb_x_policy_id = sp->id; |
2101 | p = (caddr_t)xpl + sizeof(*xpl); |
2102 | |
2103 | /* if is the policy for ipsec ? */ |
2104 | if (sp->policy == IPSEC_POLICY_IPSEC) { |
2105 | struct sadb_x_ipsecrequest *xisr; |
2106 | struct ipsecrequest *isr; |
2107 | |
2108 | for (isr = sp->req; isr != NULL; isr = isr->next) { |
2109 | |
2110 | xisr = (struct sadb_x_ipsecrequest *)(void *)p; |
2111 | |
2112 | xisr->sadb_x_ipsecrequest_proto = isr->saidx.proto; |
2113 | xisr->sadb_x_ipsecrequest_mode = isr->saidx.mode; |
2114 | xisr->sadb_x_ipsecrequest_level = isr->level; |
2115 | xisr->sadb_x_ipsecrequest_reqid = isr->saidx.reqid; |
2116 | |
2117 | p += sizeof(*xisr); |
2118 | bcopy(&isr->saidx.src, p, isr->saidx.src.ss_len); |
2119 | p += isr->saidx.src.ss_len; |
2120 | bcopy(&isr->saidx.dst, p, isr->saidx.dst.ss_len); |
2121 | p += isr->saidx.src.ss_len; |
2122 | |
2123 | xisr->sadb_x_ipsecrequest_len = |
2124 | PFKEY_ALIGN8(sizeof(*xisr) |
2125 | + isr->saidx.src.ss_len |
2126 | + isr->saidx.dst.ss_len); |
2127 | } |
2128 | } |
2129 | |
2130 | return m; |
2131 | } |
2132 | |
2133 | /* m will not be freed nor modified */ |
2134 | static struct mbuf * |
2135 | key_gather_mbuf(struct mbuf *m, const struct sadb_msghdr *mhp, |
2136 | int ndeep, int nitem, int *items) |
2137 | { |
2138 | int idx; |
2139 | int i; |
2140 | struct mbuf *result = NULL, *n; |
2141 | int len; |
2142 | |
2143 | if (m == NULL || mhp == NULL) |
2144 | panic("null pointer passed to key_gather" ); |
2145 | |
2146 | for (i = 0; i < nitem; i++) { |
2147 | idx = items[i]; |
2148 | if (idx < 0 || idx > SADB_EXT_MAX) |
2149 | goto fail; |
2150 | /* don't attempt to pull empty extension */ |
2151 | if (idx == SADB_EXT_RESERVED && mhp->msg == NULL) |
2152 | continue; |
2153 | if (idx != SADB_EXT_RESERVED && |
2154 | (mhp->ext[idx] == NULL || mhp->extlen[idx] == 0)) |
2155 | continue; |
2156 | |
2157 | if (idx == SADB_EXT_RESERVED) { |
2158 | len = PFKEY_ALIGN8(sizeof(struct sadb_msg)); |
2159 | MGETHDR(n, M_WAITOK, MT_DATA); // sadb_msg len < MHLEN - enforced by _CASSERT |
2160 | if (!n) |
2161 | goto fail; |
2162 | n->m_len = len; |
2163 | n->m_next = NULL; |
2164 | m_copydata(m, 0, sizeof(struct sadb_msg), |
2165 | mtod(n, caddr_t)); |
2166 | } else if (i < ndeep) { |
2167 | len = mhp->extlen[idx]; |
2168 | n = key_alloc_mbuf(len); |
2169 | if (!n || n->m_next) { /*XXX*/ |
2170 | if (n) |
2171 | m_freem(n); |
2172 | goto fail; |
2173 | } |
2174 | m_copydata(m, mhp->extoff[idx], mhp->extlen[idx], |
2175 | mtod(n, caddr_t)); |
2176 | } else { |
2177 | n = m_copym(m, mhp->extoff[idx], mhp->extlen[idx], |
2178 | M_WAITOK); |
2179 | } |
2180 | if (n == NULL) |
2181 | goto fail; |
2182 | |
2183 | if (result) |
2184 | m_cat(result, n); |
2185 | else |
2186 | result = n; |
2187 | } |
2188 | |
2189 | if ((result->m_flags & M_PKTHDR) != 0) { |
2190 | result->m_pkthdr.len = 0; |
2191 | for (n = result; n; n = n->m_next) |
2192 | result->m_pkthdr.len += n->m_len; |
2193 | } |
2194 | |
2195 | return result; |
2196 | |
2197 | fail: |
2198 | m_freem(result); |
2199 | return NULL; |
2200 | } |
2201 | |
2202 | /* |
2203 | * SADB_X_SPDADD, SADB_X_SPDSETIDX or SADB_X_SPDUPDATE processing |
2204 | * add a entry to SP database, when received |
2205 | * <base, address(SD), (lifetime(H),) policy> |
2206 | * from the user(?). |
2207 | * Adding to SP database, |
2208 | * and send |
2209 | * <base, address(SD), (lifetime(H),) policy> |
2210 | * to the socket which was send. |
2211 | * |
2212 | * SPDADD set a unique policy entry. |
2213 | * SPDSETIDX like SPDADD without a part of policy requests. |
2214 | * SPDUPDATE replace a unique policy entry. |
2215 | * |
2216 | * m will always be freed. |
2217 | */ |
2218 | static int |
2219 | key_spdadd( |
2220 | struct socket *so, |
2221 | struct mbuf *m, |
2222 | const struct sadb_msghdr *mhp) |
2223 | { |
2224 | struct sadb_address *src0, *dst0, *src1 = NULL, *dst1 = NULL; |
2225 | struct sadb_x_policy *xpl0, *xpl; |
2226 | struct sadb_lifetime *lft = NULL; |
2227 | struct secpolicyindex spidx; |
2228 | struct secpolicy *newsp; |
2229 | struct timeval tv; |
2230 | ifnet_t internal_if = NULL; |
2231 | char *outgoing_if = NULL; |
2232 | char *ipsec_if = NULL; |
2233 | struct sadb_x_ipsecif *ipsecifopts = NULL; |
2234 | int error; |
2235 | int use_src_range = 0; |
2236 | int use_dst_range = 0; |
2237 | int init_disabled = 0; |
2238 | int address_family, address_len; |
2239 | |
2240 | LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED); |
2241 | |
2242 | /* sanity check */ |
2243 | if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) |
2244 | panic("key_spdadd: NULL pointer is passed.\n" ); |
2245 | |
2246 | if (mhp->ext[SADB_X_EXT_ADDR_RANGE_SRC_START] != NULL && mhp->ext[SADB_X_EXT_ADDR_RANGE_SRC_END] != NULL) { |
2247 | use_src_range = 1; |
2248 | } |
2249 | if (mhp->ext[SADB_X_EXT_ADDR_RANGE_DST_START] != NULL && mhp->ext[SADB_X_EXT_ADDR_RANGE_DST_END] != NULL) { |
2250 | use_dst_range = 1; |
2251 | } |
2252 | |
2253 | if ((!use_src_range && mhp->ext[SADB_EXT_ADDRESS_SRC] == NULL) || |
2254 | (!use_dst_range && mhp->ext[SADB_EXT_ADDRESS_DST] == NULL) || |
2255 | mhp->ext[SADB_X_EXT_POLICY] == NULL) { |
2256 | ipseclog((LOG_DEBUG, "key_spdadd: invalid message is passed.\n" )); |
2257 | return key_senderror(so, m, EINVAL); |
2258 | } |
2259 | if ((use_src_range && (mhp->extlen[SADB_X_EXT_ADDR_RANGE_SRC_START] < sizeof(struct sadb_address) |
2260 | || mhp->extlen[SADB_X_EXT_ADDR_RANGE_SRC_END] < sizeof(struct sadb_address))) || |
2261 | (!use_src_range && mhp->extlen[SADB_EXT_ADDRESS_SRC] < sizeof(struct sadb_address)) || |
2262 | (use_dst_range && (mhp->extlen[SADB_X_EXT_ADDR_RANGE_DST_START] < sizeof(struct sadb_address) |
2263 | || mhp->extlen[SADB_X_EXT_ADDR_RANGE_DST_END] < sizeof(struct sadb_address))) || |
2264 | (!use_dst_range && mhp->extlen[SADB_EXT_ADDRESS_DST] < sizeof(struct sadb_address)) || |
2265 | mhp->extlen[SADB_X_EXT_POLICY] < sizeof(struct sadb_x_policy)) { |
2266 | ipseclog((LOG_DEBUG, "key_spdadd: invalid message is passed.\n" )); |
2267 | return key_senderror(so, m, EINVAL); |
2268 | } |
2269 | if (mhp->ext[SADB_EXT_LIFETIME_HARD] != NULL) { |
2270 | if (mhp->extlen[SADB_EXT_LIFETIME_HARD] |
2271 | < sizeof(struct sadb_lifetime)) { |
2272 | ipseclog((LOG_DEBUG, "key_spdadd: invalid message is passed.\n" )); |
2273 | return key_senderror(so, m, EINVAL); |
2274 | } |
2275 | lft = (struct sadb_lifetime *) |
2276 | (void *)mhp->ext[SADB_EXT_LIFETIME_HARD]; |
2277 | } |
2278 | if (mhp->ext[SADB_X_EXT_IPSECIF] != NULL) { |
2279 | if (mhp->extlen[SADB_X_EXT_IPSECIF] < sizeof(struct sadb_x_ipsecif)) { |
2280 | ipseclog((LOG_DEBUG, "key_spdadd: invalid message is passed.\n" )); |
2281 | return key_senderror(so, m, EINVAL); |
2282 | } |
2283 | } |
2284 | |
2285 | if (use_src_range) { |
2286 | src0 = (struct sadb_address *)mhp->ext[SADB_X_EXT_ADDR_RANGE_SRC_START]; |
2287 | src1 = (struct sadb_address *)mhp->ext[SADB_X_EXT_ADDR_RANGE_SRC_END]; |
2288 | } else { |
2289 | src0 = (struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_SRC]; |
2290 | } |
2291 | if (use_dst_range) { |
2292 | dst0 = (struct sadb_address *)mhp->ext[SADB_X_EXT_ADDR_RANGE_DST_START]; |
2293 | dst1 = (struct sadb_address *)mhp->ext[SADB_X_EXT_ADDR_RANGE_DST_END]; |
2294 | } else { |
2295 | dst0 = (struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_DST]; |
2296 | } |
2297 | xpl0 = (struct sadb_x_policy *)(void *)mhp->ext[SADB_X_EXT_POLICY]; |
2298 | ipsecifopts = (struct sadb_x_ipsecif *)(void *)mhp->ext[SADB_X_EXT_IPSECIF]; |
2299 | |
2300 | /* check addresses */ |
2301 | address_family = ((struct sockaddr *)(src0 + 1))->sa_family; |
2302 | address_len = ((struct sockaddr *)(src0 + 1))->sa_len; |
2303 | if (use_src_range) { |
2304 | if (((struct sockaddr *)(src1+ 1))->sa_family != address_family || |
2305 | ((struct sockaddr *)(src1+ 1))->sa_len != address_len) { |
2306 | return key_senderror(so, m, EINVAL); |
2307 | } |
2308 | } |
2309 | if (((struct sockaddr *)(dst0+ 1))->sa_family != address_family || |
2310 | ((struct sockaddr *)(dst0+ 1))->sa_len != address_len) { |
2311 | return key_senderror(so, m, EINVAL); |
2312 | } |
2313 | if (use_dst_range) { |
2314 | if (((struct sockaddr *)(dst1+ 1))->sa_family != address_family || |
2315 | ((struct sockaddr *)(dst1+ 1))->sa_len != address_len) { |
2316 | return key_senderror(so, m, EINVAL); |
2317 | } |
2318 | } |
2319 | |
2320 | /* checking the direction. */ |
2321 | switch (xpl0->sadb_x_policy_dir) { |
2322 | case IPSEC_DIR_INBOUND: |
2323 | case IPSEC_DIR_OUTBOUND: |
2324 | break; |
2325 | default: |
2326 | ipseclog((LOG_DEBUG, "key_spdadd: Invalid SP direction.\n" )); |
2327 | mhp->msg->sadb_msg_errno = EINVAL; |
2328 | return 0; |
2329 | } |
2330 | |
2331 | /* check policy */ |
2332 | /* key_spdadd() accepts DISCARD, NONE and IPSEC. */ |
2333 | if (xpl0->sadb_x_policy_type == IPSEC_POLICY_ENTRUST |
2334 | || xpl0->sadb_x_policy_type == IPSEC_POLICY_BYPASS) { |
2335 | ipseclog((LOG_DEBUG, "key_spdadd: Invalid policy type.\n" )); |
2336 | return key_senderror(so, m, EINVAL); |
2337 | } |
2338 | |
2339 | /* policy requests are mandatory when action is ipsec. */ |
2340 | if (mhp->msg->sadb_msg_type != SADB_X_SPDSETIDX |
2341 | && xpl0->sadb_x_policy_type == IPSEC_POLICY_IPSEC |
2342 | && mhp->extlen[SADB_X_EXT_POLICY] <= sizeof(*xpl0)) { |
2343 | ipseclog((LOG_DEBUG, "key_spdadd: some policy requests part required.\n" )); |
2344 | return key_senderror(so, m, EINVAL); |
2345 | } |
2346 | |
2347 | /* Process interfaces */ |
2348 | if (ipsecifopts != NULL) { |
2349 | if (ipsecifopts->sadb_x_ipsecif_internal_if[0]) { |
2350 | ifnet_find_by_name(ipsecifopts->sadb_x_ipsecif_internal_if, &internal_if); |
2351 | } |
2352 | if (ipsecifopts->sadb_x_ipsecif_outgoing_if[0]) { |
2353 | outgoing_if = ipsecifopts->sadb_x_ipsecif_outgoing_if; |
2354 | } |
2355 | if (ipsecifopts->sadb_x_ipsecif_ipsec_if[0]) { |
2356 | ipsec_if = ipsecifopts->sadb_x_ipsecif_ipsec_if; |
2357 | } |
2358 | init_disabled = ipsecifopts->sadb_x_ipsecif_init_disabled; |
2359 | } |
2360 | |
2361 | /* make secindex */ |
2362 | /* XXX boundary check against sa_len */ |
2363 | KEY_SETSECSPIDX(xpl0->sadb_x_policy_dir, |
2364 | src0 + 1, |
2365 | dst0 + 1, |
2366 | src0->sadb_address_prefixlen, |
2367 | dst0->sadb_address_prefixlen, |
2368 | src0->sadb_address_proto, |
2369 | internal_if, |
2370 | use_src_range ? src0 + 1 : NULL, |
2371 | use_src_range ? src1 + 1 : NULL, |
2372 | use_dst_range ? dst0 + 1 : NULL, |
2373 | use_dst_range ? dst1 + 1 : NULL, |
2374 | &spidx); |
2375 | |
2376 | /* |
2377 | * checking there is SP already or not. |
2378 | * SPDUPDATE doesn't depend on whether there is a SP or not. |
2379 | * If the type is either SPDADD or SPDSETIDX AND a SP is found, |
2380 | * then error. |
2381 | */ |
2382 | lck_mtx_lock(sadb_mutex); |
2383 | newsp = key_getsp(&spidx); |
2384 | if (mhp->msg->sadb_msg_type == SADB_X_SPDUPDATE) { |
2385 | if (newsp) { |
2386 | newsp->state = IPSEC_SPSTATE_DEAD; |
2387 | key_freesp(newsp, KEY_SADB_LOCKED); |
2388 | } |
2389 | } else { |
2390 | if (newsp != NULL) { |
2391 | key_freesp(newsp, KEY_SADB_LOCKED); |
2392 | ipseclog((LOG_DEBUG, "key_spdadd: a SP entry exists already.\n" )); |
2393 | lck_mtx_unlock(sadb_mutex); |
2394 | if (internal_if) { |
2395 | ifnet_release(internal_if); |
2396 | internal_if = NULL; |
2397 | } |
2398 | return key_senderror(so, m, EEXIST); |
2399 | } |
2400 | } |
2401 | lck_mtx_unlock(sadb_mutex); |
2402 | |
2403 | /* allocation new SP entry */ |
2404 | if ((newsp = key_msg2sp(xpl0, PFKEY_EXTLEN(xpl0), &error)) == NULL) { |
2405 | if (internal_if) { |
2406 | ifnet_release(internal_if); |
2407 | internal_if = NULL; |
2408 | } |
2409 | return key_senderror(so, m, error); |
2410 | } |
2411 | |
2412 | if ((newsp->id = key_getnewspid()) == 0) { |
2413 | keydb_delsecpolicy(newsp); |
2414 | if (internal_if) { |
2415 | ifnet_release(internal_if); |
2416 | internal_if = NULL; |
2417 | } |
2418 | return key_senderror(so, m, ENOBUFS); |
2419 | } |
2420 | |
2421 | /* XXX boundary check against sa_len */ |
2422 | KEY_SETSECSPIDX(xpl0->sadb_x_policy_dir, |
2423 | src0 + 1, |
2424 | dst0 + 1, |
2425 | src0->sadb_address_prefixlen, |
2426 | dst0->sadb_address_prefixlen, |
2427 | src0->sadb_address_proto, |
2428 | internal_if, |
2429 | use_src_range ? src0 + 1 : NULL, |
2430 | use_src_range ? src1 + 1 : NULL, |
2431 | use_dst_range ? dst0 + 1 : NULL, |
2432 | use_dst_range ? dst1 + 1 : NULL, |
2433 | &newsp->spidx); |
2434 | |
2435 | #if 1 |
2436 | /* |
2437 | * allow IPv6 over IPv4 or IPv4 over IPv6 tunnels using ESP - |
2438 | * otherwise reject if inner and outer address families not equal |
2439 | */ |
2440 | if (newsp->req && newsp->req->saidx.src.ss_family) { |
2441 | struct sockaddr *sa; |
2442 | sa = (struct sockaddr *)(src0 + 1); |
2443 | if (sa->sa_family != newsp->req->saidx.src.ss_family) { |
2444 | if (newsp->req->saidx.mode != IPSEC_MODE_TUNNEL || newsp->req->saidx.proto != IPPROTO_ESP) { |
2445 | keydb_delsecpolicy(newsp); |
2446 | if (internal_if) { |
2447 | ifnet_release(internal_if); |
2448 | internal_if = NULL; |
2449 | } |
2450 | return key_senderror(so, m, EINVAL); |
2451 | } |
2452 | } |
2453 | } |
2454 | if (newsp->req && newsp->req->saidx.dst.ss_family) { |
2455 | struct sockaddr *sa; |
2456 | sa = (struct sockaddr *)(dst0 + 1); |
2457 | if (sa->sa_family != newsp->req->saidx.dst.ss_family) { |
2458 | if (newsp->req->saidx.mode != IPSEC_MODE_TUNNEL || newsp->req->saidx.proto != IPPROTO_ESP) { |
2459 | keydb_delsecpolicy(newsp); |
2460 | if (internal_if) { |
2461 | ifnet_release(internal_if); |
2462 | internal_if = NULL; |
2463 | } |
2464 | return key_senderror(so, m, EINVAL); |
2465 | } |
2466 | } |
2467 | } |
2468 | #endif |
2469 | |
2470 | microtime(&tv); |
2471 | newsp->created = tv.tv_sec; |
2472 | newsp->lastused = tv.tv_sec; |
2473 | newsp->lifetime = lft ? lft->sadb_lifetime_addtime : 0; |
2474 | newsp->validtime = lft ? lft->sadb_lifetime_usetime : 0; |
2475 | |
2476 | if (outgoing_if != NULL) { |
2477 | ifnet_find_by_name(outgoing_if, &newsp->outgoing_if); |
2478 | } |
2479 | if (ipsec_if != NULL) { |
2480 | ifnet_find_by_name(ipsec_if, &newsp->ipsec_if); |
2481 | } |
2482 | if (init_disabled > 0) { |
2483 | newsp->disabled = 1; |
2484 | } |
2485 | |
2486 | newsp->refcnt = 1; /* do not reclaim until I say I do */ |
2487 | newsp->state = IPSEC_SPSTATE_ALIVE; |
2488 | lck_mtx_lock(sadb_mutex); |
2489 | /* |
2490 | * policies of type generate should be at the end of the SPD |
2491 | * because they function as default discard policies |
2492 | * Don't start timehandler for generate policies |
2493 | */ |
2494 | if (newsp->policy == IPSEC_POLICY_GENERATE) |
2495 | LIST_INSERT_TAIL(&sptree[newsp->spidx.dir], newsp, secpolicy, chain); |
2496 | else { /* XXX until we have policy ordering in the kernel */ |
2497 | struct secpolicy *tmpsp; |
2498 | |
2499 | LIST_FOREACH(tmpsp, &sptree[newsp->spidx.dir], chain) |
2500 | if (tmpsp->policy == IPSEC_POLICY_GENERATE) |
2501 | break; |
2502 | if (tmpsp) |
2503 | LIST_INSERT_BEFORE(tmpsp, newsp, chain); |
2504 | else |
2505 | LIST_INSERT_TAIL(&sptree[newsp->spidx.dir], newsp, secpolicy, chain); |
2506 | key_start_timehandler(); |
2507 | } |
2508 | |
2509 | ipsec_policy_count++; |
2510 | /* Turn off the ipsec bypass */ |
2511 | if (ipsec_bypass != 0) |
2512 | ipsec_bypass = 0; |
2513 | |
2514 | /* delete the entry in spacqtree */ |
2515 | if (mhp->msg->sadb_msg_type == SADB_X_SPDUPDATE) { |
2516 | struct secspacq *spacq; |
2517 | if ((spacq = key_getspacq(&spidx)) != NULL) { |
2518 | /* reset counter in order to deletion by timehandler. */ |
2519 | microtime(&tv); |
2520 | spacq->created = tv.tv_sec; |
2521 | spacq->count = 0; |
2522 | } |
2523 | } |
2524 | lck_mtx_unlock(sadb_mutex); |
2525 | |
2526 | { |
2527 | struct mbuf *n, *mpolicy; |
2528 | struct sadb_msg *newmsg; |
2529 | int off; |
2530 | |
2531 | /* create new sadb_msg to reply. */ |
2532 | if (lft) { |
2533 | int mbufItems[] = {SADB_EXT_RESERVED, SADB_X_EXT_POLICY, |
2534 | SADB_EXT_LIFETIME_HARD, SADB_EXT_ADDRESS_SRC, |
2535 | SADB_EXT_ADDRESS_DST, SADB_X_EXT_ADDR_RANGE_SRC_START, SADB_X_EXT_ADDR_RANGE_SRC_END, |
2536 | SADB_X_EXT_ADDR_RANGE_DST_START, SADB_X_EXT_ADDR_RANGE_DST_END}; |
2537 | n = key_gather_mbuf(m, mhp, 2, sizeof(mbufItems)/sizeof(int), mbufItems); |
2538 | } else { |
2539 | int mbufItems[] = {SADB_EXT_RESERVED, SADB_X_EXT_POLICY, |
2540 | SADB_EXT_ADDRESS_SRC, SADB_EXT_ADDRESS_DST, |
2541 | SADB_X_EXT_ADDR_RANGE_SRC_START, SADB_X_EXT_ADDR_RANGE_SRC_END, |
2542 | SADB_X_EXT_ADDR_RANGE_DST_START, SADB_X_EXT_ADDR_RANGE_DST_END}; |
2543 | n = key_gather_mbuf(m, mhp, 2, sizeof(mbufItems)/sizeof(int), mbufItems); |
2544 | } |
2545 | if (!n) |
2546 | return key_senderror(so, m, ENOBUFS); |
2547 | |
2548 | if (n->m_len < sizeof(*newmsg)) { |
2549 | n = m_pullup(n, sizeof(*newmsg)); |
2550 | if (!n) |
2551 | return key_senderror(so, m, ENOBUFS); |
2552 | } |
2553 | newmsg = mtod(n, struct sadb_msg *); |
2554 | newmsg->sadb_msg_errno = 0; |
2555 | newmsg->sadb_msg_len = PFKEY_UNIT64(n->m_pkthdr.len); |
2556 | |
2557 | off = 0; |
2558 | mpolicy = m_pulldown(n, PFKEY_ALIGN8(sizeof(struct sadb_msg)), |
2559 | sizeof(*xpl), &off); |
2560 | if (mpolicy == NULL) { |
2561 | /* n is already freed */ |
2562 | return key_senderror(so, m, ENOBUFS); |
2563 | } |
2564 | xpl = (struct sadb_x_policy *)(void *)(mtod(mpolicy, caddr_t) + off); |
2565 | if (xpl->sadb_x_policy_exttype != SADB_X_EXT_POLICY) { |
2566 | m_freem(n); |
2567 | return key_senderror(so, m, EINVAL); |
2568 | } |
2569 | xpl->sadb_x_policy_id = newsp->id; |
2570 | |
2571 | m_freem(m); |
2572 | return key_sendup_mbuf(so, n, KEY_SENDUP_ALL); |
2573 | } |
2574 | } |
2575 | |
2576 | /* |
2577 | * get new policy id. |
2578 | * OUT: |
2579 | * 0: failure. |
2580 | * others: success. |
2581 | */ |
2582 | static u_int32_t |
2583 | key_getnewspid(void) |
2584 | { |
2585 | u_int32_t newid = 0; |
2586 | int count = key_spi_trycnt; /* XXX */ |
2587 | struct secpolicy *sp; |
2588 | |
2589 | /* when requesting to allocate spi ranged */ |
2590 | lck_mtx_lock(sadb_mutex); |
2591 | while (count--) { |
2592 | newid = (policy_id = (policy_id == ~0 ? 1 : policy_id + 1)); |
2593 | |
2594 | if ((sp = __key_getspbyid(newid)) == NULL) |
2595 | break; |
2596 | |
2597 | key_freesp(sp, KEY_SADB_LOCKED); |
2598 | } |
2599 | lck_mtx_unlock(sadb_mutex); |
2600 | if (count == 0 || newid == 0) { |
2601 | ipseclog((LOG_DEBUG, "key_getnewspid: to allocate policy id is failed.\n" )); |
2602 | return 0; |
2603 | } |
2604 | |
2605 | return newid; |
2606 | } |
2607 | |
2608 | /* |
2609 | * SADB_SPDDELETE processing |
2610 | * receive |
2611 | * <base, address(SD), policy(*)> |
2612 | * from the user(?), and set SADB_SASTATE_DEAD, |
2613 | * and send, |
2614 | * <base, address(SD), policy(*)> |
2615 | * to the ikmpd. |
2616 | * policy(*) including direction of policy. |
2617 | * |
2618 | * m will always be freed. |
2619 | */ |
2620 | static int |
2621 | key_spddelete( |
2622 | struct socket *so, |
2623 | struct mbuf *m, |
2624 | const struct sadb_msghdr *mhp) |
2625 | { |
2626 | struct sadb_address *src0, *dst0, *src1 = NULL, *dst1 = NULL; |
2627 | struct sadb_x_policy *xpl0; |
2628 | struct secpolicyindex spidx; |
2629 | struct secpolicy *sp; |
2630 | ifnet_t internal_if = NULL; |
2631 | struct sadb_x_ipsecif *ipsecifopts = NULL; |
2632 | int use_src_range = 0; |
2633 | int use_dst_range = 0; |
2634 | |
2635 | LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED); |
2636 | |
2637 | /* sanity check */ |
2638 | if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) |
2639 | panic("key_spddelete: NULL pointer is passed.\n" ); |
2640 | |
2641 | if (mhp->ext[SADB_X_EXT_ADDR_RANGE_SRC_START] != NULL && mhp->ext[SADB_X_EXT_ADDR_RANGE_SRC_END] != NULL) { |
2642 | use_src_range = 1; |
2643 | } |
2644 | if (mhp->ext[SADB_X_EXT_ADDR_RANGE_DST_START] != NULL && mhp->ext[SADB_X_EXT_ADDR_RANGE_DST_END] != NULL) { |
2645 | use_dst_range = 1; |
2646 | } |
2647 | |
2648 | if ((!use_src_range && mhp->ext[SADB_EXT_ADDRESS_SRC] == NULL) || |
2649 | (!use_dst_range && mhp->ext[SADB_EXT_ADDRESS_DST] == NULL) || |
2650 | mhp->ext[SADB_X_EXT_POLICY] == NULL) { |
2651 | ipseclog((LOG_DEBUG, "key_spddelete: invalid message is passed.\n" )); |
2652 | return key_senderror(so, m, EINVAL); |
2653 | } |
2654 | if ((use_src_range && (mhp->extlen[SADB_X_EXT_ADDR_RANGE_SRC_START] < sizeof(struct sadb_address) |
2655 | || mhp->extlen[SADB_X_EXT_ADDR_RANGE_SRC_END] < sizeof(struct sadb_address))) || |
2656 | (!use_src_range && mhp->extlen[SADB_EXT_ADDRESS_SRC] < sizeof(struct sadb_address)) || |
2657 | (use_dst_range && (mhp->extlen[SADB_X_EXT_ADDR_RANGE_DST_START] < sizeof(struct sadb_address) |
2658 | || mhp->extlen[SADB_X_EXT_ADDR_RANGE_DST_END] < sizeof(struct sadb_address))) || |
2659 | (!use_dst_range && mhp->extlen[SADB_EXT_ADDRESS_DST] < sizeof(struct sadb_address)) || |
2660 | mhp->extlen[SADB_X_EXT_POLICY] < sizeof(struct sadb_x_policy)) { |
2661 | ipseclog((LOG_DEBUG, "key_spddelete: invalid message is passed.\n" )); |
2662 | return key_senderror(so, m, EINVAL); |
2663 | } |
2664 | |
2665 | if (use_src_range) { |
2666 | src0 = (struct sadb_address *)mhp->ext[SADB_X_EXT_ADDR_RANGE_SRC_START]; |
2667 | src1 = (struct sadb_address *)mhp->ext[SADB_X_EXT_ADDR_RANGE_SRC_END]; |
2668 | } else { |
2669 | src0 = (struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_SRC]; |
2670 | } |
2671 | if (use_dst_range) { |
2672 | dst0 = (struct sadb_address *)mhp->ext[SADB_X_EXT_ADDR_RANGE_DST_START]; |
2673 | dst1 = (struct sadb_address *)mhp->ext[SADB_X_EXT_ADDR_RANGE_DST_END]; |
2674 | } else { |
2675 | dst0 = (struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_DST]; |
2676 | } |
2677 | xpl0 = (struct sadb_x_policy *)(void *)mhp->ext[SADB_X_EXT_POLICY]; |
2678 | ipsecifopts = (struct sadb_x_ipsecif *)(void *)mhp->ext[SADB_X_EXT_IPSECIF]; |
2679 | |
2680 | /* checking the direction. */ |
2681 | switch (xpl0->sadb_x_policy_dir) { |
2682 | case IPSEC_DIR_INBOUND: |
2683 | case IPSEC_DIR_OUTBOUND: |
2684 | break; |
2685 | default: |
2686 | ipseclog((LOG_DEBUG, "key_spddelete: Invalid SP direction.\n" )); |
2687 | return key_senderror(so, m, EINVAL); |
2688 | } |
2689 | |
2690 | /* Process interfaces */ |
2691 | if (ipsecifopts != NULL) { |
2692 | if (ipsecifopts->sadb_x_ipsecif_internal_if[0]) { |
2693 | ifnet_find_by_name(ipsecifopts->sadb_x_ipsecif_internal_if, &internal_if); |
2694 | } |
2695 | } |
2696 | |
2697 | /* make secindex */ |
2698 | /* XXX boundary check against sa_len */ |
2699 | KEY_SETSECSPIDX(xpl0->sadb_x_policy_dir, |
2700 | src0 + 1, |
2701 | dst0 + 1, |
2702 | src0->sadb_address_prefixlen, |
2703 | dst0->sadb_address_prefixlen, |
2704 | src0->sadb_address_proto, |
2705 | internal_if, |
2706 | use_src_range ? src0 + 1 : NULL, |
2707 | use_src_range ? src1 + 1 : NULL, |
2708 | use_dst_range ? dst0 + 1 : NULL, |
2709 | use_dst_range ? dst1 + 1 : NULL, |
2710 | &spidx); |
2711 | |
2712 | /* Is there SP in SPD ? */ |
2713 | lck_mtx_lock(sadb_mutex); |
2714 | if ((sp = key_getsp(&spidx)) == NULL) { |
2715 | ipseclog((LOG_DEBUG, "key_spddelete: no SP found.\n" )); |
2716 | lck_mtx_unlock(sadb_mutex); |
2717 | if (internal_if) { |
2718 | ifnet_release(internal_if); |
2719 | internal_if = NULL; |
2720 | } |
2721 | return key_senderror(so, m, EINVAL); |
2722 | } |
2723 | |
2724 | if (internal_if) { |
2725 | ifnet_release(internal_if); |
2726 | internal_if = NULL; |
2727 | } |
2728 | |
2729 | /* save policy id to buffer to be returned. */ |
2730 | xpl0->sadb_x_policy_id = sp->id; |
2731 | |
2732 | sp->state = IPSEC_SPSTATE_DEAD; |
2733 | key_freesp(sp, KEY_SADB_LOCKED); |
2734 | lck_mtx_unlock(sadb_mutex); |
2735 | |
2736 | |
2737 | { |
2738 | struct mbuf *n; |
2739 | struct sadb_msg *newmsg; |
2740 | int mbufItems[] = {SADB_EXT_RESERVED, SADB_X_EXT_POLICY, |
2741 | SADB_EXT_ADDRESS_SRC, SADB_EXT_ADDRESS_DST, |
2742 | SADB_X_EXT_ADDR_RANGE_SRC_START, SADB_X_EXT_ADDR_RANGE_SRC_END, |
2743 | SADB_X_EXT_ADDR_RANGE_DST_START, SADB_X_EXT_ADDR_RANGE_DST_END}; |
2744 | |
2745 | /* create new sadb_msg to reply. */ |
2746 | n = key_gather_mbuf(m, mhp, 1, sizeof(mbufItems)/sizeof(int), mbufItems); |
2747 | if (!n) |
2748 | return key_senderror(so, m, ENOBUFS); |
2749 | |
2750 | newmsg = mtod(n, struct sadb_msg *); |
2751 | newmsg->sadb_msg_errno = 0; |
2752 | newmsg->sadb_msg_len = PFKEY_UNIT64(n->m_pkthdr.len); |
2753 | |
2754 | m_freem(m); |
2755 | return key_sendup_mbuf(so, n, KEY_SENDUP_ALL); |
2756 | } |
2757 | } |
2758 | |
2759 | /* |
2760 | * SADB_SPDDELETE2 processing |
2761 | * receive |
2762 | * <base, policy(*)> |
2763 | * from the user(?), and set SADB_SASTATE_DEAD, |
2764 | * and send, |
2765 | * <base, policy(*)> |
2766 | * to the ikmpd. |
2767 | * policy(*) including direction of policy. |
2768 | * |
2769 | * m will always be freed. |
2770 | */ |
2771 | static int |
2772 | key_spddelete2( |
2773 | struct socket *so, |
2774 | struct mbuf *m, |
2775 | const struct sadb_msghdr *mhp) |
2776 | { |
2777 | u_int32_t id; |
2778 | struct secpolicy *sp; |
2779 | |
2780 | LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED); |
2781 | |
2782 | /* sanity check */ |
2783 | if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) |
2784 | panic("key_spddelete2: NULL pointer is passed.\n" ); |
2785 | |
2786 | if (mhp->ext[SADB_X_EXT_POLICY] == NULL || |
2787 | mhp->extlen[SADB_X_EXT_POLICY] < sizeof(struct sadb_x_policy)) { |
2788 | ipseclog((LOG_DEBUG, "key_spddelete2: invalid message is passed.\n" )); |
2789 | key_senderror(so, m, EINVAL); |
2790 | return 0; |
2791 | } |
2792 | |
2793 | id = ((struct sadb_x_policy *) |
2794 | (void *)mhp->ext[SADB_X_EXT_POLICY])->sadb_x_policy_id; |
2795 | |
2796 | /* Is there SP in SPD ? */ |
2797 | lck_mtx_lock(sadb_mutex); |
2798 | if ((sp = __key_getspbyid(id)) == NULL) { |
2799 | lck_mtx_unlock(sadb_mutex); |
2800 | ipseclog((LOG_DEBUG, "key_spddelete2: no SP found id:%u.\n" , id)); |
2801 | return key_senderror(so, m, EINVAL); |
2802 | } |
2803 | |
2804 | sp->state = IPSEC_SPSTATE_DEAD; |
2805 | key_freesp(sp, KEY_SADB_LOCKED); |
2806 | lck_mtx_unlock(sadb_mutex); |
2807 | |
2808 | { |
2809 | struct mbuf *n, *nn; |
2810 | struct sadb_msg *newmsg; |
2811 | int off, len; |
2812 | |
2813 | /* create new sadb_msg to reply. */ |
2814 | len = PFKEY_ALIGN8(sizeof(struct sadb_msg)); |
2815 | |
2816 | if (len > MCLBYTES) |
2817 | return key_senderror(so, m, ENOBUFS); |
2818 | MGETHDR(n, M_WAITOK, MT_DATA); |
2819 | if (n && len > MHLEN) { |
2820 | MCLGET(n, M_WAITOK); |
2821 | if ((n->m_flags & M_EXT) == 0) { |
2822 | m_freem(n); |
2823 | n = NULL; |
2824 | } |
2825 | } |
2826 | if (!n) |
2827 | return key_senderror(so, m, ENOBUFS); |
2828 | |
2829 | n->m_len = len; |
2830 | n->m_next = NULL; |
2831 | off = 0; |
2832 | |
2833 | m_copydata(m, 0, sizeof(struct sadb_msg), mtod(n, caddr_t) + off); |
2834 | off += PFKEY_ALIGN8(sizeof(struct sadb_msg)); |
2835 | |
2836 | #if DIAGNOSTIC |
2837 | if (off != len) |
2838 | panic("length inconsistency in key_spddelete2" ); |
2839 | #endif |
2840 | |
2841 | n->m_next = m_copym(m, mhp->extoff[SADB_X_EXT_POLICY], |
2842 | mhp->extlen[SADB_X_EXT_POLICY], M_WAITOK); |
2843 | if (!n->m_next) { |
2844 | m_freem(n); |
2845 | return key_senderror(so, m, ENOBUFS); |
2846 | } |
2847 | |
2848 | n->m_pkthdr.len = 0; |
2849 | for (nn = n; nn; nn = nn->m_next) |
2850 | n->m_pkthdr.len += nn->m_len; |
2851 | |
2852 | newmsg = mtod(n, struct sadb_msg *); |
2853 | newmsg->sadb_msg_errno = 0; |
2854 | newmsg->sadb_msg_len = PFKEY_UNIT64(n->m_pkthdr.len); |
2855 | |
2856 | m_freem(m); |
2857 | return key_sendup_mbuf(so, n, KEY_SENDUP_ALL); |
2858 | } |
2859 | } |
2860 | |
2861 | static int |
2862 | key_spdenable( |
2863 | struct socket *so, |
2864 | struct mbuf *m, |
2865 | const struct sadb_msghdr *mhp) |
2866 | { |
2867 | u_int32_t id; |
2868 | struct secpolicy *sp; |
2869 | |
2870 | LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED); |
2871 | |
2872 | /* sanity check */ |
2873 | if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) |
2874 | panic("key_spdenable: NULL pointer is passed.\n" ); |
2875 | |
2876 | if (mhp->ext[SADB_X_EXT_POLICY] == NULL || |
2877 | mhp->extlen[SADB_X_EXT_POLICY] < sizeof(struct sadb_x_policy)) { |
2878 | ipseclog((LOG_DEBUG, "key_spdenable: invalid message is passed.\n" )); |
2879 | key_senderror(so, m, EINVAL); |
2880 | return 0; |
2881 | } |
2882 | |
2883 | id = ((struct sadb_x_policy *) |
2884 | (void *)mhp->ext[SADB_X_EXT_POLICY])->sadb_x_policy_id; |
2885 | |
2886 | /* Is there SP in SPD ? */ |
2887 | lck_mtx_lock(sadb_mutex); |
2888 | if ((sp = __key_getspbyid(id)) == NULL) { |
2889 | lck_mtx_unlock(sadb_mutex); |
2890 | ipseclog((LOG_DEBUG, "key_spdenable: no SP found id:%u.\n" , id)); |
2891 | return key_senderror(so, m, EINVAL); |
2892 | } |
2893 | |
2894 | sp->disabled = 0; |
2895 | lck_mtx_unlock(sadb_mutex); |
2896 | |
2897 | { |
2898 | struct mbuf *n; |
2899 | struct sadb_msg *newmsg; |
2900 | int mbufItems[] = {SADB_EXT_RESERVED, SADB_X_EXT_POLICY}; |
2901 | |
2902 | /* create new sadb_msg to reply. */ |
2903 | n = key_gather_mbuf(m, mhp, 1, sizeof(mbufItems)/sizeof(int), mbufItems); |
2904 | if (!n) |
2905 | return key_senderror(so, m, ENOBUFS); |
2906 | |
2907 | if (n->m_len < sizeof(struct sadb_msg)) { |
2908 | n = m_pullup(n, sizeof(struct sadb_msg)); |
2909 | if (n == NULL) |
2910 | return key_senderror(so, m, ENOBUFS); |
2911 | } |
2912 | newmsg = mtod(n, struct sadb_msg *); |
2913 | newmsg->sadb_msg_errno = 0; |
2914 | newmsg->sadb_msg_len = PFKEY_UNIT64(n->m_pkthdr.len); |
2915 | |
2916 | m_freem(m); |
2917 | return key_sendup_mbuf(so, n, KEY_SENDUP_ALL); |
2918 | } |
2919 | } |
2920 | |
2921 | static int |
2922 | key_spddisable( |
2923 | struct socket *so, |
2924 | struct mbuf *m, |
2925 | const struct sadb_msghdr *mhp) |
2926 | { |
2927 | u_int32_t id; |
2928 | struct secpolicy *sp; |
2929 | |
2930 | LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED); |
2931 | |
2932 | /* sanity check */ |
2933 | if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) |
2934 | panic("key_spddisable: NULL pointer is passed.\n" ); |
2935 | |
2936 | if (mhp->ext[SADB_X_EXT_POLICY] == NULL || |
2937 | mhp->extlen[SADB_X_EXT_POLICY] < sizeof(struct sadb_x_policy)) { |
2938 | ipseclog((LOG_DEBUG, "key_spddisable: invalid message is passed.\n" )); |
2939 | key_senderror(so, m, EINVAL); |
2940 | return 0; |
2941 | } |
2942 | |
2943 | id = ((struct sadb_x_policy *) |
2944 | (void *)mhp->ext[SADB_X_EXT_POLICY])->sadb_x_policy_id; |
2945 | |
2946 | /* Is there SP in SPD ? */ |
2947 | lck_mtx_lock(sadb_mutex); |
2948 | if ((sp = __key_getspbyid(id)) == NULL) { |
2949 | lck_mtx_unlock(sadb_mutex); |
2950 | ipseclog((LOG_DEBUG, "key_spddisable: no SP found id:%u.\n" , id)); |
2951 | return key_senderror(so, m, EINVAL); |
2952 | } |
2953 | |
2954 | sp->disabled = 1; |
2955 | lck_mtx_unlock(sadb_mutex); |
2956 | |
2957 | { |
2958 | struct mbuf *n; |
2959 | struct sadb_msg *newmsg; |
2960 | int mbufItems[] = {SADB_EXT_RESERVED, SADB_X_EXT_POLICY}; |
2961 | |
2962 | /* create new sadb_msg to reply. */ |
2963 | n = key_gather_mbuf(m, mhp, 1, sizeof(mbufItems)/sizeof(int), mbufItems); |
2964 | if (!n) |
2965 | return key_senderror(so, m, ENOBUFS); |
2966 | |
2967 | if (n->m_len < sizeof(struct sadb_msg)) { |
2968 | n = m_pullup(n, sizeof(struct sadb_msg)); |
2969 | if (n == NULL) |
2970 | return key_senderror(so, m, ENOBUFS); |
2971 | } |
2972 | newmsg = mtod(n, struct sadb_msg *); |
2973 | newmsg->sadb_msg_errno = 0; |
2974 | newmsg->sadb_msg_len = PFKEY_UNIT64(n->m_pkthdr.len); |
2975 | |
2976 | m_freem(m); |
2977 | return key_sendup_mbuf(so, n, KEY_SENDUP_ALL); |
2978 | } |
2979 | } |
2980 | |
2981 | /* |
2982 | * SADB_X_GET processing |
2983 | * receive |
2984 | * <base, policy(*)> |
2985 | * from the user(?), |
2986 | * and send, |
2987 | * <base, address(SD), policy> |
2988 | * to the ikmpd. |
2989 | * policy(*) including direction of policy. |
2990 | * |
2991 | * m will always be freed. |
2992 | */ |
2993 | static int |
2994 | key_spdget( |
2995 | struct socket *so, |
2996 | struct mbuf *m, |
2997 | const struct sadb_msghdr *mhp) |
2998 | { |
2999 | u_int32_t id; |
3000 | struct secpolicy *sp; |
3001 | struct mbuf *n; |
3002 | |
3003 | LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED); |
3004 | |
3005 | /* sanity check */ |
3006 | if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) |
3007 | panic("key_spdget: NULL pointer is passed.\n" ); |
3008 | |
3009 | if (mhp->ext[SADB_X_EXT_POLICY] == NULL || |
3010 | mhp->extlen[SADB_X_EXT_POLICY] < sizeof(struct sadb_x_policy)) { |
3011 | ipseclog((LOG_DEBUG, "key_spdget: invalid message is passed.\n" )); |
3012 | return key_senderror(so, m, EINVAL); |
3013 | } |
3014 | |
3015 | id = ((struct sadb_x_policy *) |
3016 | (void *)mhp->ext[SADB_X_EXT_POLICY])->sadb_x_policy_id; |
3017 | |
3018 | /* Is there SP in SPD ? */ |
3019 | lck_mtx_lock(sadb_mutex); |
3020 | if ((sp = __key_getspbyid(id)) == NULL) { |
3021 | ipseclog((LOG_DEBUG, "key_spdget: no SP found id:%u.\n" , id)); |
3022 | lck_mtx_unlock(sadb_mutex); |
3023 | return key_senderror(so, m, ENOENT); |
3024 | } |
3025 | lck_mtx_unlock(sadb_mutex); |
3026 | n = key_setdumpsp(sp, SADB_X_SPDGET, 0, mhp->msg->sadb_msg_pid); |
3027 | if (n != NULL) { |
3028 | m_freem(m); |
3029 | return key_sendup_mbuf(so, n, KEY_SENDUP_ONE); |
3030 | } else |
3031 | return key_senderror(so, m, ENOBUFS); |
3032 | } |
3033 | |
3034 | /* |
3035 | * SADB_X_SPDACQUIRE processing. |
3036 | * Acquire policy and SA(s) for a *OUTBOUND* packet. |
3037 | * send |
3038 | * <base, policy(*)> |
3039 | * to KMD, and expect to receive |
3040 | * <base> with SADB_X_SPDACQUIRE if error occurred, |
3041 | * or |
3042 | * <base, policy> |
3043 | * with SADB_X_SPDUPDATE from KMD by PF_KEY. |
3044 | * policy(*) is without policy requests. |
3045 | * |
3046 | * 0 : succeed |
3047 | * others: error number |
3048 | */ |
3049 | int |
3050 | key_spdacquire( |
3051 | struct secpolicy *sp) |
3052 | { |
3053 | struct mbuf *result = NULL, *m; |
3054 | struct secspacq *newspacq; |
3055 | int error; |
3056 | |
3057 | LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED); |
3058 | |
3059 | /* sanity check */ |
3060 | if (sp == NULL) |
3061 | panic("key_spdacquire: NULL pointer is passed.\n" ); |
3062 | if (sp->req != NULL) |
3063 | panic("key_spdacquire: called but there is request.\n" ); |
3064 | if (sp->policy != IPSEC_POLICY_IPSEC) |
3065 | panic("key_spdacquire: policy mismathed. IPsec is expected.\n" ); |
3066 | |
3067 | /* get a entry to check whether sent message or not. */ |
3068 | lck_mtx_lock(sadb_mutex); |
3069 | if ((newspacq = key_getspacq(&sp->spidx)) != NULL) { |
3070 | if (key_blockacq_count < newspacq->count) { |
3071 | /* reset counter and do send message. */ |
3072 | newspacq->count = 0; |
3073 | } else { |
3074 | /* increment counter and do nothing. */ |
3075 | newspacq->count++; |
3076 | lck_mtx_unlock(sadb_mutex); |
3077 | return 0; |
3078 | } |
3079 | } else { |
3080 | /* make new entry for blocking to send SADB_ACQUIRE. */ |
3081 | if ((newspacq = key_newspacq(&sp->spidx)) == NULL) { |
3082 | lck_mtx_unlock(sadb_mutex); |
3083 | return ENOBUFS; |
3084 | } |
3085 | /* add to acqtree */ |
3086 | LIST_INSERT_HEAD(&spacqtree, newspacq, chain); |
3087 | key_start_timehandler(); |
3088 | } |
3089 | lck_mtx_unlock(sadb_mutex); |
3090 | /* create new sadb_msg to reply. */ |
3091 | m = key_setsadbmsg(SADB_X_SPDACQUIRE, 0, 0, 0, 0, 0); |
3092 | if (!m) { |
3093 | error = ENOBUFS; |
3094 | goto fail; |
3095 | } |
3096 | result = m; |
3097 | |
3098 | result->m_pkthdr.len = 0; |
3099 | for (m = result; m; m = m->m_next) |
3100 | result->m_pkthdr.len += m->m_len; |
3101 | |
3102 | mtod(result, struct sadb_msg *)->sadb_msg_len = |
3103 | PFKEY_UNIT64(result->m_pkthdr.len); |
3104 | |
3105 | return key_sendup_mbuf(NULL, m, KEY_SENDUP_REGISTERED); |
3106 | |
3107 | fail: |
3108 | if (result) |
3109 | m_freem(result); |
3110 | return error; |
3111 | } |
3112 | |
3113 | /* |
3114 | * SADB_SPDFLUSH processing |
3115 | * receive |
3116 | * <base> |
3117 | * from the user, and free all entries in secpctree. |
3118 | * and send, |
3119 | * <base> |
3120 | * to the user. |
3121 | * NOTE: what to do is only marking SADB_SASTATE_DEAD. |
3122 | * |
3123 | * m will always be freed. |
3124 | */ |
3125 | static int |
3126 | key_spdflush( |
3127 | struct socket *so, |
3128 | struct mbuf *m, |
3129 | const struct sadb_msghdr *mhp) |
3130 | { |
3131 | struct sadb_msg *newmsg; |
3132 | struct secpolicy *sp; |
3133 | u_int dir; |
3134 | |
3135 | /* sanity check */ |
3136 | if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) |
3137 | panic("key_spdflush: NULL pointer is passed.\n" ); |
3138 | |
3139 | if (m->m_len != PFKEY_ALIGN8(sizeof(struct sadb_msg))) |
3140 | return key_senderror(so, m, EINVAL); |
3141 | |
3142 | lck_mtx_lock(sadb_mutex); |
3143 | for (dir = 0; dir < IPSEC_DIR_MAX; dir++) { |
3144 | LIST_FOREACH(sp, &sptree[dir], chain) { |
3145 | sp->state = IPSEC_SPSTATE_DEAD; |
3146 | } |
3147 | } |
3148 | lck_mtx_unlock(sadb_mutex); |
3149 | |
3150 | if (sizeof(struct sadb_msg) > m->m_len + M_TRAILINGSPACE(m)) { |
3151 | ipseclog((LOG_DEBUG, "key_spdflush: No more memory.\n" )); |
3152 | return key_senderror(so, m, ENOBUFS); |
3153 | } |
3154 | |
3155 | if (m->m_next) |
3156 | m_freem(m->m_next); |
3157 | m->m_next = NULL; |
3158 | m->m_pkthdr.len = m->m_len = PFKEY_ALIGN8(sizeof(struct sadb_msg)); |
3159 | newmsg = mtod(m, struct sadb_msg *); |
3160 | newmsg->sadb_msg_errno = 0; |
3161 | newmsg->sadb_msg_len = PFKEY_UNIT64(m->m_pkthdr.len); |
3162 | |
3163 | return key_sendup_mbuf(so, m, KEY_SENDUP_ALL); |
3164 | } |
3165 | |
3166 | /* |
3167 | * SADB_SPDDUMP processing |
3168 | * receive |
3169 | * <base> |
3170 | * from the user, and dump all SP leaves |
3171 | * and send, |
3172 | * <base> ..... |
3173 | * to the ikmpd. |
3174 | * |
3175 | * m will always be freed. |
3176 | */ |
3177 | |
3178 | static int |
3179 | key_spddump( |
3180 | struct socket *so, |
3181 | struct mbuf *m, |
3182 | const struct sadb_msghdr *mhp) |
3183 | { |
3184 | struct secpolicy *sp, **spbuf = NULL, **sp_ptr; |
3185 | int cnt = 0, bufcount; |
3186 | u_int dir; |
3187 | struct mbuf *n; |
3188 | int error = 0; |
3189 | |
3190 | /* sanity check */ |
3191 | if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) |
3192 | panic("key_spddump: NULL pointer is passed.\n" ); |
3193 | |
3194 | if ((bufcount = ipsec_policy_count) == 0) { |
3195 | error = ENOENT; |
3196 | goto end; |
3197 | } |
3198 | bufcount += 256; /* extra */ |
3199 | KMALLOC_WAIT(spbuf, struct secpolicy**, bufcount * sizeof(struct secpolicy*)); |
3200 | if (spbuf == NULL) { |
3201 | ipseclog((LOG_DEBUG, "key_spddump: No more memory.\n" )); |
3202 | error = ENOMEM; |
3203 | goto end; |
3204 | } |
3205 | lck_mtx_lock(sadb_mutex); |
3206 | /* search SPD entry, make list. */ |
3207 | sp_ptr = spbuf; |
3208 | for (dir = 0; dir < IPSEC_DIR_MAX; dir++) { |
3209 | LIST_FOREACH(sp, &sptree[dir], chain) { |
3210 | if (cnt == bufcount) |
3211 | break; /* buffer full */ |
3212 | *sp_ptr++ = sp; |
3213 | sp->refcnt++; |
3214 | cnt++; |
3215 | } |
3216 | } |
3217 | lck_mtx_unlock(sadb_mutex); |
3218 | |
3219 | if (cnt == 0) { |
3220 | error = ENOENT; |
3221 | goto end; |
3222 | } |
3223 | |
3224 | sp_ptr = spbuf; |
3225 | while (cnt) { |
3226 | --cnt; |
3227 | n = key_setdumpsp(*sp_ptr++, SADB_X_SPDDUMP, cnt, |
3228 | mhp->msg->sadb_msg_pid); |
3229 | |
3230 | if (n) |
3231 | key_sendup_mbuf(so, n, KEY_SENDUP_ONE); |
3232 | } |
3233 | |
3234 | lck_mtx_lock(sadb_mutex); |
3235 | while (sp_ptr > spbuf) |
3236 | key_freesp(*(--sp_ptr), KEY_SADB_LOCKED); |
3237 | lck_mtx_unlock(sadb_mutex); |
3238 | |
3239 | end: |
3240 | if (spbuf) |
3241 | KFREE(spbuf); |
3242 | if (error) |
3243 | return key_senderror(so, m, error); |
3244 | |
3245 | m_freem(m); |
3246 | return 0; |
3247 | |
3248 | } |
3249 | |
3250 | static struct mbuf * |
3251 | key_setdumpsp( |
3252 | struct secpolicy *sp, |
3253 | u_int8_t type, |
3254 | u_int32_t seq, |
3255 | u_int32_t pid) |
3256 | { |
3257 | struct mbuf *result = NULL, *m; |
3258 | |
3259 | m = key_setsadbmsg(type, 0, SADB_SATYPE_UNSPEC, seq, pid, sp->refcnt); |
3260 | if (!m) |
3261 | goto fail; |
3262 | result = m; |
3263 | |
3264 | if (sp->spidx.src_range.start.ss_len > 0) { |
3265 | m = key_setsadbaddr(SADB_X_EXT_ADDR_RANGE_SRC_START, |
3266 | (struct sockaddr *)&sp->spidx.src_range.start, sp->spidx.prefs, |
3267 | sp->spidx.ul_proto); |
3268 | if (!m) |
3269 | goto fail; |
3270 | m_cat(result, m); |
3271 | |
3272 | m = key_setsadbaddr(SADB_X_EXT_ADDR_RANGE_SRC_END, |
3273 | (struct sockaddr *)&sp->spidx.src_range.end, sp->spidx.prefs, |
3274 | sp->spidx.ul_proto); |
3275 | if (!m) |
3276 | goto fail; |
3277 | m_cat(result, m); |
3278 | } else { |
3279 | m = key_setsadbaddr(SADB_EXT_ADDRESS_SRC, |
3280 | (struct sockaddr *)&sp->spidx.src, sp->spidx.prefs, |
3281 | sp->spidx.ul_proto); |
3282 | if (!m) |
3283 | goto fail; |
3284 | m_cat(result, m); |
3285 | } |
3286 | |
3287 | if (sp->spidx.dst_range.start.ss_len > 0) { |
3288 | m = key_setsadbaddr(SADB_X_EXT_ADDR_RANGE_DST_START, |
3289 | (struct sockaddr *)&sp->spidx.dst_range.start, sp->spidx.prefd, |
3290 | sp->spidx.ul_proto); |
3291 | if (!m) |
3292 | goto fail; |
3293 | m_cat(result, m); |
3294 | |
3295 | m = key_setsadbaddr(SADB_X_EXT_ADDR_RANGE_DST_END, |
3296 | (struct sockaddr *)&sp->spidx.dst_range.end, sp->spidx.prefd, |
3297 | sp->spidx.ul_proto); |
3298 | if (!m) |
3299 | goto fail; |
3300 | m_cat(result, m); |
3301 | } else { |
3302 | m = key_setsadbaddr(SADB_EXT_ADDRESS_DST, |
3303 | (struct sockaddr *)&sp->spidx.dst, sp->spidx.prefd, |
3304 | sp->spidx.ul_proto); |
3305 | if (!m) |
3306 | goto fail; |
3307 | m_cat(result, m); |
3308 | } |
3309 | |
3310 | if (sp->spidx.internal_if || sp->outgoing_if || sp->ipsec_if || sp->disabled) { |
3311 | m = key_setsadbipsecif(sp->spidx.internal_if, sp->outgoing_if, sp->ipsec_if, sp->disabled); |
3312 | if (!m) |
3313 | goto fail; |
3314 | m_cat(result, m); |
3315 | } |
3316 | |
3317 | m = key_sp2msg(sp); |
3318 | if (!m) |
3319 | goto fail; |
3320 | m_cat(result, m); |
3321 | |
3322 | if ((result->m_flags & M_PKTHDR) == 0) |
3323 | goto fail; |
3324 | |
3325 | if (result->m_len < sizeof(struct sadb_msg)) { |
3326 | result = m_pullup(result, sizeof(struct sadb_msg)); |
3327 | if (result == NULL) |
3328 | goto fail; |
3329 | } |
3330 | |
3331 | result->m_pkthdr.len = 0; |
3332 | for (m = result; m; m = m->m_next) |
3333 | result->m_pkthdr.len += m->m_len; |
3334 | |
3335 | mtod(result, struct sadb_msg *)->sadb_msg_len = |
3336 | PFKEY_UNIT64(result->m_pkthdr.len); |
3337 | |
3338 | return result; |
3339 | |
3340 | fail: |
3341 | m_freem(result); |
3342 | return NULL; |
3343 | } |
3344 | |
3345 | /* |
3346 | * get PFKEY message length for security policy and request. |
3347 | */ |
3348 | static u_int |
3349 | key_getspreqmsglen( |
3350 | struct secpolicy *sp) |
3351 | { |
3352 | u_int tlen; |
3353 | |
3354 | tlen = sizeof(struct sadb_x_policy); |
3355 | |
3356 | /* if is the policy for ipsec ? */ |
3357 | if (sp->policy != IPSEC_POLICY_IPSEC) |
3358 | return tlen; |
3359 | |
3360 | /* get length of ipsec requests */ |
3361 | { |
3362 | struct ipsecrequest *isr; |
3363 | int len; |
3364 | |
3365 | for (isr = sp->req; isr != NULL; isr = isr->next) { |
3366 | len = sizeof(struct sadb_x_ipsecrequest) |
3367 | + isr->saidx.src.ss_len |
3368 | + isr->saidx.dst.ss_len; |
3369 | |
3370 | tlen += PFKEY_ALIGN8(len); |
3371 | } |
3372 | } |
3373 | |
3374 | return tlen; |
3375 | } |
3376 | |
3377 | /* |
3378 | * SADB_SPDEXPIRE processing |
3379 | * send |
3380 | * <base, address(SD), lifetime(CH), policy> |
3381 | * to KMD by PF_KEY. |
3382 | * |
3383 | * OUT: 0 : succeed |
3384 | * others : error number |
3385 | */ |
3386 | static int |
3387 | key_spdexpire( |
3388 | struct secpolicy *sp) |
3389 | { |
3390 | struct mbuf *result = NULL, *m; |
3391 | int len; |
3392 | int error = EINVAL; |
3393 | struct sadb_lifetime *lt; |
3394 | |
3395 | LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED); |
3396 | |
3397 | /* sanity check */ |
3398 | if (sp == NULL) |
3399 | panic("key_spdexpire: NULL pointer is passed.\n" ); |
3400 | |
3401 | /* set msg header */ |
3402 | m = key_setsadbmsg(SADB_X_SPDEXPIRE, 0, 0, 0, 0, 0); |
3403 | if (!m) { |
3404 | error = ENOBUFS; |
3405 | goto fail; |
3406 | } |
3407 | result = m; |
3408 | |
3409 | /* create lifetime extension (current and hard) */ |
3410 | len = PFKEY_ALIGN8(sizeof(*lt)) * 2; |
3411 | m = key_alloc_mbuf(len); |
3412 | if (!m || m->m_next) { /*XXX*/ |
3413 | if (m) |
3414 | m_freem(m); |
3415 | error = ENOBUFS; |
3416 | goto fail; |
3417 | } |
3418 | bzero(mtod(m, caddr_t), len); |
3419 | lt = mtod(m, struct sadb_lifetime *); |
3420 | lt->sadb_lifetime_len = PFKEY_UNIT64(sizeof(struct sadb_lifetime)); |
3421 | lt->sadb_lifetime_exttype = SADB_EXT_LIFETIME_CURRENT; |
3422 | lt->sadb_lifetime_allocations = 0; |
3423 | lt->sadb_lifetime_bytes = 0; |
3424 | lt->sadb_lifetime_addtime = sp->created; |
3425 | lt->sadb_lifetime_usetime = sp->lastused; |
3426 | lt = (struct sadb_lifetime *)(void *)(mtod(m, caddr_t) + len / 2); |
3427 | lt->sadb_lifetime_len = PFKEY_UNIT64(sizeof(struct sadb_lifetime)); |
3428 | lt->sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD; |
3429 | lt->sadb_lifetime_allocations = 0; |
3430 | lt->sadb_lifetime_bytes = 0; |
3431 | lt->sadb_lifetime_addtime = sp->lifetime; |
3432 | lt->sadb_lifetime_usetime = sp->validtime; |
3433 | m_cat(result, m); |
3434 | |
3435 | /* set sadb_address(es) for source */ |
3436 | if (sp->spidx.src_range.start.ss_len > 0) { |
3437 | m = key_setsadbaddr(SADB_X_EXT_ADDR_RANGE_SRC_START, |
3438 | (struct sockaddr *)&sp->spidx.src_range.start, sp->spidx.prefs, |
3439 | sp->spidx.ul_proto); |
3440 | if (!m) { |
3441 | error = ENOBUFS; |
3442 | goto fail; |
3443 | } |
3444 | m_cat(result, m); |
3445 | |
3446 | m = key_setsadbaddr(SADB_X_EXT_ADDR_RANGE_SRC_END, |
3447 | (struct sockaddr *)&sp->spidx.src_range.end, sp->spidx.prefs, |
3448 | sp->spidx.ul_proto); |
3449 | if (!m) { |
3450 | error = ENOBUFS; |
3451 | goto fail; |
3452 | } |
3453 | m_cat(result, m); |
3454 | } else { |
3455 | m = key_setsadbaddr(SADB_EXT_ADDRESS_SRC, |
3456 | (struct sockaddr *)&sp->spidx.src, sp->spidx.prefs, |
3457 | sp->spidx.ul_proto); |
3458 | if (!m) { |
3459 | error = ENOBUFS; |
3460 | goto fail; |
3461 | } |
3462 | m_cat(result, m); |
3463 | } |
3464 | |
3465 | /* set sadb_address(es) for dest */ |
3466 | if (sp->spidx.dst_range.start.ss_len > 0) { |
3467 | m = key_setsadbaddr(SADB_X_EXT_ADDR_RANGE_DST_START, |
3468 | (struct sockaddr *)&sp->spidx.dst_range.start, sp->spidx.prefd, |
3469 | sp->spidx.ul_proto); |
3470 | if (!m) { |
3471 | error = ENOBUFS; |
3472 | goto fail; |
3473 | } |
3474 | m_cat(result, m); |
3475 | |
3476 | m = key_setsadbaddr(SADB_X_EXT_ADDR_RANGE_DST_END, |
3477 | (struct sockaddr *)&sp->spidx.dst_range.end, sp->spidx.prefd, |
3478 | sp->spidx.ul_proto); |
3479 | if (!m) { |
3480 | error = ENOBUFS; |
3481 | goto fail; |
3482 | } |
3483 | m_cat(result, m); |
3484 | } else { |
3485 | m = key_setsadbaddr(SADB_EXT_ADDRESS_DST, |
3486 | (struct sockaddr *)&sp->spidx.dst, sp->spidx.prefd, |
3487 | sp->spidx.ul_proto); |
3488 | if (!m) { |
3489 | error = ENOBUFS; |
3490 | goto fail; |
3491 | } |
3492 | m_cat(result, m); |
3493 | } |
3494 | |
3495 | /* set secpolicy */ |
3496 | m = key_sp2msg(sp); |
3497 | if (!m) { |
3498 | error = ENOBUFS; |
3499 | goto fail; |
3500 | } |
3501 | m_cat(result, m); |
3502 | |
3503 | if ((result->m_flags & M_PKTHDR) == 0) { |
3504 | error = EINVAL; |
3505 | goto fail; |
3506 | } |
3507 | |
3508 | if (result->m_len < sizeof(struct sadb_msg)) { |
3509 | result = m_pullup(result, sizeof(struct sadb_msg)); |
3510 | if (result == NULL) { |
3511 | error = ENOBUFS; |
3512 | goto fail; |
3513 | } |
3514 | } |
3515 | |
3516 | result->m_pkthdr.len = 0; |
3517 | for (m = result; m; m = m->m_next) |
3518 | result->m_pkthdr.len += m->m_len; |
3519 | |
3520 | mtod(result, struct sadb_msg *)->sadb_msg_len = |
3521 | PFKEY_UNIT64(result->m_pkthdr.len); |
3522 | |
3523 | return key_sendup_mbuf(NULL, result, KEY_SENDUP_REGISTERED); |
3524 | |
3525 | fail: |
3526 | if (result) |
3527 | m_freem(result); |
3528 | return error; |
3529 | } |
3530 | |
3531 | /* %%% SAD management */ |
3532 | /* |
3533 | * allocating a memory for new SA head, and copy from the values of mhp. |
3534 | * OUT: NULL : failure due to the lack of memory. |
3535 | * others : pointer to new SA head. |
3536 | */ |
3537 | static struct secashead * |
3538 | key_newsah(struct secasindex *saidx, |
3539 | ifnet_t ipsec_if, |
3540 | u_int outgoing_if, |
3541 | u_int8_t dir) |
3542 | { |
3543 | struct secashead *newsah; |
3544 | |
3545 | /* sanity check */ |
3546 | if (saidx == NULL) |
3547 | panic("key_newsaidx: NULL pointer is passed.\n" ); |
3548 | |
3549 | newsah = keydb_newsecashead(); |
3550 | if (newsah == NULL) |
3551 | return NULL; |
3552 | |
3553 | bcopy(saidx, &newsah->saidx, sizeof(newsah->saidx)); |
3554 | |
3555 | /* remove the ports */ |
3556 | switch (saidx->src.ss_family) { |
3557 | case AF_INET: |
3558 | ((struct sockaddr_in *)(&newsah->saidx.src))->sin_port = IPSEC_PORT_ANY; |
3559 | break; |
3560 | case AF_INET6: |
3561 | ((struct sockaddr_in6 *)(&newsah->saidx.src))->sin6_port = IPSEC_PORT_ANY; |
3562 | break; |
3563 | default: |
3564 | break; |
3565 | } |
3566 | switch (saidx->dst.ss_family) { |
3567 | case AF_INET: |
3568 | ((struct sockaddr_in *)(&newsah->saidx.dst))->sin_port = IPSEC_PORT_ANY; |
3569 | break; |
3570 | case AF_INET6: |
3571 | ((struct sockaddr_in6 *)(&newsah->saidx.dst))->sin6_port = IPSEC_PORT_ANY; |
3572 | break; |
3573 | default: |
3574 | break; |
3575 | } |
3576 | |
3577 | newsah->outgoing_if = outgoing_if; |
3578 | if (ipsec_if) { |
3579 | ifnet_reference(ipsec_if); |
3580 | newsah->ipsec_if = ipsec_if; |
3581 | } |
3582 | newsah->dir = dir; |
3583 | /* add to saidxtree */ |
3584 | newsah->state = SADB_SASTATE_MATURE; |
3585 | LIST_INSERT_HEAD(&sahtree, newsah, chain); |
3586 | key_start_timehandler(); |
3587 | |
3588 | return(newsah); |
3589 | } |
3590 | |
3591 | /* |
3592 | * delete SA index and all SA registerd. |
3593 | */ |
3594 | void |
3595 | key_delsah( |
3596 | struct secashead *sah) |
3597 | { |
3598 | struct secasvar *sav, *nextsav; |
3599 | u_int stateidx, state; |
3600 | int zombie = 0; |
3601 | |
3602 | LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_OWNED); |
3603 | |
3604 | /* sanity check */ |
3605 | if (sah == NULL) |
3606 | panic("key_delsah: NULL pointer is passed.\n" ); |
3607 | |
3608 | /* searching all SA registerd in the secindex. */ |
3609 | for (stateidx = 0; |
3610 | stateidx < _ARRAYLEN(saorder_state_any); |
3611 | stateidx++) { |
3612 | |
3613 | state = saorder_state_any[stateidx]; |
3614 | for (sav = (struct secasvar *)LIST_FIRST(&sah->savtree[state]); |
3615 | sav != NULL; |
3616 | sav = nextsav) { |
3617 | |
3618 | nextsav = LIST_NEXT(sav, chain); |
3619 | |
3620 | if (sav->refcnt > 0) { |
3621 | /* give up to delete this sa */ |
3622 | zombie++; |
3623 | continue; |
3624 | } |
3625 | |
3626 | /* sanity check */ |
3627 | KEY_CHKSASTATE(state, sav->state, "key_delsah" ); |
3628 | |
3629 | key_freesav(sav, KEY_SADB_LOCKED); |
3630 | |
3631 | /* remove back pointer */ |
3632 | sav->sah = NULL; |
3633 | sav = NULL; |
3634 | } |
3635 | } |
3636 | |
3637 | /* don't delete sah only if there are savs. */ |
3638 | if (zombie) |
3639 | return; |
3640 | |
3641 | ROUTE_RELEASE(&sah->sa_route); |
3642 | |
3643 | if (sah->ipsec_if) { |
3644 | ifnet_release(sah->ipsec_if); |
3645 | sah->ipsec_if = NULL; |
3646 | } |
3647 | |
3648 | if (sah->idents) { |
3649 | KFREE(sah->idents); |
3650 | } |
3651 | |
3652 | if (sah->identd) { |
3653 | KFREE(sah->identd); |
3654 | } |
3655 | |
3656 | /* remove from tree of SA index */ |
3657 | if (__LIST_CHAINED(sah)) |
3658 | LIST_REMOVE(sah, chain); |
3659 | |
3660 | KFREE(sah); |
3661 | |
3662 | return; |
3663 | } |
3664 | |
3665 | /* |
3666 | * allocating a new SA with LARVAL state. key_add() and key_getspi() call, |
3667 | * and copy the values of mhp into new buffer. |
3668 | * When SAD message type is GETSPI: |
3669 | * to set sequence number from acq_seq++, |
3670 | * to set zero to SPI. |
3671 | * not to call key_setsava(). |
3672 | * OUT: NULL : fail |
3673 | * others : pointer to new secasvar. |
3674 | * |
3675 | * does not modify mbuf. does not free mbuf on error. |
3676 | */ |
3677 | static struct secasvar * |
3678 | key_newsav( |
3679 | struct mbuf *m, |
3680 | const struct sadb_msghdr *mhp, |
3681 | struct secashead *sah, |
3682 | int *errp, |
3683 | struct socket *so) |
3684 | { |
3685 | struct secasvar *newsav; |
3686 | const struct sadb_sa *xsa; |
3687 | |
3688 | LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_OWNED); |
3689 | |
3690 | /* sanity check */ |
3691 | if (m == NULL || mhp == NULL || mhp->msg == NULL || sah == NULL) |
3692 | panic("key_newsa: NULL pointer is passed.\n" ); |
3693 | |
3694 | KMALLOC_NOWAIT(newsav, struct secasvar *, sizeof(struct secasvar)); |
3695 | if (newsav == NULL) { |
3696 | lck_mtx_unlock(sadb_mutex); |
3697 | KMALLOC_WAIT(newsav, struct secasvar *, sizeof(struct secasvar)); |
3698 | lck_mtx_lock(sadb_mutex); |
3699 | if (newsav == NULL) { |
3700 | ipseclog((LOG_DEBUG, "key_newsa: No more memory.\n" )); |
3701 | *errp = ENOBUFS; |
3702 | return NULL; |
3703 | } |
3704 | } |
3705 | bzero((caddr_t)newsav, sizeof(struct secasvar)); |
3706 | |
3707 | switch (mhp->msg->sadb_msg_type) { |
3708 | case SADB_GETSPI: |
3709 | key_setspi(newsav, 0); |
3710 | |
3711 | #if IPSEC_DOSEQCHECK |
3712 | /* sync sequence number */ |
3713 | if (mhp->msg->sadb_msg_seq == 0) |
3714 | newsav->seq = |
3715 | (acq_seq = (acq_seq == ~0 ? 1 : ++acq_seq)); |
3716 | else |
3717 | #endif |
3718 | newsav->seq = mhp->msg->sadb_msg_seq; |
3719 | break; |
3720 | |
3721 | case SADB_ADD: |
3722 | /* sanity check */ |
3723 | if (mhp->ext[SADB_EXT_SA] == NULL) { |
3724 | key_delsav(newsav); |
3725 | ipseclog((LOG_DEBUG, "key_newsa: invalid message is passed.\n" )); |
3726 | *errp = EINVAL; |
3727 | return NULL; |
3728 | } |
3729 | xsa = (struct sadb_sa *)(void *)mhp->ext[SADB_EXT_SA]; |
3730 | key_setspi(newsav, xsa->sadb_sa_spi); |
3731 | newsav->seq = mhp->msg->sadb_msg_seq; |
3732 | break; |
3733 | default: |
3734 | key_delsav(newsav); |
3735 | *errp = EINVAL; |
3736 | return NULL; |
3737 | } |
3738 | |
3739 | if (mhp->ext[SADB_X_EXT_SA2] != NULL) { |
3740 | if (((struct sadb_x_sa2 *)(void *)mhp->ext[SADB_X_EXT_SA2])->sadb_x_sa2_alwaysexpire) |
3741 | newsav->always_expire = 1; |
3742 | newsav->flags2 = ((struct sadb_x_sa2 *)(void *)mhp->ext[SADB_X_EXT_SA2])->sadb_x_sa2_flags; |
3743 | if (newsav->flags2 & SADB_X_EXT_SA2_DELETE_ON_DETACH) { |
3744 | newsav->so = so; |
3745 | } |
3746 | } |
3747 | |
3748 | /* copy sav values */ |
3749 | if (mhp->msg->sadb_msg_type != SADB_GETSPI) { |
3750 | *errp = key_setsaval(newsav, m, mhp); |
3751 | if (*errp) { |
3752 | key_delsav(newsav); |
3753 | return NULL; |
3754 | } |
3755 | } else { |
3756 | /* For get SPI, if has a hard lifetime, apply */ |
3757 | const struct sadb_lifetime *lft0; |
3758 | struct timeval tv; |
3759 | |
3760 | lft0 = (struct sadb_lifetime *)(void *)mhp->ext[SADB_EXT_LIFETIME_HARD]; |
3761 | if (lft0 != NULL) { |
3762 | /* make lifetime for CURRENT */ |
3763 | KMALLOC_NOWAIT(newsav->lft_c, struct sadb_lifetime *, |
3764 | sizeof(struct sadb_lifetime)); |
3765 | if (newsav->lft_c == NULL) { |
3766 | lck_mtx_unlock(sadb_mutex); |
3767 | KMALLOC_WAIT(newsav->lft_c, struct sadb_lifetime *, |
3768 | sizeof(struct sadb_lifetime)); |
3769 | lck_mtx_lock(sadb_mutex); |
3770 | if (newsav->lft_c == NULL) { |
3771 | ipseclog((LOG_DEBUG, "key_newsa: No more memory.\n" )); |
3772 | key_delsav(newsav); |
3773 | *errp = ENOBUFS; |
3774 | return NULL; |
3775 | } |
3776 | } |
3777 | |
3778 | microtime(&tv); |
3779 | |
3780 | newsav->lft_c->sadb_lifetime_len = PFKEY_UNIT64(sizeof(struct sadb_lifetime)); |
3781 | newsav->lft_c->sadb_lifetime_exttype = SADB_EXT_LIFETIME_CURRENT; |
3782 | newsav->lft_c->sadb_lifetime_allocations = 0; |
3783 | newsav->lft_c->sadb_lifetime_bytes = 0; |
3784 | newsav->lft_c->sadb_lifetime_addtime = tv.tv_sec; |
3785 | newsav->lft_c->sadb_lifetime_usetime = 0; |
3786 | |
3787 | if (mhp->extlen[SADB_EXT_LIFETIME_HARD] < sizeof(*lft0)) { |
3788 | ipseclog((LOG_DEBUG, "key_newsa: invalid hard lifetime ext len.\n" )); |
3789 | key_delsav(newsav); |
3790 | *errp = EINVAL; |
3791 | return NULL; |
3792 | } |
3793 | newsav->lft_h = (struct sadb_lifetime *)key_newbuf(lft0, sizeof(*lft0)); |
3794 | if (newsav->lft_h == NULL) { |
3795 | ipseclog((LOG_DEBUG, "key_newsa: No more memory.\n" )); |
3796 | key_delsav(newsav); |
3797 | *errp = ENOBUFS; |
3798 | return NULL; |
3799 | } |
3800 | } |
3801 | } |
3802 | |
3803 | /* reset created */ |
3804 | { |
3805 | struct timeval tv; |
3806 | microtime(&tv); |
3807 | newsav->created = tv.tv_sec; |
3808 | } |
3809 | |
3810 | newsav->pid = mhp->msg->sadb_msg_pid; |
3811 | |
3812 | /* add to satree */ |
3813 | newsav->sah = sah; |
3814 | newsav->refcnt = 1; |
3815 | newsav->state = SADB_SASTATE_LARVAL; |
3816 | LIST_INSERT_TAIL(&sah->savtree[SADB_SASTATE_LARVAL], newsav, |
3817 | secasvar, chain); |
3818 | ipsec_sav_count++; |
3819 | |
3820 | return newsav; |
3821 | } |
3822 | |
3823 | /* |
3824 | * allocating a new SA with LARVAL state. key_add() and key_getspi() call, |
3825 | * and copy the values passed into new buffer. |
3826 | * When SAD message type is GETSPI: |
3827 | * to set sequence number from acq_seq++, |
3828 | * to set zero to SPI. |
3829 | * not to call key_setsava(). |
3830 | * OUT: NULL : fail |
3831 | * others : pointer to new secasvar. |
3832 | */ |
3833 | struct secasvar * |
3834 | key_newsav2(struct secashead *sah, |
3835 | u_int8_t satype, |
3836 | u_int8_t alg_auth, |
3837 | u_int8_t alg_enc, |
3838 | u_int32_t flags, |
3839 | u_int8_t replay, |
3840 | struct sadb_key *key_auth, |
3841 | u_int16_t key_auth_len, |
3842 | struct sadb_key *key_enc, |
3843 | u_int16_t key_enc_len, |
3844 | u_int16_t natt_port, |
3845 | u_int32_t seq, |
3846 | u_int32_t spi, |
3847 | u_int32_t pid, |
3848 | struct sadb_lifetime *lifetime_hard, |
3849 | struct sadb_lifetime *lifetime_soft) |
3850 | { |
3851 | struct secasvar *newsav; |
3852 | |
3853 | LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_OWNED); |
3854 | |
3855 | /* sanity check */ |
3856 | if (sah == NULL) |
3857 | panic("key_newsa: NULL pointer is passed.\n" ); |
3858 | |
3859 | KMALLOC_NOWAIT(newsav, struct secasvar *, sizeof(struct secasvar)); |
3860 | if (newsav == NULL) { |
3861 | lck_mtx_unlock(sadb_mutex); |
3862 | KMALLOC_WAIT(newsav, struct secasvar *, sizeof(struct secasvar)); |
3863 | lck_mtx_lock(sadb_mutex); |
3864 | if (newsav == NULL) { |
3865 | ipseclog((LOG_DEBUG, "key_newsa: No more memory.\n" )); |
3866 | return NULL; |
3867 | } |
3868 | } |
3869 | bzero((caddr_t)newsav, sizeof(struct secasvar)); |
3870 | |
3871 | #if IPSEC_DOSEQCHECK |
3872 | /* sync sequence number */ |
3873 | if (seq == 0) |
3874 | newsav->seq = (acq_seq = (acq_seq == ~0 ? 1 : ++acq_seq)); |
3875 | else |
3876 | #endif |
3877 | newsav->seq = seq; |
3878 | key_setspi(newsav, spi); |
3879 | |
3880 | if (key_setsaval2(newsav, |
3881 | satype, |
3882 | alg_auth, |
3883 | alg_enc, |
3884 | flags, |
3885 | replay, |
3886 | key_auth, |
3887 | key_auth_len, |
3888 | key_enc, |
3889 | key_enc_len, |
3890 | natt_port, |
3891 | seq, |
3892 | spi, |
3893 | pid, |
3894 | lifetime_hard, |
3895 | lifetime_soft)) { |
3896 | key_delsav(newsav); |
3897 | return NULL; |
3898 | } |
3899 | |
3900 | /* reset created */ |
3901 | { |
3902 | struct timeval tv; |
3903 | microtime(&tv); |
3904 | newsav->created = tv.tv_sec; |
3905 | } |
3906 | |
3907 | newsav->pid = pid; |
3908 | |
3909 | /* add to satree */ |
3910 | newsav->sah = sah; |
3911 | newsav->refcnt = 1; |
3912 | if (spi && key_auth && key_auth_len && key_enc && key_enc_len) { |
3913 | newsav->state = SADB_SASTATE_MATURE; |
3914 | LIST_INSERT_TAIL(&sah->savtree[SADB_SASTATE_MATURE], newsav, |
3915 | secasvar, chain); |
3916 | } else { |
3917 | newsav->state = SADB_SASTATE_LARVAL; |
3918 | LIST_INSERT_TAIL(&sah->savtree[SADB_SASTATE_LARVAL], newsav, |
3919 | secasvar, chain); |
3920 | } |
3921 | ipsec_sav_count++; |
3922 | |
3923 | return newsav; |
3924 | } |
3925 | |
3926 | static int |
3927 | key_migratesav(struct secasvar *sav, |
3928 | struct secashead *newsah) |
3929 | { |
3930 | if (sav == NULL || newsah == NULL || sav->state != SADB_SASTATE_MATURE) { |
3931 | return EINVAL; |
3932 | } |
3933 | |
3934 | /* remove from SA header */ |
3935 | if (__LIST_CHAINED(sav)) |
3936 | LIST_REMOVE(sav, chain); |
3937 | |
3938 | sav->sah = newsah; |
3939 | LIST_INSERT_TAIL(&newsah->savtree[SADB_SASTATE_MATURE], sav, secasvar, chain); |
3940 | return 0; |
3941 | } |
3942 | |
3943 | /* |
3944 | * free() SA variable entry. |
3945 | */ |
3946 | void |
3947 | key_delsav( |
3948 | struct secasvar *sav) |
3949 | { |
3950 | |
3951 | LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_OWNED); |
3952 | |
3953 | /* sanity check */ |
3954 | if (sav == NULL) |
3955 | panic("key_delsav: NULL pointer is passed.\n" ); |
3956 | |
3957 | if (sav->refcnt > 0) |
3958 | return; /* can't free */ |
3959 | |
3960 | /* remove from SA header */ |
3961 | if (__LIST_CHAINED(sav)) |
3962 | LIST_REMOVE(sav, chain); |
3963 | ipsec_sav_count--; |
3964 | |
3965 | if (sav->spihash.le_prev || sav->spihash.le_next) |
3966 | LIST_REMOVE(sav, spihash); |
3967 | |
3968 | if (sav->key_auth != NULL) { |
3969 | bzero(_KEYBUF(sav->key_auth), _KEYLEN(sav->key_auth)); |
3970 | KFREE(sav->key_auth); |
3971 | sav->key_auth = NULL; |
3972 | } |
3973 | if (sav->key_enc != NULL) { |
3974 | bzero(_KEYBUF(sav->key_enc), _KEYLEN(sav->key_enc)); |
3975 | KFREE(sav->key_enc); |
3976 | sav->key_enc = NULL; |
3977 | } |
3978 | if (sav->sched) { |
3979 | bzero(sav->sched, sav->schedlen); |
3980 | KFREE(sav->sched); |
3981 | sav->sched = NULL; |
3982 | } |
3983 | if (sav->replay != NULL) { |
3984 | keydb_delsecreplay(sav->replay); |
3985 | sav->replay = NULL; |
3986 | } |
3987 | if (sav->lft_c != NULL) { |
3988 | KFREE(sav->lft_c); |
3989 | sav->lft_c = NULL; |
3990 | } |
3991 | if (sav->lft_h != NULL) { |
3992 | KFREE(sav->lft_h); |
3993 | sav->lft_h = NULL; |
3994 | } |
3995 | if (sav->lft_s != NULL) { |
3996 | KFREE(sav->lft_s); |
3997 | sav->lft_s = NULL; |
3998 | } |
3999 | if (sav->iv != NULL) { |
4000 | KFREE(sav->iv); |
4001 | sav->iv = NULL; |
4002 | } |
4003 | |
4004 | KFREE(sav); |
4005 | |
4006 | return; |
4007 | } |
4008 | |
4009 | /* |
4010 | * search SAD. |
4011 | * OUT: |
4012 | * NULL : not found |
4013 | * others : found, pointer to a SA. |
4014 | */ |
4015 | static struct secashead * |
4016 | key_getsah(struct secasindex *saidx) |
4017 | { |
4018 | struct secashead *sah; |
4019 | |
4020 | LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_OWNED); |
4021 | |
4022 | LIST_FOREACH(sah, &sahtree, chain) { |
4023 | if (sah->state == SADB_SASTATE_DEAD) |
4024 | continue; |
4025 | if (key_cmpsaidx(&sah->saidx, saidx, CMP_REQID)) |
4026 | return sah; |
4027 | } |
4028 | |
4029 | return NULL; |
4030 | } |
4031 | |
4032 | struct secashead * |
4033 | key_newsah2 (struct secasindex *saidx, |
4034 | u_int8_t dir) |
4035 | { |
4036 | struct secashead *sah; |
4037 | |
4038 | LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_OWNED); |
4039 | |
4040 | sah = key_getsah(saidx); |
4041 | if (!sah) { |
4042 | return(key_newsah(saidx, NULL, 0, dir)); |
4043 | } |
4044 | return sah; |
4045 | } |
4046 | |
4047 | /* |
4048 | * check not to be duplicated SPI. |
4049 | * NOTE: this function is too slow due to searching all SAD. |
4050 | * OUT: |
4051 | * NULL : not found |
4052 | * others : found, pointer to a SA. |
4053 | */ |
4054 | static struct secasvar * |
4055 | key_checkspidup( |
4056 | struct secasindex *saidx, |
4057 | u_int32_t spi) |
4058 | { |
4059 | struct secasvar *sav; |
4060 | u_int stateidx, state; |
4061 | |
4062 | LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_OWNED); |
4063 | |
4064 | /* check address family */ |
4065 | if (saidx->src.ss_family != saidx->dst.ss_family) { |
4066 | ipseclog((LOG_DEBUG, "key_checkspidup: address family mismatched.\n" )); |
4067 | return NULL; |
4068 | } |
4069 | |
4070 | /* check all SAD */ |
4071 | LIST_FOREACH(sav, &spihash[SPIHASH(spi)], spihash) { |
4072 | if (sav->spi != spi) |
4073 | continue; |
4074 | for (stateidx = 0; |
4075 | stateidx < _ARRAYLEN(saorder_state_alive); |
4076 | stateidx++) { |
4077 | state = saorder_state_alive[stateidx]; |
4078 | if (sav->state == state && |
4079 | key_ismyaddr((struct sockaddr *)&sav->sah->saidx.dst)) |
4080 | return sav; |
4081 | } |
4082 | } |
4083 | |
4084 | return NULL; |
4085 | } |
4086 | |
4087 | static void |
4088 | key_setspi( |
4089 | struct secasvar *sav, |
4090 | u_int32_t spi) |
4091 | { |
4092 | LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_OWNED); |
4093 | sav->spi = spi; |
4094 | if (sav->spihash.le_prev || sav->spihash.le_next) |
4095 | LIST_REMOVE(sav, spihash); |
4096 | LIST_INSERT_HEAD(&spihash[SPIHASH(spi)], sav, spihash); |
4097 | } |
4098 | |
4099 | |
4100 | /* |
4101 | * search SAD litmited alive SA, protocol, SPI. |
4102 | * OUT: |
4103 | * NULL : not found |
4104 | * others : found, pointer to a SA. |
4105 | */ |
4106 | static struct secasvar * |
4107 | key_getsavbyspi( |
4108 | struct secashead *sah, |
4109 | u_int32_t spi) |
4110 | { |
4111 | struct secasvar *sav, *match; |
4112 | u_int stateidx, state, matchidx; |
4113 | |
4114 | LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_OWNED); |
4115 | match = NULL; |
4116 | matchidx = _ARRAYLEN(saorder_state_alive); |
4117 | LIST_FOREACH(sav, &spihash[SPIHASH(spi)], spihash) { |
4118 | if (sav->spi != spi) |
4119 | continue; |
4120 | if (sav->sah != sah) |
4121 | continue; |
4122 | for (stateidx = 0; stateidx < matchidx; stateidx++) { |
4123 | state = saorder_state_alive[stateidx]; |
4124 | if (sav->state == state) { |
4125 | match = sav; |
4126 | matchidx = stateidx; |
4127 | break; |
4128 | } |
4129 | } |
4130 | } |
4131 | |
4132 | return match; |
4133 | } |
4134 | |
4135 | /* |
4136 | * copy SA values from PF_KEY message except *SPI, SEQ, PID, STATE and TYPE*. |
4137 | * You must update these if need. |
4138 | * OUT: 0: success. |
4139 | * !0: failure. |
4140 | * |
4141 | * does not modify mbuf. does not free mbuf on error. |
4142 | */ |
4143 | static int |
4144 | key_setsaval( |
4145 | struct secasvar *sav, |
4146 | struct mbuf *m, |
4147 | const struct sadb_msghdr *mhp) |
4148 | { |
4149 | #if IPSEC_ESP |
4150 | const struct esp_algorithm *algo; |
4151 | #endif |
4152 | int error = 0; |
4153 | struct timeval tv; |
4154 | |
4155 | LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_OWNED); |
4156 | |
4157 | /* sanity check */ |
4158 | if (m == NULL || mhp == NULL || mhp->msg == NULL) |
4159 | panic("key_setsaval: NULL pointer is passed.\n" ); |
4160 | |
4161 | /* initialization */ |
4162 | sav->replay = NULL; |
4163 | sav->key_auth = NULL; |
4164 | sav->key_enc = NULL; |
4165 | sav->sched = NULL; |
4166 | sav->schedlen = 0; |
4167 | sav->iv = NULL; |
4168 | sav->lft_c = NULL; |
4169 | sav->lft_h = NULL; |
4170 | sav->lft_s = NULL; |
4171 | sav->remote_ike_port = 0; |
4172 | sav->natt_last_activity = natt_now; |
4173 | sav->natt_encapsulated_src_port = 0; |
4174 | |
4175 | /* SA */ |
4176 | if (mhp->ext[SADB_EXT_SA] != NULL) { |
4177 | const struct sadb_sa *sa0; |
4178 | |
4179 | sa0 = (struct sadb_sa *)(void *)mhp->ext[SADB_EXT_SA]; |
4180 | if (mhp->extlen[SADB_EXT_SA] < sizeof(*sa0)) { |
4181 | ipseclog((LOG_DEBUG, "key_setsaval: invalid message size.\n" )); |
4182 | error = EINVAL; |
4183 | goto fail; |
4184 | } |
4185 | |
4186 | sav->alg_auth = sa0->sadb_sa_auth; |
4187 | sav->alg_enc = sa0->sadb_sa_encrypt; |
4188 | sav->flags = sa0->sadb_sa_flags; |
4189 | |
4190 | /* |
4191 | * Verify that a nat-traversal port was specified if |
4192 | * the nat-traversal flag is set. |
4193 | */ |
4194 | if ((sav->flags & SADB_X_EXT_NATT) != 0) { |
4195 | if (mhp->extlen[SADB_EXT_SA] < sizeof(struct sadb_sa_2) || |
4196 | ((const struct sadb_sa_2*)(sa0))->sadb_sa_natt_port == 0) { |
4197 | ipseclog((LOG_DEBUG, "key_setsaval: natt port not set.\n" )); |
4198 | error = EINVAL; |
4199 | goto fail; |
4200 | } |
4201 | sav->remote_ike_port = ((const struct sadb_sa_2*)(sa0))->sadb_sa_natt_port; |
4202 | sav->natt_interval = ((const struct sadb_sa_2*)(sa0))->sadb_sa_natt_interval; |
4203 | sav->natt_offload_interval = ((const struct sadb_sa_2*)(sa0))->sadb_sa_natt_offload_interval; |
4204 | } |
4205 | |
4206 | /* |
4207 | * Verify if SADB_X_EXT_NATT_MULTIPLEUSERS flag is set that |
4208 | * SADB_X_EXT_NATT is set and SADB_X_EXT_NATT_KEEPALIVE is not |
4209 | * set (we're not behind nat) - otherwise clear it. |
4210 | */ |
4211 | if ((sav->flags & SADB_X_EXT_NATT_MULTIPLEUSERS) != 0) |
4212 | if ((sav->flags & SADB_X_EXT_NATT) == 0 || |
4213 | (sav->flags & SADB_X_EXT_NATT_KEEPALIVE) != 0) |
4214 | sav->flags &= ~SADB_X_EXT_NATT_MULTIPLEUSERS; |
4215 | |
4216 | /* replay window */ |
4217 | if ((sa0->sadb_sa_flags & SADB_X_EXT_OLD) == 0) { |
4218 | sav->replay = keydb_newsecreplay(sa0->sadb_sa_replay); |
4219 | if (sav->replay == NULL) { |
4220 | ipseclog((LOG_DEBUG, "key_setsaval: No more memory.\n" )); |
4221 | error = ENOBUFS; |
4222 | goto fail; |
4223 | } |
4224 | } |
4225 | } |
4226 | |
4227 | /* Authentication keys */ |
4228 | if (mhp->ext[SADB_EXT_KEY_AUTH] != NULL) { |
4229 | const struct sadb_key *key0; |
4230 | int len; |
4231 | |
4232 | key0 = (const struct sadb_key *)mhp->ext[SADB_EXT_KEY_AUTH]; |
4233 | len = mhp->extlen[SADB_EXT_KEY_AUTH]; |
4234 | |
4235 | error = 0; |
4236 | if (len < sizeof(*key0)) { |
4237 | ipseclog((LOG_DEBUG, "key_setsaval: invalid auth key ext len. len = %d\n" , len)); |
4238 | error = EINVAL; |
4239 | goto fail; |
4240 | } |
4241 | switch (mhp->msg->sadb_msg_satype) { |
4242 | case SADB_SATYPE_AH: |
4243 | case SADB_SATYPE_ESP: |
4244 | if (len == PFKEY_ALIGN8(sizeof(struct sadb_key)) && |
4245 | sav->alg_auth != SADB_X_AALG_NULL) |
4246 | error = EINVAL; |
4247 | break; |
4248 | case SADB_X_SATYPE_IPCOMP: |
4249 | default: |
4250 | error = EINVAL; |
4251 | break; |
4252 | } |
4253 | if (error) { |
4254 | ipseclog((LOG_DEBUG, "key_setsaval: invalid key_auth values.\n" )); |
4255 | goto fail; |
4256 | } |
4257 | |
4258 | sav->key_auth = (struct sadb_key *)key_newbuf(key0, len); |
4259 | if (sav->key_auth == NULL) { |
4260 | ipseclog((LOG_DEBUG, "key_setsaval: No more memory.\n" )); |
4261 | error = ENOBUFS; |
4262 | goto fail; |
4263 | } |
4264 | } |
4265 | |
4266 | /* Encryption key */ |
4267 | if (mhp->ext[SADB_EXT_KEY_ENCRYPT] != NULL) { |
4268 | const struct sadb_key *key0; |
4269 | int len; |
4270 | |
4271 | key0 = (const struct sadb_key *)mhp->ext[SADB_EXT_KEY_ENCRYPT]; |
4272 | len = mhp->extlen[SADB_EXT_KEY_ENCRYPT]; |
4273 | |
4274 | error = 0; |
4275 | if (len < sizeof(*key0)) { |
4276 | ipseclog((LOG_DEBUG, "key_setsaval: invalid encryption key ext len. len = %d\n" , len)); |
4277 | error = EINVAL; |
4278 | goto fail; |
4279 | } |
4280 | switch (mhp->msg->sadb_msg_satype) { |
4281 | case SADB_SATYPE_ESP: |
4282 | if (len == PFKEY_ALIGN8(sizeof(struct sadb_key)) && |
4283 | sav->alg_enc != SADB_EALG_NULL) { |
4284 | ipseclog((LOG_DEBUG, "key_setsaval: invalid ESP algorithm.\n" )); |
4285 | error = EINVAL; |
4286 | break; |
4287 | } |
4288 | sav->key_enc = (struct sadb_key *)key_newbuf(key0, len); |
4289 | if (sav->key_enc == NULL) { |
4290 | ipseclog((LOG_DEBUG, "key_setsaval: No more memory.\n" )); |
4291 | error = ENOBUFS; |
4292 | goto fail; |
4293 | } |
4294 | break; |
4295 | case SADB_X_SATYPE_IPCOMP: |
4296 | if (len != PFKEY_ALIGN8(sizeof(struct sadb_key))) |
4297 | error = EINVAL; |
4298 | sav->key_enc = NULL; /*just in case*/ |
4299 | break; |
4300 | case SADB_SATYPE_AH: |
4301 | default: |
4302 | error = EINVAL; |
4303 | break; |
4304 | } |
4305 | if (error) { |
4306 | ipseclog((LOG_DEBUG, "key_setsaval: invalid key_enc value.\n" )); |
4307 | goto fail; |
4308 | } |
4309 | } |
4310 | |
4311 | /* set iv */ |
4312 | sav->ivlen = 0; |
4313 | |
4314 | switch (mhp->msg->sadb_msg_satype) { |
4315 | case SADB_SATYPE_ESP: |
4316 | #if IPSEC_ESP |
4317 | algo = esp_algorithm_lookup(sav->alg_enc); |
4318 | if (algo && algo->ivlen) |
4319 | sav->ivlen = (*algo->ivlen)(algo, sav); |
4320 | if (sav->ivlen == 0) |
4321 | break; |
4322 | KMALLOC_NOWAIT(sav->iv, caddr_t, sav->ivlen); |
4323 | if (sav->iv == 0) { |
4324 | lck_mtx_unlock(sadb_mutex); |
4325 | KMALLOC_WAIT(sav->iv, caddr_t, sav->ivlen); |
4326 | lck_mtx_lock(sadb_mutex); |
4327 | if (sav->iv == 0) { |
4328 | ipseclog((LOG_DEBUG, "key_setsaval: No more memory.\n" )); |
4329 | error = ENOBUFS; |
4330 | goto fail; |
4331 | } |
4332 | } |
4333 | |
4334 | /* initialize */ |
4335 | if (sav->alg_enc == SADB_X_EALG_AES_GCM) { |
4336 | bzero(sav->iv, sav->ivlen); |
4337 | } else { |
4338 | key_randomfill(sav->iv, sav->ivlen); |
4339 | } |
4340 | #endif |
4341 | break; |
4342 | case SADB_SATYPE_AH: |
4343 | case SADB_X_SATYPE_IPCOMP: |
4344 | break; |
4345 | default: |
4346 | ipseclog((LOG_DEBUG, "key_setsaval: invalid SA type.\n" )); |
4347 | error = EINVAL; |
4348 | goto fail; |
4349 | } |
4350 | |
4351 | /* reset created */ |
4352 | microtime(&tv); |
4353 | sav->created = tv.tv_sec; |
4354 | |
4355 | /* make lifetime for CURRENT */ |
4356 | KMALLOC_NOWAIT(sav->lft_c, struct sadb_lifetime *, |
4357 | sizeof(struct sadb_lifetime)); |
4358 | if (sav->lft_c == NULL) { |
4359 | lck_mtx_unlock(sadb_mutex); |
4360 | KMALLOC_WAIT(sav->lft_c, struct sadb_lifetime *, |
4361 | sizeof(struct sadb_lifetime)); |
4362 | lck_mtx_lock(sadb_mutex); |
4363 | if (sav->lft_c == NULL) { |
4364 | ipseclog((LOG_DEBUG, "key_setsaval: No more memory.\n" )); |
4365 | error = ENOBUFS; |
4366 | goto fail; |
4367 | } |
4368 | } |
4369 | |
4370 | microtime(&tv); |
4371 | |
4372 | sav->lft_c->sadb_lifetime_len = |
4373 | PFKEY_UNIT64(sizeof(struct sadb_lifetime)); |
4374 | sav->lft_c->sadb_lifetime_exttype = SADB_EXT_LIFETIME_CURRENT; |
4375 | sav->lft_c->sadb_lifetime_allocations = 0; |
4376 | sav->lft_c->sadb_lifetime_bytes = 0; |
4377 | sav->lft_c->sadb_lifetime_addtime = tv.tv_sec; |
4378 | sav->lft_c->sadb_lifetime_usetime = 0; |
4379 | |
4380 | /* lifetimes for HARD and SOFT */ |
4381 | { |
4382 | const struct sadb_lifetime *lft0; |
4383 | |
4384 | lft0 = (struct sadb_lifetime *) |
4385 | (void *)mhp->ext[SADB_EXT_LIFETIME_HARD]; |
4386 | if (lft0 != NULL) { |
4387 | if (mhp->extlen[SADB_EXT_LIFETIME_HARD] < sizeof(*lft0)) { |
4388 | ipseclog((LOG_DEBUG, "key_setsaval: invalid hard lifetime ext len.\n" )); |
4389 | error = EINVAL; |
4390 | goto fail; |
4391 | } |
4392 | sav->lft_h = (struct sadb_lifetime *)key_newbuf(lft0, |
4393 | sizeof(*lft0)); |
4394 | if (sav->lft_h == NULL) { |
4395 | ipseclog((LOG_DEBUG, "key_setsaval: No more memory.\n" )); |
4396 | error = ENOBUFS; |
4397 | goto fail; |
4398 | } |
4399 | /* to be initialize ? */ |
4400 | } |
4401 | |
4402 | lft0 = (struct sadb_lifetime *) |
4403 | (void *)mhp->ext[SADB_EXT_LIFETIME_SOFT]; |
4404 | if (lft0 != NULL) { |
4405 | if (mhp->extlen[SADB_EXT_LIFETIME_SOFT] < sizeof(*lft0)) { |
4406 | ipseclog((LOG_DEBUG, "key_setsaval: invalid soft lifetime ext len.\n" )); |
4407 | error = EINVAL; |
4408 | goto fail; |
4409 | } |
4410 | sav->lft_s = (struct sadb_lifetime *)key_newbuf(lft0, |
4411 | sizeof(*lft0)); |
4412 | if (sav->lft_s == NULL) { |
4413 | ipseclog((LOG_DEBUG, "key_setsaval: No more memory.\n" )); |
4414 | error = ENOBUFS; |
4415 | goto fail; |
4416 | } |
4417 | /* to be initialize ? */ |
4418 | } |
4419 | } |
4420 | |
4421 | return 0; |
4422 | |
4423 | fail: |
4424 | /* initialization */ |
4425 | if (sav->replay != NULL) { |
4426 | keydb_delsecreplay(sav->replay); |
4427 | sav->replay = NULL; |
4428 | } |
4429 | if (sav->key_auth != NULL) { |
4430 | bzero(_KEYBUF(sav->key_auth), _KEYLEN(sav->key_auth)); |
4431 | KFREE(sav->key_auth); |
4432 | sav->key_auth = NULL; |
4433 | } |
4434 | if (sav->key_enc != NULL) { |
4435 | bzero(_KEYBUF(sav->key_enc), _KEYLEN(sav->key_enc)); |
4436 | KFREE(sav->key_enc); |
4437 | sav->key_enc = NULL; |
4438 | } |
4439 | if (sav->sched) { |
4440 | bzero(sav->sched, sav->schedlen); |
4441 | KFREE(sav->sched); |
4442 | sav->sched = NULL; |
4443 | } |
4444 | if (sav->iv != NULL) { |
4445 | KFREE(sav->iv); |
4446 | sav->iv = NULL; |
4447 | } |
4448 | if (sav->lft_c != NULL) { |
4449 | KFREE(sav->lft_c); |
4450 | sav->lft_c = NULL; |
4451 | } |
4452 | if (sav->lft_h != NULL) { |
4453 | KFREE(sav->lft_h); |
4454 | sav->lft_h = NULL; |
4455 | } |
4456 | if (sav->lft_s != NULL) { |
4457 | KFREE(sav->lft_s); |
4458 | sav->lft_s = NULL; |
4459 | } |
4460 | |
4461 | return error; |
4462 | } |
4463 | |
4464 | /* |
4465 | * copy SA values from PF_KEY message except *SPI, SEQ, PID, STATE and TYPE*. |
4466 | * You must update these if need. |
4467 | * OUT: 0: success. |
4468 | * !0: failure. |
4469 | * |
4470 | * does not modify mbuf. does not free mbuf on error. |
4471 | */ |
4472 | int |
4473 | key_setsaval2(struct secasvar *sav, |
4474 | u_int8_t satype, |
4475 | u_int8_t alg_auth, |
4476 | u_int8_t alg_enc, |
4477 | u_int32_t flags, |
4478 | u_int8_t replay, |
4479 | struct sadb_key *key_auth, |
4480 | u_int16_t key_auth_len, |
4481 | struct sadb_key *key_enc, |
4482 | u_int16_t key_enc_len, |
4483 | u_int16_t natt_port, |
4484 | u_int32_t seq, |
4485 | u_int32_t spi, |
4486 | u_int32_t pid, |
4487 | struct sadb_lifetime *lifetime_hard, |
4488 | struct sadb_lifetime *lifetime_soft) |
4489 | { |
4490 | #if IPSEC_ESP |
4491 | const struct esp_algorithm *algo; |
4492 | #endif |
4493 | int error = 0; |
4494 | struct timeval tv; |
4495 | |
4496 | LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_OWNED); |
4497 | |
4498 | /* initialization */ |
4499 | sav->replay = NULL; |
4500 | sav->key_auth = NULL; |
4501 | sav->key_enc = NULL; |
4502 | sav->sched = NULL; |
4503 | sav->schedlen = 0; |
4504 | sav->iv = NULL; |
4505 | sav->lft_c = NULL; |
4506 | sav->lft_h = NULL; |
4507 | sav->lft_s = NULL; |
4508 | sav->remote_ike_port = 0; |
4509 | sav->natt_last_activity = natt_now; |
4510 | sav->natt_encapsulated_src_port = 0; |
4511 | |
4512 | sav->alg_auth = alg_auth; |
4513 | sav->alg_enc = alg_enc; |
4514 | sav->flags = flags; |
4515 | sav->pid = pid; |
4516 | sav->seq = seq; |
4517 | key_setspi(sav, htonl(spi)); |
4518 | |
4519 | /* |
4520 | * Verify that a nat-traversal port was specified if |
4521 | * the nat-traversal flag is set. |
4522 | */ |
4523 | if ((sav->flags & SADB_X_EXT_NATT) != 0) { |
4524 | if (natt_port == 0) { |
4525 | ipseclog((LOG_DEBUG, "key_setsaval2: natt port not set.\n" )); |
4526 | error = EINVAL; |
4527 | goto fail; |
4528 | } |
4529 | sav->remote_ike_port = natt_port; |
4530 | } |
4531 | |
4532 | /* |
4533 | * Verify if SADB_X_EXT_NATT_MULTIPLEUSERS flag is set that |
4534 | * SADB_X_EXT_NATT is set and SADB_X_EXT_NATT_KEEPALIVE is not |
4535 | * set (we're not behind nat) - otherwise clear it. |
4536 | */ |
4537 | if ((sav->flags & SADB_X_EXT_NATT_MULTIPLEUSERS) != 0) |
4538 | if ((sav->flags & SADB_X_EXT_NATT) == 0 || |
4539 | (sav->flags & SADB_X_EXT_NATT_KEEPALIVE) != 0) |
4540 | sav->flags &= ~SADB_X_EXT_NATT_MULTIPLEUSERS; |
4541 | |
4542 | /* replay window */ |
4543 | if ((flags & SADB_X_EXT_OLD) == 0) { |
4544 | sav->replay = keydb_newsecreplay(replay); |
4545 | if (sav->replay == NULL) { |
4546 | ipseclog((LOG_DEBUG, "key_setsaval: No more memory.\n" )); |
4547 | error = ENOBUFS; |
4548 | goto fail; |
4549 | } |
4550 | } |
4551 | |
4552 | /* Authentication keys */ |
4553 | sav->key_auth = (__typeof__(sav->key_auth))key_newbuf(key_auth, key_auth_len); |
4554 | if (sav->key_auth == NULL) { |
4555 | ipseclog((LOG_DEBUG, "key_setsaval: No more memory.\n" )); |
4556 | error = ENOBUFS; |
4557 | goto fail; |
4558 | } |
4559 | |
4560 | /* Encryption key */ |
4561 | sav->key_enc = (__typeof__(sav->key_enc))key_newbuf(key_enc, key_enc_len); |
4562 | if (sav->key_enc == NULL) { |
4563 | ipseclog((LOG_DEBUG, "key_setsaval: No more memory.\n" )); |
4564 | error = ENOBUFS; |
4565 | goto fail; |
4566 | } |
4567 | |
4568 | /* set iv */ |
4569 | sav->ivlen = 0; |
4570 | |
4571 | if (satype == SADB_SATYPE_ESP) { |
4572 | #if IPSEC_ESP |
4573 | algo = esp_algorithm_lookup(sav->alg_enc); |
4574 | if (algo && algo->ivlen) |
4575 | sav->ivlen = (*algo->ivlen)(algo, sav); |
4576 | if (sav->ivlen != 0) { |
4577 | KMALLOC_NOWAIT(sav->iv, caddr_t, sav->ivlen); |
4578 | if (sav->iv == 0) { |
4579 | lck_mtx_unlock(sadb_mutex); |
4580 | KMALLOC_WAIT(sav->iv, caddr_t, sav->ivlen); |
4581 | lck_mtx_lock(sadb_mutex); |
4582 | if (sav->iv == 0) { |
4583 | ipseclog((LOG_DEBUG, "key_setsaval: No more memory.\n" )); |
4584 | error = ENOBUFS; |
4585 | goto fail; |
4586 | } |
4587 | } |
4588 | /* initialize */ |
4589 | if (sav->alg_enc == SADB_X_EALG_AES_GCM) { |
4590 | bzero(sav->iv, sav->ivlen); |
4591 | } else { |
4592 | key_randomfill(sav->iv, sav->ivlen); |
4593 | } |
4594 | } |
4595 | #endif |
4596 | } |
4597 | |
4598 | /* reset created */ |
4599 | microtime(&tv); |
4600 | sav->created = tv.tv_sec; |
4601 | |
4602 | /* make lifetime for CURRENT */ |
4603 | KMALLOC_NOWAIT(sav->lft_c, struct sadb_lifetime *, |
4604 | sizeof(struct sadb_lifetime)); |
4605 | if (sav->lft_c == NULL) { |
4606 | lck_mtx_unlock(sadb_mutex); |
4607 | KMALLOC_WAIT(sav->lft_c, struct sadb_lifetime *, |
4608 | sizeof(struct sadb_lifetime)); |
4609 | lck_mtx_lock(sadb_mutex); |
4610 | if (sav->lft_c == NULL) { |
4611 | ipseclog((LOG_DEBUG, "key_setsaval: No more memory.\n" )); |
4612 | error = ENOBUFS; |
4613 | goto fail; |
4614 | } |
4615 | } |
4616 | |
4617 | microtime(&tv); |
4618 | |
4619 | sav->lft_c->sadb_lifetime_len = |
4620 | PFKEY_UNIT64(sizeof(struct sadb_lifetime)); |
4621 | sav->lft_c->sadb_lifetime_exttype = SADB_EXT_LIFETIME_CURRENT; |
4622 | sav->lft_c->sadb_lifetime_allocations = 0; |
4623 | sav->lft_c->sadb_lifetime_bytes = 0; |
4624 | sav->lft_c->sadb_lifetime_addtime = tv.tv_sec; |
4625 | sav->lft_c->sadb_lifetime_usetime = 0; |
4626 | |
4627 | /* lifetimes for HARD and SOFT */ |
4628 | sav->lft_h = (__typeof__(sav->lft_h))key_newbuf(lifetime_hard, |
4629 | sizeof(*lifetime_hard)); |
4630 | if (sav->lft_h == NULL) { |
4631 | ipseclog((LOG_DEBUG, "key_setsaval: No more memory.\n" )); |
4632 | error = ENOBUFS; |
4633 | goto fail; |
4634 | } |
4635 | sav->lft_s = (__typeof__(sav->lft_s))key_newbuf(lifetime_soft, |
4636 | sizeof(*lifetime_soft)); |
4637 | if (sav->lft_s == NULL) { |
4638 | ipseclog((LOG_DEBUG, "key_setsaval: No more memory.\n" )); |
4639 | error = ENOBUFS; |
4640 | goto fail; |
4641 | } |
4642 | |
4643 | return 0; |
4644 | |
4645 | fail: |
4646 | /* initialization */ |
4647 | if (sav->replay != NULL) { |
4648 | keydb_delsecreplay(sav->replay); |
4649 | sav->replay = NULL; |
4650 | } |
4651 | if (sav->key_auth != NULL) { |
4652 | bzero(_KEYBUF(sav->key_auth), _KEYLEN(sav->key_auth)); |
4653 | KFREE(sav->key_auth); |
4654 | sav->key_auth = NULL; |
4655 | } |
4656 | if (sav->key_enc != NULL) { |
4657 | bzero(_KEYBUF(sav->key_enc), _KEYLEN(sav->key_enc)); |
4658 | KFREE(sav->key_enc); |
4659 | sav->key_enc = NULL; |
4660 | } |
4661 | if (sav->sched) { |
4662 | bzero(sav->sched, sav->schedlen); |
4663 | KFREE(sav->sched); |
4664 | sav->sched = NULL; |
4665 | } |
4666 | if (sav->iv != NULL) { |
4667 | KFREE(sav->iv); |
4668 | sav->iv = NULL; |
4669 | } |
4670 | if (sav->lft_c != NULL) { |
4671 | KFREE(sav->lft_c); |
4672 | sav->lft_c = NULL; |
4673 | } |
4674 | if (sav->lft_h != NULL) { |
4675 | KFREE(sav->lft_h); |
4676 | sav->lft_h = NULL; |
4677 | } |
4678 | if (sav->lft_s != NULL) { |
4679 | KFREE(sav->lft_s); |
4680 | sav->lft_s = NULL; |
4681 | } |
4682 | |
4683 | return error; |
4684 | } |
4685 | |
4686 | /* |
4687 | * validation with a secasvar entry, and set SADB_SATYPE_MATURE. |
4688 | * OUT: 0: valid |
4689 | * other: errno |
4690 | */ |
4691 | static int |
4692 | key_mature( |
4693 | struct secasvar *sav) |
4694 | { |
4695 | int mature; |
4696 | int checkmask = 0; /* 2^0: ealg 2^1: aalg 2^2: calg */ |
4697 | int mustmask = 0; /* 2^0: ealg 2^1: aalg 2^2: calg */ |
4698 | |
4699 | mature = 0; |
4700 | |
4701 | LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_OWNED); |
4702 | |
4703 | /* check SPI value */ |
4704 | switch (sav->sah->saidx.proto) { |
4705 | case IPPROTO_ESP: |
4706 | case IPPROTO_AH: |
4707 | |
4708 | /* No reason to test if this is >= 0, because ntohl(sav->spi) is unsigned. */ |
4709 | if (ntohl(sav->spi) <= 255) { |
4710 | ipseclog((LOG_DEBUG, |
4711 | "key_mature: illegal range of SPI %u.\n" , |
4712 | (u_int32_t)ntohl(sav->spi))); |
4713 | return EINVAL; |
4714 | } |
4715 | break; |
4716 | } |
4717 | |
4718 | /* check satype */ |
4719 | switch (sav->sah->saidx.proto) { |
4720 | case IPPROTO_ESP: |
4721 | /* check flags */ |
4722 | if ((sav->flags & SADB_X_EXT_OLD) |
4723 | && (sav->flags & SADB_X_EXT_DERIV)) { |
4724 | ipseclog((LOG_DEBUG, "key_mature: " |
4725 | "invalid flag (derived) given to old-esp.\n" )); |
4726 | return EINVAL; |
4727 | } |
4728 | if (sav->alg_auth == SADB_AALG_NONE) |
4729 | checkmask = 1; |
4730 | else |
4731 | checkmask = 3; |
4732 | mustmask = 1; |
4733 | break; |
4734 | case IPPROTO_AH: |
4735 | /* check flags */ |
4736 | if (sav->flags & SADB_X_EXT_DERIV) { |
4737 | ipseclog((LOG_DEBUG, "key_mature: " |
4738 | "invalid flag (derived) given to AH SA.\n" )); |
4739 | return EINVAL; |
4740 | } |
4741 | if (sav->alg_enc != SADB_EALG_NONE) { |
4742 | ipseclog((LOG_DEBUG, "key_mature: " |
4743 | "protocol and algorithm mismated.\n" )); |
4744 | return(EINVAL); |
4745 | } |
4746 | checkmask = 2; |
4747 | mustmask = 2; |
4748 | break; |
4749 | case IPPROTO_IPCOMP: |
4750 | if (sav->alg_auth != SADB_AALG_NONE) { |
4751 | ipseclog((LOG_DEBUG, "key_mature: " |
4752 | "protocol and algorithm mismated.\n" )); |
4753 | return(EINVAL); |
4754 | } |
4755 | if ((sav->flags & SADB_X_EXT_RAWCPI) == 0 |
4756 | && ntohl(sav->spi) >= 0x10000) { |
4757 | ipseclog((LOG_DEBUG, "key_mature: invalid cpi for IPComp.\n" )); |
4758 | return(EINVAL); |
4759 | } |
4760 | checkmask = 4; |
4761 | mustmask = 4; |
4762 | break; |
4763 | default: |
4764 | ipseclog((LOG_DEBUG, "key_mature: Invalid satype.\n" )); |
4765 | return EPROTONOSUPPORT; |
4766 | } |
4767 | |
4768 | /* check authentication algorithm */ |
4769 | if ((checkmask & 2) != 0) { |
4770 | const struct ah_algorithm *algo; |
4771 | int keylen; |
4772 | |
4773 | algo = ah_algorithm_lookup(sav->alg_auth); |
4774 | if (!algo) { |
4775 | ipseclog((LOG_DEBUG,"key_mature: " |
4776 | "unknown authentication algorithm.\n" )); |
4777 | return EINVAL; |
4778 | } |
4779 | |
4780 | /* algorithm-dependent check */ |
4781 | if (sav->key_auth) |
4782 | keylen = sav->key_auth->sadb_key_bits; |
4783 | else |
4784 | keylen = 0; |
4785 | if (keylen < algo->keymin || algo->keymax < keylen) { |
4786 | ipseclog((LOG_DEBUG, |
4787 | "key_mature: invalid AH key length %d " |
4788 | "(%d-%d allowed)\n" , |
4789 | keylen, algo->keymin, algo->keymax)); |
4790 | return EINVAL; |
4791 | } |
4792 | |
4793 | if (algo->mature) { |
4794 | if ((*algo->mature)(sav)) { |
4795 | /* message generated in per-algorithm function*/ |
4796 | return EINVAL; |
4797 | } else |
4798 | mature = SADB_SATYPE_AH; |
4799 | } |
4800 | |
4801 | if ((mustmask & 2) != 0 && mature != SADB_SATYPE_AH) { |
4802 | ipseclog((LOG_DEBUG, "key_mature: no satisfy algorithm for AH\n" )); |
4803 | return EINVAL; |
4804 | } |
4805 | } |
4806 | |
4807 | /* check encryption algorithm */ |
4808 | if ((checkmask & 1) != 0) { |
4809 | #if IPSEC_ESP |
4810 | const struct esp_algorithm *algo; |
4811 | int keylen; |
4812 | |
4813 | algo = esp_algorithm_lookup(sav->alg_enc); |
4814 | if (!algo) { |
4815 | ipseclog((LOG_DEBUG, "key_mature: unknown encryption algorithm.\n" )); |
4816 | return EINVAL; |
4817 | } |
4818 | |
4819 | /* algorithm-dependent check */ |
4820 | if (sav->key_enc) |
4821 | keylen = sav->key_enc->sadb_key_bits; |
4822 | else |
4823 | keylen = 0; |
4824 | if (keylen < algo->keymin || algo->keymax < keylen) { |
4825 | ipseclog((LOG_DEBUG, |
4826 | "key_mature: invalid ESP key length %d " |
4827 | "(%d-%d allowed)\n" , |
4828 | keylen, algo->keymin, algo->keymax)); |
4829 | return EINVAL; |
4830 | } |
4831 | |
4832 | if (algo->mature) { |
4833 | if ((*algo->mature)(sav)) { |
4834 | /* message generated in per-algorithm function*/ |
4835 | return EINVAL; |
4836 | } else |
4837 | mature = SADB_SATYPE_ESP; |
4838 | } |
4839 | |
4840 | if ((mustmask & 1) != 0 && mature != SADB_SATYPE_ESP) { |
4841 | ipseclog((LOG_DEBUG, "key_mature: no satisfy algorithm for ESP\n" )); |
4842 | return EINVAL; |
4843 | } |
4844 | #else /*IPSEC_ESP*/ |
4845 | ipseclog((LOG_DEBUG, "key_mature: ESP not supported in this configuration\n" )); |
4846 | return EINVAL; |
4847 | #endif |
4848 | } |
4849 | |
4850 | /* check compression algorithm */ |
4851 | if ((checkmask & 4) != 0) { |
4852 | const struct ipcomp_algorithm *algo; |
4853 | |
4854 | /* algorithm-dependent check */ |
4855 | algo = ipcomp_algorithm_lookup(sav->alg_enc); |
4856 | if (!algo) { |
4857 | ipseclog((LOG_DEBUG, "key_mature: unknown compression algorithm.\n" )); |
4858 | return EINVAL; |
4859 | } |
4860 | } |
4861 | |
4862 | key_sa_chgstate(sav, SADB_SASTATE_MATURE); |
4863 | |
4864 | return 0; |
4865 | } |
4866 | |
4867 | /* |
4868 | * subroutine for SADB_GET and SADB_DUMP. |
4869 | */ |
4870 | static struct mbuf * |
4871 | key_setdumpsa( |
4872 | struct secasvar *sav, |
4873 | u_int8_t type, |
4874 | u_int8_t satype, |
4875 | u_int32_t seq, |
4876 | u_int32_t pid) |
4877 | { |
4878 | struct mbuf *result = NULL, *tres = NULL, *m; |
4879 | int l = 0; |
4880 | int i; |
4881 | void *p; |
4882 | int dumporder[] = { |
4883 | SADB_EXT_SA, SADB_X_EXT_SA2, |
4884 | SADB_EXT_LIFETIME_HARD, SADB_EXT_LIFETIME_SOFT, |
4885 | SADB_EXT_LIFETIME_CURRENT, SADB_EXT_ADDRESS_SRC, |
4886 | SADB_EXT_ADDRESS_DST, SADB_EXT_ADDRESS_PROXY, SADB_EXT_KEY_AUTH, |
4887 | SADB_EXT_KEY_ENCRYPT, SADB_EXT_IDENTITY_SRC, |
4888 | SADB_EXT_IDENTITY_DST, SADB_EXT_SENSITIVITY, |
4889 | }; |
4890 | |
4891 | m = key_setsadbmsg(type, 0, satype, seq, pid, sav->refcnt); |
4892 | if (m == NULL) |
4893 | goto fail; |
4894 | result = m; |
4895 | |
4896 | for (i = sizeof(dumporder)/sizeof(dumporder[0]) - 1; i >= 0; i--) { |
4897 | m = NULL; |
4898 | p = NULL; |
4899 | switch (dumporder[i]) { |
4900 | case SADB_EXT_SA: |
4901 | m = key_setsadbsa(sav); |
4902 | if (!m) |
4903 | goto fail; |
4904 | break; |
4905 | |
4906 | case SADB_X_EXT_SA2: |
4907 | m = key_setsadbxsa2(sav->sah->saidx.mode, |
4908 | sav->replay ? sav->replay->count : 0, |
4909 | sav->sah->saidx.reqid, |
4910 | sav->flags2); |
4911 | if (!m) |
4912 | goto fail; |
4913 | break; |
4914 | |
4915 | case SADB_EXT_ADDRESS_SRC: |
4916 | m = key_setsadbaddr(SADB_EXT_ADDRESS_SRC, |
4917 | (struct sockaddr *)&sav->sah->saidx.src, |
4918 | FULLMASK, IPSEC_ULPROTO_ANY); |
4919 | if (!m) |
4920 | goto fail; |
4921 | break; |
4922 | |
4923 | case SADB_EXT_ADDRESS_DST: |
4924 | m = key_setsadbaddr(SADB_EXT_ADDRESS_DST, |
4925 | (struct sockaddr *)&sav->sah->saidx.dst, |
4926 | FULLMASK, IPSEC_ULPROTO_ANY); |
4927 | if (!m) |
4928 | goto fail; |
4929 | break; |
4930 | |
4931 | case SADB_EXT_KEY_AUTH: |
4932 | if (!sav->key_auth) |
4933 | continue; |
4934 | l = PFKEY_UNUNIT64(sav->key_auth->sadb_key_len); |
4935 | p = sav->key_auth; |
4936 | break; |
4937 | |
4938 | case SADB_EXT_KEY_ENCRYPT: |
4939 | if (!sav->key_enc) |
4940 | continue; |
4941 | l = PFKEY_UNUNIT64(sav->key_enc->sadb_key_len); |
4942 | p = sav->key_enc; |
4943 | break; |
4944 | |
4945 | case SADB_EXT_LIFETIME_CURRENT: |
4946 | if (!sav->lft_c) |
4947 | continue; |
4948 | l = PFKEY_UNUNIT64(((struct sadb_ext *)sav->lft_c)->sadb_ext_len); |
4949 | p = sav->lft_c; |
4950 | break; |
4951 | |
4952 | case SADB_EXT_LIFETIME_HARD: |
4953 | if (!sav->lft_h) |
4954 | continue; |
4955 | l = PFKEY_UNUNIT64(((struct sadb_ext *)sav->lft_h)->sadb_ext_len); |
4956 | p = sav->lft_h; |
4957 | break; |
4958 | |
4959 | case SADB_EXT_LIFETIME_SOFT: |
4960 | if (!sav->lft_s) |
4961 | continue; |
4962 | l = PFKEY_UNUNIT64(((struct sadb_ext *)sav->lft_s)->sadb_ext_len); |
4963 | p = sav->lft_s; |
4964 | break; |
4965 | |
4966 | case SADB_EXT_ADDRESS_PROXY: |
4967 | case SADB_EXT_IDENTITY_SRC: |
4968 | case SADB_EXT_IDENTITY_DST: |
4969 | /* XXX: should we brought from SPD ? */ |
4970 | case SADB_EXT_SENSITIVITY: |
4971 | default: |
4972 | continue; |
4973 | } |
4974 | |
4975 | if ((!m && !p) || (m && p)) |
4976 | goto fail; |
4977 | if (p && tres) { |
4978 | M_PREPEND(tres, l, M_WAITOK, 1); |
4979 | if (!tres) |
4980 | goto fail; |
4981 | bcopy(p, mtod(tres, caddr_t), l); |
4982 | continue; |
4983 | } |
4984 | if (p) { |
4985 | m = key_alloc_mbuf(l); |
4986 | if (!m) |
4987 | goto fail; |
4988 | m_copyback(m, 0, l, p); |
4989 | } |
4990 | |
4991 | if (tres) |
4992 | m_cat(m, tres); |
4993 | tres = m; |
4994 | } |
4995 | |
4996 | m_cat(result, tres); |
4997 | |
4998 | if (sav->sah && (sav->sah->outgoing_if || sav->sah->ipsec_if)) { |
4999 | m = key_setsadbipsecif(NULL, ifindex2ifnet[sav->sah->outgoing_if], sav->sah->ipsec_if, 0); |
5000 | if (!m) |
5001 | goto fail; |
5002 | m_cat(result, m); |
5003 | } |
5004 | |
5005 | if (result->m_len < sizeof(struct sadb_msg)) { |
5006 | result = m_pullup(result, sizeof(struct sadb_msg)); |
5007 | if (result == NULL) |
5008 | goto fail; |
5009 | } |
5010 | |
5011 | result->m_pkthdr.len = 0; |
5012 | for (m = result; m; m = m->m_next) |
5013 | result->m_pkthdr.len += m->m_len; |
5014 | |
5015 | mtod(result, struct sadb_msg *)->sadb_msg_len = |
5016 | PFKEY_UNIT64(result->m_pkthdr.len); |
5017 | |
5018 | return result; |
5019 | |
5020 | fail: |
5021 | m_freem(result); |
5022 | m_freem(tres); |
5023 | return NULL; |
5024 | } |
5025 | |
5026 | /* |
5027 | * set data into sadb_msg. |
5028 | */ |
5029 | static struct mbuf * |
5030 | key_setsadbmsg( |
5031 | u_int8_t type, |
5032 | u_int16_t tlen, |
5033 | u_int8_t satype, |
5034 | u_int32_t seq, |
5035 | pid_t pid, |
5036 | u_int16_t reserved) |
5037 | { |
5038 | struct mbuf *m; |
5039 | struct sadb_msg *p; |
5040 | int len; |
5041 | |
5042 | len = PFKEY_ALIGN8(sizeof(struct sadb_msg)); |
5043 | if (len > MCLBYTES) |
5044 | return NULL; |
5045 | MGETHDR(m, M_DONTWAIT, MT_DATA); |
5046 | if (m && len > MHLEN) { |
5047 | MCLGET(m, M_DONTWAIT); |
5048 | if ((m->m_flags & M_EXT) == 0) { |
5049 | m_freem(m); |
5050 | m = NULL; |
5051 | } |
5052 | } |
5053 | if (!m) |
5054 | return NULL; |
5055 | m->m_pkthdr.len = m->m_len = len; |
5056 | m->m_next = NULL; |
5057 | |
5058 | p = mtod(m, struct sadb_msg *); |
5059 | |
5060 | bzero(p, len); |
5061 | p->sadb_msg_version = PF_KEY_V2; |
5062 | p->sadb_msg_type = type; |
5063 | p->sadb_msg_errno = 0; |
5064 | p->sadb_msg_satype = satype; |
5065 | p->sadb_msg_len = PFKEY_UNIT64(tlen); |
5066 | p->sadb_msg_reserved = reserved; |
5067 | p->sadb_msg_seq = seq; |
5068 | p->sadb_msg_pid = (u_int32_t)pid; |
5069 | |
5070 | return m; |
5071 | } |
5072 | |
5073 | /* |
5074 | * copy secasvar data into sadb_address. |
5075 | */ |
5076 | static struct mbuf * |
5077 | key_setsadbsa( |
5078 | struct secasvar *sav) |
5079 | { |
5080 | struct mbuf *m; |
5081 | struct sadb_sa *p; |
5082 | int len; |
5083 | |
5084 | len = PFKEY_ALIGN8(sizeof(struct sadb_sa)); |
5085 | m = key_alloc_mbuf(len); |
5086 | if (!m || m->m_next) { /*XXX*/ |
5087 | if (m) |
5088 | m_freem(m); |
5089 | return NULL; |
5090 | } |
5091 | |
5092 | p = mtod(m, struct sadb_sa *); |
5093 | |
5094 | bzero(p, len); |
5095 | p->sadb_sa_len = PFKEY_UNIT64(len); |
5096 | p->sadb_sa_exttype = SADB_EXT_SA; |
5097 | p->sadb_sa_spi = sav->spi; |
5098 | p->sadb_sa_replay = (sav->replay != NULL ? sav->replay->wsize : 0); |
5099 | p->sadb_sa_state = sav->state; |
5100 | p->sadb_sa_auth = sav->alg_auth; |
5101 | p->sadb_sa_encrypt = sav->alg_enc; |
5102 | p->sadb_sa_flags = sav->flags; |
5103 | |
5104 | return m; |
5105 | } |
5106 | |
5107 | /* |
5108 | * set data into sadb_address. |
5109 | */ |
5110 | static struct mbuf * |
5111 | key_setsadbaddr( |
5112 | u_int16_t exttype, |
5113 | struct sockaddr *saddr, |
5114 | u_int8_t prefixlen, |
5115 | u_int16_t ul_proto) |
5116 | { |
5117 | struct mbuf *m; |
5118 | struct sadb_address *p; |
5119 | size_t len; |
5120 | |
5121 | len = PFKEY_ALIGN8(sizeof(struct sadb_address)) + |
5122 | PFKEY_ALIGN8(saddr->sa_len); |
5123 | m = key_alloc_mbuf(len); |
5124 | if (!m || m->m_next) { /*XXX*/ |
5125 | if (m) |
5126 | m_freem(m); |
5127 | return NULL; |
5128 | } |
5129 | |
5130 | p = mtod(m, struct sadb_address *); |
5131 | |
5132 | bzero(p, len); |
5133 | p->sadb_address_len = PFKEY_UNIT64(len); |
5134 | p->sadb_address_exttype = exttype; |
5135 | p->sadb_address_proto = ul_proto; |
5136 | if (prefixlen == FULLMASK) { |
5137 | switch (saddr->sa_family) { |
5138 | case AF_INET: |
5139 | prefixlen = sizeof(struct in_addr) << 3; |
5140 | break; |
5141 | case AF_INET6: |
5142 | prefixlen = sizeof(struct in6_addr) << 3; |
5143 | break; |
5144 | default: |
5145 | ; /*XXX*/ |
5146 | } |
5147 | } |
5148 | p->sadb_address_prefixlen = prefixlen; |
5149 | p->sadb_address_reserved = 0; |
5150 | |
5151 | bcopy(saddr, |
5152 | mtod(m, caddr_t) + PFKEY_ALIGN8(sizeof(struct sadb_address)), |
5153 | saddr->sa_len); |
5154 | |
5155 | return m; |
5156 | } |
5157 | |
5158 | static struct mbuf * |
5159 | key_setsadbipsecif(ifnet_t internal_if, |
5160 | ifnet_t outgoing_if, |
5161 | ifnet_t ipsec_if, |
5162 | int init_disabled) |
5163 | { |
5164 | struct mbuf *m; |
5165 | struct sadb_x_ipsecif *p; |
5166 | size_t len; |
5167 | |
5168 | len = PFKEY_ALIGN8(sizeof(struct sadb_x_ipsecif)); |
5169 | m = key_alloc_mbuf(len); |
5170 | if (!m || m->m_next) { /*XXX*/ |
5171 | if (m) |
5172 | m_freem(m); |
5173 | return NULL; |
5174 | } |
5175 | |
5176 | p = mtod(m, struct sadb_x_ipsecif *); |
5177 | |
5178 | bzero(p, len); |
5179 | p->sadb_x_ipsecif_len = PFKEY_UNIT64(len); |
5180 | p->sadb_x_ipsecif_exttype = SADB_X_EXT_IPSECIF; |
5181 | |
5182 | if (internal_if && internal_if->if_xname) |
5183 | strlcpy(p->sadb_x_ipsecif_internal_if, internal_if->if_xname, IFXNAMSIZ); |
5184 | if (outgoing_if && outgoing_if->if_xname) |
5185 | strlcpy(p->sadb_x_ipsecif_outgoing_if, outgoing_if->if_xname, IFXNAMSIZ); |
5186 | if (ipsec_if && ipsec_if->if_xname) |
5187 | strlcpy(p->sadb_x_ipsecif_ipsec_if, ipsec_if->if_xname, IFXNAMSIZ); |
5188 | |
5189 | p->sadb_x_ipsecif_init_disabled = init_disabled; |
5190 | |
5191 | return m; |
5192 | } |
5193 | |
5194 | /* |
5195 | * set data into sadb_session_id |
5196 | */ |
5197 | static struct mbuf * |
5198 | key_setsadbsession_id (u_int64_t session_ids[]) |
5199 | { |
5200 | struct mbuf *m; |
5201 | struct sadb_session_id *p; |
5202 | size_t len; |
5203 | |
5204 | len = PFKEY_ALIGN8(sizeof(*p)); |
5205 | m = key_alloc_mbuf(len); |
5206 | if (!m || m->m_next) { /*XXX*/ |
5207 | if (m) |
5208 | m_freem(m); |
5209 | return NULL; |
5210 | } |
5211 | |
5212 | p = mtod(m, __typeof__(p)); |
5213 | |
5214 | bzero(p, len); |
5215 | p->sadb_session_id_len = PFKEY_UNIT64(len); |
5216 | p->sadb_session_id_exttype = SADB_EXT_SESSION_ID; |
5217 | p->sadb_session_id_v[0] = session_ids[0]; |
5218 | p->sadb_session_id_v[1] = session_ids[1]; |
5219 | |
5220 | return m; |
5221 | } |
5222 | |
5223 | /* |
5224 | * copy stats data into sadb_sastat type. |
5225 | */ |
5226 | static struct mbuf * |
5227 | key_setsadbsastat (u_int32_t dir, |
5228 | struct sastat *stats, |
5229 | u_int32_t max_stats) |
5230 | { |
5231 | struct mbuf *m; |
5232 | struct sadb_sastat *p; |
5233 | int list_len, len; |
5234 | |
5235 | if (!stats) { |
5236 | return NULL; |
5237 | } |
5238 | |
5239 | list_len = sizeof(*stats) * max_stats; |
5240 | len = PFKEY_ALIGN8(sizeof(*p)) + PFKEY_ALIGN8(list_len); |
5241 | m = key_alloc_mbuf(len); |
5242 | if (!m || m->m_next) { /*XXX*/ |
5243 | if (m) |
5244 | m_freem(m); |
5245 | return NULL; |
5246 | } |
5247 | |
5248 | p = mtod(m, __typeof__(p)); |
5249 | |
5250 | bzero(p, len); |
5251 | p->sadb_sastat_len = PFKEY_UNIT64(len); |
5252 | p->sadb_sastat_exttype = SADB_EXT_SASTAT; |
5253 | p->sadb_sastat_dir = dir; |
5254 | p->sadb_sastat_list_len = max_stats; |
5255 | if (list_len) { |
5256 | bcopy(stats, |
5257 | mtod(m, caddr_t) + PFKEY_ALIGN8(sizeof(*p)), |
5258 | list_len); |
5259 | } |
5260 | |
5261 | return m; |
5262 | } |
5263 | |
5264 | #if 0 |
5265 | /* |
5266 | * set data into sadb_ident. |
5267 | */ |
5268 | static struct mbuf * |
5269 | key_setsadbident( |
5270 | u_int16_t exttype, |
5271 | u_int16_t idtype, |
5272 | caddr_t string, |
5273 | int stringlen, |
5274 | u_int64_t id) |
5275 | { |
5276 | struct mbuf *m; |
5277 | struct sadb_ident *p; |
5278 | size_t len; |
5279 | |
5280 | len = PFKEY_ALIGN8(sizeof(struct sadb_ident)) + PFKEY_ALIGN8(stringlen); |
5281 | m = key_alloc_mbuf(len); |
5282 | if (!m || m->m_next) { /*XXX*/ |
5283 | if (m) |
5284 | m_freem(m); |
5285 | return NULL; |
5286 | } |
5287 | |
5288 | p = mtod(m, struct sadb_ident *); |
5289 | |
5290 | bzero(p, len); |
5291 | p->sadb_ident_len = PFKEY_UNIT64(len); |
5292 | p->sadb_ident_exttype = exttype; |
5293 | p->sadb_ident_type = idtype; |
5294 | p->sadb_ident_reserved = 0; |
5295 | p->sadb_ident_id = id; |
5296 | |
5297 | bcopy(string, |
5298 | mtod(m, caddr_t) + PFKEY_ALIGN8(sizeof(struct sadb_ident)), |
5299 | stringlen); |
5300 | |
5301 | return m; |
5302 | } |
5303 | #endif |
5304 | |
5305 | /* |
5306 | * set data into sadb_x_sa2. |
5307 | */ |
5308 | static struct mbuf * |
5309 | key_setsadbxsa2( |
5310 | u_int8_t mode, |
5311 | u_int32_t seq, |
5312 | u_int32_t reqid, |
5313 | u_int16_t flags) |
5314 | { |
5315 | struct mbuf *m; |
5316 | struct sadb_x_sa2 *p; |
5317 | size_t len; |
5318 | |
5319 | len = PFKEY_ALIGN8(sizeof(struct sadb_x_sa2)); |
5320 | m = key_alloc_mbuf(len); |
5321 | if (!m || m->m_next) { /*XXX*/ |
5322 | if (m) |
5323 | m_freem(m); |
5324 | return NULL; |
5325 | } |
5326 | |
5327 | p = mtod(m, struct sadb_x_sa2 *); |
5328 | |
5329 | bzero(p, len); |
5330 | p->sadb_x_sa2_len = PFKEY_UNIT64(len); |
5331 | p->sadb_x_sa2_exttype = SADB_X_EXT_SA2; |
5332 | p->sadb_x_sa2_mode = mode; |
5333 | p->sadb_x_sa2_reserved1 = 0; |
5334 | p->sadb_x_sa2_reserved2 = 0; |
5335 | p->sadb_x_sa2_sequence = seq; |
5336 | p->sadb_x_sa2_reqid = reqid; |
5337 | p->sadb_x_sa2_flags = flags; |
5338 | |
5339 | return m; |
5340 | } |
5341 | |
5342 | /* |
5343 | * set data into sadb_x_policy |
5344 | */ |
5345 | static struct mbuf * |
5346 | key_setsadbxpolicy( |
5347 | u_int16_t type, |
5348 | u_int8_t dir, |
5349 | u_int32_t id) |
5350 | { |
5351 | struct mbuf *m; |
5352 | struct sadb_x_policy *p; |
5353 | size_t len; |
5354 | |
5355 | len = PFKEY_ALIGN8(sizeof(struct sadb_x_policy)); |
5356 | m = key_alloc_mbuf(len); |
5357 | if (!m || m->m_next) { /*XXX*/ |
5358 | if (m) |
5359 | m_freem(m); |
5360 | return NULL; |
5361 | } |
5362 | |
5363 | p = mtod(m, struct sadb_x_policy *); |
5364 | |
5365 | bzero(p, len); |
5366 | p->sadb_x_policy_len = PFKEY_UNIT64(len); |
5367 | p->sadb_x_policy_exttype = SADB_X_EXT_POLICY; |
5368 | p->sadb_x_policy_type = type; |
5369 | p->sadb_x_policy_dir = dir; |
5370 | p->sadb_x_policy_id = id; |
5371 | |
5372 | return m; |
5373 | } |
5374 | |
5375 | /* %%% utilities */ |
5376 | /* |
5377 | * copy a buffer into the new buffer allocated. |
5378 | */ |
5379 | static void * |
5380 | key_newbuf( |
5381 | const void *src, |
5382 | u_int len) |
5383 | { |
5384 | caddr_t new; |
5385 | |
5386 | LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_OWNED); |
5387 | KMALLOC_NOWAIT(new, caddr_t, len); |
5388 | if (new == NULL) { |
5389 | lck_mtx_unlock(sadb_mutex); |
5390 | KMALLOC_WAIT(new, caddr_t, len); |
5391 | lck_mtx_lock(sadb_mutex); |
5392 | if (new == NULL) { |
5393 | ipseclog((LOG_DEBUG, "key_newbuf: No more memory.\n" )); |
5394 | return NULL; |
5395 | } |
5396 | } |
5397 | bcopy(src, new, len); |
5398 | |
5399 | return new; |
5400 | } |
5401 | |
5402 | /* compare my own address |
5403 | * OUT: 1: true, i.e. my address. |
5404 | * 0: false |
5405 | */ |
5406 | int |
5407 | key_ismyaddr( |
5408 | struct sockaddr *sa) |
5409 | { |
5410 | #if INET |
5411 | struct sockaddr_in *sin; |
5412 | struct in_ifaddr *ia; |
5413 | #endif |
5414 | |
5415 | /* sanity check */ |
5416 | if (sa == NULL) |
5417 | panic("key_ismyaddr: NULL pointer is passed.\n" ); |
5418 | |
5419 | switch (sa->sa_family) { |
5420 | #if INET |
5421 | case AF_INET: |
5422 | lck_rw_lock_shared(in_ifaddr_rwlock); |
5423 | sin = (struct sockaddr_in *)(void *)sa; |
5424 | for (ia = in_ifaddrhead.tqh_first; ia; |
5425 | ia = ia->ia_link.tqe_next) { |
5426 | IFA_LOCK_SPIN(&ia->ia_ifa); |
5427 | if (sin->sin_family == ia->ia_addr.sin_family && |
5428 | sin->sin_len == ia->ia_addr.sin_len && |
5429 | sin->sin_addr.s_addr == ia->ia_addr.sin_addr.s_addr) |
5430 | { |
5431 | IFA_UNLOCK(&ia->ia_ifa); |
5432 | lck_rw_done(in_ifaddr_rwlock); |
5433 | return 1; |
5434 | } |
5435 | IFA_UNLOCK(&ia->ia_ifa); |
5436 | } |
5437 | lck_rw_done(in_ifaddr_rwlock); |
5438 | break; |
5439 | #endif |
5440 | #if INET6 |
5441 | case AF_INET6: |
5442 | return key_ismyaddr6((struct sockaddr_in6 *)(void *)sa); |
5443 | #endif |
5444 | } |
5445 | |
5446 | return 0; |
5447 | } |
5448 | |
5449 | #if INET6 |
5450 | /* |
5451 | * compare my own address for IPv6. |
5452 | * 1: ours |
5453 | * 0: other |
5454 | * NOTE: derived ip6_input() in KAME. This is necessary to modify more. |
5455 | */ |
5456 | #include <netinet6/in6_var.h> |
5457 | |
5458 | static int |
5459 | key_ismyaddr6( |
5460 | struct sockaddr_in6 *sin6) |
5461 | { |
5462 | struct in6_ifaddr *ia; |
5463 | struct in6_multi *in6m; |
5464 | |
5465 | lck_rw_lock_shared(&in6_ifaddr_rwlock); |
5466 | for (ia = in6_ifaddrs; ia; ia = ia->ia_next) { |
5467 | IFA_LOCK(&ia->ia_ifa); |
5468 | if (key_sockaddrcmp((struct sockaddr *)&sin6, |
5469 | (struct sockaddr *)&ia->ia_addr, 0) == 0) { |
5470 | IFA_UNLOCK(&ia->ia_ifa); |
5471 | lck_rw_done(&in6_ifaddr_rwlock); |
5472 | return 1; |
5473 | } |
5474 | IFA_UNLOCK(&ia->ia_ifa); |
5475 | |
5476 | /* |
5477 | * XXX Multicast |
5478 | * XXX why do we care about multlicast here while we don't care |
5479 | * about IPv4 multicast?? |
5480 | * XXX scope |
5481 | */ |
5482 | in6m = NULL; |
5483 | in6_multihead_lock_shared(); |
5484 | IN6_LOOKUP_MULTI(&sin6->sin6_addr, ia->ia_ifp, in6m); |
5485 | in6_multihead_lock_done(); |
5486 | if (in6m != NULL) { |
5487 | lck_rw_done(&in6_ifaddr_rwlock); |
5488 | IN6M_REMREF(in6m); |
5489 | return 1; |
5490 | } |
5491 | } |
5492 | lck_rw_done(&in6_ifaddr_rwlock); |
5493 | |
5494 | /* loopback, just for safety */ |
5495 | if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr)) |
5496 | return 1; |
5497 | |
5498 | return 0; |
5499 | } |
5500 | #endif /*INET6*/ |
5501 | |
5502 | /* |
5503 | * compare two secasindex structure. |
5504 | * flag can specify to compare 2 saidxes. |
5505 | * compare two secasindex structure without both mode and reqid. |
5506 | * don't compare port. |
5507 | * IN: |
5508 | * saidx0: source, it can be in SAD. |
5509 | * saidx1: object. |
5510 | * OUT: |
5511 | * 1 : equal |
5512 | * 0 : not equal |
5513 | */ |
5514 | static int |
5515 | key_cmpsaidx( |
5516 | struct secasindex *saidx0, |
5517 | struct secasindex *saidx1, |
5518 | int flag) |
5519 | { |
5520 | /* sanity */ |
5521 | if (saidx0 == NULL && saidx1 == NULL) |
5522 | return 1; |
5523 | |
5524 | if (saidx0 == NULL || saidx1 == NULL) |
5525 | return 0; |
5526 | |
5527 | if (saidx0->ipsec_ifindex != 0 && saidx0->ipsec_ifindex != saidx1->ipsec_ifindex) |
5528 | return 0; |
5529 | |
5530 | if (saidx0->proto != saidx1->proto) |
5531 | return 0; |
5532 | |
5533 | if (flag == CMP_EXACTLY) { |
5534 | if (saidx0->mode != saidx1->mode) |
5535 | return 0; |
5536 | if (saidx0->reqid != saidx1->reqid) |
5537 | return 0; |
5538 | if (bcmp(&saidx0->src, &saidx1->src, saidx0->src.ss_len) != 0 || |
5539 | bcmp(&saidx0->dst, &saidx1->dst, saidx0->dst.ss_len) != 0) |
5540 | return 0; |
5541 | } else { |
5542 | |
5543 | /* CMP_MODE_REQID, CMP_REQID, CMP_HEAD */ |
5544 | if (flag & CMP_REQID) { |
5545 | /* |
5546 | * If reqid of SPD is non-zero, unique SA is required. |
5547 | * The result must be of same reqid in this case. |
5548 | */ |
5549 | if (saidx1->reqid != 0 && saidx0->reqid != saidx1->reqid) |
5550 | return 0; |
5551 | } |
5552 | |
5553 | if (flag & CMP_MODE) { |
5554 | if (saidx0->mode != IPSEC_MODE_ANY |
5555 | && saidx0->mode != saidx1->mode) |
5556 | return 0; |
5557 | } |
5558 | |
5559 | if (key_sockaddrcmp((struct sockaddr *)&saidx0->src, |
5560 | (struct sockaddr *)&saidx1->src, flag & CMP_PORT ? 1 : 0) != 0) { |
5561 | return 0; |
5562 | } |
5563 | if (key_sockaddrcmp((struct sockaddr *)&saidx0->dst, |
5564 | (struct sockaddr *)&saidx1->dst, flag & CMP_PORT ? 1 : 0) != 0) { |
5565 | return 0; |
5566 | } |
5567 | } |
5568 | |
5569 | return 1; |
5570 | } |
5571 | |
5572 | /* |
5573 | * compare two secindex structure exactly. |
5574 | * IN: |
5575 | * spidx0: source, it is often in SPD. |
5576 | * spidx1: object, it is often from PFKEY message. |
5577 | * OUT: |
5578 | * 1 : equal |
5579 | * 0 : not equal |
5580 | */ |
5581 | static int |
5582 | key_cmpspidx_exactly( |
5583 | struct secpolicyindex *spidx0, |
5584 | struct secpolicyindex *spidx1) |
5585 | { |
5586 | /* sanity */ |
5587 | if (spidx0 == NULL && spidx1 == NULL) |
5588 | return 1; |
5589 | |
5590 | if (spidx0 == NULL || spidx1 == NULL) |
5591 | return 0; |
5592 | |
5593 | if (spidx0->prefs != spidx1->prefs |
5594 | || spidx0->prefd != spidx1->prefd |
5595 | || spidx0->ul_proto != spidx1->ul_proto |
5596 | || spidx0->internal_if != spidx1->internal_if) |
5597 | return 0; |
5598 | |
5599 | if (key_sockaddrcmp((struct sockaddr *)&spidx0->src, |
5600 | (struct sockaddr *)&spidx1->src, 1) != 0) { |
5601 | return 0; |
5602 | } |
5603 | if (key_sockaddrcmp((struct sockaddr *)&spidx0->dst, |
5604 | (struct sockaddr *)&spidx1->dst, 1) != 0) { |
5605 | return 0; |
5606 | } |
5607 | |
5608 | if (key_sockaddrcmp((struct sockaddr *)&spidx0->src_range.start, |
5609 | (struct sockaddr *)&spidx1->src_range.start, 1) != 0) { |
5610 | return 0; |
5611 | } |
5612 | if (key_sockaddrcmp((struct sockaddr *)&spidx0->src_range.end, |
5613 | (struct sockaddr *)&spidx1->src_range.end, 1) != 0) { |
5614 | return 0; |
5615 | } |
5616 | if (key_sockaddrcmp((struct sockaddr *)&spidx0->dst_range.start, |
5617 | (struct sockaddr *)&spidx1->dst_range.start, 1) != 0) { |
5618 | return 0; |
5619 | } |
5620 | if (key_sockaddrcmp((struct sockaddr *)&spidx0->dst_range.end, |
5621 | (struct sockaddr *)&spidx1->dst_range.end, 1) != 0) { |
5622 | return 0; |
5623 | } |
5624 | |
5625 | return 1; |
5626 | } |
5627 | |
5628 | /* |
5629 | * compare two secindex structure with mask. |
5630 | * IN: |
5631 | * spidx0: source, it is often in SPD. |
5632 | * spidx1: object, it is often from IP header. |
5633 | * OUT: |
5634 | * 1 : equal |
5635 | * 0 : not equal |
5636 | */ |
5637 | static int |
5638 | key_cmpspidx_withmask( |
5639 | struct secpolicyindex *spidx0, |
5640 | struct secpolicyindex *spidx1) |
5641 | { |
5642 | int spidx0_src_is_range = 0; |
5643 | int spidx0_dst_is_range = 0; |
5644 | |
5645 | /* sanity */ |
5646 | if (spidx0 == NULL && spidx1 == NULL) |
5647 | return 1; |
5648 | |
5649 | if (spidx0 == NULL || spidx1 == NULL) |
5650 | return 0; |
5651 | |
5652 | if (spidx0->src_range.start.ss_len > 0) |
5653 | spidx0_src_is_range = 1; |
5654 | |
5655 | if (spidx0->dst_range.start.ss_len > 0) |
5656 | spidx0_dst_is_range = 1; |
5657 | |
5658 | if ((spidx0_src_is_range ? spidx0->src_range.start.ss_family : spidx0->src.ss_family) != spidx1->src.ss_family || |
5659 | (spidx0_dst_is_range ? spidx0->dst_range.start.ss_family : spidx0->dst.ss_family) != spidx1->dst.ss_family || |
5660 | (spidx0_src_is_range ? spidx0->src_range.start.ss_len : spidx0->src.ss_len) != spidx1->src.ss_len || |
5661 | (spidx0_dst_is_range ? spidx0->dst_range.start.ss_len : spidx0->dst.ss_len) != spidx1->dst.ss_len) |
5662 | return 0; |
5663 | |
5664 | /* if spidx.ul_proto == IPSEC_ULPROTO_ANY, ignore. */ |
5665 | if (spidx0->ul_proto != (u_int16_t)IPSEC_ULPROTO_ANY |
5666 | && spidx0->ul_proto != spidx1->ul_proto) |
5667 | return 0; |
5668 | |
5669 | /* If spidx1 specifies interface, ignore src addr */ |
5670 | if (spidx1->internal_if != NULL) { |
5671 | if (spidx0->internal_if == NULL |
5672 | || spidx0->internal_if != spidx1->internal_if) |
5673 | return 0; |
5674 | |
5675 | /* Still check ports */ |
5676 | switch (spidx0->src.ss_family) { |
5677 | case AF_INET: |
5678 | if (spidx0_src_is_range && |
5679 | (satosin(&spidx1->src)->sin_port < satosin(&spidx0->src_range.start)->sin_port |
5680 | || satosin(&spidx1->src)->sin_port > satosin(&spidx0->src_range.end)->sin_port)) |
5681 | return 0; |
5682 | else if (satosin(&spidx0->src)->sin_port != IPSEC_PORT_ANY |
5683 | && satosin(&spidx0->src)->sin_port != |
5684 | satosin(&spidx1->src)->sin_port) |
5685 | return 0; |
5686 | break; |
5687 | case AF_INET6: |
5688 | if (spidx0_src_is_range && |
5689 | (satosin6(&spidx1->src)->sin6_port < satosin6(&spidx0->src_range.start)->sin6_port |
5690 | || satosin6(&spidx1->src)->sin6_port > satosin6(&spidx0->src_range.end)->sin6_port)) |
5691 | return 0; |
5692 | else if (satosin6(&spidx0->src)->sin6_port != IPSEC_PORT_ANY |
5693 | && satosin6(&spidx0->src)->sin6_port != |
5694 | satosin6(&spidx1->src)->sin6_port) |
5695 | return 0; |
5696 | break; |
5697 | default: |
5698 | break; |
5699 | } |
5700 | } else if (spidx0_src_is_range) { |
5701 | if (!key_is_addr_in_range(&spidx1->src, &spidx0->src_range)) |
5702 | return 0; |
5703 | } else { |
5704 | switch (spidx0->src.ss_family) { |
5705 | case AF_INET: |
5706 | if (satosin(&spidx0->src)->sin_port != IPSEC_PORT_ANY |
5707 | && satosin(&spidx0->src)->sin_port != |
5708 | satosin(&spidx1->src)->sin_port) |
5709 | return 0; |
5710 | if (!key_bbcmp((caddr_t)&satosin(&spidx0->src)->sin_addr, |
5711 | (caddr_t)&satosin(&spidx1->src)->sin_addr, spidx0->prefs)) |
5712 | return 0; |
5713 | break; |
5714 | case AF_INET6: |
5715 | if (satosin6(&spidx0->src)->sin6_port != IPSEC_PORT_ANY |
5716 | && satosin6(&spidx0->src)->sin6_port != |
5717 | satosin6(&spidx1->src)->sin6_port) |
5718 | return 0; |
5719 | /* |
5720 | * scope_id check. if sin6_scope_id is 0, we regard it |
5721 | * as a wildcard scope, which matches any scope zone ID. |
5722 | */ |
5723 | if (satosin6(&spidx0->src)->sin6_scope_id && |
5724 | satosin6(&spidx1->src)->sin6_scope_id && |
5725 | satosin6(&spidx0->src)->sin6_scope_id != |
5726 | satosin6(&spidx1->src)->sin6_scope_id) |
5727 | return 0; |
5728 | if (!key_bbcmp((caddr_t)&satosin6(&spidx0->src)->sin6_addr, |
5729 | (caddr_t)&satosin6(&spidx1->src)->sin6_addr, spidx0->prefs)) |
5730 | return 0; |
5731 | break; |
5732 | default: |
5733 | /* XXX */ |
5734 | if (bcmp(&spidx0->src, &spidx1->src, spidx0->src.ss_len) != 0) |
5735 | return 0; |
5736 | break; |
5737 | } |
5738 | } |
5739 | |
5740 | if (spidx0_dst_is_range) { |
5741 | if (!key_is_addr_in_range(&spidx1->dst, &spidx0->dst_range)) |
5742 | return 0; |
5743 | } else { |
5744 | switch (spidx0->dst.ss_family) { |
5745 | case AF_INET: |
5746 | if (satosin(&spidx0->dst)->sin_port != IPSEC_PORT_ANY |
5747 | && satosin(&spidx0->dst)->sin_port != |
5748 | satosin(&spidx1->dst)->sin_port) |
5749 | return 0; |
5750 | if (!key_bbcmp((caddr_t)&satosin(&spidx0->dst)->sin_addr, |
5751 | (caddr_t)&satosin(&spidx1->dst)->sin_addr, spidx0->prefd)) |
5752 | return 0; |
5753 | break; |
5754 | case AF_INET6: |
5755 | if (satosin6(&spidx0->dst)->sin6_port != IPSEC_PORT_ANY |
5756 | && satosin6(&spidx0->dst)->sin6_port != |
5757 | satosin6(&spidx1->dst)->sin6_port) |
5758 | return 0; |
5759 | /* |
5760 | * scope_id check. if sin6_scope_id is 0, we regard it |
5761 | * as a wildcard scope, which matches any scope zone ID. |
5762 | */ |
5763 | if (satosin6(&spidx0->src)->sin6_scope_id && |
5764 | satosin6(&spidx1->src)->sin6_scope_id && |
5765 | satosin6(&spidx0->dst)->sin6_scope_id != |
5766 | satosin6(&spidx1->dst)->sin6_scope_id) |
5767 | return 0; |
5768 | if (!key_bbcmp((caddr_t)&satosin6(&spidx0->dst)->sin6_addr, |
5769 | (caddr_t)&satosin6(&spidx1->dst)->sin6_addr, spidx0->prefd)) |
5770 | return 0; |
5771 | break; |
5772 | default: |
5773 | /* XXX */ |
5774 | if (bcmp(&spidx0->dst, &spidx1->dst, spidx0->dst.ss_len) != 0) |
5775 | return 0; |
5776 | break; |
5777 | } |
5778 | } |
5779 | |
5780 | /* XXX Do we check other field ? e.g. flowinfo */ |
5781 | |
5782 | return 1; |
5783 | } |
5784 | |
5785 | static int |
5786 | key_is_addr_in_range(struct sockaddr_storage *addr, struct secpolicyaddrrange *addr_range) |
5787 | { |
5788 | int cmp = 0; |
5789 | |
5790 | if (addr == NULL || addr_range == NULL) |
5791 | return 0; |
5792 | |
5793 | /* Must be greater than or equal to start */ |
5794 | cmp = key_sockaddrcmp((struct sockaddr *)addr, (struct sockaddr *)&addr_range->start, 1); |
5795 | if (cmp != 0 && cmp != 1) |
5796 | return 0; |
5797 | |
5798 | /* Must be less than or equal to end */ |
5799 | cmp = key_sockaddrcmp((struct sockaddr *)addr, (struct sockaddr *)&addr_range->end, 1); |
5800 | if (cmp != 0 && cmp != -1) |
5801 | return 0; |
5802 | |
5803 | return 1; |
5804 | } |
5805 | |
5806 | /* |
5807 | Return values: |
5808 | -1: sa1 < sa2 |
5809 | 0: sa1 == sa2 |
5810 | 1: sa1 > sa2 |
5811 | 2: Not comparable or error |
5812 | */ |
5813 | static int |
5814 | key_sockaddrcmp( |
5815 | struct sockaddr *sa1, |
5816 | struct sockaddr *sa2, |
5817 | int port) |
5818 | { |
5819 | int result = 0; |
5820 | int port_result = 0; |
5821 | |
5822 | if (sa1->sa_family != sa2->sa_family || sa1->sa_len != sa2->sa_len) |
5823 | return 2; |
5824 | |
5825 | if (sa1->sa_len == 0) |
5826 | return 0; |
5827 | |
5828 | switch (sa1->sa_family) { |
5829 | case AF_INET: |
5830 | if (sa1->sa_len != sizeof(struct sockaddr_in)) |
5831 | return 2; |
5832 | |
5833 | result = memcmp(&satosin(sa1)->sin_addr.s_addr, &satosin(sa2)->sin_addr.s_addr, sizeof(satosin(sa1)->sin_addr.s_addr)); |
5834 | |
5835 | if (port) { |
5836 | if (satosin(sa1)->sin_port < satosin(sa2)->sin_port) { |
5837 | port_result = -1; |
5838 | } else if (satosin(sa1)->sin_port > satosin(sa2)->sin_port) { |
5839 | port_result = 1; |
5840 | } |
5841 | |
5842 | if (result == 0) |
5843 | result = port_result; |
5844 | else if ((result > 0 && port_result < 0) || (result < 0 && port_result > 0)) |
5845 | return 2; |
5846 | } |
5847 | |
5848 | break; |
5849 | case AF_INET6: |
5850 | if (sa1->sa_len != sizeof(struct sockaddr_in6)) |
5851 | return 2; /*EINVAL*/ |
5852 | |
5853 | if (satosin6(sa1)->sin6_scope_id != |
5854 | satosin6(sa2)->sin6_scope_id) { |
5855 | return 2; |
5856 | } |
5857 | |
5858 | result = memcmp(&satosin6(sa1)->sin6_addr.s6_addr[0], &satosin6(sa2)->sin6_addr.s6_addr[0], sizeof(struct in6_addr)); |
5859 | |
5860 | if (port) { |
5861 | if (satosin6(sa1)->sin6_port < satosin6(sa2)->sin6_port) { |
5862 | port_result = -1; |
5863 | } else if (satosin6(sa1)->sin6_port > satosin6(sa2)->sin6_port) { |
5864 | port_result = 1; |
5865 | } |
5866 | |
5867 | if (result == 0) |
5868 | result = port_result; |
5869 | else if ((result > 0 && port_result < 0) || (result < 0 && port_result > 0)) |
5870 | return 2; |
5871 | } |
5872 | |
5873 | break; |
5874 | default: |
5875 | result = memcmp(sa1, sa2, sa1->sa_len); |
5876 | break; |
5877 | } |
5878 | |
5879 | if (result < 0) result = -1; |
5880 | else if (result > 0) result = 1; |
5881 | |
5882 | return result; |
5883 | } |
5884 | |
5885 | /* |
5886 | * compare two buffers with mask. |
5887 | * IN: |
5888 | * addr1: source |
5889 | * addr2: object |
5890 | * bits: Number of bits to compare |
5891 | * OUT: |
5892 | * 1 : equal |
5893 | * 0 : not equal |
5894 | */ |
5895 | static int |
5896 | key_bbcmp( |
5897 | caddr_t p1, |
5898 | caddr_t p2, |
5899 | u_int bits) |
5900 | { |
5901 | u_int8_t mask; |
5902 | |
5903 | /* XXX: This could be considerably faster if we compare a word |
5904 | * at a time, but it is complicated on LSB Endian machines */ |
5905 | |
5906 | /* Handle null pointers */ |
5907 | if (p1 == NULL || p2 == NULL) |
5908 | return (p1 == p2); |
5909 | |
5910 | while (bits >= 8) { |
5911 | if (*p1++ != *p2++) |
5912 | return 0; |
5913 | bits -= 8; |
5914 | } |
5915 | |
5916 | if (bits > 0) { |
5917 | mask = ~((1<<(8-bits))-1); |
5918 | if ((*p1 & mask) != (*p2 & mask)) |
5919 | return 0; |
5920 | } |
5921 | return 1; /* Match! */ |
5922 | } |
5923 | |
5924 | /* |
5925 | * time handler. |
5926 | * scanning SPD and SAD to check status for each entries, |
5927 | * and do to remove or to expire. |
5928 | * XXX: year 2038 problem may remain. |
5929 | */ |
5930 | int key_timehandler_debug = 0; |
5931 | u_int32_t spd_count = 0, sah_count = 0, dead_sah_count = 0, empty_sah_count = 0, larval_sav_count = 0, mature_sav_count = 0, dying_sav_count = 0, dead_sav_count = 0; |
5932 | u_int64_t total_sav_count = 0; |
5933 | void |
5934 | key_timehandler(void) |
5935 | { |
5936 | u_int dir; |
5937 | struct timeval tv; |
5938 | struct secpolicy **spbuf = NULL, **spptr = NULL; |
5939 | struct secasvar **savexbuf = NULL, **savexptr = NULL; |
5940 | struct secasvar **savkabuf = NULL, **savkaptr = NULL; |
5941 | int spbufcount = 0, savbufcount = 0, spcount = 0, savexcount = 0, savkacount = 0, cnt; |
5942 | int stop_handler = 1; /* stop the timehandler */ |
5943 | |
5944 | microtime(&tv); |
5945 | |
5946 | /* pre-allocate buffers before taking the lock */ |
5947 | /* if allocation failures occur - portions of the processing will be skipped */ |
5948 | if ((spbufcount = ipsec_policy_count) != 0) { |
5949 | spbufcount += 256; |
5950 | KMALLOC_WAIT(spbuf, struct secpolicy **, spbufcount * sizeof(struct secpolicy *)); |
5951 | if (spbuf) |
5952 | spptr = spbuf; |
5953 | } |
5954 | if ((savbufcount = ipsec_sav_count) != 0) { |
5955 | savbufcount += 512; |
5956 | KMALLOC_WAIT(savexbuf, struct secasvar **, savbufcount * sizeof(struct secasvar *)); |
5957 | if (savexbuf) |
5958 | savexptr = savexbuf; |
5959 | KMALLOC_WAIT(savkabuf, struct secasvar **, savbufcount * sizeof(struct secasvar *)); |
5960 | if (savkabuf) |
5961 | savkaptr = savkabuf; |
5962 | } |
5963 | lck_mtx_lock(sadb_mutex); |
5964 | /* SPD */ |
5965 | if (spbuf) { |
5966 | |
5967 | struct secpolicy *sp, *nextsp; |
5968 | |
5969 | for (dir = 0; dir < IPSEC_DIR_MAX; dir++) { |
5970 | for (sp = LIST_FIRST(&sptree[dir]); |
5971 | sp != NULL; |
5972 | sp = nextsp) { |
5973 | |
5974 | /* don't prevent timehandler from stopping for generate policy */ |
5975 | if (sp->policy != IPSEC_POLICY_GENERATE) |
5976 | stop_handler = 0; |
5977 | spd_count++; |
5978 | nextsp = LIST_NEXT(sp, chain); |
5979 | |
5980 | if (sp->state == IPSEC_SPSTATE_DEAD) { |
5981 | key_freesp(sp, KEY_SADB_LOCKED); |
5982 | continue; |
5983 | } |
5984 | |
5985 | if (sp->lifetime == 0 && sp->validtime == 0) |
5986 | continue; |
5987 | if (spbuf && spcount < spbufcount) { |
5988 | /* the deletion will occur next time */ |
5989 | if ((sp->lifetime |
5990 | && tv.tv_sec - sp->created > sp->lifetime) |
5991 | || (sp->validtime |
5992 | && tv.tv_sec - sp->lastused > sp->validtime)) { |
5993 | //key_spdexpire(sp); |
5994 | sp->state = IPSEC_SPSTATE_DEAD; |
5995 | sp->refcnt++; |
5996 | *spptr++ = sp; |
5997 | spcount++; |
5998 | } |
5999 | } |
6000 | } |
6001 | } |
6002 | } |
6003 | |
6004 | /* SAD */ |
6005 | { |
6006 | struct secashead *sah, *nextsah; |
6007 | struct secasvar *sav, *nextsav; |
6008 | |
6009 | for (sah = LIST_FIRST(&sahtree); |
6010 | sah != NULL; |
6011 | sah = nextsah) { |
6012 | |
6013 | sah_count++; |
6014 | nextsah = LIST_NEXT(sah, chain); |
6015 | |
6016 | /* if sah has been dead, then delete it and process next sah. */ |
6017 | if (sah->state == SADB_SASTATE_DEAD) { |
6018 | key_delsah(sah); |
6019 | dead_sah_count++; |
6020 | continue; |
6021 | } |
6022 | |
6023 | if (LIST_FIRST(&sah->savtree[SADB_SASTATE_LARVAL]) == NULL && |
6024 | LIST_FIRST(&sah->savtree[SADB_SASTATE_MATURE]) == NULL && |
6025 | LIST_FIRST(&sah->savtree[SADB_SASTATE_DYING]) == NULL && |
6026 | LIST_FIRST(&sah->savtree[SADB_SASTATE_DEAD]) == NULL) { |
6027 | key_delsah(sah); |
6028 | empty_sah_count++; |
6029 | continue; |
6030 | } |
6031 | |
6032 | if (savbufcount == 0) { |
6033 | continue; |
6034 | } |
6035 | |
6036 | stop_handler = 0; |
6037 | |
6038 | /* if LARVAL entry doesn't become MATURE, delete it. */ |
6039 | for (sav = LIST_FIRST(&sah->savtree[SADB_SASTATE_LARVAL]); |
6040 | sav != NULL; |
6041 | sav = nextsav) { |
6042 | |
6043 | larval_sav_count++; |
6044 | total_sav_count++; |
6045 | nextsav = LIST_NEXT(sav, chain); |
6046 | |
6047 | if (sav->lft_h != NULL) { |
6048 | /* If a hard lifetime is defined for the LARVAL SA, use it */ |
6049 | if (sav->lft_h->sadb_lifetime_addtime != 0 |
6050 | && tv.tv_sec - sav->created > sav->lft_h->sadb_lifetime_addtime) { |
6051 | if (sav->always_expire) { |
6052 | key_send_delete(sav); |
6053 | sav = NULL; |
6054 | } else { |
6055 | key_sa_chgstate(sav, SADB_SASTATE_DEAD); |
6056 | key_freesav(sav, KEY_SADB_LOCKED); |
6057 | sav = NULL; |
6058 | } |
6059 | } |
6060 | } else { |
6061 | if (tv.tv_sec - sav->created > key_larval_lifetime) { |
6062 | key_freesav(sav, KEY_SADB_LOCKED); |
6063 | } |
6064 | } |
6065 | } |
6066 | |
6067 | /* |
6068 | * If this is a NAT traversal SA with no activity, |
6069 | * we need to send a keep alive. |
6070 | * |
6071 | * Performed outside of the loop before so we will |
6072 | * only ever send one keepalive. The first SA on |
6073 | * the list is the one that will be used for sending |
6074 | * traffic, so this is the one we use for determining |
6075 | * when to send the keepalive. |
6076 | */ |
6077 | if (savkabuf && savkacount < savbufcount) { |
6078 | sav = LIST_FIRST(&sah->savtree[SADB_SASTATE_MATURE]); //%%% should we check dying list if this is empty??? |
6079 | if (sav && (natt_keepalive_interval || sav->natt_interval) && |
6080 | (sav->flags & (SADB_X_EXT_NATT_KEEPALIVE | SADB_X_EXT_ESP_KEEPALIVE)) != 0) { |
6081 | sav->refcnt++; |
6082 | *savkaptr++ = sav; |
6083 | savkacount++; |
6084 | } |
6085 | } |
6086 | |
6087 | /* |
6088 | * check MATURE entry to start to send expire message |
6089 | * whether or not. |
6090 | */ |
6091 | for (sav = LIST_FIRST(&sah->savtree[SADB_SASTATE_MATURE]); |
6092 | sav != NULL; |
6093 | sav = nextsav) { |
6094 | |
6095 | mature_sav_count++; |
6096 | total_sav_count++; |
6097 | nextsav = LIST_NEXT(sav, chain); |
6098 | |
6099 | /* we don't need to check. */ |
6100 | if (sav->lft_s == NULL) |
6101 | continue; |
6102 | |
6103 | /* sanity check */ |
6104 | if (sav->lft_c == NULL) { |
6105 | ipseclog((LOG_DEBUG,"key_timehandler: " |
6106 | "There is no CURRENT time, why?\n" )); |
6107 | continue; |
6108 | } |
6109 | |
6110 | /* check SOFT lifetime */ |
6111 | if (sav->lft_s->sadb_lifetime_addtime != 0 |
6112 | && tv.tv_sec - sav->created > sav->lft_s->sadb_lifetime_addtime) { |
6113 | /* |
6114 | * If always_expire is set, expire. Otherwise, |
6115 | * if the SA has not been used, delete immediately. |
6116 | */ |
6117 | if (sav->lft_c->sadb_lifetime_usetime == 0 |
6118 | && sav->always_expire == 0) { |
6119 | key_sa_chgstate(sav, SADB_SASTATE_DEAD); |
6120 | key_freesav(sav, KEY_SADB_LOCKED); |
6121 | sav = NULL; |
6122 | } else if (savexbuf && savexcount < savbufcount) { |
6123 | key_sa_chgstate(sav, SADB_SASTATE_DYING); |
6124 | sav->refcnt++; |
6125 | *savexptr++ = sav; |
6126 | savexcount++; |
6127 | } |
6128 | } |
6129 | |
6130 | /* check SOFT lifetime by bytes */ |
6131 | /* |
6132 | * XXX I don't know the way to delete this SA |
6133 | * when new SA is installed. Caution when it's |
6134 | * installed too big lifetime by time. |
6135 | */ |
6136 | else if (savexbuf && savexcount < savbufcount |
6137 | && sav->lft_s->sadb_lifetime_bytes != 0 |
6138 | && sav->lft_s->sadb_lifetime_bytes < sav->lft_c->sadb_lifetime_bytes) { |
6139 | |
6140 | /* |
6141 | * XXX If we keep to send expire |
6142 | * message in the status of |
6143 | * DYING. Do remove below code. |
6144 | */ |
6145 | //key_expire(sav); |
6146 | key_sa_chgstate(sav, SADB_SASTATE_DYING); |
6147 | sav->refcnt++; |
6148 | *savexptr++ = sav; |
6149 | savexcount++; |
6150 | } |
6151 | } |
6152 | |
6153 | /* check DYING entry to change status to DEAD. */ |
6154 | for (sav = LIST_FIRST(&sah->savtree[SADB_SASTATE_DYING]); |
6155 | sav != NULL; |
6156 | sav = nextsav) { |
6157 | |
6158 | dying_sav_count++; |
6159 | total_sav_count++; |
6160 | nextsav = LIST_NEXT(sav, chain); |
6161 | |
6162 | /* we don't need to check. */ |
6163 | if (sav->lft_h == NULL) |
6164 | continue; |
6165 | |
6166 | /* sanity check */ |
6167 | if (sav->lft_c == NULL) { |
6168 | ipseclog((LOG_DEBUG, "key_timehandler: " |
6169 | "There is no CURRENT time, why?\n" )); |
6170 | continue; |
6171 | } |
6172 | |
6173 | if (sav->lft_h->sadb_lifetime_addtime != 0 |
6174 | && tv.tv_sec - sav->created > sav->lft_h->sadb_lifetime_addtime) { |
6175 | if (sav->always_expire) { |
6176 | key_send_delete(sav); |
6177 | sav = NULL; |
6178 | } else { |
6179 | key_sa_chgstate(sav, SADB_SASTATE_DEAD); |
6180 | key_freesav(sav, KEY_SADB_LOCKED); |
6181 | sav = NULL; |
6182 | } |
6183 | } |
6184 | #if 0 /* XXX Should we keep to send expire message until HARD lifetime ? */ |
6185 | else if (savbuf && savexcount < savbufcount |
6186 | && sav->lft_s != NULL |
6187 | && sav->lft_s->sadb_lifetime_addtime != 0 |
6188 | && tv.tv_sec - sav->created > sav->lft_s->sadb_lifetime_addtime) { |
6189 | /* |
6190 | * XXX: should be checked to be |
6191 | * installed the valid SA. |
6192 | */ |
6193 | |
6194 | /* |
6195 | * If there is no SA then sending |
6196 | * expire message. |
6197 | */ |
6198 | //key_expire(sav); |
6199 | sav->refcnt++; |
6200 | *savexptr++ = sav; |
6201 | savexcount++; |
6202 | } |
6203 | #endif |
6204 | /* check HARD lifetime by bytes */ |
6205 | else if (sav->lft_h->sadb_lifetime_bytes != 0 |
6206 | && sav->lft_h->sadb_lifetime_bytes < sav->lft_c->sadb_lifetime_bytes) { |
6207 | key_sa_chgstate(sav, SADB_SASTATE_DEAD); |
6208 | key_freesav(sav, KEY_SADB_LOCKED); |
6209 | sav = NULL; |
6210 | } |
6211 | } |
6212 | |
6213 | /* delete entry in DEAD */ |
6214 | for (sav = LIST_FIRST(&sah->savtree[SADB_SASTATE_DEAD]); |
6215 | sav != NULL; |
6216 | sav = nextsav) { |
6217 | |
6218 | dead_sav_count++; |
6219 | total_sav_count++; |
6220 | nextsav = LIST_NEXT(sav, chain); |
6221 | |
6222 | /* sanity check */ |
6223 | if (sav->state != SADB_SASTATE_DEAD) { |
6224 | ipseclog((LOG_DEBUG, "key_timehandler: " |
6225 | "invalid sav->state " |
6226 | "(queue: %d SA: %d): " |
6227 | "kill it anyway\n" , |
6228 | SADB_SASTATE_DEAD, sav->state)); |
6229 | } |
6230 | |
6231 | /* |
6232 | * do not call key_freesav() here. |
6233 | * sav should already be freed, and sav->refcnt |
6234 | * shows other references to sav |
6235 | * (such as from SPD). |
6236 | */ |
6237 | } |
6238 | } |
6239 | } |
6240 | |
6241 | if (++key_timehandler_debug >= 300) { |
6242 | if (key_debug_level) { |
6243 | printf("%s: total stats for %u calls\n" , __FUNCTION__, key_timehandler_debug); |
6244 | printf("%s: walked %u SPDs\n" , __FUNCTION__, spd_count); |
6245 | printf("%s: walked %llu SAs: LARVAL SAs %u, MATURE SAs %u, DYING SAs %u, DEAD SAs %u\n" , __FUNCTION__, |
6246 | total_sav_count, larval_sav_count, mature_sav_count, dying_sav_count, dead_sav_count); |
6247 | printf("%s: walked %u SAHs: DEAD SAHs %u, EMPTY SAHs %u\n" , __FUNCTION__, |
6248 | sah_count, dead_sah_count, empty_sah_count); |
6249 | if (sah_search_calls) { |
6250 | printf("%s: SAH search cost %d iters per call\n" , __FUNCTION__, |
6251 | (sah_search_count/sah_search_calls)); |
6252 | } |
6253 | } |
6254 | spd_count = 0; |
6255 | sah_count = 0; |
6256 | dead_sah_count = 0; |
6257 | empty_sah_count = 0; |
6258 | larval_sav_count = 0; |
6259 | mature_sav_count = 0; |
6260 | dying_sav_count = 0; |
6261 | dead_sav_count = 0; |
6262 | total_sav_count = 0; |
6263 | sah_search_count = 0; |
6264 | sah_search_calls = 0; |
6265 | key_timehandler_debug = 0; |
6266 | } |
6267 | #ifndef IPSEC_NONBLOCK_ACQUIRE |
6268 | /* ACQ tree */ |
6269 | { |
6270 | struct secacq *acq, *nextacq; |
6271 | |
6272 | for (acq = LIST_FIRST(&acqtree); |
6273 | acq != NULL; |
6274 | acq = nextacq) { |
6275 | |
6276 | stop_handler = 0; |
6277 | nextacq = LIST_NEXT(acq, chain); |
6278 | |
6279 | if (tv.tv_sec - acq->created > key_blockacq_lifetime |
6280 | && __LIST_CHAINED(acq)) { |
6281 | LIST_REMOVE(acq, chain); |
6282 | KFREE(acq); |
6283 | } |
6284 | } |
6285 | } |
6286 | #endif |
6287 | |
6288 | /* SP ACQ tree */ |
6289 | { |
6290 | struct secspacq *acq, *nextacq; |
6291 | |
6292 | for (acq = LIST_FIRST(&spacqtree); |
6293 | acq != NULL; |
6294 | acq = nextacq) { |
6295 | |
6296 | stop_handler = 0; |
6297 | nextacq = LIST_NEXT(acq, chain); |
6298 | |
6299 | if (tv.tv_sec - acq->created > key_blockacq_lifetime |
6300 | && __LIST_CHAINED(acq)) { |
6301 | LIST_REMOVE(acq, chain); |
6302 | KFREE(acq); |
6303 | } |
6304 | } |
6305 | } |
6306 | |
6307 | /* initialize random seed */ |
6308 | if (key_tick_init_random++ > key_int_random) { |
6309 | key_tick_init_random = 0; |
6310 | key_srandom(); |
6311 | } |
6312 | |
6313 | uint64_t acc_sleep_time = 0; |
6314 | absolutetime_to_nanoseconds(mach_absolutetime_asleep, &acc_sleep_time); |
6315 | natt_now = ++up_time + (acc_sleep_time / NSEC_PER_SEC); |
6316 | |
6317 | lck_mtx_unlock(sadb_mutex); |
6318 | |
6319 | /* send messages outside of sadb_mutex */ |
6320 | if (spbuf && spcount > 0) { |
6321 | cnt = spcount; |
6322 | while (cnt--) |
6323 | key_spdexpire(*(--spptr)); |
6324 | } |
6325 | if (savkabuf && savkacount > 0) { |
6326 | struct secasvar **savkaptr_sav = savkaptr; |
6327 | int cnt_send = savkacount; |
6328 | |
6329 | while (cnt_send--) { |
6330 | if (ipsec_send_natt_keepalive(*(--savkaptr))) { |
6331 | // <rdar://6768487> iterate (all over again) and update timestamps |
6332 | struct secasvar **savkaptr_update = savkaptr_sav; |
6333 | int cnt_update = savkacount; |
6334 | while (cnt_update--) { |
6335 | key_update_natt_keepalive_timestamp(*savkaptr, |
6336 | *(--savkaptr_update)); |
6337 | } |
6338 | } |
6339 | } |
6340 | } |
6341 | if (savexbuf && savexcount > 0) { |
6342 | cnt = savexcount; |
6343 | while (cnt--) |
6344 | key_expire(*(--savexptr)); |
6345 | } |
6346 | |
6347 | /* decrement ref counts and free buffers */ |
6348 | lck_mtx_lock(sadb_mutex); |
6349 | if (spbuf) { |
6350 | while (spcount--) |
6351 | key_freesp(*spptr++, KEY_SADB_LOCKED); |
6352 | KFREE(spbuf); |
6353 | } |
6354 | if (savkabuf) { |
6355 | while (savkacount--) |
6356 | key_freesav(*savkaptr++, KEY_SADB_LOCKED); |
6357 | KFREE(savkabuf); |
6358 | } |
6359 | if (savexbuf) { |
6360 | while (savexcount--) |
6361 | key_freesav(*savexptr++, KEY_SADB_LOCKED); |
6362 | KFREE(savexbuf); |
6363 | } |
6364 | |
6365 | if (stop_handler) { |
6366 | key_timehandler_running = 0; |
6367 | /* Turn on the ipsec bypass */ |
6368 | ipsec_bypass = 1; |
6369 | } else { |
6370 | /* do exchange to tick time !! */ |
6371 | (void)timeout((void *)key_timehandler, (void *)0, hz); |
6372 | } |
6373 | |
6374 | lck_mtx_unlock(sadb_mutex); |
6375 | return; |
6376 | } |
6377 | |
6378 | /* |
6379 | * to initialize a seed for random() |
6380 | */ |
6381 | static void |
6382 | key_srandom(void) |
6383 | { |
6384 | #ifdef __APPLE__ |
6385 | /* Our PRNG is based on Yarrow and doesn't need to be seeded */ |
6386 | random(); |
6387 | #else |
6388 | struct timeval tv; |
6389 | |
6390 | microtime(&tv); |
6391 | |
6392 | srandom(tv.tv_usec); |
6393 | #endif |
6394 | |
6395 | return; |
6396 | } |
6397 | |
6398 | u_int32_t |
6399 | key_random(void) |
6400 | { |
6401 | u_int32_t value; |
6402 | |
6403 | key_randomfill(&value, sizeof(value)); |
6404 | return value; |
6405 | } |
6406 | |
6407 | void |
6408 | key_randomfill( |
6409 | void *p, |
6410 | size_t l) |
6411 | { |
6412 | #ifdef __APPLE__ |
6413 | cc_rand_generate(p, l); |
6414 | #else |
6415 | size_t n; |
6416 | u_int32_t v; |
6417 | static int warn = 1; |
6418 | |
6419 | n = 0; |
6420 | n = (size_t)read_random(p, (u_int)l); |
6421 | /* last resort */ |
6422 | while (n < l) { |
6423 | v = random(); |
6424 | bcopy(&v, (u_int8_t *)p + n, |
6425 | l - n < sizeof(v) ? l - n : sizeof(v)); |
6426 | n += sizeof(v); |
6427 | |
6428 | if (warn) { |
6429 | printf("WARNING: pseudo-random number generator " |
6430 | "used for IPsec processing\n" ); |
6431 | warn = 0; |
6432 | } |
6433 | } |
6434 | #endif |
6435 | } |
6436 | |
6437 | /* |
6438 | * map SADB_SATYPE_* to IPPROTO_*. |
6439 | * if satype == SADB_SATYPE then satype is mapped to ~0. |
6440 | * OUT: |
6441 | * 0: invalid satype. |
6442 | */ |
6443 | static u_int16_t |
6444 | key_satype2proto( |
6445 | u_int8_t satype) |
6446 | { |
6447 | switch (satype) { |
6448 | case SADB_SATYPE_UNSPEC: |
6449 | return IPSEC_PROTO_ANY; |
6450 | case SADB_SATYPE_AH: |
6451 | return IPPROTO_AH; |
6452 | case SADB_SATYPE_ESP: |
6453 | return IPPROTO_ESP; |
6454 | case SADB_X_SATYPE_IPCOMP: |
6455 | return IPPROTO_IPCOMP; |
6456 | default: |
6457 | return 0; |
6458 | } |
6459 | /* NOTREACHED */ |
6460 | } |
6461 | |
6462 | /* |
6463 | * map IPPROTO_* to SADB_SATYPE_* |
6464 | * OUT: |
6465 | * 0: invalid protocol type. |
6466 | */ |
6467 | static u_int8_t |
6468 | key_proto2satype( |
6469 | u_int16_t proto) |
6470 | { |
6471 | switch (proto) { |
6472 | case IPPROTO_AH: |
6473 | return SADB_SATYPE_AH; |
6474 | case IPPROTO_ESP: |
6475 | return SADB_SATYPE_ESP; |
6476 | case IPPROTO_IPCOMP: |
6477 | return SADB_X_SATYPE_IPCOMP; |
6478 | default: |
6479 | return 0; |
6480 | } |
6481 | /* NOTREACHED */ |
6482 | } |
6483 | |
6484 | static ifnet_t |
6485 | key_get_ipsec_if_from_message (const struct sadb_msghdr *mhp, int message_type) |
6486 | { |
6487 | struct sadb_x_ipsecif *ipsecifopts = NULL; |
6488 | ifnet_t ipsec_if = NULL; |
6489 | |
6490 | ipsecifopts = (struct sadb_x_ipsecif *)(void *)mhp->ext[message_type]; |
6491 | if (ipsecifopts != NULL) { |
6492 | if (ipsecifopts->sadb_x_ipsecif_ipsec_if[0]) { |
6493 | ifnet_find_by_name(ipsecifopts->sadb_x_ipsecif_ipsec_if, &ipsec_if); |
6494 | } |
6495 | } |
6496 | |
6497 | return ipsec_if; |
6498 | } |
6499 | |
6500 | static u_int |
6501 | key_get_outgoing_ifindex_from_message (const struct sadb_msghdr *mhp, int message_type) |
6502 | { |
6503 | struct sadb_x_ipsecif *ipsecifopts = NULL; |
6504 | ifnet_t outgoing_if = NULL; |
6505 | |
6506 | ipsecifopts = (struct sadb_x_ipsecif *)(void *)mhp->ext[message_type]; |
6507 | if (ipsecifopts != NULL) { |
6508 | if (ipsecifopts->sadb_x_ipsecif_outgoing_if[0]) { |
6509 | ifnet_find_by_name(ipsecifopts->sadb_x_ipsecif_outgoing_if, &outgoing_if); |
6510 | } |
6511 | } |
6512 | |
6513 | return outgoing_if ? outgoing_if->if_index : 0; |
6514 | } |
6515 | |
6516 | /* %%% PF_KEY */ |
6517 | /* |
6518 | * SADB_GETSPI processing is to receive |
6519 | * <base, (SA2), src address, dst address, (SPI range)> |
6520 | * from the IKMPd, to assign a unique spi value, to hang on the INBOUND |
6521 | * tree with the status of LARVAL, and send |
6522 | * <base, SA(*), address(SD)> |
6523 | * to the IKMPd. |
6524 | * |
6525 | * IN: mhp: pointer to the pointer to each header. |
6526 | * OUT: NULL if fail. |
6527 | * other if success, return pointer to the message to send. |
6528 | */ |
6529 | static int |
6530 | key_getspi( |
6531 | struct socket *so, |
6532 | struct mbuf *m, |
6533 | const struct sadb_msghdr *mhp) |
6534 | { |
6535 | struct sadb_address *src0, *dst0; |
6536 | struct secasindex saidx; |
6537 | struct secashead *newsah; |
6538 | struct secasvar *newsav; |
6539 | ifnet_t ipsec_if = NULL; |
6540 | u_int8_t proto; |
6541 | u_int32_t spi; |
6542 | u_int8_t mode; |
6543 | u_int32_t reqid; |
6544 | int error; |
6545 | |
6546 | LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED); |
6547 | |
6548 | /* sanity check */ |
6549 | if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) |
6550 | panic("key_getspi: NULL pointer is passed.\n" ); |
6551 | |
6552 | if (mhp->ext[SADB_EXT_ADDRESS_SRC] == NULL || |
6553 | mhp->ext[SADB_EXT_ADDRESS_DST] == NULL) { |
6554 | ipseclog((LOG_DEBUG, "key_getspi: invalid message is passed.\n" )); |
6555 | return key_senderror(so, m, EINVAL); |
6556 | } |
6557 | if (mhp->extlen[SADB_EXT_ADDRESS_SRC] < sizeof(struct sadb_address) || |
6558 | mhp->extlen[SADB_EXT_ADDRESS_DST] < sizeof(struct sadb_address)) { |
6559 | ipseclog((LOG_DEBUG, "key_getspi: invalid message is passed.\n" )); |
6560 | return key_senderror(so, m, EINVAL); |
6561 | } |
6562 | if (mhp->ext[SADB_X_EXT_SA2] != NULL) { |
6563 | mode = ((struct sadb_x_sa2 *) |
6564 | (void *)mhp->ext[SADB_X_EXT_SA2])->sadb_x_sa2_mode; |
6565 | reqid = ((struct sadb_x_sa2 *) |
6566 | (void *)mhp->ext[SADB_X_EXT_SA2])->sadb_x_sa2_reqid; |
6567 | } else { |
6568 | mode = IPSEC_MODE_ANY; |
6569 | reqid = 0; |
6570 | } |
6571 | |
6572 | src0 = (struct sadb_address *)(mhp->ext[SADB_EXT_ADDRESS_SRC]); |
6573 | dst0 = (struct sadb_address *)(mhp->ext[SADB_EXT_ADDRESS_DST]); |
6574 | |
6575 | ipsec_if = key_get_ipsec_if_from_message(mhp, SADB_X_EXT_IPSECIF); |
6576 | |
6577 | /* map satype to proto */ |
6578 | if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) { |
6579 | ipseclog((LOG_DEBUG, "key_getspi: invalid satype is passed.\n" )); |
6580 | return key_senderror(so, m, EINVAL); |
6581 | } |
6582 | |
6583 | /* make sure if port number is zero. */ |
6584 | switch (((struct sockaddr *)(src0 + 1))->sa_family) { |
6585 | case AF_INET: |
6586 | if (((struct sockaddr *)(src0 + 1))->sa_len != |
6587 | sizeof(struct sockaddr_in)) |
6588 | return key_senderror(so, m, EINVAL); |
6589 | ((struct sockaddr_in *)(void *)(src0 + 1))->sin_port = 0; |
6590 | break; |
6591 | case AF_INET6: |
6592 | if (((struct sockaddr *)(src0 + 1))->sa_len != |
6593 | sizeof(struct sockaddr_in6)) |
6594 | return key_senderror(so, m, EINVAL); |
6595 | ((struct sockaddr_in6 *)(void *)(src0 + 1))->sin6_port = 0; |
6596 | break; |
6597 | default: |
6598 | ; /*???*/ |
6599 | } |
6600 | switch (((struct sockaddr *)(dst0 + 1))->sa_family) { |
6601 | case AF_INET: |
6602 | if (((struct sockaddr *)(dst0 + 1))->sa_len != |
6603 | sizeof(struct sockaddr_in)) |
6604 | return key_senderror(so, m, EINVAL); |
6605 | ((struct sockaddr_in *)(void *)(dst0 + 1))->sin_port = 0; |
6606 | break; |
6607 | case AF_INET6: |
6608 | if (((struct sockaddr *)(dst0 + 1))->sa_len != |
6609 | sizeof(struct sockaddr_in6)) |
6610 | return key_senderror(so, m, EINVAL); |
6611 | ((struct sockaddr_in6 *)(void *)(dst0 + 1))->sin6_port = 0; |
6612 | break; |
6613 | default: |
6614 | ; /*???*/ |
6615 | } |
6616 | |
6617 | /* XXX boundary check against sa_len */ |
6618 | KEY_SETSECASIDX(proto, mode, reqid, src0 + 1, dst0 + 1, ipsec_if ? ipsec_if->if_index : 0, &saidx); |
6619 | |
6620 | lck_mtx_lock(sadb_mutex); |
6621 | |
6622 | /* SPI allocation */ |
6623 | spi = key_do_getnewspi((struct sadb_spirange *) |
6624 | (void *)mhp->ext[SADB_EXT_SPIRANGE], &saidx); |
6625 | if (spi == 0) { |
6626 | lck_mtx_unlock(sadb_mutex); |
6627 | return key_senderror(so, m, EINVAL); |
6628 | } |
6629 | |
6630 | /* get a SA index */ |
6631 | if ((newsah = key_getsah(&saidx)) == NULL) { |
6632 | /* create a new SA index: key_addspi is always used for inbound spi */ |
6633 | if ((newsah = key_newsah(&saidx, ipsec_if, key_get_outgoing_ifindex_from_message(mhp, SADB_X_EXT_IPSECIF), IPSEC_DIR_INBOUND)) == NULL) { |
6634 | lck_mtx_unlock(sadb_mutex); |
6635 | ipseclog((LOG_DEBUG, "key_getspi: No more memory.\n" )); |
6636 | return key_senderror(so, m, ENOBUFS); |
6637 | } |
6638 | } |
6639 | |
6640 | /* get a new SA */ |
6641 | /* XXX rewrite */ |
6642 | newsav = key_newsav(m, mhp, newsah, &error, so); |
6643 | if (newsav == NULL) { |
6644 | /* XXX don't free new SA index allocated in above. */ |
6645 | lck_mtx_unlock(sadb_mutex); |
6646 | return key_senderror(so, m, error); |
6647 | } |
6648 | |
6649 | /* set spi */ |
6650 | key_setspi(newsav, htonl(spi)); |
6651 | |
6652 | #ifndef IPSEC_NONBLOCK_ACQUIRE |
6653 | /* delete the entry in acqtree */ |
6654 | if (mhp->msg->sadb_msg_seq != 0) { |
6655 | struct secacq *acq; |
6656 | if ((acq = key_getacqbyseq(mhp->msg->sadb_msg_seq)) != NULL) { |
6657 | /* reset counter in order to deletion by timehandler. */ |
6658 | struct timeval tv; |
6659 | microtime(&tv); |
6660 | acq->created = tv.tv_sec; |
6661 | acq->count = 0; |
6662 | } |
6663 | } |
6664 | #endif |
6665 | |
6666 | lck_mtx_unlock(sadb_mutex); |
6667 | |
6668 | { |
6669 | struct mbuf *n, *nn; |
6670 | struct sadb_sa *m_sa; |
6671 | struct sadb_msg *newmsg; |
6672 | int off, len; |
6673 | |
6674 | /* create new sadb_msg to reply. */ |
6675 | len = PFKEY_ALIGN8(sizeof(struct sadb_msg)) + |
6676 | PFKEY_ALIGN8(sizeof(struct sadb_sa)); |
6677 | if (len > MCLBYTES) |
6678 | return key_senderror(so, m, ENOBUFS); |
6679 | |
6680 | MGETHDR(n, M_WAITOK, MT_DATA); |
6681 | if (n && len > MHLEN) { |
6682 | MCLGET(n, M_WAITOK); |
6683 | if ((n->m_flags & M_EXT) == 0) { |
6684 | m_freem(n); |
6685 | n = NULL; |
6686 | } |
6687 | } |
6688 | if (!n) |
6689 | return key_senderror(so, m, ENOBUFS); |
6690 | |
6691 | n->m_len = len; |
6692 | n->m_next = NULL; |
6693 | off = 0; |
6694 | |
6695 | m_copydata(m, 0, sizeof(struct sadb_msg), mtod(n, caddr_t) + off); |
6696 | off += PFKEY_ALIGN8(sizeof(struct sadb_msg)); |
6697 | |
6698 | m_sa = (struct sadb_sa *)(void *)(mtod(n, caddr_t) + off); |
6699 | m_sa->sadb_sa_len = PFKEY_UNIT64(sizeof(struct sadb_sa)); |
6700 | m_sa->sadb_sa_exttype = SADB_EXT_SA; |
6701 | m_sa->sadb_sa_spi = htonl(spi); |
6702 | off += PFKEY_ALIGN8(sizeof(struct sadb_sa)); |
6703 | |
6704 | #if DIAGNOSTIC |
6705 | if (off != len) |
6706 | panic("length inconsistency in key_getspi" ); |
6707 | #endif |
6708 | { |
6709 | int mbufItems[] = {SADB_EXT_ADDRESS_SRC, SADB_EXT_ADDRESS_DST}; |
6710 | n->m_next = key_gather_mbuf(m, mhp, 0, sizeof(mbufItems)/sizeof(int), mbufItems); |
6711 | if (!n->m_next) { |
6712 | m_freem(n); |
6713 | return key_senderror(so, m, ENOBUFS); |
6714 | } |
6715 | } |
6716 | |
6717 | if (n->m_len < sizeof(struct sadb_msg)) { |
6718 | n = m_pullup(n, sizeof(struct sadb_msg)); |
6719 | if (n == NULL) |
6720 | return key_sendup_mbuf(so, m, KEY_SENDUP_ONE); |
6721 | } |
6722 | |
6723 | n->m_pkthdr.len = 0; |
6724 | for (nn = n; nn; nn = nn->m_next) |
6725 | n->m_pkthdr.len += nn->m_len; |
6726 | |
6727 | newmsg = mtod(n, struct sadb_msg *); |
6728 | newmsg->sadb_msg_seq = newsav->seq; |
6729 | newmsg->sadb_msg_errno = 0; |
6730 | newmsg->sadb_msg_len = PFKEY_UNIT64(n->m_pkthdr.len); |
6731 | |
6732 | m_freem(m); |
6733 | return key_sendup_mbuf(so, n, KEY_SENDUP_ONE); |
6734 | } |
6735 | } |
6736 | |
6737 | u_int32_t |
6738 | key_getspi2(struct sockaddr *src, |
6739 | struct sockaddr *dst, |
6740 | u_int8_t proto, |
6741 | u_int8_t mode, |
6742 | u_int32_t reqid, |
6743 | struct sadb_spirange *spirange) |
6744 | { |
6745 | u_int32_t spi; |
6746 | struct secasindex saidx; |
6747 | |
6748 | LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED); |
6749 | |
6750 | /* XXX boundary check against sa_len */ |
6751 | KEY_SETSECASIDX(proto, mode, reqid, src, dst, 0, &saidx); |
6752 | |
6753 | /* make sure if port number is zero. */ |
6754 | switch (((struct sockaddr *)&saidx.src)->sa_family) { |
6755 | case AF_INET: |
6756 | if (((struct sockaddr *)&saidx.src)->sa_len != sizeof(struct sockaddr_in)) |
6757 | return 0; |
6758 | ((struct sockaddr_in *)&saidx.src)->sin_port = 0; |
6759 | break; |
6760 | case AF_INET6: |
6761 | if (((struct sockaddr *)&saidx.src)->sa_len != sizeof(struct sockaddr_in6)) |
6762 | return 0; |
6763 | ((struct sockaddr_in6 *)&saidx.src)->sin6_port = 0; |
6764 | break; |
6765 | default: |
6766 | ; /*???*/ |
6767 | } |
6768 | switch (((struct sockaddr *)&saidx.dst)->sa_family) { |
6769 | case AF_INET: |
6770 | if (((struct sockaddr *)&saidx.dst)->sa_len != sizeof(struct sockaddr_in)) |
6771 | return 0; |
6772 | ((struct sockaddr_in *)&saidx.dst)->sin_port = 0; |
6773 | break; |
6774 | case AF_INET6: |
6775 | if (((struct sockaddr *)&saidx.dst)->sa_len != sizeof(struct sockaddr_in6)) |
6776 | return 0; |
6777 | ((struct sockaddr_in6 *)&saidx.dst)->sin6_port = 0; |
6778 | break; |
6779 | default: |
6780 | ; /*???*/ |
6781 | } |
6782 | |
6783 | lck_mtx_lock(sadb_mutex); |
6784 | |
6785 | /* SPI allocation */ |
6786 | spi = key_do_getnewspi(spirange, &saidx); |
6787 | |
6788 | lck_mtx_unlock(sadb_mutex); |
6789 | |
6790 | return spi; |
6791 | } |
6792 | |
6793 | /* |
6794 | * allocating new SPI |
6795 | * called by key_getspi() and key_getspi2(). |
6796 | * OUT: |
6797 | * 0: failure. |
6798 | * others: success. |
6799 | */ |
6800 | static u_int32_t |
6801 | key_do_getnewspi( |
6802 | struct sadb_spirange *spirange, |
6803 | struct secasindex *saidx) |
6804 | { |
6805 | u_int32_t newspi; |
6806 | u_int32_t keymin, keymax; |
6807 | int count = key_spi_trycnt; |
6808 | |
6809 | LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_OWNED); |
6810 | |
6811 | /* set spi range to allocate */ |
6812 | if (spirange != NULL) { |
6813 | keymin = spirange->sadb_spirange_min; |
6814 | keymax = spirange->sadb_spirange_max; |
6815 | } else { |
6816 | keymin = key_spi_minval; |
6817 | keymax = key_spi_maxval; |
6818 | } |
6819 | /* IPCOMP needs 2-byte SPI */ |
6820 | if (saidx->proto == IPPROTO_IPCOMP) { |
6821 | u_int32_t t; |
6822 | if (keymin >= 0x10000) |
6823 | keymin = 0xffff; |
6824 | if (keymax >= 0x10000) |
6825 | keymax = 0xffff; |
6826 | if (keymin > keymax) { |
6827 | t = keymin; keymin = keymax; keymax = t; |
6828 | } |
6829 | } |
6830 | |
6831 | if (keymin == keymax) { |
6832 | if (key_checkspidup(saidx, keymin) != NULL) { |
6833 | ipseclog((LOG_DEBUG, "key_do_getnewspi: SPI %u exists already.\n" , keymin)); |
6834 | return 0; |
6835 | } |
6836 | |
6837 | count--; /* taking one cost. */ |
6838 | newspi = keymin; |
6839 | |
6840 | } else { |
6841 | |
6842 | u_int32_t range = keymax - keymin + 1; /* overflow value of zero means full range */ |
6843 | |
6844 | /* init SPI */ |
6845 | newspi = 0; |
6846 | |
6847 | /* when requesting to allocate spi ranged */ |
6848 | while (count--) { |
6849 | u_int32_t rand_val = key_random(); |
6850 | |
6851 | /* generate pseudo-random SPI value ranged. */ |
6852 | newspi = (range == 0 ? rand_val : keymin + (rand_val % range)); |
6853 | |
6854 | if (key_checkspidup(saidx, newspi) == NULL) |
6855 | break; |
6856 | } |
6857 | |
6858 | if (count == 0 || newspi == 0) { |
6859 | ipseclog((LOG_DEBUG, "key_do_getnewspi: to allocate spi is failed.\n" )); |
6860 | return 0; |
6861 | } |
6862 | } |
6863 | |
6864 | /* statistics */ |
6865 | keystat.getspi_count = |
6866 | (keystat.getspi_count + key_spi_trycnt - count) / 2; |
6867 | |
6868 | return newspi; |
6869 | } |
6870 | |
6871 | /* |
6872 | * SADB_UPDATE processing |
6873 | * receive |
6874 | * <base, SA, (SA2), (lifetime(HSC),) address(SD), (address(P),) |
6875 | * key(AE), (identity(SD),) (sensitivity)> |
6876 | * from the ikmpd, and update a secasvar entry whose status is SADB_SASTATE_LARVAL. |
6877 | * and send |
6878 | * <base, SA, (SA2), (lifetime(HSC),) address(SD), (address(P),) |
6879 | * (identity(SD),) (sensitivity)> |
6880 | * to the ikmpd. |
6881 | * |
6882 | * m will always be freed. |
6883 | */ |
6884 | static int |
6885 | key_update( |
6886 | struct socket *so, |
6887 | struct mbuf *m, |
6888 | const struct sadb_msghdr *mhp) |
6889 | { |
6890 | struct sadb_sa *sa0; |
6891 | struct sadb_address *src0, *dst0; |
6892 | ifnet_t ipsec_if = NULL; |
6893 | struct secasindex saidx; |
6894 | struct secashead *sah; |
6895 | struct secasvar *sav; |
6896 | u_int16_t proto; |
6897 | u_int8_t mode; |
6898 | u_int32_t reqid; |
6899 | u_int16_t flags2; |
6900 | int error; |
6901 | |
6902 | LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED); |
6903 | |
6904 | /* sanity check */ |
6905 | if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) |
6906 | panic("key_update: NULL pointer is passed.\n" ); |
6907 | |
6908 | /* map satype to proto */ |
6909 | if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) { |
6910 | ipseclog((LOG_DEBUG, "key_update: invalid satype is passed.\n" )); |
6911 | return key_senderror(so, m, EINVAL); |
6912 | } |
6913 | |
6914 | if (mhp->ext[SADB_EXT_SA] == NULL || |
6915 | mhp->ext[SADB_EXT_ADDRESS_SRC] == NULL || |
6916 | mhp->ext[SADB_EXT_ADDRESS_DST] == NULL || |
6917 | (mhp->msg->sadb_msg_satype == SADB_SATYPE_ESP && |
6918 | mhp->ext[SADB_EXT_KEY_ENCRYPT] == NULL) || |
6919 | (mhp->msg->sadb_msg_satype == SADB_SATYPE_AH && |
6920 | mhp->ext[SADB_EXT_KEY_AUTH] == NULL) || |
6921 | (mhp->ext[SADB_EXT_LIFETIME_HARD] != NULL && |
6922 | mhp->ext[SADB_EXT_LIFETIME_SOFT] == NULL) || |
6923 | (mhp->ext[SADB_EXT_LIFETIME_HARD] == NULL && |
6924 | mhp->ext[SADB_EXT_LIFETIME_SOFT] != NULL)) { |
6925 | ipseclog((LOG_DEBUG, "key_update: invalid message is passed.\n" )); |
6926 | return key_senderror(so, m, EINVAL); |
6927 | } |
6928 | if (mhp->extlen[SADB_EXT_SA] < sizeof(struct sadb_sa) || |
6929 | mhp->extlen[SADB_EXT_ADDRESS_SRC] < sizeof(struct sadb_address) || |
6930 | mhp->extlen[SADB_EXT_ADDRESS_DST] < sizeof(struct sadb_address)) { |
6931 | ipseclog((LOG_DEBUG, "key_update: invalid message is passed.\n" )); |
6932 | return key_senderror(so, m, EINVAL); |
6933 | } |
6934 | if (mhp->ext[SADB_X_EXT_SA2] != NULL) { |
6935 | mode = ((struct sadb_x_sa2 *) |
6936 | (void *)mhp->ext[SADB_X_EXT_SA2])->sadb_x_sa2_mode; |
6937 | reqid = ((struct sadb_x_sa2 *) |
6938 | (void *)mhp->ext[SADB_X_EXT_SA2])->sadb_x_sa2_reqid; |
6939 | flags2 = ((struct sadb_x_sa2 *)(void *)mhp->ext[SADB_X_EXT_SA2])->sadb_x_sa2_flags; |
6940 | } else { |
6941 | mode = IPSEC_MODE_ANY; |
6942 | reqid = 0; |
6943 | flags2 = 0; |
6944 | } |
6945 | /* XXX boundary checking for other extensions */ |
6946 | |
6947 | sa0 = (struct sadb_sa *)(void *)mhp->ext[SADB_EXT_SA]; |
6948 | src0 = (struct sadb_address *)(mhp->ext[SADB_EXT_ADDRESS_SRC]); |
6949 | dst0 = (struct sadb_address *)(mhp->ext[SADB_EXT_ADDRESS_DST]); |
6950 | ipsec_if = key_get_ipsec_if_from_message(mhp, SADB_X_EXT_IPSECIF); |
6951 | |
6952 | /* XXX boundary check against sa_len */ |
6953 | KEY_SETSECASIDX(proto, mode, reqid, src0 + 1, dst0 + 1, ipsec_if ? ipsec_if->if_index : 0, &saidx); |
6954 | |
6955 | lck_mtx_lock(sadb_mutex); |
6956 | |
6957 | /* get a SA header */ |
6958 | if ((sah = key_getsah(&saidx)) == NULL) { |
6959 | lck_mtx_unlock(sadb_mutex); |
6960 | ipseclog((LOG_DEBUG, "key_update: no SA index found.\n" )); |
6961 | return key_senderror(so, m, ENOENT); |
6962 | } |
6963 | |
6964 | /* set spidx if there */ |
6965 | /* XXX rewrite */ |
6966 | error = key_setident(sah, m, mhp); |
6967 | if (error) { |
6968 | lck_mtx_unlock(sadb_mutex); |
6969 | return key_senderror(so, m, error); |
6970 | } |
6971 | |
6972 | /* find a SA with sequence number. */ |
6973 | #if IPSEC_DOSEQCHECK |
6974 | if (mhp->msg->sadb_msg_seq != 0 |
6975 | && (sav = key_getsavbyseq(sah, mhp->msg->sadb_msg_seq)) == NULL) { |
6976 | lck_mtx_unlock(sadb_mutex); |
6977 | ipseclog((LOG_DEBUG, |
6978 | "key_update: no larval SA with sequence %u exists.\n" , |
6979 | mhp->msg->sadb_msg_seq)); |
6980 | return key_senderror(so, m, ENOENT); |
6981 | } |
6982 | #else |
6983 | if ((sav = key_getsavbyspi(sah, sa0->sadb_sa_spi)) == NULL) { |
6984 | lck_mtx_unlock(sadb_mutex); |
6985 | ipseclog((LOG_DEBUG, |
6986 | "key_update: no such a SA found (spi:%u)\n" , |
6987 | (u_int32_t)ntohl(sa0->sadb_sa_spi))); |
6988 | return key_senderror(so, m, EINVAL); |
6989 | } |
6990 | #endif |
6991 | |
6992 | /* validity check */ |
6993 | if (sav->sah->saidx.proto != proto) { |
6994 | lck_mtx_unlock(sadb_mutex); |
6995 | ipseclog((LOG_DEBUG, |
6996 | "key_update: protocol mismatched (DB=%u param=%u)\n" , |
6997 | sav->sah->saidx.proto, proto)); |
6998 | return key_senderror(so, m, EINVAL); |
6999 | } |
7000 | #if IPSEC_DOSEQCHECK |
7001 | if (sav->spi != sa0->sadb_sa_spi) { |
7002 | lck_mtx_unlock(sadb_mutex); |
7003 | ipseclog((LOG_DEBUG, |
7004 | "key_update: SPI mismatched (DB:%u param:%u)\n" , |
7005 | (u_int32_t)ntohl(sav->spi), |
7006 | (u_int32_t)ntohl(sa0->sadb_sa_spi))); |
7007 | return key_senderror(so, m, EINVAL); |
7008 | } |
7009 | #endif |
7010 | if (sav->pid != mhp->msg->sadb_msg_pid) { |
7011 | lck_mtx_unlock(sadb_mutex); |
7012 | ipseclog((LOG_DEBUG, |
7013 | "key_update: pid mismatched (DB:%u param:%u)\n" , |
7014 | sav->pid, mhp->msg->sadb_msg_pid)); |
7015 | return key_senderror(so, m, EINVAL); |
7016 | } |
7017 | |
7018 | /* copy sav values */ |
7019 | error = key_setsaval(sav, m, mhp); |
7020 | if (error) { |
7021 | key_freesav(sav, KEY_SADB_LOCKED); |
7022 | lck_mtx_unlock(sadb_mutex); |
7023 | return key_senderror(so, m, error); |
7024 | } |
7025 | |
7026 | sav->flags2 = flags2; |
7027 | if (flags2 & SADB_X_EXT_SA2_DELETE_ON_DETACH) { |
7028 | sav->so = so; |
7029 | } |
7030 | |
7031 | /* |
7032 | * Verify if SADB_X_EXT_NATT_MULTIPLEUSERS flag is set that |
7033 | * this SA is for transport mode - otherwise clear it. |
7034 | */ |
7035 | if ((sav->flags & SADB_X_EXT_NATT_MULTIPLEUSERS) != 0 && |
7036 | (sav->sah->saidx.mode != IPSEC_MODE_TRANSPORT || |
7037 | sav->sah->saidx.src.ss_family != AF_INET)) |
7038 | sav->flags &= ~SADB_X_EXT_NATT_MULTIPLEUSERS; |
7039 | |
7040 | /* check SA values to be mature. */ |
7041 | if ((error = key_mature(sav)) != 0) { |
7042 | key_freesav(sav, KEY_SADB_LOCKED); |
7043 | lck_mtx_unlock(sadb_mutex); |
7044 | return key_senderror(so, m, error); |
7045 | } |
7046 | |
7047 | lck_mtx_unlock(sadb_mutex); |
7048 | |
7049 | { |
7050 | struct mbuf *n; |
7051 | |
7052 | /* set msg buf from mhp */ |
7053 | n = key_getmsgbuf_x1(m, mhp); |
7054 | if (n == NULL) { |
7055 | ipseclog((LOG_DEBUG, "key_update: No more memory.\n" )); |
7056 | return key_senderror(so, m, ENOBUFS); |
7057 | } |
7058 | |
7059 | m_freem(m); |
7060 | return key_sendup_mbuf(so, n, KEY_SENDUP_ALL); |
7061 | } |
7062 | } |
7063 | |
7064 | static int |
7065 | key_migrate(struct socket *so, |
7066 | struct mbuf *m, |
7067 | const struct sadb_msghdr *mhp) |
7068 | { |
7069 | struct sadb_sa *sa0 = NULL; |
7070 | struct sadb_address *src0 = NULL; |
7071 | struct sadb_address *dst0 = NULL; |
7072 | struct sadb_address *src1 = NULL; |
7073 | struct sadb_address *dst1 = NULL; |
7074 | ifnet_t ipsec_if0 = NULL; |
7075 | ifnet_t ipsec_if1 = NULL; |
7076 | struct secasindex saidx0; |
7077 | struct secasindex saidx1; |
7078 | struct secashead *sah = NULL; |
7079 | struct secashead *newsah = NULL; |
7080 | struct secasvar *sav = NULL; |
7081 | u_int16_t proto; |
7082 | |
7083 | LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED); |
7084 | |
7085 | /* sanity check */ |
7086 | if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) |
7087 | panic("key_migrate: NULL pointer is passed.\n" ); |
7088 | |
7089 | /* map satype to proto */ |
7090 | if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) { |
7091 | ipseclog((LOG_DEBUG, "key_migrate: invalid satype is passed.\n" )); |
7092 | return key_senderror(so, m, EINVAL); |
7093 | } |
7094 | |
7095 | if (mhp->ext[SADB_EXT_SA] == NULL || |
7096 | mhp->ext[SADB_EXT_ADDRESS_SRC] == NULL || |
7097 | mhp->ext[SADB_EXT_ADDRESS_DST] == NULL || |
7098 | mhp->ext[SADB_EXT_MIGRATE_ADDRESS_SRC] == NULL || |
7099 | mhp->ext[SADB_EXT_MIGRATE_ADDRESS_DST] == NULL) { |
7100 | ipseclog((LOG_DEBUG, "key_migrate: invalid message is passed.\n" )); |
7101 | return key_senderror(so, m, EINVAL); |
7102 | } |
7103 | |
7104 | if (mhp->extlen[SADB_EXT_SA] < sizeof(struct sadb_sa) || |
7105 | mhp->extlen[SADB_EXT_ADDRESS_SRC] < sizeof(struct sadb_address) || |
7106 | mhp->extlen[SADB_EXT_ADDRESS_DST] < sizeof(struct sadb_address) || |
7107 | mhp->extlen[SADB_EXT_MIGRATE_ADDRESS_SRC] < sizeof(struct sadb_address) || |
7108 | mhp->extlen[SADB_EXT_MIGRATE_ADDRESS_DST] < sizeof(struct sadb_address)) { |
7109 | ipseclog((LOG_DEBUG, "key_migrate: invalid message is passed.\n" )); |
7110 | return key_senderror(so, m, EINVAL); |
7111 | } |
7112 | |
7113 | lck_mtx_lock(sadb_mutex); |
7114 | |
7115 | sa0 = (struct sadb_sa *)(void *)mhp->ext[SADB_EXT_SA]; |
7116 | src0 = (struct sadb_address *)(mhp->ext[SADB_EXT_ADDRESS_SRC]); |
7117 | dst0 = (struct sadb_address *)(mhp->ext[SADB_EXT_ADDRESS_DST]); |
7118 | src1 = (struct sadb_address *)(mhp->ext[SADB_EXT_MIGRATE_ADDRESS_SRC]); |
7119 | dst1 = (struct sadb_address *)(mhp->ext[SADB_EXT_MIGRATE_ADDRESS_DST]); |
7120 | ipsec_if0 = key_get_ipsec_if_from_message(mhp, SADB_X_EXT_IPSECIF); |
7121 | ipsec_if1 = key_get_ipsec_if_from_message(mhp, SADB_X_EXT_MIGRATE_IPSECIF); |
7122 | |
7123 | /* Find existing SAH and SAV */ |
7124 | KEY_SETSECASIDX(proto, IPSEC_MODE_ANY, 0, src0 + 1, dst0 + 1, ipsec_if0 ? ipsec_if0->if_index : 0, &saidx0); |
7125 | |
7126 | LIST_FOREACH(sah, &sahtree, chain) { |
7127 | if (sah->state != SADB_SASTATE_MATURE) |
7128 | continue; |
7129 | if (key_cmpsaidx(&sah->saidx, &saidx0, CMP_HEAD) == 0) |
7130 | continue; |
7131 | |
7132 | sav = key_getsavbyspi(sah, sa0->sadb_sa_spi); |
7133 | if (sav && sav->state == SADB_SASTATE_MATURE) |
7134 | break; |
7135 | } |
7136 | if (sah == NULL) { |
7137 | lck_mtx_unlock(sadb_mutex); |
7138 | ipseclog((LOG_DEBUG, "key_migrate: no mature SAH found.\n" )); |
7139 | return key_senderror(so, m, ENOENT); |
7140 | } |
7141 | |
7142 | if (sav == NULL) { |
7143 | lck_mtx_unlock(sadb_mutex); |
7144 | ipseclog((LOG_DEBUG, "key_migrate: no SA found.\n" )); |
7145 | return key_senderror(so, m, ENOENT); |
7146 | } |
7147 | |
7148 | /* Find or create new SAH */ |
7149 | KEY_SETSECASIDX(proto, sah->saidx.mode, sah->saidx.reqid, src1 + 1, dst1 + 1, ipsec_if1 ? ipsec_if1->if_index : 0, &saidx1); |
7150 | |
7151 | if ((newsah = key_getsah(&saidx1)) == NULL) { |
7152 | if ((newsah = key_newsah(&saidx1, ipsec_if1, key_get_outgoing_ifindex_from_message(mhp, SADB_X_EXT_MIGRATE_IPSECIF), sah->dir)) == NULL) { |
7153 | lck_mtx_unlock(sadb_mutex); |
7154 | ipseclog((LOG_DEBUG, "key_migrate: No more memory.\n" )); |
7155 | return key_senderror(so, m, ENOBUFS); |
7156 | } |
7157 | } |
7158 | |
7159 | /* Migrate SAV in to new SAH */ |
7160 | if (key_migratesav(sav, newsah) != 0) { |
7161 | lck_mtx_unlock(sadb_mutex); |
7162 | ipseclog((LOG_DEBUG, "key_migrate: Failed to migrate SA to new SAH.\n" )); |
7163 | return key_senderror(so, m, EINVAL); |
7164 | } |
7165 | |
7166 | /* Reset NAT values */ |
7167 | sav->flags = sa0->sadb_sa_flags; |
7168 | sav->remote_ike_port = ((const struct sadb_sa_2*)(sa0))->sadb_sa_natt_port; |
7169 | sav->natt_interval = ((const struct sadb_sa_2*)(sa0))->sadb_sa_natt_interval; |
7170 | sav->natt_offload_interval = ((const struct sadb_sa_2*)(sa0))->sadb_sa_natt_offload_interval; |
7171 | sav->natt_last_activity = natt_now; |
7172 | |
7173 | /* |
7174 | * Verify if SADB_X_EXT_NATT_MULTIPLEUSERS flag is set that |
7175 | * SADB_X_EXT_NATT is set and SADB_X_EXT_NATT_KEEPALIVE is not |
7176 | * set (we're not behind nat) - otherwise clear it. |
7177 | */ |
7178 | if ((sav->flags & SADB_X_EXT_NATT_MULTIPLEUSERS) != 0) |
7179 | if ((sav->flags & SADB_X_EXT_NATT) == 0 || |
7180 | (sav->flags & SADB_X_EXT_NATT_KEEPALIVE) != 0) |
7181 | sav->flags &= ~SADB_X_EXT_NATT_MULTIPLEUSERS; |
7182 | |
7183 | lck_mtx_unlock(sadb_mutex); |
7184 | { |
7185 | struct mbuf *n; |
7186 | struct sadb_msg *newmsg; |
7187 | int mbufItems[] = {SADB_EXT_RESERVED, SADB_EXT_SA, |
7188 | SADB_EXT_ADDRESS_SRC, SADB_EXT_ADDRESS_DST, SADB_X_EXT_IPSECIF, |
7189 | SADB_EXT_MIGRATE_ADDRESS_SRC, SADB_EXT_MIGRATE_ADDRESS_DST, SADB_X_EXT_MIGRATE_IPSECIF}; |
7190 | |
7191 | /* create new sadb_msg to reply. */ |
7192 | n = key_gather_mbuf(m, mhp, 1, sizeof(mbufItems)/sizeof(int), mbufItems); |
7193 | if (!n) |
7194 | return key_senderror(so, m, ENOBUFS); |
7195 | |
7196 | if (n->m_len < sizeof(struct sadb_msg)) { |
7197 | n = m_pullup(n, sizeof(struct sadb_msg)); |
7198 | if (n == NULL) |
7199 | return key_senderror(so, m, ENOBUFS); |
7200 | } |
7201 | newmsg = mtod(n, struct sadb_msg *); |
7202 | newmsg->sadb_msg_errno = 0; |
7203 | newmsg->sadb_msg_len = PFKEY_UNIT64(n->m_pkthdr.len); |
7204 | |
7205 | m_freem(m); |
7206 | return key_sendup_mbuf(so, n, KEY_SENDUP_ALL); |
7207 | } |
7208 | } |
7209 | |
7210 | /* |
7211 | * search SAD with sequence for a SA which state is SADB_SASTATE_LARVAL. |
7212 | * only called by key_update(). |
7213 | * OUT: |
7214 | * NULL : not found |
7215 | * others : found, pointer to a SA. |
7216 | */ |
7217 | #if IPSEC_DOSEQCHECK |
7218 | static struct secasvar * |
7219 | key_getsavbyseq( |
7220 | struct secashead *sah, |
7221 | u_int32_t seq) |
7222 | { |
7223 | struct secasvar *sav; |
7224 | u_int state; |
7225 | |
7226 | LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_OWNED); |
7227 | |
7228 | state = SADB_SASTATE_LARVAL; |
7229 | |
7230 | /* search SAD with sequence number ? */ |
7231 | LIST_FOREACH(sav, &sah->savtree[state], chain) { |
7232 | |
7233 | KEY_CHKSASTATE(state, sav->state, "key_getsabyseq" ); |
7234 | |
7235 | if (sav->seq == seq) { |
7236 | sav->refcnt++; |
7237 | KEYDEBUG(KEYDEBUG_IPSEC_STAMP, |
7238 | printf("DP key_getsavbyseq cause " |
7239 | "refcnt++:%d SA:0x%llx\n" , sav->refcnt, |
7240 | (uint64_t)VM_KERNEL_ADDRPERM(sav))); |
7241 | return sav; |
7242 | } |
7243 | } |
7244 | |
7245 | return NULL; |
7246 | } |
7247 | #endif |
7248 | |
7249 | /* |
7250 | * SADB_ADD processing |
7251 | * add a entry to SA database, when received |
7252 | * <base, SA, (SA2), (lifetime(HSC),) address(SD), (address(P),) |
7253 | * key(AE), (identity(SD),) (sensitivity)> |
7254 | * from the ikmpd, |
7255 | * and send |
7256 | * <base, SA, (SA2), (lifetime(HSC),) address(SD), (address(P),) |
7257 | * (identity(SD),) (sensitivity)> |
7258 | * to the ikmpd. |
7259 | * |
7260 | * IGNORE identity and sensitivity messages. |
7261 | * |
7262 | * m will always be freed. |
7263 | */ |
7264 | static int |
7265 | key_add( |
7266 | struct socket *so, |
7267 | struct mbuf *m, |
7268 | const struct sadb_msghdr *mhp) |
7269 | { |
7270 | struct sadb_sa *sa0; |
7271 | struct sadb_address *src0, *dst0; |
7272 | ifnet_t ipsec_if = NULL; |
7273 | struct secasindex saidx; |
7274 | struct secashead *newsah; |
7275 | struct secasvar *newsav; |
7276 | u_int16_t proto; |
7277 | u_int8_t mode; |
7278 | u_int32_t reqid; |
7279 | int error; |
7280 | |
7281 | LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED); |
7282 | |
7283 | /* sanity check */ |
7284 | if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) |
7285 | panic("key_add: NULL pointer is passed.\n" ); |
7286 | |
7287 | /* map satype to proto */ |
7288 | if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) { |
7289 | ipseclog((LOG_DEBUG, "key_add: invalid satype is passed.\n" )); |
7290 | bzero_keys(mhp); |
7291 | return key_senderror(so, m, EINVAL); |
7292 | } |
7293 | |
7294 | if (mhp->ext[SADB_EXT_SA] == NULL || |
7295 | mhp->ext[SADB_EXT_ADDRESS_SRC] == NULL || |
7296 | mhp->ext[SADB_EXT_ADDRESS_DST] == NULL || |
7297 | (mhp->msg->sadb_msg_satype == SADB_SATYPE_ESP && |
7298 | mhp->ext[SADB_EXT_KEY_ENCRYPT] == NULL) || |
7299 | (mhp->msg->sadb_msg_satype == SADB_SATYPE_AH && |
7300 | mhp->ext[SADB_EXT_KEY_AUTH] == NULL) || |
7301 | (mhp->ext[SADB_EXT_LIFETIME_HARD] != NULL && |
7302 | mhp->ext[SADB_EXT_LIFETIME_SOFT] == NULL) || |
7303 | (mhp->ext[SADB_EXT_LIFETIME_HARD] == NULL && |
7304 | mhp->ext[SADB_EXT_LIFETIME_SOFT] != NULL)) { |
7305 | ipseclog((LOG_DEBUG, "key_add: invalid message is passed.\n" )); |
7306 | bzero_keys(mhp); |
7307 | return key_senderror(so, m, EINVAL); |
7308 | } |
7309 | if (mhp->extlen[SADB_EXT_SA] < sizeof(struct sadb_sa) || |
7310 | mhp->extlen[SADB_EXT_ADDRESS_SRC] < sizeof(struct sadb_address) || |
7311 | mhp->extlen[SADB_EXT_ADDRESS_DST] < sizeof(struct sadb_address)) { |
7312 | /* XXX need more */ |
7313 | ipseclog((LOG_DEBUG, "key_add: invalid message is passed.\n" )); |
7314 | bzero_keys(mhp); |
7315 | return key_senderror(so, m, EINVAL); |
7316 | } |
7317 | if (mhp->ext[SADB_X_EXT_SA2] != NULL) { |
7318 | mode = ((struct sadb_x_sa2 *) |
7319 | (void *)mhp->ext[SADB_X_EXT_SA2])->sadb_x_sa2_mode; |
7320 | reqid = ((struct sadb_x_sa2 *) |
7321 | (void *)mhp->ext[SADB_X_EXT_SA2])->sadb_x_sa2_reqid; |
7322 | } else { |
7323 | mode = IPSEC_MODE_ANY; |
7324 | reqid = 0; |
7325 | } |
7326 | |
7327 | sa0 = (struct sadb_sa *)(void *)mhp->ext[SADB_EXT_SA]; |
7328 | src0 = (struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_SRC]; |
7329 | dst0 = (struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_DST]; |
7330 | ipsec_if = key_get_ipsec_if_from_message(mhp, SADB_X_EXT_IPSECIF); |
7331 | |
7332 | /* XXX boundary check against sa_len */ |
7333 | KEY_SETSECASIDX(proto, mode, reqid, src0 + 1, dst0 + 1, ipsec_if ? ipsec_if->if_index : 0, &saidx); |
7334 | |
7335 | lck_mtx_lock(sadb_mutex); |
7336 | |
7337 | /* get a SA header */ |
7338 | if ((newsah = key_getsah(&saidx)) == NULL) { |
7339 | /* create a new SA header: key_addspi is always used for outbound spi */ |
7340 | if ((newsah = key_newsah(&saidx, ipsec_if, key_get_outgoing_ifindex_from_message(mhp, SADB_X_EXT_IPSECIF), IPSEC_DIR_OUTBOUND)) == NULL) { |
7341 | lck_mtx_unlock(sadb_mutex); |
7342 | ipseclog((LOG_DEBUG, "key_add: No more memory.\n" )); |
7343 | bzero_keys(mhp); |
7344 | return key_senderror(so, m, ENOBUFS); |
7345 | } |
7346 | } |
7347 | |
7348 | /* set spidx if there */ |
7349 | /* XXX rewrite */ |
7350 | error = key_setident(newsah, m, mhp); |
7351 | if (error) { |
7352 | lck_mtx_unlock(sadb_mutex); |
7353 | bzero_keys(mhp); |
7354 | return key_senderror(so, m, error); |
7355 | } |
7356 | |
7357 | /* create new SA entry. */ |
7358 | /* We can create new SA only if SPI is different. */ |
7359 | if (key_getsavbyspi(newsah, sa0->sadb_sa_spi)) { |
7360 | lck_mtx_unlock(sadb_mutex); |
7361 | ipseclog((LOG_DEBUG, "key_add: SA already exists.\n" )); |
7362 | bzero_keys(mhp); |
7363 | return key_senderror(so, m, EEXIST); |
7364 | } |
7365 | newsav = key_newsav(m, mhp, newsah, &error, so); |
7366 | if (newsav == NULL) { |
7367 | lck_mtx_unlock(sadb_mutex); |
7368 | bzero_keys(mhp); |
7369 | return key_senderror(so, m, error); |
7370 | } |
7371 | |
7372 | /* |
7373 | * Verify if SADB_X_EXT_NATT_MULTIPLEUSERS flag is set that |
7374 | * this SA is for transport mode - otherwise clear it. |
7375 | */ |
7376 | if ((newsav->flags & SADB_X_EXT_NATT_MULTIPLEUSERS) != 0 && |
7377 | (newsah->saidx.mode != IPSEC_MODE_TRANSPORT || |
7378 | newsah->saidx.dst.ss_family != AF_INET)) |
7379 | newsav->flags &= ~SADB_X_EXT_NATT_MULTIPLEUSERS; |
7380 | |
7381 | /* check SA values to be mature. */ |
7382 | if ((error = key_mature(newsav)) != 0) { |
7383 | key_freesav(newsav, KEY_SADB_LOCKED); |
7384 | lck_mtx_unlock(sadb_mutex); |
7385 | bzero_keys(mhp); |
7386 | return key_senderror(so, m, error); |
7387 | } |
7388 | |
7389 | lck_mtx_unlock(sadb_mutex); |
7390 | |
7391 | /* |
7392 | * don't call key_freesav() here, as we would like to keep the SA |
7393 | * in the database on success. |
7394 | */ |
7395 | |
7396 | { |
7397 | struct mbuf *n; |
7398 | |
7399 | /* set msg buf from mhp */ |
7400 | n = key_getmsgbuf_x1(m, mhp); |
7401 | if (n == NULL) { |
7402 | ipseclog((LOG_DEBUG, "key_update: No more memory.\n" )); |
7403 | bzero_keys(mhp); |
7404 | return key_senderror(so, m, ENOBUFS); |
7405 | } |
7406 | |
7407 | // mh.ext points to the mbuf content. |
7408 | // Zero out Encryption and Integrity keys if present. |
7409 | bzero_keys(mhp); |
7410 | m_freem(m); |
7411 | return key_sendup_mbuf(so, n, KEY_SENDUP_ALL); |
7412 | } |
7413 | } |
7414 | |
7415 | /* m is retained */ |
7416 | static int |
7417 | key_setident( |
7418 | struct secashead *sah, |
7419 | struct mbuf *m, |
7420 | const struct sadb_msghdr *mhp) |
7421 | { |
7422 | const struct sadb_ident *idsrc, *iddst; |
7423 | int idsrclen, iddstlen; |
7424 | |
7425 | LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_OWNED); |
7426 | |
7427 | /* sanity check */ |
7428 | if (sah == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) |
7429 | panic("key_setident: NULL pointer is passed.\n" ); |
7430 | |
7431 | /* don't make buffer if not there */ |
7432 | if (mhp->ext[SADB_EXT_IDENTITY_SRC] == NULL && |
7433 | mhp->ext[SADB_EXT_IDENTITY_DST] == NULL) { |
7434 | sah->idents = NULL; |
7435 | sah->identd = NULL; |
7436 | return 0; |
7437 | } |
7438 | |
7439 | if (mhp->ext[SADB_EXT_IDENTITY_SRC] == NULL || |
7440 | mhp->ext[SADB_EXT_IDENTITY_DST] == NULL) { |
7441 | ipseclog((LOG_DEBUG, "key_setident: invalid identity.\n" )); |
7442 | return EINVAL; |
7443 | } |
7444 | |
7445 | idsrc = (const struct sadb_ident *) |
7446 | (void *)mhp->ext[SADB_EXT_IDENTITY_SRC]; |
7447 | iddst = (const struct sadb_ident *) |
7448 | (void *)mhp->ext[SADB_EXT_IDENTITY_DST]; |
7449 | idsrclen = mhp->extlen[SADB_EXT_IDENTITY_SRC]; |
7450 | iddstlen = mhp->extlen[SADB_EXT_IDENTITY_DST]; |
7451 | |
7452 | /* validity check */ |
7453 | if (idsrc->sadb_ident_type != iddst->sadb_ident_type) { |
7454 | ipseclog((LOG_DEBUG, "key_setident: ident type mismatch.\n" )); |
7455 | return EINVAL; |
7456 | } |
7457 | |
7458 | switch (idsrc->sadb_ident_type) { |
7459 | case SADB_IDENTTYPE_PREFIX: |
7460 | case SADB_IDENTTYPE_FQDN: |
7461 | case SADB_IDENTTYPE_USERFQDN: |
7462 | default: |
7463 | /* XXX do nothing */ |
7464 | sah->idents = NULL; |
7465 | sah->identd = NULL; |
7466 | return 0; |
7467 | } |
7468 | |
7469 | /* make structure */ |
7470 | KMALLOC_NOWAIT(sah->idents, struct sadb_ident *, idsrclen); |
7471 | if (sah->idents == NULL) { |
7472 | lck_mtx_unlock(sadb_mutex); |
7473 | KMALLOC_WAIT(sah->idents, struct sadb_ident *, idsrclen); |
7474 | lck_mtx_lock(sadb_mutex); |
7475 | if (sah->idents == NULL) { |
7476 | ipseclog((LOG_DEBUG, "key_setident: No more memory.\n" )); |
7477 | return ENOBUFS; |
7478 | } |
7479 | } |
7480 | KMALLOC_NOWAIT(sah->identd, struct sadb_ident *, iddstlen); |
7481 | if (sah->identd == NULL) { |
7482 | lck_mtx_unlock(sadb_mutex); |
7483 | KMALLOC_WAIT(sah->identd, struct sadb_ident *, iddstlen); |
7484 | lck_mtx_lock(sadb_mutex); |
7485 | if (sah->identd == NULL) { |
7486 | KFREE(sah->idents); |
7487 | sah->idents = NULL; |
7488 | ipseclog((LOG_DEBUG, "key_setident: No more memory.\n" )); |
7489 | return ENOBUFS; |
7490 | } |
7491 | } |
7492 | bcopy(idsrc, sah->idents, idsrclen); |
7493 | bcopy(iddst, sah->identd, iddstlen); |
7494 | |
7495 | return 0; |
7496 | } |
7497 | |
7498 | /* |
7499 | * m will not be freed on return. |
7500 | * it is caller's responsibility to free the result. |
7501 | */ |
7502 | static struct mbuf * |
7503 | key_getmsgbuf_x1( |
7504 | struct mbuf *m, |
7505 | const struct sadb_msghdr *mhp) |
7506 | { |
7507 | struct mbuf *n; |
7508 | int mbufItems[] = {SADB_EXT_RESERVED, SADB_EXT_SA, |
7509 | SADB_X_EXT_SA2, SADB_EXT_ADDRESS_SRC, |
7510 | SADB_EXT_ADDRESS_DST, SADB_EXT_LIFETIME_HARD, |
7511 | SADB_EXT_LIFETIME_SOFT, SADB_EXT_IDENTITY_SRC, |
7512 | SADB_EXT_IDENTITY_DST}; |
7513 | |
7514 | /* sanity check */ |
7515 | if (m == NULL || mhp == NULL || mhp->msg == NULL) |
7516 | panic("key_getmsgbuf_x1: NULL pointer is passed.\n" ); |
7517 | |
7518 | /* create new sadb_msg to reply. */ |
7519 | n = key_gather_mbuf(m, mhp, 1, sizeof(mbufItems)/sizeof(int), mbufItems); |
7520 | if (!n) |
7521 | return NULL; |
7522 | |
7523 | if (n->m_len < sizeof(struct sadb_msg)) { |
7524 | n = m_pullup(n, sizeof(struct sadb_msg)); |
7525 | if (n == NULL) |
7526 | return NULL; |
7527 | } |
7528 | mtod(n, struct sadb_msg *)->sadb_msg_errno = 0; |
7529 | mtod(n, struct sadb_msg *)->sadb_msg_len = |
7530 | PFKEY_UNIT64(n->m_pkthdr.len); |
7531 | |
7532 | return n; |
7533 | } |
7534 | |
7535 | static int key_delete_all(struct socket *, struct mbuf *, |
7536 | const struct sadb_msghdr *, u_int16_t); |
7537 | |
7538 | /* |
7539 | * SADB_DELETE processing |
7540 | * receive |
7541 | * <base, SA(*), address(SD)> |
7542 | * from the ikmpd, and set SADB_SASTATE_DEAD, |
7543 | * and send, |
7544 | * <base, SA(*), address(SD)> |
7545 | * to the ikmpd. |
7546 | * |
7547 | * m will always be freed. |
7548 | */ |
7549 | static int |
7550 | key_delete( |
7551 | struct socket *so, |
7552 | struct mbuf *m, |
7553 | const struct sadb_msghdr *mhp) |
7554 | { |
7555 | struct sadb_sa *sa0; |
7556 | struct sadb_address *src0, *dst0; |
7557 | ifnet_t ipsec_if = NULL; |
7558 | struct secasindex saidx; |
7559 | struct secashead *sah; |
7560 | struct secasvar *sav = NULL; |
7561 | u_int16_t proto; |
7562 | |
7563 | LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED); |
7564 | |
7565 | /* sanity check */ |
7566 | if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) |
7567 | panic("key_delete: NULL pointer is passed.\n" ); |
7568 | |
7569 | /* map satype to proto */ |
7570 | if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) { |
7571 | ipseclog((LOG_DEBUG, "key_delete: invalid satype is passed.\n" )); |
7572 | return key_senderror(so, m, EINVAL); |
7573 | } |
7574 | |
7575 | if (mhp->ext[SADB_EXT_ADDRESS_SRC] == NULL || |
7576 | mhp->ext[SADB_EXT_ADDRESS_DST] == NULL) { |
7577 | ipseclog((LOG_DEBUG, "key_delete: invalid message is passed.\n" )); |
7578 | return key_senderror(so, m, EINVAL); |
7579 | } |
7580 | |
7581 | if (mhp->extlen[SADB_EXT_ADDRESS_SRC] < sizeof(struct sadb_address) || |
7582 | mhp->extlen[SADB_EXT_ADDRESS_DST] < sizeof(struct sadb_address)) { |
7583 | ipseclog((LOG_DEBUG, "key_delete: invalid message is passed.\n" )); |
7584 | return key_senderror(so, m, EINVAL); |
7585 | } |
7586 | |
7587 | lck_mtx_lock(sadb_mutex); |
7588 | |
7589 | if (mhp->ext[SADB_EXT_SA] == NULL) { |
7590 | /* |
7591 | * Caller wants us to delete all non-LARVAL SAs |
7592 | * that match the src/dst. This is used during |
7593 | * IKE INITIAL-CONTACT. |
7594 | */ |
7595 | ipseclog((LOG_DEBUG, "key_delete: doing delete all.\n" )); |
7596 | /* key_delete_all will unlock sadb_mutex */ |
7597 | return key_delete_all(so, m, mhp, proto); |
7598 | } else if (mhp->extlen[SADB_EXT_SA] < sizeof(struct sadb_sa)) { |
7599 | lck_mtx_unlock(sadb_mutex); |
7600 | ipseclog((LOG_DEBUG, "key_delete: invalid message is passed.\n" )); |
7601 | return key_senderror(so, m, EINVAL); |
7602 | } |
7603 | |
7604 | sa0 = (struct sadb_sa *)(void *)mhp->ext[SADB_EXT_SA]; |
7605 | src0 = (struct sadb_address *)(mhp->ext[SADB_EXT_ADDRESS_SRC]); |
7606 | dst0 = (struct sadb_address *)(mhp->ext[SADB_EXT_ADDRESS_DST]); |
7607 | ipsec_if = key_get_ipsec_if_from_message(mhp, SADB_X_EXT_IPSECIF); |
7608 | |
7609 | /* XXX boundary check against sa_len */ |
7610 | KEY_SETSECASIDX(proto, IPSEC_MODE_ANY, 0, src0 + 1, dst0 + 1, ipsec_if ? ipsec_if->if_index : 0, &saidx); |
7611 | |
7612 | /* get a SA header */ |
7613 | LIST_FOREACH(sah, &sahtree, chain) { |
7614 | if (sah->state == SADB_SASTATE_DEAD) |
7615 | continue; |
7616 | if (key_cmpsaidx(&sah->saidx, &saidx, CMP_HEAD) == 0) |
7617 | continue; |
7618 | |
7619 | /* get a SA with SPI. */ |
7620 | sav = key_getsavbyspi(sah, sa0->sadb_sa_spi); |
7621 | if (sav) |
7622 | break; |
7623 | } |
7624 | if (sah == NULL) { |
7625 | lck_mtx_unlock(sadb_mutex); |
7626 | ipseclog((LOG_DEBUG, "key_delete: no SA found.\n" )); |
7627 | return key_senderror(so, m, ENOENT); |
7628 | } |
7629 | |
7630 | key_sa_chgstate(sav, SADB_SASTATE_DEAD); |
7631 | key_freesav(sav, KEY_SADB_LOCKED); |
7632 | |
7633 | lck_mtx_unlock(sadb_mutex); |
7634 | sav = NULL; |
7635 | |
7636 | { |
7637 | struct mbuf *n; |
7638 | struct sadb_msg *newmsg; |
7639 | int mbufItems[] = {SADB_EXT_RESERVED, SADB_EXT_SA, |
7640 | SADB_EXT_ADDRESS_SRC, SADB_EXT_ADDRESS_DST}; |
7641 | |
7642 | /* create new sadb_msg to reply. */ |
7643 | n = key_gather_mbuf(m, mhp, 1, sizeof(mbufItems)/sizeof(int), mbufItems); |
7644 | if (!n) |
7645 | return key_senderror(so, m, ENOBUFS); |
7646 | |
7647 | if (n->m_len < sizeof(struct sadb_msg)) { |
7648 | n = m_pullup(n, sizeof(struct sadb_msg)); |
7649 | if (n == NULL) |
7650 | return key_senderror(so, m, ENOBUFS); |
7651 | } |
7652 | newmsg = mtod(n, struct sadb_msg *); |
7653 | newmsg->sadb_msg_errno = 0; |
7654 | newmsg->sadb_msg_len = PFKEY_UNIT64(n->m_pkthdr.len); |
7655 | |
7656 | m_freem(m); |
7657 | return key_sendup_mbuf(so, n, KEY_SENDUP_ALL); |
7658 | } |
7659 | } |
7660 | |
7661 | /* |
7662 | * delete all SAs for src/dst. Called from key_delete(). |
7663 | */ |
7664 | static int |
7665 | key_delete_all( |
7666 | struct socket *so, |
7667 | struct mbuf *m, |
7668 | const struct sadb_msghdr *mhp, |
7669 | u_int16_t proto) |
7670 | { |
7671 | struct sadb_address *src0, *dst0; |
7672 | ifnet_t ipsec_if = NULL; |
7673 | struct secasindex saidx; |
7674 | struct secashead *sah; |
7675 | struct secasvar *sav, *nextsav; |
7676 | u_int stateidx, state; |
7677 | |
7678 | LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_OWNED); |
7679 | |
7680 | src0 = (struct sadb_address *)(mhp->ext[SADB_EXT_ADDRESS_SRC]); |
7681 | dst0 = (struct sadb_address *)(mhp->ext[SADB_EXT_ADDRESS_DST]); |
7682 | ipsec_if = key_get_ipsec_if_from_message(mhp, SADB_X_EXT_IPSECIF); |
7683 | |
7684 | /* XXX boundary check against sa_len */ |
7685 | KEY_SETSECASIDX(proto, IPSEC_MODE_ANY, 0, src0 + 1, dst0 + 1, ipsec_if ? ipsec_if->if_index : 0, &saidx); |
7686 | |
7687 | LIST_FOREACH(sah, &sahtree, chain) { |
7688 | if (sah->state == SADB_SASTATE_DEAD) |
7689 | continue; |
7690 | if (key_cmpsaidx(&sah->saidx, &saidx, CMP_HEAD) == 0) |
7691 | continue; |
7692 | |
7693 | /* Delete all non-LARVAL SAs. */ |
7694 | for (stateidx = 0; |
7695 | stateidx < _ARRAYLEN(saorder_state_alive); |
7696 | stateidx++) { |
7697 | state = saorder_state_alive[stateidx]; |
7698 | if (state == SADB_SASTATE_LARVAL) |
7699 | continue; |
7700 | for (sav = LIST_FIRST(&sah->savtree[state]); |
7701 | sav != NULL; sav = nextsav) { |
7702 | nextsav = LIST_NEXT(sav, chain); |
7703 | /* sanity check */ |
7704 | if (sav->state != state) { |
7705 | ipseclog((LOG_DEBUG, "key_delete_all: " |
7706 | "invalid sav->state " |
7707 | "(queue: %d SA: %d)\n" , |
7708 | state, sav->state)); |
7709 | continue; |
7710 | } |
7711 | |
7712 | key_sa_chgstate(sav, SADB_SASTATE_DEAD); |
7713 | key_freesav(sav, KEY_SADB_LOCKED); |
7714 | } |
7715 | } |
7716 | } |
7717 | lck_mtx_unlock(sadb_mutex); |
7718 | |
7719 | { |
7720 | struct mbuf *n; |
7721 | struct sadb_msg *newmsg; |
7722 | int mbufItems[] = {SADB_EXT_RESERVED, SADB_EXT_ADDRESS_SRC, |
7723 | SADB_EXT_ADDRESS_DST}; |
7724 | |
7725 | /* create new sadb_msg to reply. */ |
7726 | n = key_gather_mbuf(m, mhp, 1, sizeof(mbufItems)/sizeof(int), mbufItems); |
7727 | if (!n) |
7728 | return key_senderror(so, m, ENOBUFS); |
7729 | |
7730 | if (n->m_len < sizeof(struct sadb_msg)) { |
7731 | n = m_pullup(n, sizeof(struct sadb_msg)); |
7732 | if (n == NULL) |
7733 | return key_senderror(so, m, ENOBUFS); |
7734 | } |
7735 | newmsg = mtod(n, struct sadb_msg *); |
7736 | newmsg->sadb_msg_errno = 0; |
7737 | newmsg->sadb_msg_len = PFKEY_UNIT64(n->m_pkthdr.len); |
7738 | |
7739 | m_freem(m); |
7740 | return key_sendup_mbuf(so, n, KEY_SENDUP_ALL); |
7741 | } |
7742 | } |
7743 | |
7744 | /* |
7745 | * SADB_GET processing |
7746 | * receive |
7747 | * <base, SA(*), address(SD)> |
7748 | * from the ikmpd, and get a SP and a SA to respond, |
7749 | * and send, |
7750 | * <base, SA, (lifetime(HSC),) address(SD), (address(P),) key(AE), |
7751 | * (identity(SD),) (sensitivity)> |
7752 | * to the ikmpd. |
7753 | * |
7754 | * m will always be freed. |
7755 | */ |
7756 | static int |
7757 | key_get( |
7758 | struct socket *so, |
7759 | struct mbuf *m, |
7760 | const struct sadb_msghdr *mhp) |
7761 | { |
7762 | struct sadb_sa *sa0; |
7763 | struct sadb_address *src0, *dst0; |
7764 | ifnet_t ipsec_if = NULL; |
7765 | struct secasindex saidx; |
7766 | struct secashead *sah; |
7767 | struct secasvar *sav = NULL; |
7768 | u_int16_t proto; |
7769 | |
7770 | LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED); |
7771 | |
7772 | /* sanity check */ |
7773 | if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) |
7774 | panic("key_get: NULL pointer is passed.\n" ); |
7775 | |
7776 | /* map satype to proto */ |
7777 | if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) { |
7778 | ipseclog((LOG_DEBUG, "key_get: invalid satype is passed.\n" )); |
7779 | return key_senderror(so, m, EINVAL); |
7780 | } |
7781 | |
7782 | if (mhp->ext[SADB_EXT_SA] == NULL || |
7783 | mhp->ext[SADB_EXT_ADDRESS_SRC] == NULL || |
7784 | mhp->ext[SADB_EXT_ADDRESS_DST] == NULL) { |
7785 | ipseclog((LOG_DEBUG, "key_get: invalid message is passed.\n" )); |
7786 | return key_senderror(so, m, EINVAL); |
7787 | } |
7788 | if (mhp->extlen[SADB_EXT_SA] < sizeof(struct sadb_sa) || |
7789 | mhp->extlen[SADB_EXT_ADDRESS_SRC] < sizeof(struct sadb_address) || |
7790 | mhp->extlen[SADB_EXT_ADDRESS_DST] < sizeof(struct sadb_address)) { |
7791 | ipseclog((LOG_DEBUG, "key_get: invalid message is passed.\n" )); |
7792 | return key_senderror(so, m, EINVAL); |
7793 | } |
7794 | |
7795 | sa0 = (struct sadb_sa *)(void *)mhp->ext[SADB_EXT_SA]; |
7796 | src0 = (struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_SRC]; |
7797 | dst0 = (struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_DST]; |
7798 | ipsec_if = key_get_ipsec_if_from_message(mhp, SADB_X_EXT_IPSECIF); |
7799 | |
7800 | /* XXX boundary check against sa_len */ |
7801 | KEY_SETSECASIDX(proto, IPSEC_MODE_ANY, 0, src0 + 1, dst0 + 1, ipsec_if ? ipsec_if->if_index : 0, &saidx); |
7802 | |
7803 | lck_mtx_lock(sadb_mutex); |
7804 | |
7805 | /* get a SA header */ |
7806 | LIST_FOREACH(sah, &sahtree, chain) { |
7807 | if (sah->state == SADB_SASTATE_DEAD) |
7808 | continue; |
7809 | if (key_cmpsaidx(&sah->saidx, &saidx, CMP_HEAD) == 0) |
7810 | continue; |
7811 | |
7812 | /* get a SA with SPI. */ |
7813 | sav = key_getsavbyspi(sah, sa0->sadb_sa_spi); |
7814 | if (sav) |
7815 | break; |
7816 | } |
7817 | if (sah == NULL) { |
7818 | lck_mtx_unlock(sadb_mutex); |
7819 | ipseclog((LOG_DEBUG, "key_get: no SA found.\n" )); |
7820 | return key_senderror(so, m, ENOENT); |
7821 | } |
7822 | |
7823 | { |
7824 | struct mbuf *n; |
7825 | u_int8_t satype; |
7826 | |
7827 | /* map proto to satype */ |
7828 | if ((satype = key_proto2satype(sah->saidx.proto)) == 0) { |
7829 | lck_mtx_unlock(sadb_mutex); |
7830 | ipseclog((LOG_DEBUG, "key_get: there was invalid proto in SAD.\n" )); |
7831 | return key_senderror(so, m, EINVAL); |
7832 | } |
7833 | lck_mtx_unlock(sadb_mutex); |
7834 | |
7835 | /* create new sadb_msg to reply. */ |
7836 | n = key_setdumpsa(sav, SADB_GET, satype, mhp->msg->sadb_msg_seq, |
7837 | mhp->msg->sadb_msg_pid); |
7838 | |
7839 | |
7840 | |
7841 | if (!n) |
7842 | return key_senderror(so, m, ENOBUFS); |
7843 | |
7844 | m_freem(m); |
7845 | return key_sendup_mbuf(so, n, KEY_SENDUP_ONE); |
7846 | } |
7847 | } |
7848 | |
7849 | /* |
7850 | * get SA stats by spi. |
7851 | * OUT: -1 : not found |
7852 | * 0 : found, arg pointer to a SA stats is updated. |
7853 | */ |
7854 | static int |
7855 | key_getsastatbyspi_one (u_int32_t spi, |
7856 | struct sastat *stat) |
7857 | { |
7858 | struct secashead *sah; |
7859 | struct secasvar *sav = NULL; |
7860 | |
7861 | if ((void *)stat == NULL) { |
7862 | return -1; |
7863 | } |
7864 | |
7865 | lck_mtx_lock(sadb_mutex); |
7866 | |
7867 | /* get a SA header */ |
7868 | LIST_FOREACH(sah, &sahtree, chain) { |
7869 | if (sah->state == SADB_SASTATE_DEAD) |
7870 | continue; |
7871 | |
7872 | /* get a SA with SPI. */ |
7873 | sav = key_getsavbyspi(sah, spi); |
7874 | if (sav) { |
7875 | stat->spi = sav->spi; |
7876 | stat->created = sav->created; |
7877 | if (sav->lft_c) { |
7878 | bcopy(sav->lft_c,&stat->lft_c, sizeof(stat->lft_c)); |
7879 | } else { |
7880 | bzero(&stat->lft_c, sizeof(stat->lft_c)); |
7881 | } |
7882 | lck_mtx_unlock(sadb_mutex); |
7883 | return 0; |
7884 | } |
7885 | } |
7886 | |
7887 | lck_mtx_unlock(sadb_mutex); |
7888 | |
7889 | return -1; |
7890 | } |
7891 | |
7892 | /* |
7893 | * get SA stats collection by indices. |
7894 | * OUT: -1 : not found |
7895 | * 0 : found, arg pointers to a SA stats and 'maximum stats' are updated. |
7896 | */ |
7897 | static int |
7898 | key_getsastatbyspi (struct sastat *stat_arg, |
7899 | u_int32_t max_stat_arg, |
7900 | struct sastat *stat_res, |
7901 | u_int32_t *max_stat_res) |
7902 | { |
7903 | int cur, found = 0; |
7904 | |
7905 | if (stat_arg == NULL || |
7906 | stat_res == NULL || |
7907 | max_stat_res == NULL) { |
7908 | return -1; |
7909 | } |
7910 | |
7911 | for (cur = 0; cur < max_stat_arg; cur++) { |
7912 | if (key_getsastatbyspi_one(stat_arg[cur].spi, |
7913 | &stat_res[found]) == 0) { |
7914 | found++; |
7915 | } |
7916 | } |
7917 | *max_stat_res = found; |
7918 | |
7919 | if (found) { |
7920 | return 0; |
7921 | } |
7922 | return -1; |
7923 | } |
7924 | |
7925 | /* XXX make it sysctl-configurable? */ |
7926 | static void |
7927 | key_getcomb_setlifetime( |
7928 | struct sadb_comb *comb) |
7929 | { |
7930 | |
7931 | comb->sadb_comb_soft_allocations = 1; |
7932 | comb->sadb_comb_hard_allocations = 1; |
7933 | comb->sadb_comb_soft_bytes = 0; |
7934 | comb->sadb_comb_hard_bytes = 0; |
7935 | comb->sadb_comb_hard_addtime = 86400; /* 1 day */ |
7936 | comb->sadb_comb_soft_addtime = comb->sadb_comb_soft_addtime * 80 / 100; |
7937 | comb->sadb_comb_soft_usetime = 28800; /* 8 hours */ |
7938 | comb->sadb_comb_hard_usetime = comb->sadb_comb_hard_usetime * 80 / 100; |
7939 | } |
7940 | |
7941 | #if IPSEC_ESP |
7942 | /* |
7943 | * XXX reorder combinations by preference |
7944 | * XXX no idea if the user wants ESP authentication or not |
7945 | */ |
7946 | static struct mbuf * |
7947 | key_getcomb_esp(void) |
7948 | { |
7949 | struct sadb_comb *comb; |
7950 | const struct esp_algorithm *algo; |
7951 | struct mbuf *result = NULL, *m, *n; |
7952 | int encmin; |
7953 | int i, off, o; |
7954 | int totlen; |
7955 | const int l = PFKEY_ALIGN8(sizeof(struct sadb_comb)); |
7956 | |
7957 | m = NULL; |
7958 | for (i = 1; i <= SADB_EALG_MAX; i++) { |
7959 | algo = esp_algorithm_lookup(i); |
7960 | if (!algo) |
7961 | continue; |
7962 | |
7963 | if (algo->keymax < ipsec_esp_keymin) |
7964 | continue; |
7965 | if (algo->keymin < ipsec_esp_keymin) |
7966 | encmin = ipsec_esp_keymin; |
7967 | else |
7968 | encmin = algo->keymin; |
7969 | |
7970 | if (ipsec_esp_auth) |
7971 | m = key_getcomb_ah(); |
7972 | else { |
7973 | #if DIAGNOSTIC |
7974 | if (l > MLEN) |
7975 | panic("assumption failed in key_getcomb_esp" ); |
7976 | #endif |
7977 | MGET(m, M_WAITOK, MT_DATA); |
7978 | if (m) { |
7979 | M_ALIGN(m, l); |
7980 | m->m_len = l; |
7981 | m->m_next = NULL; |
7982 | bzero(mtod(m, caddr_t), m->m_len); |
7983 | } |
7984 | } |
7985 | if (!m) |
7986 | goto fail; |
7987 | |
7988 | totlen = 0; |
7989 | for (n = m; n; n = n->m_next) |
7990 | totlen += n->m_len; |
7991 | #if DIAGNOSTIC |
7992 | if (totlen % l) |
7993 | panic("assumption failed in key_getcomb_esp" ); |
7994 | #endif |
7995 | |
7996 | for (off = 0; off < totlen; off += l) { |
7997 | n = m_pulldown(m, off, l, &o); |
7998 | if (!n) { |
7999 | /* m is already freed */ |
8000 | goto fail; |
8001 | } |
8002 | comb = (struct sadb_comb *) |
8003 | (void *)(mtod(n, caddr_t) + o); |
8004 | bzero(comb, sizeof(*comb)); |
8005 | key_getcomb_setlifetime(comb); |
8006 | comb->sadb_comb_encrypt = i; |
8007 | comb->sadb_comb_encrypt_minbits = encmin; |
8008 | comb->sadb_comb_encrypt_maxbits = algo->keymax; |
8009 | } |
8010 | |
8011 | if (!result) |
8012 | result = m; |
8013 | else |
8014 | m_cat(result, m); |
8015 | } |
8016 | |
8017 | return result; |
8018 | |
8019 | fail: |
8020 | if (result) |
8021 | m_freem(result); |
8022 | return NULL; |
8023 | } |
8024 | #endif |
8025 | |
8026 | /* |
8027 | * XXX reorder combinations by preference |
8028 | */ |
8029 | static struct mbuf * |
8030 | key_getcomb_ah(void) |
8031 | { |
8032 | struct sadb_comb *comb; |
8033 | const struct ah_algorithm *algo; |
8034 | struct mbuf *m; |
8035 | int keymin; |
8036 | int i; |
8037 | const int l = PFKEY_ALIGN8(sizeof(struct sadb_comb)); |
8038 | |
8039 | m = NULL; |
8040 | for (i = 1; i <= SADB_AALG_MAX; i++) { |
8041 | #if 1 |
8042 | /* we prefer HMAC algorithms, not old algorithms */ |
8043 | if (i != SADB_AALG_SHA1HMAC && i != SADB_AALG_MD5HMAC) |
8044 | continue; |
8045 | #endif |
8046 | algo = ah_algorithm_lookup(i); |
8047 | if (!algo) |
8048 | continue; |
8049 | |
8050 | if (algo->keymax < ipsec_ah_keymin) |
8051 | continue; |
8052 | if (algo->keymin < ipsec_ah_keymin) |
8053 | keymin = ipsec_ah_keymin; |
8054 | else |
8055 | keymin = algo->keymin; |
8056 | |
8057 | if (!m) { |
8058 | #if DIAGNOSTIC |
8059 | if (l > MLEN) |
8060 | panic("assumption failed in key_getcomb_ah" ); |
8061 | #endif |
8062 | MGET(m, M_WAITOK, MT_DATA); |
8063 | if (m) { |
8064 | M_ALIGN(m, l); |
8065 | m->m_len = l; |
8066 | m->m_next = NULL; |
8067 | } |
8068 | } else |
8069 | M_PREPEND(m, l, M_WAITOK, 1); |
8070 | if (!m) |
8071 | return NULL; |
8072 | |
8073 | comb = mtod(m, struct sadb_comb *); |
8074 | bzero(comb, sizeof(*comb)); |
8075 | key_getcomb_setlifetime(comb); |
8076 | comb->sadb_comb_auth = i; |
8077 | comb->sadb_comb_auth_minbits = keymin; |
8078 | comb->sadb_comb_auth_maxbits = algo->keymax; |
8079 | } |
8080 | |
8081 | return m; |
8082 | } |
8083 | |
8084 | /* |
8085 | * not really an official behavior. discussed in pf_key@inner.net in Sep2000. |
8086 | * XXX reorder combinations by preference |
8087 | */ |
8088 | static struct mbuf * |
8089 | key_getcomb_ipcomp(void) |
8090 | { |
8091 | struct sadb_comb *comb; |
8092 | const struct ipcomp_algorithm *algo; |
8093 | struct mbuf *m; |
8094 | int i; |
8095 | const int l = PFKEY_ALIGN8(sizeof(struct sadb_comb)); |
8096 | |
8097 | m = NULL; |
8098 | for (i = 1; i <= SADB_X_CALG_MAX; i++) { |
8099 | algo = ipcomp_algorithm_lookup(i); |
8100 | if (!algo) |
8101 | continue; |
8102 | |
8103 | if (!m) { |
8104 | #if DIAGNOSTIC |
8105 | if (l > MLEN) |
8106 | panic("assumption failed in key_getcomb_ipcomp" ); |
8107 | #endif |
8108 | MGET(m, M_WAITOK, MT_DATA); |
8109 | if (m) { |
8110 | M_ALIGN(m, l); |
8111 | m->m_len = l; |
8112 | m->m_next = NULL; |
8113 | } |
8114 | } else |
8115 | M_PREPEND(m, l, M_WAITOK, 1); |
8116 | if (!m) |
8117 | return NULL; |
8118 | |
8119 | comb = mtod(m, struct sadb_comb *); |
8120 | bzero(comb, sizeof(*comb)); |
8121 | key_getcomb_setlifetime(comb); |
8122 | comb->sadb_comb_encrypt = i; |
8123 | /* what should we set into sadb_comb_*_{min,max}bits? */ |
8124 | } |
8125 | |
8126 | return m; |
8127 | } |
8128 | |
8129 | /* |
8130 | * XXX no way to pass mode (transport/tunnel) to userland |
8131 | * XXX replay checking? |
8132 | * XXX sysctl interface to ipsec_{ah,esp}_keymin |
8133 | */ |
8134 | static struct mbuf * |
8135 | key_getprop( |
8136 | const struct secasindex *saidx) |
8137 | { |
8138 | struct sadb_prop *prop; |
8139 | struct mbuf *m, *n; |
8140 | const int l = PFKEY_ALIGN8(sizeof(struct sadb_prop)); |
8141 | int totlen; |
8142 | |
8143 | switch (saidx->proto) { |
8144 | #if IPSEC_ESP |
8145 | case IPPROTO_ESP: |
8146 | m = key_getcomb_esp(); |
8147 | break; |
8148 | #endif |
8149 | case IPPROTO_AH: |
8150 | m = key_getcomb_ah(); |
8151 | break; |
8152 | case IPPROTO_IPCOMP: |
8153 | m = key_getcomb_ipcomp(); |
8154 | break; |
8155 | default: |
8156 | return NULL; |
8157 | } |
8158 | |
8159 | if (!m) |
8160 | return NULL; |
8161 | M_PREPEND(m, l, M_WAITOK, 1); |
8162 | if (!m) |
8163 | return NULL; |
8164 | |
8165 | totlen = 0; |
8166 | for (n = m; n; n = n->m_next) |
8167 | totlen += n->m_len; |
8168 | |
8169 | prop = mtod(m, struct sadb_prop *); |
8170 | bzero(prop, sizeof(*prop)); |
8171 | prop->sadb_prop_len = PFKEY_UNIT64(totlen); |
8172 | prop->sadb_prop_exttype = SADB_EXT_PROPOSAL; |
8173 | prop->sadb_prop_replay = 32; /* XXX */ |
8174 | |
8175 | return m; |
8176 | } |
8177 | |
8178 | /* |
8179 | * SADB_ACQUIRE processing called by key_checkrequest() and key_acquire2(). |
8180 | * send |
8181 | * <base, SA, address(SD), (address(P)), x_policy, |
8182 | * (identity(SD),) (sensitivity,) proposal> |
8183 | * to KMD, and expect to receive |
8184 | * <base> with SADB_ACQUIRE if error occurred, |
8185 | * or |
8186 | * <base, src address, dst address, (SPI range)> with SADB_GETSPI |
8187 | * from KMD by PF_KEY. |
8188 | * |
8189 | * XXX x_policy is outside of RFC2367 (KAME extension). |
8190 | * XXX sensitivity is not supported. |
8191 | * XXX for ipcomp, RFC2367 does not define how to fill in proposal. |
8192 | * see comment for key_getcomb_ipcomp(). |
8193 | * |
8194 | * OUT: |
8195 | * 0 : succeed |
8196 | * others: error number |
8197 | */ |
8198 | static int |
8199 | key_acquire( |
8200 | struct secasindex *saidx, |
8201 | struct secpolicy *sp) |
8202 | { |
8203 | struct mbuf *result = NULL, *m; |
8204 | #ifndef IPSEC_NONBLOCK_ACQUIRE |
8205 | struct secacq *newacq; |
8206 | #endif |
8207 | u_int8_t satype; |
8208 | int error = -1; |
8209 | u_int32_t seq; |
8210 | |
8211 | LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED); |
8212 | |
8213 | /* sanity check */ |
8214 | if (saidx == NULL) |
8215 | panic("key_acquire: NULL pointer is passed.\n" ); |
8216 | if ((satype = key_proto2satype(saidx->proto)) == 0) |
8217 | panic("key_acquire: invalid proto is passed.\n" ); |
8218 | |
8219 | #ifndef IPSEC_NONBLOCK_ACQUIRE |
8220 | /* |
8221 | * We never do anything about acquirng SA. There is anather |
8222 | * solution that kernel blocks to send SADB_ACQUIRE message until |
8223 | * getting something message from IKEd. In later case, to be |
8224 | * managed with ACQUIRING list. |
8225 | */ |
8226 | /* get a entry to check whether sending message or not. */ |
8227 | lck_mtx_lock(sadb_mutex); |
8228 | if ((newacq = key_getacq(saidx)) != NULL) { |
8229 | if (key_blockacq_count < newacq->count) { |
8230 | /* reset counter and do send message. */ |
8231 | newacq->count = 0; |
8232 | } else { |
8233 | /* increment counter and do nothing. */ |
8234 | newacq->count++; |
8235 | lck_mtx_unlock(sadb_mutex); |
8236 | return 0; |
8237 | } |
8238 | } else { |
8239 | /* make new entry for blocking to send SADB_ACQUIRE. */ |
8240 | if ((newacq = key_newacq(saidx)) == NULL) { |
8241 | lck_mtx_unlock(sadb_mutex); |
8242 | return ENOBUFS; |
8243 | } |
8244 | |
8245 | /* add to acqtree */ |
8246 | LIST_INSERT_HEAD(&acqtree, newacq, chain); |
8247 | key_start_timehandler(); |
8248 | } |
8249 | seq = newacq->seq; |
8250 | lck_mtx_unlock(sadb_mutex); |
8251 | |
8252 | #else |
8253 | seq = (acq_seq = (acq_seq == ~0 ? 1 : ++acq_seq)); |
8254 | #endif |
8255 | m = key_setsadbmsg(SADB_ACQUIRE, 0, satype, seq, 0, 0); |
8256 | if (!m) { |
8257 | error = ENOBUFS; |
8258 | goto fail; |
8259 | } |
8260 | result = m; |
8261 | |
8262 | /* set sadb_address for saidx's. */ |
8263 | m = key_setsadbaddr(SADB_EXT_ADDRESS_SRC, |
8264 | (struct sockaddr *)&saidx->src, FULLMASK, IPSEC_ULPROTO_ANY); |
8265 | if (!m) { |
8266 | error = ENOBUFS; |
8267 | goto fail; |
8268 | } |
8269 | m_cat(result, m); |
8270 | |
8271 | m = key_setsadbaddr(SADB_EXT_ADDRESS_DST, |
8272 | (struct sockaddr *)&saidx->dst, FULLMASK, IPSEC_ULPROTO_ANY); |
8273 | if (!m) { |
8274 | error = ENOBUFS; |
8275 | goto fail; |
8276 | } |
8277 | m_cat(result, m); |
8278 | |
8279 | /* XXX proxy address (optional) */ |
8280 | |
8281 | /* set sadb_x_policy */ |
8282 | if (sp) { |
8283 | m = key_setsadbxpolicy(sp->policy, sp->spidx.dir, sp->id); |
8284 | if (!m) { |
8285 | error = ENOBUFS; |
8286 | goto fail; |
8287 | } |
8288 | m_cat(result, m); |
8289 | } |
8290 | |
8291 | /* XXX identity (optional) */ |
8292 | #if 0 |
8293 | if (idexttype && fqdn) { |
8294 | /* create identity extension (FQDN) */ |
8295 | struct sadb_ident *id; |
8296 | int fqdnlen; |
8297 | |
8298 | fqdnlen = strlen(fqdn) + 1; /* +1 for terminating-NUL */ |
8299 | id = (struct sadb_ident *)p; |
8300 | bzero(id, sizeof(*id) + PFKEY_ALIGN8(fqdnlen)); |
8301 | id->sadb_ident_len = PFKEY_UNIT64(sizeof(*id) + PFKEY_ALIGN8(fqdnlen)); |
8302 | id->sadb_ident_exttype = idexttype; |
8303 | id->sadb_ident_type = SADB_IDENTTYPE_FQDN; |
8304 | bcopy(fqdn, id + 1, fqdnlen); |
8305 | p += sizeof(struct sadb_ident) + PFKEY_ALIGN8(fqdnlen); |
8306 | } |
8307 | |
8308 | if (idexttype) { |
8309 | /* create identity extension (USERFQDN) */ |
8310 | struct sadb_ident *id; |
8311 | int userfqdnlen; |
8312 | |
8313 | if (userfqdn) { |
8314 | /* +1 for terminating-NUL */ |
8315 | userfqdnlen = strlen(userfqdn) + 1; |
8316 | } else |
8317 | userfqdnlen = 0; |
8318 | id = (struct sadb_ident *)p; |
8319 | bzero(id, sizeof(*id) + PFKEY_ALIGN8(userfqdnlen)); |
8320 | id->sadb_ident_len = PFKEY_UNIT64(sizeof(*id) + PFKEY_ALIGN8(userfqdnlen)); |
8321 | id->sadb_ident_exttype = idexttype; |
8322 | id->sadb_ident_type = SADB_IDENTTYPE_USERFQDN; |
8323 | /* XXX is it correct? */ |
8324 | if (curproc && curproc->p_cred) |
8325 | id->sadb_ident_id = curproc->p_cred->p_ruid; |
8326 | if (userfqdn && userfqdnlen) |
8327 | bcopy(userfqdn, id + 1, userfqdnlen); |
8328 | p += sizeof(struct sadb_ident) + PFKEY_ALIGN8(userfqdnlen); |
8329 | } |
8330 | #endif |
8331 | |
8332 | /* XXX sensitivity (optional) */ |
8333 | |
8334 | /* create proposal/combination extension */ |
8335 | m = key_getprop(saidx); |
8336 | #if 0 |
8337 | /* |
8338 | * spec conformant: always attach proposal/combination extension, |
8339 | * the problem is that we have no way to attach it for ipcomp, |
8340 | * due to the way sadb_comb is declared in RFC2367. |
8341 | */ |
8342 | if (!m) { |
8343 | error = ENOBUFS; |
8344 | goto fail; |
8345 | } |
8346 | m_cat(result, m); |
8347 | #else |
8348 | /* |
8349 | * outside of spec; make proposal/combination extension optional. |
8350 | */ |
8351 | if (m) |
8352 | m_cat(result, m); |
8353 | #endif |
8354 | |
8355 | if ((result->m_flags & M_PKTHDR) == 0) { |
8356 | error = EINVAL; |
8357 | goto fail; |
8358 | } |
8359 | |
8360 | if (result->m_len < sizeof(struct sadb_msg)) { |
8361 | result = m_pullup(result, sizeof(struct sadb_msg)); |
8362 | if (result == NULL) { |
8363 | error = ENOBUFS; |
8364 | goto fail; |
8365 | } |
8366 | } |
8367 | |
8368 | result->m_pkthdr.len = 0; |
8369 | for (m = result; m; m = m->m_next) |
8370 | result->m_pkthdr.len += m->m_len; |
8371 | |
8372 | mtod(result, struct sadb_msg *)->sadb_msg_len = |
8373 | PFKEY_UNIT64(result->m_pkthdr.len); |
8374 | |
8375 | return key_sendup_mbuf(NULL, result, KEY_SENDUP_REGISTERED); |
8376 | |
8377 | fail: |
8378 | if (result) |
8379 | m_freem(result); |
8380 | return error; |
8381 | } |
8382 | |
8383 | #ifndef IPSEC_NONBLOCK_ACQUIRE |
8384 | static struct secacq * |
8385 | key_newacq( |
8386 | struct secasindex *saidx) |
8387 | { |
8388 | struct secacq *newacq; |
8389 | struct timeval tv; |
8390 | |
8391 | /* get new entry */ |
8392 | KMALLOC_NOWAIT(newacq, struct secacq *, sizeof(struct secacq)); |
8393 | if (newacq == NULL) { |
8394 | lck_mtx_unlock(sadb_mutex); |
8395 | KMALLOC_WAIT(newacq, struct secacq *, sizeof(struct secacq)); |
8396 | lck_mtx_lock(sadb_mutex); |
8397 | if (newacq == NULL) { |
8398 | ipseclog((LOG_DEBUG, "key_newacq: No more memory.\n" )); |
8399 | return NULL; |
8400 | } |
8401 | } |
8402 | bzero(newacq, sizeof(*newacq)); |
8403 | |
8404 | /* copy secindex */ |
8405 | bcopy(saidx, &newacq->saidx, sizeof(newacq->saidx)); |
8406 | newacq->seq = (acq_seq == ~0 ? 1 : ++acq_seq); |
8407 | microtime(&tv); |
8408 | newacq->created = tv.tv_sec; |
8409 | newacq->count = 0; |
8410 | |
8411 | return newacq; |
8412 | } |
8413 | |
8414 | static struct secacq * |
8415 | key_getacq( |
8416 | struct secasindex *saidx) |
8417 | { |
8418 | struct secacq *acq; |
8419 | |
8420 | LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_OWNED); |
8421 | |
8422 | LIST_FOREACH(acq, &acqtree, chain) { |
8423 | if (key_cmpsaidx(saidx, &acq->saidx, CMP_EXACTLY)) |
8424 | return acq; |
8425 | } |
8426 | |
8427 | return NULL; |
8428 | } |
8429 | |
8430 | static struct secacq * |
8431 | key_getacqbyseq( |
8432 | u_int32_t seq) |
8433 | { |
8434 | struct secacq *acq; |
8435 | |
8436 | LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_OWNED); |
8437 | |
8438 | LIST_FOREACH(acq, &acqtree, chain) { |
8439 | if (acq->seq == seq) |
8440 | return acq; |
8441 | } |
8442 | |
8443 | return NULL; |
8444 | } |
8445 | #endif |
8446 | |
8447 | static struct secspacq * |
8448 | key_newspacq( |
8449 | struct secpolicyindex *spidx) |
8450 | { |
8451 | struct secspacq *acq; |
8452 | struct timeval tv; |
8453 | |
8454 | /* get new entry */ |
8455 | KMALLOC_NOWAIT(acq, struct secspacq *, sizeof(struct secspacq)); |
8456 | if (acq == NULL) { |
8457 | lck_mtx_unlock(sadb_mutex); |
8458 | KMALLOC_WAIT(acq, struct secspacq *, sizeof(struct secspacq)); |
8459 | lck_mtx_lock(sadb_mutex); |
8460 | if (acq == NULL) { |
8461 | ipseclog((LOG_DEBUG, "key_newspacq: No more memory.\n" )); |
8462 | return NULL; |
8463 | } |
8464 | } |
8465 | bzero(acq, sizeof(*acq)); |
8466 | |
8467 | /* copy secindex */ |
8468 | bcopy(spidx, &acq->spidx, sizeof(acq->spidx)); |
8469 | microtime(&tv); |
8470 | acq->created = tv.tv_sec; |
8471 | acq->count = 0; |
8472 | |
8473 | return acq; |
8474 | } |
8475 | |
8476 | static struct secspacq * |
8477 | key_getspacq( |
8478 | struct secpolicyindex *spidx) |
8479 | { |
8480 | struct secspacq *acq; |
8481 | |
8482 | LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_OWNED); |
8483 | |
8484 | LIST_FOREACH(acq, &spacqtree, chain) { |
8485 | if (key_cmpspidx_exactly(spidx, &acq->spidx)) |
8486 | return acq; |
8487 | } |
8488 | |
8489 | return NULL; |
8490 | } |
8491 | |
8492 | /* |
8493 | * SADB_ACQUIRE processing, |
8494 | * in first situation, is receiving |
8495 | * <base> |
8496 | * from the ikmpd, and clear sequence of its secasvar entry. |
8497 | * |
8498 | * In second situation, is receiving |
8499 | * <base, address(SD), (address(P),) (identity(SD),) (sensitivity,) proposal> |
8500 | * from a user land process, and return |
8501 | * <base, address(SD), (address(P),) (identity(SD),) (sensitivity,) proposal> |
8502 | * to the socket. |
8503 | * |
8504 | * m will always be freed. |
8505 | */ |
8506 | static int |
8507 | key_acquire2( |
8508 | struct socket *so, |
8509 | struct mbuf *m, |
8510 | const struct sadb_msghdr *mhp) |
8511 | { |
8512 | const struct sadb_address *src0, *dst0; |
8513 | ifnet_t ipsec_if = NULL; |
8514 | struct secasindex saidx; |
8515 | struct secashead *sah; |
8516 | u_int16_t proto; |
8517 | int error; |
8518 | |
8519 | |
8520 | /* sanity check */ |
8521 | if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) |
8522 | panic("key_acquire2: NULL pointer is passed.\n" ); |
8523 | |
8524 | /* |
8525 | * Error message from KMd. |
8526 | * We assume that if error was occurred in IKEd, the length of PFKEY |
8527 | * message is equal to the size of sadb_msg structure. |
8528 | * We do not raise error even if error occurred in this function. |
8529 | */ |
8530 | lck_mtx_lock(sadb_mutex); |
8531 | |
8532 | if (mhp->msg->sadb_msg_len == PFKEY_UNIT64(sizeof(struct sadb_msg))) { |
8533 | #ifndef IPSEC_NONBLOCK_ACQUIRE |
8534 | struct secacq *acq; |
8535 | struct timeval tv; |
8536 | |
8537 | /* check sequence number */ |
8538 | if (mhp->msg->sadb_msg_seq == 0) { |
8539 | lck_mtx_unlock(sadb_mutex); |
8540 | ipseclog((LOG_DEBUG, "key_acquire2: must specify sequence number.\n" )); |
8541 | m_freem(m); |
8542 | return 0; |
8543 | } |
8544 | |
8545 | if ((acq = key_getacqbyseq(mhp->msg->sadb_msg_seq)) == NULL) { |
8546 | /* |
8547 | * the specified larval SA is already gone, or we got |
8548 | * a bogus sequence number. we can silently ignore it. |
8549 | */ |
8550 | lck_mtx_unlock(sadb_mutex); |
8551 | m_freem(m); |
8552 | return 0; |
8553 | } |
8554 | |
8555 | /* reset acq counter in order to deletion by timehander. */ |
8556 | microtime(&tv); |
8557 | acq->created = tv.tv_sec; |
8558 | acq->count = 0; |
8559 | #endif |
8560 | lck_mtx_unlock(sadb_mutex); |
8561 | m_freem(m); |
8562 | return 0; |
8563 | } |
8564 | |
8565 | /* |
8566 | * This message is from user land. |
8567 | */ |
8568 | |
8569 | /* map satype to proto */ |
8570 | if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) { |
8571 | lck_mtx_unlock(sadb_mutex); |
8572 | ipseclog((LOG_DEBUG, "key_acquire2: invalid satype is passed.\n" )); |
8573 | return key_senderror(so, m, EINVAL); |
8574 | } |
8575 | |
8576 | if (mhp->ext[SADB_EXT_ADDRESS_SRC] == NULL || |
8577 | mhp->ext[SADB_EXT_ADDRESS_DST] == NULL || |
8578 | mhp->ext[SADB_EXT_PROPOSAL] == NULL) { |
8579 | /* error */ |
8580 | lck_mtx_unlock(sadb_mutex); |
8581 | ipseclog((LOG_DEBUG, "key_acquire2: invalid message is passed.\n" )); |
8582 | return key_senderror(so, m, EINVAL); |
8583 | } |
8584 | if (mhp->extlen[SADB_EXT_ADDRESS_SRC] < sizeof(struct sadb_address) || |
8585 | mhp->extlen[SADB_EXT_ADDRESS_DST] < sizeof(struct sadb_address) || |
8586 | mhp->extlen[SADB_EXT_PROPOSAL] < sizeof(struct sadb_prop)) { |
8587 | /* error */ |
8588 | lck_mtx_unlock(sadb_mutex); |
8589 | ipseclog((LOG_DEBUG, "key_acquire2: invalid message is passed.\n" )); |
8590 | return key_senderror(so, m, EINVAL); |
8591 | } |
8592 | |
8593 | src0 = (const struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_SRC]; |
8594 | dst0 = (const struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_DST]; |
8595 | ipsec_if = key_get_ipsec_if_from_message(mhp, SADB_X_EXT_IPSECIF); |
8596 | |
8597 | /* XXX boundary check against sa_len */ |
8598 | /* cast warnings */ |
8599 | KEY_SETSECASIDX(proto, IPSEC_MODE_ANY, 0, src0 + 1, dst0 + 1, ipsec_if ? ipsec_if->if_index : 0, &saidx); |
8600 | |
8601 | /* get a SA index */ |
8602 | LIST_FOREACH(sah, &sahtree, chain) { |
8603 | if (sah->state == SADB_SASTATE_DEAD) |
8604 | continue; |
8605 | if (key_cmpsaidx(&sah->saidx, &saidx, CMP_MODE | CMP_REQID)) |
8606 | break; |
8607 | } |
8608 | if (sah != NULL) { |
8609 | lck_mtx_unlock(sadb_mutex); |
8610 | ipseclog((LOG_DEBUG, "key_acquire2: a SA exists already.\n" )); |
8611 | return key_senderror(so, m, EEXIST); |
8612 | } |
8613 | lck_mtx_unlock(sadb_mutex); |
8614 | error = key_acquire(&saidx, NULL); |
8615 | if (error != 0) { |
8616 | ipseclog((LOG_DEBUG, "key_acquire2: error %d returned " |
8617 | "from key_acquire.\n" , mhp->msg->sadb_msg_errno)); |
8618 | return key_senderror(so, m, error); |
8619 | } |
8620 | |
8621 | return key_sendup_mbuf(so, m, KEY_SENDUP_REGISTERED); |
8622 | } |
8623 | |
8624 | /* |
8625 | * SADB_REGISTER processing. |
8626 | * If SATYPE_UNSPEC has been passed as satype, only return sadb_supported. |
8627 | * receive |
8628 | * <base> |
8629 | * from the ikmpd, and register a socket to send PF_KEY messages, |
8630 | * and send |
8631 | * <base, supported> |
8632 | * to KMD by PF_KEY. |
8633 | * If socket is detached, must free from regnode. |
8634 | * |
8635 | * m will always be freed. |
8636 | */ |
8637 | static int |
8638 | key_register( |
8639 | struct socket *so, |
8640 | struct mbuf *m, |
8641 | const struct sadb_msghdr *mhp) |
8642 | { |
8643 | struct secreg *reg, *newreg = 0; |
8644 | |
8645 | /* sanity check */ |
8646 | if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) |
8647 | panic("key_register: NULL pointer is passed.\n" ); |
8648 | |
8649 | /* check for invalid register message */ |
8650 | if (mhp->msg->sadb_msg_satype >= sizeof(regtree)/sizeof(regtree[0])) |
8651 | return key_senderror(so, m, EINVAL); |
8652 | |
8653 | /* When SATYPE_UNSPEC is specified, only return sadb_supported. */ |
8654 | if (mhp->msg->sadb_msg_satype == SADB_SATYPE_UNSPEC) |
8655 | goto setmsg; |
8656 | |
8657 | /* create regnode */ |
8658 | KMALLOC_WAIT(newreg, struct secreg *, sizeof(*newreg)); |
8659 | if (newreg == NULL) { |
8660 | ipseclog((LOG_DEBUG, "key_register: No more memory.\n" )); |
8661 | return key_senderror(so, m, ENOBUFS); |
8662 | } |
8663 | bzero((caddr_t)newreg, sizeof(*newreg)); |
8664 | |
8665 | lck_mtx_lock(sadb_mutex); |
8666 | /* check whether existing or not */ |
8667 | LIST_FOREACH(reg, ®tree[mhp->msg->sadb_msg_satype], chain) { |
8668 | if (reg->so == so) { |
8669 | lck_mtx_unlock(sadb_mutex); |
8670 | ipseclog((LOG_DEBUG, "key_register: socket exists already.\n" )); |
8671 | KFREE(newreg); |
8672 | return key_senderror(so, m, EEXIST); |
8673 | } |
8674 | } |
8675 | |
8676 | socket_lock(so, 1); |
8677 | newreg->so = so; |
8678 | ((struct keycb *)sotorawcb(so))->kp_registered++; |
8679 | socket_unlock(so, 1); |
8680 | |
8681 | /* add regnode to regtree. */ |
8682 | LIST_INSERT_HEAD(®tree[mhp->msg->sadb_msg_satype], newreg, chain); |
8683 | lck_mtx_unlock(sadb_mutex); |
8684 | setmsg: |
8685 | { |
8686 | struct mbuf *n; |
8687 | struct sadb_msg *newmsg; |
8688 | struct sadb_supported *sup; |
8689 | u_int len, alen, elen; |
8690 | int off; |
8691 | int i; |
8692 | struct sadb_alg *alg; |
8693 | |
8694 | /* create new sadb_msg to reply. */ |
8695 | alen = 0; |
8696 | for (i = 1; i <= SADB_AALG_MAX; i++) { |
8697 | if (ah_algorithm_lookup(i)) |
8698 | alen += sizeof(struct sadb_alg); |
8699 | } |
8700 | if (alen) |
8701 | alen += sizeof(struct sadb_supported); |
8702 | elen = 0; |
8703 | #if IPSEC_ESP |
8704 | for (i = 1; i <= SADB_EALG_MAX; i++) { |
8705 | if (esp_algorithm_lookup(i)) |
8706 | elen += sizeof(struct sadb_alg); |
8707 | } |
8708 | if (elen) |
8709 | elen += sizeof(struct sadb_supported); |
8710 | #endif |
8711 | |
8712 | len = sizeof(struct sadb_msg) + alen + elen; |
8713 | |
8714 | if (len > MCLBYTES) |
8715 | return key_senderror(so, m, ENOBUFS); |
8716 | |
8717 | MGETHDR(n, M_WAITOK, MT_DATA); |
8718 | if (n && len > MHLEN) { |
8719 | MCLGET(n, M_WAITOK); |
8720 | if ((n->m_flags & M_EXT) == 0) { |
8721 | m_freem(n); |
8722 | n = NULL; |
8723 | } |
8724 | } |
8725 | if (!n) |
8726 | return key_senderror(so, m, ENOBUFS); |
8727 | |
8728 | n->m_pkthdr.len = n->m_len = len; |
8729 | n->m_next = NULL; |
8730 | off = 0; |
8731 | |
8732 | m_copydata(m, 0, sizeof(struct sadb_msg), mtod(n, caddr_t) + off); |
8733 | newmsg = mtod(n, struct sadb_msg *); |
8734 | newmsg->sadb_msg_errno = 0; |
8735 | newmsg->sadb_msg_len = PFKEY_UNIT64(len); |
8736 | off += PFKEY_ALIGN8(sizeof(struct sadb_msg)); |
8737 | |
8738 | /* for authentication algorithm */ |
8739 | if (alen) { |
8740 | sup = (struct sadb_supported *)(void *)(mtod(n, caddr_t) + off); |
8741 | sup->sadb_supported_len = PFKEY_UNIT64(alen); |
8742 | sup->sadb_supported_exttype = SADB_EXT_SUPPORTED_AUTH; |
8743 | off += PFKEY_ALIGN8(sizeof(*sup)); |
8744 | |
8745 | for (i = 1; i <= SADB_AALG_MAX; i++) { |
8746 | const struct ah_algorithm *aalgo; |
8747 | |
8748 | aalgo = ah_algorithm_lookup(i); |
8749 | if (!aalgo) |
8750 | continue; |
8751 | alg = (struct sadb_alg *) |
8752 | (void *)(mtod(n, caddr_t) + off); |
8753 | alg->sadb_alg_id = i; |
8754 | alg->sadb_alg_ivlen = 0; |
8755 | alg->sadb_alg_minbits = aalgo->keymin; |
8756 | alg->sadb_alg_maxbits = aalgo->keymax; |
8757 | off += PFKEY_ALIGN8(sizeof(*alg)); |
8758 | } |
8759 | } |
8760 | |
8761 | #if IPSEC_ESP |
8762 | /* for encryption algorithm */ |
8763 | if (elen) { |
8764 | sup = (struct sadb_supported *)(void *)(mtod(n, caddr_t) + off); |
8765 | sup->sadb_supported_len = PFKEY_UNIT64(elen); |
8766 | sup->sadb_supported_exttype = SADB_EXT_SUPPORTED_ENCRYPT; |
8767 | off += PFKEY_ALIGN8(sizeof(*sup)); |
8768 | |
8769 | for (i = 1; i <= SADB_EALG_MAX; i++) { |
8770 | const struct esp_algorithm *ealgo; |
8771 | |
8772 | ealgo = esp_algorithm_lookup(i); |
8773 | if (!ealgo) |
8774 | continue; |
8775 | alg = (struct sadb_alg *) |
8776 | (void *)(mtod(n, caddr_t) + off); |
8777 | alg->sadb_alg_id = i; |
8778 | if (ealgo && ealgo->ivlen) { |
8779 | /* |
8780 | * give NULL to get the value preferred by |
8781 | * algorithm XXX SADB_X_EXT_DERIV ? |
8782 | */ |
8783 | alg->sadb_alg_ivlen = |
8784 | (*ealgo->ivlen)(ealgo, NULL); |
8785 | } else |
8786 | alg->sadb_alg_ivlen = 0; |
8787 | alg->sadb_alg_minbits = ealgo->keymin; |
8788 | alg->sadb_alg_maxbits = ealgo->keymax; |
8789 | off += PFKEY_ALIGN8(sizeof(struct sadb_alg)); |
8790 | } |
8791 | } |
8792 | #endif |
8793 | |
8794 | #if DIGAGNOSTIC |
8795 | if (off != len) |
8796 | panic("length assumption failed in key_register" ); |
8797 | #endif |
8798 | |
8799 | m_freem(m); |
8800 | return key_sendup_mbuf(so, n, KEY_SENDUP_REGISTERED); |
8801 | } |
8802 | } |
8803 | |
8804 | static void |
8805 | key_delete_all_for_socket (struct socket *so) |
8806 | { |
8807 | struct secashead *sah, *nextsah; |
8808 | struct secasvar *sav, *nextsav; |
8809 | u_int stateidx; |
8810 | u_int state; |
8811 | |
8812 | for (sah = LIST_FIRST(&sahtree); |
8813 | sah != NULL; |
8814 | sah = nextsah) { |
8815 | nextsah = LIST_NEXT(sah, chain); |
8816 | for (stateidx = 0; stateidx < _ARRAYLEN(saorder_state_alive); stateidx++) { |
8817 | state = saorder_state_any[stateidx]; |
8818 | for (sav = LIST_FIRST(&sah->savtree[state]); sav != NULL; sav = nextsav) { |
8819 | nextsav = LIST_NEXT(sav, chain); |
8820 | if (sav->flags2 & SADB_X_EXT_SA2_DELETE_ON_DETACH && |
8821 | sav->so == so) { |
8822 | key_sa_chgstate(sav, SADB_SASTATE_DEAD); |
8823 | key_freesav(sav, KEY_SADB_LOCKED); |
8824 | } |
8825 | } |
8826 | } |
8827 | } |
8828 | } |
8829 | |
8830 | /* |
8831 | * free secreg entry registered. |
8832 | * XXX: I want to do free a socket marked done SADB_RESIGER to socket. |
8833 | */ |
8834 | void |
8835 | key_freereg( |
8836 | struct socket *so) |
8837 | { |
8838 | struct secreg *reg; |
8839 | int i; |
8840 | |
8841 | /* sanity check */ |
8842 | if (so == NULL) |
8843 | panic("key_freereg: NULL pointer is passed.\n" ); |
8844 | |
8845 | /* |
8846 | * check whether existing or not. |
8847 | * check all type of SA, because there is a potential that |
8848 | * one socket is registered to multiple type of SA. |
8849 | */ |
8850 | lck_mtx_lock(sadb_mutex); |
8851 | key_delete_all_for_socket(so); |
8852 | for (i = 0; i <= SADB_SATYPE_MAX; i++) { |
8853 | LIST_FOREACH(reg, ®tree[i], chain) { |
8854 | if (reg->so == so |
8855 | && __LIST_CHAINED(reg)) { |
8856 | LIST_REMOVE(reg, chain); |
8857 | KFREE(reg); |
8858 | break; |
8859 | } |
8860 | } |
8861 | } |
8862 | lck_mtx_unlock(sadb_mutex); |
8863 | return; |
8864 | } |
8865 | |
8866 | /* |
8867 | * SADB_EXPIRE processing |
8868 | * send |
8869 | * <base, SA, SA2, lifetime(C and one of HS), address(SD)> |
8870 | * to KMD by PF_KEY. |
8871 | * NOTE: We send only soft lifetime extension. |
8872 | * |
8873 | * OUT: 0 : succeed |
8874 | * others : error number |
8875 | */ |
8876 | static int |
8877 | key_expire( |
8878 | struct secasvar *sav) |
8879 | { |
8880 | int satype; |
8881 | struct mbuf *result = NULL, *m; |
8882 | int len; |
8883 | int error = -1; |
8884 | struct sadb_lifetime *lt; |
8885 | |
8886 | LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED); |
8887 | |
8888 | /* sanity check */ |
8889 | if (sav == NULL) |
8890 | panic("key_expire: NULL pointer is passed.\n" ); |
8891 | if (sav->sah == NULL) |
8892 | panic("key_expire: Why was SA index in SA NULL.\n" ); |
8893 | if ((satype = key_proto2satype(sav->sah->saidx.proto)) == 0) |
8894 | panic("key_expire: invalid proto is passed.\n" ); |
8895 | |
8896 | /* set msg header */ |
8897 | m = key_setsadbmsg(SADB_EXPIRE, 0, satype, sav->seq, 0, sav->refcnt); |
8898 | if (!m) { |
8899 | error = ENOBUFS; |
8900 | goto fail; |
8901 | } |
8902 | result = m; |
8903 | |
8904 | /* create SA extension */ |
8905 | m = key_setsadbsa(sav); |
8906 | if (!m) { |
8907 | error = ENOBUFS; |
8908 | goto fail; |
8909 | } |
8910 | m_cat(result, m); |
8911 | |
8912 | /* create SA extension */ |
8913 | m = key_setsadbxsa2(sav->sah->saidx.mode, |
8914 | sav->replay ? sav->replay->count : 0, |
8915 | sav->sah->saidx.reqid, |
8916 | sav->flags2); |
8917 | if (!m) { |
8918 | error = ENOBUFS; |
8919 | goto fail; |
8920 | } |
8921 | m_cat(result, m); |
8922 | |
8923 | /* create lifetime extension (current and soft) */ |
8924 | len = PFKEY_ALIGN8(sizeof(*lt)) * 2; |
8925 | m = key_alloc_mbuf(len); |
8926 | if (!m || m->m_next) { /*XXX*/ |
8927 | if (m) |
8928 | m_freem(m); |
8929 | error = ENOBUFS; |
8930 | goto fail; |
8931 | } |
8932 | bzero(mtod(m, caddr_t), len); |
8933 | lt = mtod(m, struct sadb_lifetime *); |
8934 | lt->sadb_lifetime_len = PFKEY_UNIT64(sizeof(struct sadb_lifetime)); |
8935 | lt->sadb_lifetime_exttype = SADB_EXT_LIFETIME_CURRENT; |
8936 | lt->sadb_lifetime_allocations = sav->lft_c->sadb_lifetime_allocations; |
8937 | lt->sadb_lifetime_bytes = sav->lft_c->sadb_lifetime_bytes; |
8938 | lt->sadb_lifetime_addtime = sav->lft_c->sadb_lifetime_addtime; |
8939 | lt->sadb_lifetime_usetime = sav->lft_c->sadb_lifetime_usetime; |
8940 | lt = (struct sadb_lifetime *)(void *)(mtod(m, caddr_t) + len / 2); |
8941 | bcopy(sav->lft_s, lt, sizeof(*lt)); |
8942 | m_cat(result, m); |
8943 | |
8944 | /* set sadb_address for source */ |
8945 | m = key_setsadbaddr(SADB_EXT_ADDRESS_SRC, |
8946 | (struct sockaddr *)&sav->sah->saidx.src, |
8947 | FULLMASK, IPSEC_ULPROTO_ANY); |
8948 | if (!m) { |
8949 | error = ENOBUFS; |
8950 | goto fail; |
8951 | } |
8952 | m_cat(result, m); |
8953 | |
8954 | /* set sadb_address for destination */ |
8955 | m = key_setsadbaddr(SADB_EXT_ADDRESS_DST, |
8956 | (struct sockaddr *)&sav->sah->saidx.dst, |
8957 | FULLMASK, IPSEC_ULPROTO_ANY); |
8958 | if (!m) { |
8959 | error = ENOBUFS; |
8960 | goto fail; |
8961 | } |
8962 | m_cat(result, m); |
8963 | |
8964 | if ((result->m_flags & M_PKTHDR) == 0) { |
8965 | error = EINVAL; |
8966 | goto fail; |
8967 | } |
8968 | |
8969 | if (result->m_len < sizeof(struct sadb_msg)) { |
8970 | result = m_pullup(result, sizeof(struct sadb_msg)); |
8971 | if (result == NULL) { |
8972 | error = ENOBUFS; |
8973 | goto fail; |
8974 | } |
8975 | } |
8976 | |
8977 | result->m_pkthdr.len = 0; |
8978 | for (m = result; m; m = m->m_next) |
8979 | result->m_pkthdr.len += m->m_len; |
8980 | |
8981 | mtod(result, struct sadb_msg *)->sadb_msg_len = |
8982 | PFKEY_UNIT64(result->m_pkthdr.len); |
8983 | |
8984 | return key_sendup_mbuf(NULL, result, KEY_SENDUP_REGISTERED); |
8985 | |
8986 | fail: |
8987 | if (result) |
8988 | m_freem(result); |
8989 | return error; |
8990 | } |
8991 | |
8992 | /* |
8993 | * SADB_FLUSH processing |
8994 | * receive |
8995 | * <base> |
8996 | * from the ikmpd, and free all entries in secastree. |
8997 | * and send, |
8998 | * <base> |
8999 | * to the ikmpd. |
9000 | * NOTE: to do is only marking SADB_SASTATE_DEAD. |
9001 | * |
9002 | * m will always be freed. |
9003 | */ |
9004 | static int |
9005 | key_flush( |
9006 | struct socket *so, |
9007 | struct mbuf *m, |
9008 | const struct sadb_msghdr *mhp) |
9009 | { |
9010 | struct sadb_msg *newmsg; |
9011 | struct secashead *sah, *nextsah; |
9012 | struct secasvar *sav, *nextsav; |
9013 | u_int16_t proto; |
9014 | u_int8_t state; |
9015 | u_int stateidx; |
9016 | |
9017 | /* sanity check */ |
9018 | if (so == NULL || mhp == NULL || mhp->msg == NULL) |
9019 | panic("key_flush: NULL pointer is passed.\n" ); |
9020 | |
9021 | /* map satype to proto */ |
9022 | if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) { |
9023 | ipseclog((LOG_DEBUG, "key_flush: invalid satype is passed.\n" )); |
9024 | return key_senderror(so, m, EINVAL); |
9025 | } |
9026 | |
9027 | lck_mtx_lock(sadb_mutex); |
9028 | |
9029 | /* no SATYPE specified, i.e. flushing all SA. */ |
9030 | for (sah = LIST_FIRST(&sahtree); |
9031 | sah != NULL; |
9032 | sah = nextsah) { |
9033 | nextsah = LIST_NEXT(sah, chain); |
9034 | |
9035 | if (mhp->msg->sadb_msg_satype != SADB_SATYPE_UNSPEC |
9036 | && proto != sah->saidx.proto) |
9037 | continue; |
9038 | |
9039 | for (stateidx = 0; |
9040 | stateidx < _ARRAYLEN(saorder_state_alive); |
9041 | stateidx++) { |
9042 | state = saorder_state_any[stateidx]; |
9043 | for (sav = LIST_FIRST(&sah->savtree[state]); |
9044 | sav != NULL; |
9045 | sav = nextsav) { |
9046 | |
9047 | nextsav = LIST_NEXT(sav, chain); |
9048 | |
9049 | key_sa_chgstate(sav, SADB_SASTATE_DEAD); |
9050 | key_freesav(sav, KEY_SADB_LOCKED); |
9051 | } |
9052 | } |
9053 | |
9054 | sah->state = SADB_SASTATE_DEAD; |
9055 | } |
9056 | lck_mtx_unlock(sadb_mutex); |
9057 | |
9058 | if (m->m_len < sizeof(struct sadb_msg) || |
9059 | sizeof(struct sadb_msg) > m->m_len + M_TRAILINGSPACE(m)) { |
9060 | ipseclog((LOG_DEBUG, "key_flush: No more memory.\n" )); |
9061 | return key_senderror(so, m, ENOBUFS); |
9062 | } |
9063 | |
9064 | if (m->m_next) |
9065 | m_freem(m->m_next); |
9066 | m->m_next = NULL; |
9067 | m->m_pkthdr.len = m->m_len = sizeof(struct sadb_msg); |
9068 | newmsg = mtod(m, struct sadb_msg *); |
9069 | newmsg->sadb_msg_errno = 0; |
9070 | newmsg->sadb_msg_len = PFKEY_UNIT64(m->m_pkthdr.len); |
9071 | |
9072 | return key_sendup_mbuf(so, m, KEY_SENDUP_ALL); |
9073 | } |
9074 | |
9075 | /* |
9076 | * SADB_DUMP processing |
9077 | * dump all entries including status of DEAD in SAD. |
9078 | * receive |
9079 | * <base> |
9080 | * from the ikmpd, and dump all secasvar leaves |
9081 | * and send, |
9082 | * <base> ..... |
9083 | * to the ikmpd. |
9084 | * |
9085 | * m will always be freed. |
9086 | */ |
9087 | |
9088 | struct sav_dump_elem { |
9089 | struct secasvar *sav; |
9090 | u_int8_t satype; |
9091 | }; |
9092 | |
9093 | static int |
9094 | key_dump( |
9095 | struct socket *so, |
9096 | struct mbuf *m, |
9097 | const struct sadb_msghdr *mhp) |
9098 | { |
9099 | struct secashead *sah; |
9100 | struct secasvar *sav; |
9101 | struct sav_dump_elem *savbuf = NULL, *elem_ptr; |
9102 | u_int16_t proto; |
9103 | u_int stateidx; |
9104 | u_int8_t satype; |
9105 | u_int8_t state; |
9106 | int cnt = 0, cnt2, bufcount; |
9107 | struct mbuf *n; |
9108 | int error = 0; |
9109 | |
9110 | LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED); |
9111 | |
9112 | /* sanity check */ |
9113 | if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) |
9114 | panic("key_dump: NULL pointer is passed.\n" ); |
9115 | |
9116 | /* map satype to proto */ |
9117 | if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) { |
9118 | ipseclog((LOG_DEBUG, "key_dump: invalid satype is passed.\n" )); |
9119 | return key_senderror(so, m, EINVAL); |
9120 | } |
9121 | |
9122 | if ((bufcount = ipsec_sav_count) <= 0) { |
9123 | error = ENOENT; |
9124 | goto end; |
9125 | } |
9126 | bufcount += 512; /* extra */ |
9127 | KMALLOC_WAIT(savbuf, struct sav_dump_elem*, bufcount * sizeof(struct sav_dump_elem)); |
9128 | if (savbuf == NULL) { |
9129 | ipseclog((LOG_DEBUG, "key_dump: No more memory.\n" )); |
9130 | error = ENOMEM; |
9131 | goto end; |
9132 | } |
9133 | |
9134 | /* count sav entries to be sent to the userland. */ |
9135 | lck_mtx_lock(sadb_mutex); |
9136 | elem_ptr = savbuf; |
9137 | LIST_FOREACH(sah, &sahtree, chain) { |
9138 | if (mhp->msg->sadb_msg_satype != SADB_SATYPE_UNSPEC |
9139 | && proto != sah->saidx.proto) |
9140 | continue; |
9141 | |
9142 | /* map proto to satype */ |
9143 | if ((satype = key_proto2satype(sah->saidx.proto)) == 0) { |
9144 | lck_mtx_unlock(sadb_mutex); |
9145 | ipseclog((LOG_DEBUG, "key_dump: there was invalid proto in SAD.\n" )); |
9146 | error = EINVAL; |
9147 | goto end; |
9148 | } |
9149 | |
9150 | for (stateidx = 0; |
9151 | stateidx < _ARRAYLEN(saorder_state_any); |
9152 | stateidx++) { |
9153 | state = saorder_state_any[stateidx]; |
9154 | LIST_FOREACH(sav, &sah->savtree[state], chain) { |
9155 | if (cnt == bufcount) |
9156 | break; /* out of buffer space */ |
9157 | elem_ptr->sav = sav; |
9158 | elem_ptr->satype = satype; |
9159 | sav->refcnt++; |
9160 | elem_ptr++; |
9161 | cnt++; |
9162 | } |
9163 | } |
9164 | } |
9165 | lck_mtx_unlock(sadb_mutex); |
9166 | |
9167 | if (cnt == 0) { |
9168 | error = ENOENT; |
9169 | goto end; |
9170 | } |
9171 | |
9172 | /* send this to the userland, one at a time. */ |
9173 | elem_ptr = savbuf; |
9174 | cnt2 = cnt; |
9175 | while (cnt2) { |
9176 | n = key_setdumpsa(elem_ptr->sav, SADB_DUMP, elem_ptr->satype, |
9177 | --cnt2, mhp->msg->sadb_msg_pid); |
9178 | |
9179 | if (!n) { |
9180 | error = ENOBUFS; |
9181 | goto end; |
9182 | } |
9183 | |
9184 | key_sendup_mbuf(so, n, KEY_SENDUP_ONE); |
9185 | elem_ptr++; |
9186 | } |
9187 | |
9188 | end: |
9189 | if (savbuf) { |
9190 | if (cnt) { |
9191 | elem_ptr = savbuf; |
9192 | lck_mtx_lock(sadb_mutex); |
9193 | while (cnt--) |
9194 | key_freesav((elem_ptr++)->sav, KEY_SADB_LOCKED); |
9195 | lck_mtx_unlock(sadb_mutex); |
9196 | } |
9197 | KFREE(savbuf); |
9198 | } |
9199 | |
9200 | if (error) |
9201 | return key_senderror(so, m, error); |
9202 | |
9203 | m_freem(m); |
9204 | return 0; |
9205 | } |
9206 | |
9207 | /* |
9208 | * SADB_X_PROMISC processing |
9209 | * |
9210 | * m will always be freed. |
9211 | */ |
9212 | static int |
9213 | key_promisc( |
9214 | struct socket *so, |
9215 | struct mbuf *m, |
9216 | const struct sadb_msghdr *mhp) |
9217 | { |
9218 | int olen; |
9219 | |
9220 | /* sanity check */ |
9221 | if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) |
9222 | panic("key_promisc: NULL pointer is passed.\n" ); |
9223 | |
9224 | olen = PFKEY_UNUNIT64(mhp->msg->sadb_msg_len); |
9225 | |
9226 | if (olen < sizeof(struct sadb_msg)) { |
9227 | #if 1 |
9228 | return key_senderror(so, m, EINVAL); |
9229 | #else |
9230 | m_freem(m); |
9231 | return 0; |
9232 | #endif |
9233 | } else if (olen == sizeof(struct sadb_msg)) { |
9234 | /* enable/disable promisc mode */ |
9235 | struct keycb *kp; |
9236 | |
9237 | socket_lock(so, 1); |
9238 | if ((kp = (struct keycb *)sotorawcb(so)) == NULL) |
9239 | return key_senderror(so, m, EINVAL); |
9240 | mhp->msg->sadb_msg_errno = 0; |
9241 | switch (mhp->msg->sadb_msg_satype) { |
9242 | case 0: |
9243 | case 1: |
9244 | kp->kp_promisc = mhp->msg->sadb_msg_satype; |
9245 | break; |
9246 | default: |
9247 | socket_unlock(so, 1); |
9248 | return key_senderror(so, m, EINVAL); |
9249 | } |
9250 | socket_unlock(so, 1); |
9251 | |
9252 | /* send the original message back to everyone */ |
9253 | mhp->msg->sadb_msg_errno = 0; |
9254 | return key_sendup_mbuf(so, m, KEY_SENDUP_ALL); |
9255 | } else { |
9256 | /* send packet as is */ |
9257 | |
9258 | m_adj(m, PFKEY_ALIGN8(sizeof(struct sadb_msg))); |
9259 | |
9260 | /* TODO: if sadb_msg_seq is specified, send to specific pid */ |
9261 | return key_sendup_mbuf(so, m, KEY_SENDUP_ALL); |
9262 | } |
9263 | } |
9264 | |
9265 | static int (*const key_typesw[])(struct socket *, struct mbuf *, |
9266 | const struct sadb_msghdr *) = { |
9267 | NULL, /* SADB_RESERVED */ |
9268 | key_getspi, /* SADB_GETSPI */ |
9269 | key_update, /* SADB_UPDATE */ |
9270 | key_add, /* SADB_ADD */ |
9271 | key_delete, /* SADB_DELETE */ |
9272 | key_get, /* SADB_GET */ |
9273 | key_acquire2, /* SADB_ACQUIRE */ |
9274 | key_register, /* SADB_REGISTER */ |
9275 | NULL, /* SADB_EXPIRE */ |
9276 | key_flush, /* SADB_FLUSH */ |
9277 | key_dump, /* SADB_DUMP */ |
9278 | key_promisc, /* SADB_X_PROMISC */ |
9279 | NULL, /* SADB_X_PCHANGE */ |
9280 | key_spdadd, /* SADB_X_SPDUPDATE */ |
9281 | key_spdadd, /* SADB_X_SPDADD */ |
9282 | key_spddelete, /* SADB_X_SPDDELETE */ |
9283 | key_spdget, /* SADB_X_SPDGET */ |
9284 | NULL, /* SADB_X_SPDACQUIRE */ |
9285 | key_spddump, /* SADB_X_SPDDUMP */ |
9286 | key_spdflush, /* SADB_X_SPDFLUSH */ |
9287 | key_spdadd, /* SADB_X_SPDSETIDX */ |
9288 | NULL, /* SADB_X_SPDEXPIRE */ |
9289 | key_spddelete2, /* SADB_X_SPDDELETE2 */ |
9290 | key_getsastat, /* SADB_GETSASTAT */ |
9291 | key_spdenable, /* SADB_X_SPDENABLE */ |
9292 | key_spddisable, /* SADB_X_SPDDISABLE */ |
9293 | key_migrate, /* SADB_MIGRATE */ |
9294 | }; |
9295 | |
9296 | static void |
9297 | bzero_mbuf(struct mbuf *m) |
9298 | { |
9299 | struct mbuf *mptr = m; |
9300 | struct sadb_msg *msg = NULL; |
9301 | int offset = 0; |
9302 | |
9303 | if (!mptr) { |
9304 | return; |
9305 | } |
9306 | |
9307 | if (mptr->m_len >= sizeof(struct sadb_msg)) { |
9308 | msg = mtod(mptr, struct sadb_msg *); |
9309 | if (msg->sadb_msg_type != SADB_ADD && |
9310 | msg->sadb_msg_type != SADB_UPDATE) { |
9311 | return; |
9312 | } |
9313 | offset = sizeof(struct sadb_msg); |
9314 | } |
9315 | bzero(mptr->m_data+offset, mptr->m_len-offset); |
9316 | mptr = mptr->m_next; |
9317 | while (mptr != NULL) { |
9318 | bzero(mptr->m_data, mptr->m_len); |
9319 | mptr = mptr->m_next; |
9320 | } |
9321 | } |
9322 | |
9323 | static void |
9324 | bzero_keys(const struct sadb_msghdr *mh) |
9325 | { |
9326 | int extlen = 0; |
9327 | int offset = 0; |
9328 | |
9329 | if (!mh) { |
9330 | return; |
9331 | } |
9332 | offset = sizeof(struct sadb_key); |
9333 | |
9334 | if (mh->ext[SADB_EXT_KEY_ENCRYPT]) { |
9335 | struct sadb_key *key = (struct sadb_key*)mh->ext[SADB_EXT_KEY_ENCRYPT]; |
9336 | extlen = key->sadb_key_bits >> 3; |
9337 | |
9338 | if (mh->extlen[SADB_EXT_KEY_ENCRYPT] >= offset + extlen) { |
9339 | bzero((uint8_t *)mh->ext[SADB_EXT_KEY_ENCRYPT]+offset, extlen); |
9340 | } else { |
9341 | bzero(mh->ext[SADB_EXT_KEY_ENCRYPT], mh->extlen[SADB_EXT_KEY_ENCRYPT]); |
9342 | } |
9343 | } |
9344 | if (mh->ext[SADB_EXT_KEY_AUTH]) { |
9345 | struct sadb_key *key = (struct sadb_key*)mh->ext[SADB_EXT_KEY_AUTH]; |
9346 | extlen = key->sadb_key_bits >> 3; |
9347 | |
9348 | if (mh->extlen[SADB_EXT_KEY_AUTH] >= offset + extlen) { |
9349 | bzero((uint8_t *)mh->ext[SADB_EXT_KEY_AUTH]+offset, extlen); |
9350 | } else { |
9351 | bzero(mh->ext[SADB_EXT_KEY_AUTH], mh->extlen[SADB_EXT_KEY_AUTH]); |
9352 | } |
9353 | } |
9354 | } |
9355 | |
9356 | static int |
9357 | key_validate_address_pair(struct sadb_address *src0, |
9358 | struct sadb_address *dst0) |
9359 | { |
9360 | u_int plen = 0; |
9361 | |
9362 | /* check upper layer protocol */ |
9363 | if (src0->sadb_address_proto != dst0->sadb_address_proto) { |
9364 | ipseclog((LOG_DEBUG, "key_parse: upper layer protocol mismatched.\n" )); |
9365 | PFKEY_STAT_INCREMENT(pfkeystat.out_invaddr); |
9366 | return (EINVAL); |
9367 | } |
9368 | |
9369 | /* check family */ |
9370 | if (PFKEY_ADDR_SADDR(src0)->sa_family != |
9371 | PFKEY_ADDR_SADDR(dst0)->sa_family) { |
9372 | ipseclog((LOG_DEBUG, "key_parse: address family mismatched.\n" )); |
9373 | PFKEY_STAT_INCREMENT(pfkeystat.out_invaddr); |
9374 | return (EINVAL); |
9375 | } |
9376 | if (PFKEY_ADDR_SADDR(src0)->sa_len != |
9377 | PFKEY_ADDR_SADDR(dst0)->sa_len) { |
9378 | ipseclog((LOG_DEBUG, |
9379 | "key_parse: address struct size mismatched.\n" )); |
9380 | PFKEY_STAT_INCREMENT(pfkeystat.out_invaddr); |
9381 | return (EINVAL); |
9382 | } |
9383 | |
9384 | switch (PFKEY_ADDR_SADDR(src0)->sa_family) { |
9385 | case AF_INET: |
9386 | if (PFKEY_ADDR_SADDR(src0)->sa_len != sizeof(struct sockaddr_in)) { |
9387 | PFKEY_STAT_INCREMENT(pfkeystat.out_invaddr); |
9388 | return (EINVAL); |
9389 | } |
9390 | break; |
9391 | case AF_INET6: |
9392 | if (PFKEY_ADDR_SADDR(src0)->sa_len != sizeof(struct sockaddr_in6)) { |
9393 | PFKEY_STAT_INCREMENT(pfkeystat.out_invaddr); |
9394 | return (EINVAL); |
9395 | } |
9396 | break; |
9397 | default: |
9398 | ipseclog((LOG_DEBUG, |
9399 | "key_parse: unsupported address family.\n" )); |
9400 | PFKEY_STAT_INCREMENT(pfkeystat.out_invaddr); |
9401 | return (EAFNOSUPPORT); |
9402 | } |
9403 | |
9404 | switch (PFKEY_ADDR_SADDR(src0)->sa_family) { |
9405 | case AF_INET: |
9406 | plen = sizeof(struct in_addr) << 3; |
9407 | break; |
9408 | case AF_INET6: |
9409 | plen = sizeof(struct in6_addr) << 3; |
9410 | break; |
9411 | default: |
9412 | plen = 0; /*fool gcc*/ |
9413 | break; |
9414 | } |
9415 | |
9416 | /* check max prefix length */ |
9417 | if (src0->sadb_address_prefixlen > plen || |
9418 | dst0->sadb_address_prefixlen > plen) { |
9419 | ipseclog((LOG_DEBUG, |
9420 | "key_parse: illegal prefixlen.\n" )); |
9421 | PFKEY_STAT_INCREMENT(pfkeystat.out_invaddr); |
9422 | return (EINVAL); |
9423 | } |
9424 | |
9425 | /* |
9426 | * prefixlen == 0 is valid because there can be a case when |
9427 | * all addresses are matched. |
9428 | */ |
9429 | return (0); |
9430 | } |
9431 | |
9432 | /* |
9433 | * parse sadb_msg buffer to process PFKEYv2, |
9434 | * and create a data to response if needed. |
9435 | * I think to be dealed with mbuf directly. |
9436 | * IN: |
9437 | * msgp : pointer to pointer to a received buffer pulluped. |
9438 | * This is rewrited to response. |
9439 | * so : pointer to socket. |
9440 | * OUT: |
9441 | * length for buffer to send to user process. |
9442 | */ |
9443 | int |
9444 | key_parse( |
9445 | struct mbuf *m, |
9446 | struct socket *so) |
9447 | { |
9448 | struct sadb_msg *msg; |
9449 | struct sadb_msghdr mh; |
9450 | u_int orglen; |
9451 | int error; |
9452 | int target; |
9453 | Boolean keyAligned = FALSE; |
9454 | |
9455 | LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED); |
9456 | |
9457 | /* sanity check */ |
9458 | if (m == NULL || so == NULL) |
9459 | panic("key_parse: NULL pointer is passed.\n" ); |
9460 | |
9461 | #if 0 /*kdebug_sadb assumes msg in linear buffer*/ |
9462 | KEYDEBUG(KEYDEBUG_KEY_DUMP, |
9463 | ipseclog((LOG_DEBUG, "key_parse: passed sadb_msg\n" )); |
9464 | kdebug_sadb(msg)); |
9465 | #endif |
9466 | |
9467 | if (m->m_len < sizeof(struct sadb_msg)) { |
9468 | m = m_pullup(m, sizeof(struct sadb_msg)); |
9469 | if (!m) |
9470 | return ENOBUFS; |
9471 | } |
9472 | msg = mtod(m, struct sadb_msg *); |
9473 | orglen = PFKEY_UNUNIT64(msg->sadb_msg_len); |
9474 | target = KEY_SENDUP_ONE; |
9475 | |
9476 | if ((m->m_flags & M_PKTHDR) == 0 || |
9477 | m->m_pkthdr.len != m->m_pkthdr.len) { |
9478 | ipseclog((LOG_DEBUG, "key_parse: invalid message length.\n" )); |
9479 | PFKEY_STAT_INCREMENT(pfkeystat.out_invlen); |
9480 | error = EINVAL; |
9481 | goto senderror; |
9482 | } |
9483 | |
9484 | if (msg->sadb_msg_version != PF_KEY_V2) { |
9485 | ipseclog((LOG_DEBUG, |
9486 | "key_parse: PF_KEY version %u is mismatched.\n" , |
9487 | msg->sadb_msg_version)); |
9488 | PFKEY_STAT_INCREMENT(pfkeystat.out_invver); |
9489 | error = EINVAL; |
9490 | goto senderror; |
9491 | } |
9492 | |
9493 | if (msg->sadb_msg_type > SADB_MAX) { |
9494 | ipseclog((LOG_DEBUG, "key_parse: invalid type %u is passed.\n" , |
9495 | msg->sadb_msg_type)); |
9496 | PFKEY_STAT_INCREMENT(pfkeystat.out_invmsgtype); |
9497 | error = EINVAL; |
9498 | goto senderror; |
9499 | } |
9500 | |
9501 | /* for old-fashioned code - should be nuked */ |
9502 | if (m->m_pkthdr.len > MCLBYTES) { |
9503 | m_freem(m); |
9504 | return ENOBUFS; |
9505 | } |
9506 | if (m->m_next) { |
9507 | struct mbuf *n; |
9508 | |
9509 | MGETHDR(n, M_WAITOK, MT_DATA); |
9510 | if (n && m->m_pkthdr.len > MHLEN) { |
9511 | MCLGET(n, M_WAITOK); |
9512 | if ((n->m_flags & M_EXT) == 0) { |
9513 | m_free(n); |
9514 | n = NULL; |
9515 | } |
9516 | } |
9517 | if (!n) { |
9518 | bzero_mbuf(m); |
9519 | m_freem(m); |
9520 | return ENOBUFS; |
9521 | } |
9522 | m_copydata(m, 0, m->m_pkthdr.len, mtod(n, caddr_t)); |
9523 | n->m_pkthdr.len = n->m_len = m->m_pkthdr.len; |
9524 | n->m_next = NULL; |
9525 | bzero_mbuf(m); |
9526 | m_freem(m); |
9527 | m = n; |
9528 | } |
9529 | |
9530 | /* align the mbuf chain so that extensions are in contiguous region. */ |
9531 | error = key_align(m, &mh); |
9532 | if (error) |
9533 | return error; |
9534 | |
9535 | if (m->m_next) { /*XXX*/ |
9536 | bzero_mbuf(m); |
9537 | m_freem(m); |
9538 | return ENOBUFS; |
9539 | } |
9540 | |
9541 | keyAligned = TRUE; |
9542 | msg = mh.msg; |
9543 | |
9544 | /* check SA type */ |
9545 | switch (msg->sadb_msg_satype) { |
9546 | case SADB_SATYPE_UNSPEC: |
9547 | switch (msg->sadb_msg_type) { |
9548 | case SADB_GETSPI: |
9549 | case SADB_UPDATE: |
9550 | case SADB_ADD: |
9551 | case SADB_DELETE: |
9552 | case SADB_GET: |
9553 | case SADB_ACQUIRE: |
9554 | case SADB_EXPIRE: |
9555 | ipseclog((LOG_DEBUG, "key_parse: must specify satype " |
9556 | "when msg type=%u.\n" , msg->sadb_msg_type)); |
9557 | PFKEY_STAT_INCREMENT(pfkeystat.out_invsatype); |
9558 | error = EINVAL; |
9559 | goto senderror; |
9560 | } |
9561 | break; |
9562 | case SADB_SATYPE_AH: |
9563 | case SADB_SATYPE_ESP: |
9564 | case SADB_X_SATYPE_IPCOMP: |
9565 | switch (msg->sadb_msg_type) { |
9566 | case SADB_X_SPDADD: |
9567 | case SADB_X_SPDDELETE: |
9568 | case SADB_X_SPDGET: |
9569 | case SADB_X_SPDDUMP: |
9570 | case SADB_X_SPDFLUSH: |
9571 | case SADB_X_SPDSETIDX: |
9572 | case SADB_X_SPDUPDATE: |
9573 | case SADB_X_SPDDELETE2: |
9574 | case SADB_X_SPDENABLE: |
9575 | case SADB_X_SPDDISABLE: |
9576 | ipseclog((LOG_DEBUG, "key_parse: illegal satype=%u\n" , |
9577 | msg->sadb_msg_type)); |
9578 | PFKEY_STAT_INCREMENT(pfkeystat.out_invsatype); |
9579 | error = EINVAL; |
9580 | goto senderror; |
9581 | } |
9582 | break; |
9583 | case SADB_SATYPE_RSVP: |
9584 | case SADB_SATYPE_OSPFV2: |
9585 | case SADB_SATYPE_RIPV2: |
9586 | case SADB_SATYPE_MIP: |
9587 | ipseclog((LOG_DEBUG, "key_parse: type %u isn't supported.\n" , |
9588 | msg->sadb_msg_satype)); |
9589 | PFKEY_STAT_INCREMENT(pfkeystat.out_invsatype); |
9590 | error = EOPNOTSUPP; |
9591 | goto senderror; |
9592 | case 1: /* XXX: What does it do? */ |
9593 | if (msg->sadb_msg_type == SADB_X_PROMISC) |
9594 | break; |
9595 | /*FALLTHROUGH*/ |
9596 | default: |
9597 | ipseclog((LOG_DEBUG, "key_parse: invalid type %u is passed.\n" , |
9598 | msg->sadb_msg_satype)); |
9599 | PFKEY_STAT_INCREMENT(pfkeystat.out_invsatype); |
9600 | error = EINVAL; |
9601 | goto senderror; |
9602 | } |
9603 | |
9604 | /* Validate address fields for matching families, lengths, etc. */ |
9605 | void *src0 = mh.ext[SADB_EXT_ADDRESS_SRC]; |
9606 | void *dst0 = mh.ext[SADB_EXT_ADDRESS_DST]; |
9607 | if (mh.ext[SADB_X_EXT_ADDR_RANGE_SRC_START] != NULL && |
9608 | mh.ext[SADB_X_EXT_ADDR_RANGE_SRC_END] != NULL) { |
9609 | |
9610 | error = key_validate_address_pair((struct sadb_address *)(mh.ext[SADB_X_EXT_ADDR_RANGE_SRC_START]), |
9611 | (struct sadb_address *)(mh.ext[SADB_X_EXT_ADDR_RANGE_SRC_END])); |
9612 | if (error != 0) { |
9613 | goto senderror; |
9614 | } |
9615 | |
9616 | if (src0 == NULL) { |
9617 | src0 = mh.ext[SADB_X_EXT_ADDR_RANGE_SRC_START]; |
9618 | } |
9619 | } |
9620 | if (mh.ext[SADB_X_EXT_ADDR_RANGE_DST_START] != NULL && |
9621 | mh.ext[SADB_X_EXT_ADDR_RANGE_DST_END] != NULL) { |
9622 | |
9623 | error = key_validate_address_pair((struct sadb_address *)(mh.ext[SADB_X_EXT_ADDR_RANGE_DST_START]), |
9624 | (struct sadb_address *)(mh.ext[SADB_X_EXT_ADDR_RANGE_DST_END])); |
9625 | if (error != 0) { |
9626 | goto senderror; |
9627 | } |
9628 | |
9629 | if (dst0 == NULL) { |
9630 | dst0 = mh.ext[SADB_X_EXT_ADDR_RANGE_DST_START]; |
9631 | } |
9632 | } |
9633 | if (src0 != NULL && dst0 != NULL) { |
9634 | error = key_validate_address_pair((struct sadb_address *)(src0), |
9635 | (struct sadb_address *)(dst0)); |
9636 | if (error != 0) { |
9637 | goto senderror; |
9638 | } |
9639 | } |
9640 | |
9641 | if (msg->sadb_msg_type >= sizeof(key_typesw)/sizeof(key_typesw[0]) || |
9642 | key_typesw[msg->sadb_msg_type] == NULL) { |
9643 | PFKEY_STAT_INCREMENT(pfkeystat.out_invmsgtype); |
9644 | error = EINVAL; |
9645 | goto senderror; |
9646 | } |
9647 | |
9648 | error = (*key_typesw[msg->sadb_msg_type])(so, m, &mh); |
9649 | |
9650 | return error; |
9651 | |
9652 | senderror: |
9653 | if (keyAligned) { |
9654 | bzero_keys(&mh); |
9655 | } else { |
9656 | bzero_mbuf(m); |
9657 | } |
9658 | msg->sadb_msg_errno = error; |
9659 | return key_sendup_mbuf(so, m, target); |
9660 | } |
9661 | |
9662 | static int |
9663 | key_senderror( |
9664 | struct socket *so, |
9665 | struct mbuf *m, |
9666 | int code) |
9667 | { |
9668 | struct sadb_msg *msg; |
9669 | |
9670 | LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED); |
9671 | |
9672 | if (m->m_len < sizeof(struct sadb_msg)) |
9673 | panic("invalid mbuf passed to key_senderror" ); |
9674 | |
9675 | msg = mtod(m, struct sadb_msg *); |
9676 | msg->sadb_msg_errno = code; |
9677 | return key_sendup_mbuf(so, m, KEY_SENDUP_ONE); |
9678 | } |
9679 | |
9680 | /* |
9681 | * set the pointer to each header into message buffer. |
9682 | * m will be freed on error. |
9683 | * XXX larger-than-MCLBYTES extension? |
9684 | */ |
9685 | static int |
9686 | key_align( |
9687 | struct mbuf *m, |
9688 | struct sadb_msghdr *mhp) |
9689 | { |
9690 | struct mbuf *n; |
9691 | struct sadb_ext *ext; |
9692 | size_t off, end; |
9693 | int extlen; |
9694 | int toff; |
9695 | |
9696 | /* sanity check */ |
9697 | if (m == NULL || mhp == NULL) |
9698 | panic("key_align: NULL pointer is passed.\n" ); |
9699 | if (m->m_len < sizeof(struct sadb_msg)) |
9700 | panic("invalid mbuf passed to key_align" ); |
9701 | |
9702 | /* initialize */ |
9703 | bzero(mhp, sizeof(*mhp)); |
9704 | |
9705 | mhp->msg = mtod(m, struct sadb_msg *); |
9706 | mhp->ext[0] = (struct sadb_ext *)mhp->msg; /*XXX backward compat */ |
9707 | |
9708 | end = PFKEY_UNUNIT64(mhp->msg->sadb_msg_len); |
9709 | extlen = end; /*just in case extlen is not updated*/ |
9710 | for (off = sizeof(struct sadb_msg); off < end; off += extlen) { |
9711 | n = m_pulldown(m, off, sizeof(struct sadb_ext), &toff); |
9712 | if (!n) { |
9713 | /* m is already freed */ |
9714 | return ENOBUFS; |
9715 | } |
9716 | ext = (struct sadb_ext *)(void *)(mtod(n, caddr_t) + toff); |
9717 | |
9718 | /* set pointer */ |
9719 | switch (ext->sadb_ext_type) { |
9720 | case SADB_EXT_SA: |
9721 | case SADB_EXT_ADDRESS_SRC: |
9722 | case SADB_EXT_ADDRESS_DST: |
9723 | case SADB_EXT_ADDRESS_PROXY: |
9724 | case SADB_EXT_LIFETIME_CURRENT: |
9725 | case SADB_EXT_LIFETIME_HARD: |
9726 | case SADB_EXT_LIFETIME_SOFT: |
9727 | case SADB_EXT_KEY_AUTH: |
9728 | case SADB_EXT_KEY_ENCRYPT: |
9729 | case SADB_EXT_IDENTITY_SRC: |
9730 | case SADB_EXT_IDENTITY_DST: |
9731 | case SADB_EXT_SENSITIVITY: |
9732 | case SADB_EXT_PROPOSAL: |
9733 | case SADB_EXT_SUPPORTED_AUTH: |
9734 | case SADB_EXT_SUPPORTED_ENCRYPT: |
9735 | case SADB_EXT_SPIRANGE: |
9736 | case SADB_X_EXT_POLICY: |
9737 | case SADB_X_EXT_SA2: |
9738 | case SADB_EXT_SESSION_ID: |
9739 | case SADB_EXT_SASTAT: |
9740 | case SADB_X_EXT_IPSECIF: |
9741 | case SADB_X_EXT_ADDR_RANGE_SRC_START: |
9742 | case SADB_X_EXT_ADDR_RANGE_SRC_END: |
9743 | case SADB_X_EXT_ADDR_RANGE_DST_START: |
9744 | case SADB_X_EXT_ADDR_RANGE_DST_END: |
9745 | case SADB_EXT_MIGRATE_ADDRESS_SRC: |
9746 | case SADB_EXT_MIGRATE_ADDRESS_DST: |
9747 | case SADB_X_EXT_MIGRATE_IPSECIF: |
9748 | /* duplicate check */ |
9749 | /* |
9750 | * XXX Are there duplication payloads of either |
9751 | * KEY_AUTH or KEY_ENCRYPT ? |
9752 | */ |
9753 | if (mhp->ext[ext->sadb_ext_type] != NULL) { |
9754 | ipseclog((LOG_DEBUG, |
9755 | "key_align: duplicate ext_type %u " |
9756 | "is passed.\n" , ext->sadb_ext_type)); |
9757 | bzero_mbuf(m); |
9758 | m_freem(m); |
9759 | PFKEY_STAT_INCREMENT(pfkeystat.out_dupext); |
9760 | return EINVAL; |
9761 | } |
9762 | break; |
9763 | default: |
9764 | ipseclog((LOG_DEBUG, |
9765 | "key_align: invalid ext_type %u is passed.\n" , |
9766 | ext->sadb_ext_type)); |
9767 | bzero_mbuf(m); |
9768 | m_freem(m); |
9769 | PFKEY_STAT_INCREMENT(pfkeystat.out_invexttype); |
9770 | return EINVAL; |
9771 | } |
9772 | |
9773 | extlen = PFKEY_UNUNIT64(ext->sadb_ext_len); |
9774 | |
9775 | if (key_validate_ext(ext, extlen)) { |
9776 | bzero_mbuf(m); |
9777 | m_freem(m); |
9778 | PFKEY_STAT_INCREMENT(pfkeystat.out_invlen); |
9779 | return EINVAL; |
9780 | } |
9781 | |
9782 | n = m_pulldown(m, off, extlen, &toff); |
9783 | if (!n) { |
9784 | /* m is already freed */ |
9785 | return ENOBUFS; |
9786 | } |
9787 | ext = (struct sadb_ext *)(void *)(mtod(n, caddr_t) + toff); |
9788 | |
9789 | mhp->ext[ext->sadb_ext_type] = ext; |
9790 | mhp->extoff[ext->sadb_ext_type] = off; |
9791 | mhp->extlen[ext->sadb_ext_type] = extlen; |
9792 | } |
9793 | |
9794 | if (off != end) { |
9795 | bzero_mbuf(m); |
9796 | m_freem(m); |
9797 | PFKEY_STAT_INCREMENT(pfkeystat.out_invlen); |
9798 | return EINVAL; |
9799 | } |
9800 | |
9801 | return 0; |
9802 | } |
9803 | |
9804 | static int |
9805 | key_validate_ext( |
9806 | const struct sadb_ext *ext, |
9807 | int len) |
9808 | { |
9809 | struct sockaddr *sa; |
9810 | enum { NONE, ADDR } checktype = NONE; |
9811 | int baselen = 0; |
9812 | const int sal = offsetof(struct sockaddr, sa_len) + sizeof(sa->sa_len); |
9813 | |
9814 | if (len != PFKEY_UNUNIT64(ext->sadb_ext_len)) |
9815 | return EINVAL; |
9816 | |
9817 | /* if it does not match minimum/maximum length, bail */ |
9818 | if (ext->sadb_ext_type >= sizeof(minsize) / sizeof(minsize[0]) || |
9819 | ext->sadb_ext_type >= sizeof(maxsize) / sizeof(maxsize[0])) |
9820 | return EINVAL; |
9821 | if (!minsize[ext->sadb_ext_type] || len < minsize[ext->sadb_ext_type]) |
9822 | return EINVAL; |
9823 | if (maxsize[ext->sadb_ext_type] && len > maxsize[ext->sadb_ext_type]) |
9824 | return EINVAL; |
9825 | |
9826 | /* more checks based on sadb_ext_type XXX need more */ |
9827 | switch (ext->sadb_ext_type) { |
9828 | case SADB_EXT_ADDRESS_SRC: |
9829 | case SADB_EXT_ADDRESS_DST: |
9830 | case SADB_EXT_ADDRESS_PROXY: |
9831 | case SADB_X_EXT_ADDR_RANGE_SRC_START: |
9832 | case SADB_X_EXT_ADDR_RANGE_SRC_END: |
9833 | case SADB_X_EXT_ADDR_RANGE_DST_START: |
9834 | case SADB_X_EXT_ADDR_RANGE_DST_END: |
9835 | case SADB_EXT_MIGRATE_ADDRESS_SRC: |
9836 | case SADB_EXT_MIGRATE_ADDRESS_DST: |
9837 | baselen = PFKEY_ALIGN8(sizeof(struct sadb_address)); |
9838 | checktype = ADDR; |
9839 | break; |
9840 | case SADB_EXT_IDENTITY_SRC: |
9841 | case SADB_EXT_IDENTITY_DST: |
9842 | if (((struct sadb_ident *)(uintptr_t)(size_t)ext)-> |
9843 | sadb_ident_type == SADB_X_IDENTTYPE_ADDR) { |
9844 | baselen = PFKEY_ALIGN8(sizeof(struct sadb_ident)); |
9845 | checktype = ADDR; |
9846 | } else |
9847 | checktype = NONE; |
9848 | break; |
9849 | default: |
9850 | checktype = NONE; |
9851 | break; |
9852 | } |
9853 | |
9854 | switch (checktype) { |
9855 | case NONE: |
9856 | break; |
9857 | case ADDR: |
9858 | sa = (struct sockaddr *)((caddr_t)(uintptr_t)ext + baselen); |
9859 | |
9860 | if (len < baselen + sal) |
9861 | return EINVAL; |
9862 | if (baselen + PFKEY_ALIGN8(sa->sa_len) != len) |
9863 | return EINVAL; |
9864 | break; |
9865 | } |
9866 | |
9867 | return 0; |
9868 | } |
9869 | |
9870 | /* |
9871 | * XXX: maybe This function is called after INBOUND IPsec processing. |
9872 | * |
9873 | * Special check for tunnel-mode packets. |
9874 | * We must make some checks for consistency between inner and outer IP header. |
9875 | * |
9876 | * xxx more checks to be provided |
9877 | */ |
9878 | int |
9879 | key_checktunnelsanity( |
9880 | struct secasvar *sav, |
9881 | __unused u_int family, |
9882 | __unused caddr_t src, |
9883 | __unused caddr_t dst) |
9884 | { |
9885 | |
9886 | /* sanity check */ |
9887 | if (sav->sah == NULL) |
9888 | panic("sav->sah == NULL at key_checktunnelsanity" ); |
9889 | |
9890 | /* XXX: check inner IP header */ |
9891 | |
9892 | return 1; |
9893 | } |
9894 | |
9895 | /* record data transfer on SA, and update timestamps */ |
9896 | void |
9897 | key_sa_recordxfer( |
9898 | struct secasvar *sav, |
9899 | struct mbuf *m) |
9900 | { |
9901 | |
9902 | |
9903 | if (!sav) |
9904 | panic("key_sa_recordxfer called with sav == NULL" ); |
9905 | if (!m) |
9906 | panic("key_sa_recordxfer called with m == NULL" ); |
9907 | if (!sav->lft_c) |
9908 | return; |
9909 | |
9910 | lck_mtx_lock(sadb_mutex); |
9911 | /* |
9912 | * XXX Currently, there is a difference of bytes size |
9913 | * between inbound and outbound processing. |
9914 | */ |
9915 | sav->lft_c->sadb_lifetime_bytes += m->m_pkthdr.len; |
9916 | /* to check bytes lifetime is done in key_timehandler(). */ |
9917 | |
9918 | /* |
9919 | * We use the number of packets as the unit of |
9920 | * sadb_lifetime_allocations. We increment the variable |
9921 | * whenever {esp,ah}_{in,out}put is called. |
9922 | */ |
9923 | sav->lft_c->sadb_lifetime_allocations++; |
9924 | /* XXX check for expires? */ |
9925 | |
9926 | /* |
9927 | * NOTE: We record CURRENT sadb_lifetime_usetime by using wall clock, |
9928 | * in seconds. HARD and SOFT lifetime are measured by the time |
9929 | * difference (again in seconds) from sadb_lifetime_usetime. |
9930 | * |
9931 | * usetime |
9932 | * v expire expire |
9933 | * -----+-----+--------+---> t |
9934 | * <--------------> HARD |
9935 | * <-----> SOFT |
9936 | */ |
9937 | { |
9938 | struct timeval tv; |
9939 | microtime(&tv); |
9940 | sav->lft_c->sadb_lifetime_usetime = tv.tv_sec; |
9941 | /* XXX check for expires? */ |
9942 | } |
9943 | lck_mtx_unlock(sadb_mutex); |
9944 | |
9945 | return; |
9946 | } |
9947 | |
9948 | /* dumb version */ |
9949 | void |
9950 | key_sa_routechange( |
9951 | struct sockaddr *dst) |
9952 | { |
9953 | struct secashead *sah; |
9954 | struct route *ro; |
9955 | |
9956 | lck_mtx_lock(sadb_mutex); |
9957 | LIST_FOREACH(sah, &sahtree, chain) { |
9958 | ro = (struct route *)&sah->sa_route; |
9959 | if (ro->ro_rt && dst->sa_len == ro->ro_dst.sa_len |
9960 | && bcmp(dst, &ro->ro_dst, dst->sa_len) == 0) { |
9961 | ROUTE_RELEASE(ro); |
9962 | } |
9963 | } |
9964 | lck_mtx_unlock(sadb_mutex); |
9965 | |
9966 | return; |
9967 | } |
9968 | |
9969 | void |
9970 | key_sa_chgstate( |
9971 | struct secasvar *sav, |
9972 | u_int8_t state) |
9973 | { |
9974 | |
9975 | if (sav == NULL) |
9976 | panic("key_sa_chgstate called with sav == NULL" ); |
9977 | |
9978 | if (sav->state == state) |
9979 | return; |
9980 | |
9981 | LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_OWNED); |
9982 | |
9983 | if (__LIST_CHAINED(sav)) |
9984 | LIST_REMOVE(sav, chain); |
9985 | |
9986 | sav->state = state; |
9987 | LIST_INSERT_HEAD(&sav->sah->savtree[state], sav, chain); |
9988 | |
9989 | } |
9990 | |
9991 | void |
9992 | key_sa_stir_iv( |
9993 | struct secasvar *sav) |
9994 | { |
9995 | lck_mtx_lock(sadb_mutex); |
9996 | if (!sav->iv) |
9997 | panic("key_sa_stir_iv called with sav == NULL" ); |
9998 | key_randomfill(sav->iv, sav->ivlen); |
9999 | lck_mtx_unlock(sadb_mutex); |
10000 | } |
10001 | |
10002 | /* XXX too much? */ |
10003 | static struct mbuf * |
10004 | key_alloc_mbuf( |
10005 | int l) |
10006 | { |
10007 | struct mbuf *m = NULL, *n; |
10008 | int len, t; |
10009 | |
10010 | len = l; |
10011 | while (len > 0) { |
10012 | MGET(n, M_DONTWAIT, MT_DATA); |
10013 | if (n && len > MLEN) |
10014 | MCLGET(n, M_DONTWAIT); |
10015 | if (!n) { |
10016 | m_freem(m); |
10017 | return NULL; |
10018 | } |
10019 | |
10020 | n->m_next = NULL; |
10021 | n->m_len = 0; |
10022 | n->m_len = M_TRAILINGSPACE(n); |
10023 | /* use the bottom of mbuf, hoping we can prepend afterwards */ |
10024 | if (n->m_len > len) { |
10025 | t = (n->m_len - len) & ~(sizeof(long) - 1); |
10026 | n->m_data += t; |
10027 | n->m_len = len; |
10028 | } |
10029 | |
10030 | len -= n->m_len; |
10031 | |
10032 | if (m) |
10033 | m_cat(m, n); |
10034 | else |
10035 | m = n; |
10036 | } |
10037 | |
10038 | return m; |
10039 | } |
10040 | |
10041 | static struct mbuf * |
10042 | key_setdumpsastats (u_int32_t dir, |
10043 | struct sastat *stats, |
10044 | u_int32_t max_stats, |
10045 | u_int64_t session_ids[], |
10046 | u_int32_t seq, |
10047 | u_int32_t pid) |
10048 | { |
10049 | struct mbuf *result = NULL, *m = NULL; |
10050 | |
10051 | m = key_setsadbmsg(SADB_GETSASTAT, 0, 0, seq, pid, 0); |
10052 | if (!m) { |
10053 | goto fail; |
10054 | } |
10055 | result = m; |
10056 | |
10057 | m = key_setsadbsession_id(session_ids); |
10058 | if (!m) { |
10059 | goto fail; |
10060 | } |
10061 | m_cat(result, m); |
10062 | |
10063 | m = key_setsadbsastat(dir, |
10064 | stats, |
10065 | max_stats); |
10066 | if (!m) { |
10067 | goto fail; |
10068 | } |
10069 | m_cat(result, m); |
10070 | |
10071 | if ((result->m_flags & M_PKTHDR) == 0) { |
10072 | goto fail; |
10073 | } |
10074 | |
10075 | if (result->m_len < sizeof(struct sadb_msg)) { |
10076 | result = m_pullup(result, sizeof(struct sadb_msg)); |
10077 | if (result == NULL) { |
10078 | goto fail; |
10079 | } |
10080 | } |
10081 | |
10082 | result->m_pkthdr.len = 0; |
10083 | for (m = result; m; m = m->m_next) { |
10084 | result->m_pkthdr.len += m->m_len; |
10085 | } |
10086 | |
10087 | mtod(result, struct sadb_msg *)->sadb_msg_len = |
10088 | PFKEY_UNIT64(result->m_pkthdr.len); |
10089 | |
10090 | return result; |
10091 | |
10092 | fail: |
10093 | if (result) { |
10094 | m_freem(result); |
10095 | } |
10096 | return NULL; |
10097 | } |
10098 | |
10099 | /* |
10100 | * SADB_GETSASTAT processing |
10101 | * dump all stats for matching entries in SAD. |
10102 | * |
10103 | * m will always be freed. |
10104 | */ |
10105 | |
10106 | static int |
10107 | key_getsastat (struct socket *so, |
10108 | struct mbuf *m, |
10109 | const struct sadb_msghdr *mhp) |
10110 | { |
10111 | struct sadb_session_id *session_id; |
10112 | u_int32_t bufsize, arg_count, res_count; |
10113 | struct sadb_sastat *sa_stats_arg; |
10114 | struct sastat *sa_stats_sav = NULL; |
10115 | struct mbuf *n; |
10116 | int error = 0; |
10117 | |
10118 | /* sanity check */ |
10119 | if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) |
10120 | panic("%s: NULL pointer is passed.\n" , __FUNCTION__); |
10121 | |
10122 | if (mhp->ext[SADB_EXT_SESSION_ID] == NULL) { |
10123 | printf("%s: invalid message is passed. missing session-id.\n" , __FUNCTION__); |
10124 | return key_senderror(so, m, EINVAL); |
10125 | } |
10126 | if (mhp->extlen[SADB_EXT_SESSION_ID] < sizeof(struct sadb_session_id)) { |
10127 | printf("%s: invalid message is passed. short session-id.\n" , __FUNCTION__); |
10128 | return key_senderror(so, m, EINVAL); |
10129 | } |
10130 | if (mhp->ext[SADB_EXT_SASTAT] == NULL) { |
10131 | printf("%s: invalid message is passed. missing stat args.\n" , __FUNCTION__); |
10132 | return key_senderror(so, m, EINVAL); |
10133 | } |
10134 | if (mhp->extlen[SADB_EXT_SASTAT] < sizeof(*sa_stats_arg)) { |
10135 | printf("%s: invalid message is passed. short stat args.\n" , __FUNCTION__); |
10136 | return key_senderror(so, m, EINVAL); |
10137 | } |
10138 | |
10139 | LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED); |
10140 | |
10141 | // exit early if there are no active SAs |
10142 | if (ipsec_sav_count <= 0) { |
10143 | printf("%s: No active SAs.\n" , __FUNCTION__); |
10144 | error = ENOENT; |
10145 | goto end; |
10146 | } |
10147 | bufsize = (ipsec_sav_count + 1) * sizeof(*sa_stats_sav); |
10148 | |
10149 | KMALLOC_WAIT(sa_stats_sav, __typeof__(sa_stats_sav), bufsize); |
10150 | if (sa_stats_sav == NULL) { |
10151 | printf("%s: No more memory.\n" , __FUNCTION__); |
10152 | error = ENOMEM; |
10153 | goto end; |
10154 | } |
10155 | bzero(sa_stats_sav, bufsize); |
10156 | |
10157 | sa_stats_arg = (__typeof__(sa_stats_arg)) |
10158 | (void *)mhp->ext[SADB_EXT_SASTAT]; |
10159 | arg_count = sa_stats_arg->sadb_sastat_list_len; |
10160 | // exit early if there are no requested SAs |
10161 | if (arg_count == 0) { |
10162 | printf("%s: No SAs requested.\n" , __FUNCTION__); |
10163 | error = ENOENT; |
10164 | goto end; |
10165 | } |
10166 | res_count = 0; |
10167 | |
10168 | if (key_getsastatbyspi((struct sastat *)(sa_stats_arg + 1), |
10169 | arg_count, |
10170 | sa_stats_sav, |
10171 | &res_count)) { |
10172 | printf("%s: Error finding SAs.\n" , __FUNCTION__); |
10173 | error = ENOENT; |
10174 | goto end; |
10175 | } |
10176 | if (!res_count) { |
10177 | printf("%s: No SAs found.\n" , __FUNCTION__); |
10178 | error = ENOENT; |
10179 | goto end; |
10180 | } |
10181 | |
10182 | session_id = (__typeof__(session_id)) |
10183 | (void *)mhp->ext[SADB_EXT_SESSION_ID]; |
10184 | |
10185 | /* send this to the userland. */ |
10186 | n = key_setdumpsastats(sa_stats_arg->sadb_sastat_dir, |
10187 | sa_stats_sav, |
10188 | res_count, |
10189 | session_id->sadb_session_id_v, |
10190 | mhp->msg->sadb_msg_seq, |
10191 | mhp->msg->sadb_msg_pid); |
10192 | if (!n) { |
10193 | printf("%s: No bufs to dump stats.\n" , __FUNCTION__); |
10194 | error = ENOBUFS; |
10195 | goto end; |
10196 | } |
10197 | |
10198 | key_sendup_mbuf(so, n, KEY_SENDUP_ALL); |
10199 | end: |
10200 | if (sa_stats_sav) { |
10201 | KFREE(sa_stats_sav); |
10202 | } |
10203 | |
10204 | if (error) |
10205 | return key_senderror(so, m, error); |
10206 | |
10207 | m_freem(m); |
10208 | return 0; |
10209 | } |
10210 | |
10211 | static void |
10212 | key_update_natt_keepalive_timestamp (struct secasvar *sav_sent, |
10213 | struct secasvar *sav_update) |
10214 | { |
10215 | struct secasindex saidx_swap_sent_addr; |
10216 | |
10217 | // exit early if two SAs are identical, or if sav_update is current |
10218 | if (sav_sent == sav_update || |
10219 | sav_update->natt_last_activity == natt_now) { |
10220 | return; |
10221 | } |
10222 | |
10223 | // assuming that (sav_update->remote_ike_port != 0 && (esp_udp_encap_port & 0xFFFF) != 0) |
10224 | |
10225 | bzero(&saidx_swap_sent_addr, sizeof(saidx_swap_sent_addr)); |
10226 | memcpy(&saidx_swap_sent_addr.src, &sav_sent->sah->saidx.dst, sizeof(saidx_swap_sent_addr.src)); |
10227 | memcpy(&saidx_swap_sent_addr.dst, &sav_sent->sah->saidx.src, sizeof(saidx_swap_sent_addr.dst)); |
10228 | saidx_swap_sent_addr.proto = sav_sent->sah->saidx.proto; |
10229 | saidx_swap_sent_addr.mode = sav_sent->sah->saidx.mode; |
10230 | // we ignore reqid for split-tunnel setups |
10231 | |
10232 | if (key_cmpsaidx(&sav_sent->sah->saidx, &sav_update->sah->saidx, CMP_MODE | CMP_PORT) || |
10233 | key_cmpsaidx(&saidx_swap_sent_addr, &sav_update->sah->saidx, CMP_MODE | CMP_PORT)) { |
10234 | sav_update->natt_last_activity = natt_now; |
10235 | } |
10236 | } |
10237 | |
10238 | static int |
10239 | key_send_delsp (struct secpolicy *sp) |
10240 | { |
10241 | struct mbuf *result = NULL, *m; |
10242 | |
10243 | if (sp == NULL) |
10244 | goto fail; |
10245 | |
10246 | /* set msg header */ |
10247 | m = key_setsadbmsg(SADB_X_SPDDELETE, 0, 0, 0, 0, 0); |
10248 | if (!m) { |
10249 | goto fail; |
10250 | } |
10251 | result = m; |
10252 | |
10253 | /* set sadb_address(es) for source */ |
10254 | if (sp->spidx.src_range.start.ss_len > 0) { |
10255 | m = key_setsadbaddr(SADB_X_EXT_ADDR_RANGE_SRC_START, |
10256 | (struct sockaddr *)&sp->spidx.src_range.start, sp->spidx.prefs, |
10257 | sp->spidx.ul_proto); |
10258 | if (!m) |
10259 | goto fail; |
10260 | m_cat(result, m); |
10261 | |
10262 | m = key_setsadbaddr(SADB_X_EXT_ADDR_RANGE_SRC_END, |
10263 | (struct sockaddr *)&sp->spidx.src_range.end, sp->spidx.prefs, |
10264 | sp->spidx.ul_proto); |
10265 | if (!m) |
10266 | goto fail; |
10267 | m_cat(result, m); |
10268 | } else { |
10269 | m = key_setsadbaddr(SADB_EXT_ADDRESS_SRC, |
10270 | (struct sockaddr *)&sp->spidx.src, sp->spidx.prefs, |
10271 | sp->spidx.ul_proto); |
10272 | if (!m) |
10273 | goto fail; |
10274 | m_cat(result, m); |
10275 | } |
10276 | |
10277 | /* set sadb_address(es) for destination */ |
10278 | if (sp->spidx.dst_range.start.ss_len > 0) { |
10279 | m = key_setsadbaddr(SADB_X_EXT_ADDR_RANGE_DST_START, |
10280 | (struct sockaddr *)&sp->spidx.dst_range.start, sp->spidx.prefd, |
10281 | sp->spidx.ul_proto); |
10282 | if (!m) |
10283 | goto fail; |
10284 | m_cat(result, m); |
10285 | |
10286 | m = key_setsadbaddr(SADB_X_EXT_ADDR_RANGE_DST_END, |
10287 | (struct sockaddr *)&sp->spidx.dst_range.end, sp->spidx.prefd, |
10288 | sp->spidx.ul_proto); |
10289 | if (!m) |
10290 | goto fail; |
10291 | m_cat(result, m); |
10292 | } else { |
10293 | m = key_setsadbaddr(SADB_EXT_ADDRESS_DST, |
10294 | (struct sockaddr *)&sp->spidx.dst, sp->spidx.prefd, |
10295 | sp->spidx.ul_proto); |
10296 | if (!m) |
10297 | goto fail; |
10298 | m_cat(result, m); |
10299 | } |
10300 | |
10301 | /* set secpolicy */ |
10302 | m = key_sp2msg(sp); |
10303 | if (!m) { |
10304 | goto fail; |
10305 | } |
10306 | m_cat(result, m); |
10307 | |
10308 | if ((result->m_flags & M_PKTHDR) == 0) { |
10309 | goto fail; |
10310 | } |
10311 | |
10312 | if (result->m_len < sizeof(struct sadb_msg)) { |
10313 | result = m_pullup(result, sizeof(struct sadb_msg)); |
10314 | if (result == NULL) { |
10315 | goto fail; |
10316 | } |
10317 | } |
10318 | |
10319 | result->m_pkthdr.len = 0; |
10320 | for (m = result; m; m = m->m_next) |
10321 | result->m_pkthdr.len += m->m_len; |
10322 | |
10323 | mtod(result, struct sadb_msg *)->sadb_msg_len = PFKEY_UNIT64(result->m_pkthdr.len); |
10324 | |
10325 | return key_sendup_mbuf(NULL, result, KEY_SENDUP_REGISTERED); |
10326 | |
10327 | fail: |
10328 | if (result) |
10329 | m_free(result); |
10330 | return -1; |
10331 | } |
10332 | |
10333 | void |
10334 | key_delsp_for_ipsec_if (ifnet_t ipsec_if) |
10335 | { |
10336 | struct secashead *sah; |
10337 | struct secasvar *sav, *nextsav; |
10338 | u_int stateidx; |
10339 | u_int state; |
10340 | struct secpolicy *sp, *nextsp; |
10341 | int dir; |
10342 | |
10343 | if (ipsec_if == NULL) |
10344 | return; |
10345 | |
10346 | LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED); |
10347 | |
10348 | lck_mtx_lock(sadb_mutex); |
10349 | |
10350 | for (dir = 0; dir < IPSEC_DIR_MAX; dir++) { |
10351 | for (sp = LIST_FIRST(&sptree[dir]); |
10352 | sp != NULL; |
10353 | sp = nextsp) { |
10354 | |
10355 | nextsp = LIST_NEXT(sp, chain); |
10356 | |
10357 | if (sp->ipsec_if == ipsec_if) { |
10358 | ifnet_release(sp->ipsec_if); |
10359 | sp->ipsec_if = NULL; |
10360 | |
10361 | key_send_delsp(sp); |
10362 | |
10363 | sp->state = IPSEC_SPSTATE_DEAD; |
10364 | key_freesp(sp, KEY_SADB_LOCKED); |
10365 | } |
10366 | } |
10367 | } |
10368 | |
10369 | LIST_FOREACH(sah, &sahtree, chain) { |
10370 | if (sah->ipsec_if == ipsec_if) { |
10371 | /* This SAH is linked to the IPSec interface. It now needs to close. */ |
10372 | ifnet_release(sah->ipsec_if); |
10373 | sah->ipsec_if = NULL; |
10374 | |
10375 | for (stateidx = 0; stateidx < _ARRAYLEN(saorder_state_alive); stateidx++) { |
10376 | state = saorder_state_any[stateidx]; |
10377 | for (sav = LIST_FIRST(&sah->savtree[state]); sav != NULL; sav = nextsav) { |
10378 | nextsav = LIST_NEXT(sav, chain); |
10379 | |
10380 | key_sa_chgstate(sav, SADB_SASTATE_DEAD); |
10381 | key_freesav(sav, KEY_SADB_LOCKED); |
10382 | } |
10383 | } |
10384 | |
10385 | sah->state = SADB_SASTATE_DEAD; |
10386 | } |
10387 | } |
10388 | |
10389 | lck_mtx_unlock(sadb_mutex); |
10390 | } |
10391 | |
10392 | __private_extern__ u_int32_t |
10393 | key_fill_offload_frames_for_savs (ifnet_t ifp, |
10394 | struct ifnet_keepalive_offload_frame *frames_array, |
10395 | u_int32_t frames_array_count, |
10396 | size_t frame_data_offset) |
10397 | { |
10398 | struct secashead *sah = NULL; |
10399 | struct secasvar *sav = NULL; |
10400 | struct ifnet_keepalive_offload_frame *frame = frames_array; |
10401 | u_int32_t frame_index = 0; |
10402 | |
10403 | if (frame == NULL || frames_array_count == 0) { |
10404 | return (frame_index); |
10405 | } |
10406 | |
10407 | lck_mtx_lock(sadb_mutex); |
10408 | LIST_FOREACH(sah, &sahtree, chain) { |
10409 | LIST_FOREACH(sav, &sah->savtree[SADB_SASTATE_MATURE], chain) { |
10410 | if (ipsec_fill_offload_frame(ifp, sav, frame, frame_data_offset)) { |
10411 | frame_index++; |
10412 | if (frame_index >= frames_array_count) { |
10413 | lck_mtx_unlock(sadb_mutex); |
10414 | return (frame_index); |
10415 | } |
10416 | frame = &(frames_array[frame_index]); |
10417 | } |
10418 | } |
10419 | } |
10420 | lck_mtx_unlock(sadb_mutex); |
10421 | |
10422 | return (frame_index); |
10423 | } |
10424 | |