Print this page
C. Fraire's code review fixes
8529 Extended and regular SADB_ACQUIREs should share address extension code
Portions contributed by: Bayard Bell <buffer.g.overflow@gmail.com>
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/uts/common/inet/ip/sadb.c
+++ new/usr/src/uts/common/inet/ip/sadb.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 * Copyright (c) 2012 Nexenta Systems, Inc. All rights reserved.
25 + * Copyright (c) 2017 Joyent, Inc.
25 26 */
26 27
27 28 #include <sys/types.h>
28 29 #include <sys/stream.h>
29 30 #include <sys/stropts.h>
30 31 #include <sys/strsubr.h>
31 32 #include <sys/errno.h>
32 33 #include <sys/ddi.h>
33 34 #include <sys/debug.h>
34 35 #include <sys/cmn_err.h>
35 36 #include <sys/stream.h>
36 37 #include <sys/strlog.h>
37 38 #include <sys/kmem.h>
38 39 #include <sys/sunddi.h>
39 40 #include <sys/tihdr.h>
40 41 #include <sys/atomic.h>
41 42 #include <sys/socket.h>
42 43 #include <sys/sysmacros.h>
43 44 #include <sys/crypto/common.h>
44 45 #include <sys/crypto/api.h>
45 46 #include <sys/zone.h>
46 47 #include <netinet/in.h>
47 48 #include <net/if.h>
48 49 #include <net/pfkeyv2.h>
49 50 #include <net/pfpolicy.h>
50 51 #include <inet/common.h>
51 52 #include <netinet/ip6.h>
52 53 #include <inet/ip.h>
53 54 #include <inet/ip_ire.h>
54 55 #include <inet/ip6.h>
55 56 #include <inet/ipsec_info.h>
56 57 #include <inet/tcp.h>
57 58 #include <inet/sadb.h>
58 59 #include <inet/ipsec_impl.h>
59 60 #include <inet/ipsecah.h>
60 61 #include <inet/ipsecesp.h>
61 62 #include <sys/random.h>
62 63 #include <sys/dlpi.h>
63 64 #include <sys/strsun.h>
64 65 #include <sys/strsubr.h>
65 66 #include <inet/ip_if.h>
66 67 #include <inet/ipdrop.h>
|
↓ open down ↓ |
32 lines elided |
↑ open up ↑ |
67 68 #include <inet/ipclassifier.h>
68 69 #include <inet/sctp_ip.h>
69 70 #include <sys/tsol/tnet.h>
70 71
71 72 /*
72 73 * This source file contains Security Association Database (SADB) common
73 74 * routines. They are linked in with the AH module. Since AH has no chance
74 75 * of falling under export control, it was safe to link it in there.
75 76 */
76 77
77 -static mblk_t *sadb_extended_acquire(ipsec_selector_t *, ipsec_policy_t *,
78 - ipsec_action_t *, boolean_t, uint32_t, uint32_t, sadb_sens_t *,
78 +static uint8_t *sadb_action_to_ecomb(uint8_t *, uint8_t *, ipsec_action_t *,
79 79 netstack_t *);
80 80 static ipsa_t *sadb_torch_assoc(isaf_t *, ipsa_t *);
81 81 static void sadb_destroy_acqlist(iacqf_t **, uint_t, boolean_t,
82 82 netstack_t *);
83 83 static void sadb_destroy(sadb_t *, netstack_t *);
84 84 static mblk_t *sadb_sa2msg(ipsa_t *, sadb_msg_t *);
85 85 static ts_label_t *sadb_label_from_sens(sadb_sens_t *, uint64_t *);
86 -static sadb_sens_t *sadb_make_sens_ext(ts_label_t *tsl, int *len);
87 86
88 87 static time_t sadb_add_time(time_t, uint64_t);
89 88 static void lifetime_fuzz(ipsa_t *);
90 89 static void age_pair_peer_list(templist_t *, sadb_t *, boolean_t);
91 90 static int get_ipsa_pair(ipsa_query_t *, ipsap_t *, int *);
92 91 static void init_ipsa_pair(ipsap_t *);
93 92 static void destroy_ipsa_pair(ipsap_t *);
94 93 static int update_pairing(ipsap_t *, ipsa_query_t *, keysock_in_t *, int *);
95 94 static void ipsa_set_replay(ipsa_t *ipsa, uint32_t offset);
96 95
97 96 /*
98 97 * ipsacq_maxpackets is defined here to make it tunable
99 98 * from /etc/system.
100 99 */
101 100 extern uint64_t ipsacq_maxpackets;
102 101
103 102 #define SET_EXPIRE(sa, delta, exp) { \
104 103 if (((sa)->ipsa_ ## delta) != 0) { \
105 104 (sa)->ipsa_ ## exp = sadb_add_time((sa)->ipsa_addtime, \
106 105 (sa)->ipsa_ ## delta); \
107 106 } \
108 107 }
109 108
110 109 #define UPDATE_EXPIRE(sa, delta, exp) { \
111 110 if (((sa)->ipsa_ ## delta) != 0) { \
112 111 time_t tmp = sadb_add_time((sa)->ipsa_usetime, \
113 112 (sa)->ipsa_ ## delta); \
114 113 if (((sa)->ipsa_ ## exp) == 0) \
115 114 (sa)->ipsa_ ## exp = tmp; \
116 115 else \
117 116 (sa)->ipsa_ ## exp = \
118 117 MIN((sa)->ipsa_ ## exp, tmp); \
119 118 } \
120 119 }
121 120
122 121
123 122 /* wrap the macro so we can pass it as a function pointer */
124 123 void
125 124 sadb_sa_refrele(void *target)
126 125 {
127 126 IPSA_REFRELE(((ipsa_t *)target));
128 127 }
129 128
130 129 /*
131 130 * We presume that sizeof (long) == sizeof (time_t) and that time_t is
132 131 * a signed type.
133 132 */
134 133 #define TIME_MAX LONG_MAX
135 134
136 135 /*
137 136 * PF_KEY gives us lifetimes in uint64_t seconds. We presume that
138 137 * time_t is defined to be a signed type with the same range as
139 138 * "long". On ILP32 systems, we thus run the risk of wrapping around
140 139 * at end of time, as well as "overwrapping" the clock back around
141 140 * into a seemingly valid but incorrect future date earlier than the
142 141 * desired expiration.
143 142 *
144 143 * In order to avoid odd behavior (either negative lifetimes or loss
145 144 * of high order bits) when someone asks for bizarrely long SA
146 145 * lifetimes, we do a saturating add for expire times.
147 146 *
148 147 * We presume that ILP32 systems will be past end of support life when
149 148 * the 32-bit time_t overflows (a dangerous assumption, mind you..).
150 149 *
151 150 * On LP64, 2^64 seconds are about 5.8e11 years, at which point we
152 151 * will hopefully have figured out clever ways to avoid the use of
153 152 * fixed-sized integers in computation.
154 153 */
155 154 static time_t
156 155 sadb_add_time(time_t base, uint64_t delta)
157 156 {
158 157 time_t sum;
159 158
160 159 /*
161 160 * Clip delta to the maximum possible time_t value to
162 161 * prevent "overwrapping" back into a shorter-than-desired
163 162 * future time.
164 163 */
165 164 if (delta > TIME_MAX)
166 165 delta = TIME_MAX;
167 166 /*
168 167 * This sum may still overflow.
169 168 */
170 169 sum = base + delta;
171 170
172 171 /*
173 172 * .. so if the result is less than the base, we overflowed.
174 173 */
175 174 if (sum < base)
176 175 sum = TIME_MAX;
177 176
178 177 return (sum);
179 178 }
180 179
181 180 /*
182 181 * Callers of this function have already created a working security
183 182 * association, and have found the appropriate table & hash chain. All this
184 183 * function does is check duplicates, and insert the SA. The caller needs to
185 184 * hold the hash bucket lock and increment the refcnt before insertion.
186 185 *
187 186 * Return 0 if success, EEXIST if collision.
188 187 */
189 188 #define SA_UNIQUE_MATCH(sa1, sa2) \
190 189 (((sa1)->ipsa_unique_id & (sa1)->ipsa_unique_mask) == \
191 190 ((sa2)->ipsa_unique_id & (sa2)->ipsa_unique_mask))
192 191
193 192 int
194 193 sadb_insertassoc(ipsa_t *ipsa, isaf_t *bucket)
195 194 {
196 195 ipsa_t **ptpn = NULL;
197 196 ipsa_t *walker;
198 197 boolean_t unspecsrc;
199 198
200 199 ASSERT(MUTEX_HELD(&bucket->isaf_lock));
201 200
202 201 unspecsrc = IPSA_IS_ADDR_UNSPEC(ipsa->ipsa_srcaddr, ipsa->ipsa_addrfam);
203 202
204 203 walker = bucket->isaf_ipsa;
205 204 ASSERT(walker == NULL || ipsa->ipsa_addrfam == walker->ipsa_addrfam);
206 205
207 206 /*
208 207 * Find insertion point (pointed to with **ptpn). Insert at the head
209 208 * of the list unless there's an unspecified source address, then
210 209 * insert it after the last SA with a specified source address.
211 210 *
212 211 * BTW, you'll have to walk the whole chain, matching on {DST, SPI}
213 212 * checking for collisions.
214 213 */
215 214
216 215 while (walker != NULL) {
217 216 if (IPSA_ARE_ADDR_EQUAL(walker->ipsa_dstaddr,
218 217 ipsa->ipsa_dstaddr, ipsa->ipsa_addrfam)) {
219 218 if (walker->ipsa_spi == ipsa->ipsa_spi)
220 219 return (EEXIST);
221 220
222 221 mutex_enter(&walker->ipsa_lock);
223 222 if (ipsa->ipsa_state == IPSA_STATE_MATURE &&
224 223 (walker->ipsa_flags & IPSA_F_USED) &&
225 224 SA_UNIQUE_MATCH(walker, ipsa)) {
226 225 walker->ipsa_flags |= IPSA_F_CINVALID;
227 226 }
228 227 mutex_exit(&walker->ipsa_lock);
229 228 }
230 229
231 230 if (ptpn == NULL && unspecsrc) {
232 231 if (IPSA_IS_ADDR_UNSPEC(walker->ipsa_srcaddr,
233 232 walker->ipsa_addrfam))
234 233 ptpn = walker->ipsa_ptpn;
235 234 else if (walker->ipsa_next == NULL)
236 235 ptpn = &walker->ipsa_next;
237 236 }
238 237
239 238 walker = walker->ipsa_next;
240 239 }
241 240
242 241 if (ptpn == NULL)
243 242 ptpn = &bucket->isaf_ipsa;
244 243 ipsa->ipsa_next = *ptpn;
245 244 ipsa->ipsa_ptpn = ptpn;
246 245 if (ipsa->ipsa_next != NULL)
247 246 ipsa->ipsa_next->ipsa_ptpn = &ipsa->ipsa_next;
248 247 *ptpn = ipsa;
249 248 ipsa->ipsa_linklock = &bucket->isaf_lock;
250 249
251 250 return (0);
252 251 }
253 252 #undef SA_UNIQUE_MATCH
254 253
255 254 /*
256 255 * Free a security association. Its reference count is 0, which means
257 256 * I must free it. The SA must be unlocked and must not be linked into
258 257 * any fanout list.
259 258 */
260 259 static void
261 260 sadb_freeassoc(ipsa_t *ipsa)
262 261 {
263 262 ipsec_stack_t *ipss = ipsa->ipsa_netstack->netstack_ipsec;
264 263 mblk_t *asyncmp, *mp;
265 264
266 265 ASSERT(ipss != NULL);
267 266 ASSERT(MUTEX_NOT_HELD(&ipsa->ipsa_lock));
268 267 ASSERT(ipsa->ipsa_refcnt == 0);
269 268 ASSERT(ipsa->ipsa_next == NULL);
270 269 ASSERT(ipsa->ipsa_ptpn == NULL);
271 270
272 271
273 272 asyncmp = sadb_clear_lpkt(ipsa);
274 273 if (asyncmp != NULL) {
275 274 mp = ip_recv_attr_free_mblk(asyncmp);
276 275 ip_drop_packet(mp, B_TRUE, NULL,
277 276 DROPPER(ipss, ipds_sadb_inlarval_timeout),
278 277 &ipss->ipsec_sadb_dropper);
279 278 }
280 279 mutex_enter(&ipsa->ipsa_lock);
281 280
282 281 if (ipsa->ipsa_tsl != NULL) {
283 282 label_rele(ipsa->ipsa_tsl);
284 283 ipsa->ipsa_tsl = NULL;
285 284 }
286 285
287 286 if (ipsa->ipsa_otsl != NULL) {
288 287 label_rele(ipsa->ipsa_otsl);
289 288 ipsa->ipsa_otsl = NULL;
290 289 }
291 290
292 291 ipsec_destroy_ctx_tmpl(ipsa, IPSEC_ALG_AUTH);
293 292 ipsec_destroy_ctx_tmpl(ipsa, IPSEC_ALG_ENCR);
294 293 mutex_exit(&ipsa->ipsa_lock);
295 294
296 295 /* bzero() these fields for paranoia's sake. */
297 296 if (ipsa->ipsa_authkey != NULL) {
298 297 bzero(ipsa->ipsa_authkey, ipsa->ipsa_authkeylen);
299 298 kmem_free(ipsa->ipsa_authkey, ipsa->ipsa_authkeylen);
300 299 }
301 300 if (ipsa->ipsa_encrkey != NULL) {
302 301 bzero(ipsa->ipsa_encrkey, ipsa->ipsa_encrkeylen);
303 302 kmem_free(ipsa->ipsa_encrkey, ipsa->ipsa_encrkeylen);
304 303 }
305 304 if (ipsa->ipsa_nonce_buf != NULL) {
306 305 bzero(ipsa->ipsa_nonce_buf, sizeof (ipsec_nonce_t));
307 306 kmem_free(ipsa->ipsa_nonce_buf, sizeof (ipsec_nonce_t));
308 307 }
309 308 if (ipsa->ipsa_src_cid != NULL) {
310 309 IPSID_REFRELE(ipsa->ipsa_src_cid);
311 310 }
312 311 if (ipsa->ipsa_dst_cid != NULL) {
313 312 IPSID_REFRELE(ipsa->ipsa_dst_cid);
314 313 }
315 314 if (ipsa->ipsa_emech.cm_param != NULL)
316 315 kmem_free(ipsa->ipsa_emech.cm_param,
317 316 ipsa->ipsa_emech.cm_param_len);
318 317
319 318 mutex_destroy(&ipsa->ipsa_lock);
320 319 kmem_free(ipsa, sizeof (*ipsa));
321 320 }
322 321
323 322 /*
324 323 * Unlink a security association from a hash bucket. Assume the hash bucket
325 324 * lock is held, but the association's lock is not.
326 325 *
327 326 * Note that we do not bump the bucket's generation number here because
328 327 * we might not be making a visible change to the set of visible SA's.
329 328 * All callers MUST bump the bucket's generation number before they unlock
330 329 * the bucket if they use sadb_unlinkassoc to permanetly remove an SA which
331 330 * was present in the bucket at the time it was locked.
332 331 */
333 332 void
334 333 sadb_unlinkassoc(ipsa_t *ipsa)
335 334 {
336 335 ASSERT(ipsa->ipsa_linklock != NULL);
337 336 ASSERT(MUTEX_HELD(ipsa->ipsa_linklock));
338 337
339 338 /* These fields are protected by the link lock. */
340 339 *(ipsa->ipsa_ptpn) = ipsa->ipsa_next;
341 340 if (ipsa->ipsa_next != NULL) {
342 341 ipsa->ipsa_next->ipsa_ptpn = ipsa->ipsa_ptpn;
343 342 ipsa->ipsa_next = NULL;
344 343 }
345 344
346 345 ipsa->ipsa_ptpn = NULL;
347 346
348 347 /* This may destroy the SA. */
349 348 IPSA_REFRELE(ipsa);
350 349 }
351 350
352 351 void
353 352 sadb_delete_cluster(ipsa_t *assoc)
354 353 {
355 354 uint8_t protocol;
356 355
357 356 if (cl_inet_deletespi &&
358 357 ((assoc->ipsa_state == IPSA_STATE_LARVAL) ||
359 358 (assoc->ipsa_state == IPSA_STATE_MATURE))) {
360 359 protocol = (assoc->ipsa_type == SADB_SATYPE_AH) ?
361 360 IPPROTO_AH : IPPROTO_ESP;
362 361 cl_inet_deletespi(assoc->ipsa_netstack->netstack_stackid,
363 362 protocol, assoc->ipsa_spi, NULL);
364 363 }
365 364 }
366 365
367 366 /*
368 367 * Create a larval security association with the specified SPI. All other
369 368 * fields are zeroed.
370 369 */
371 370 static ipsa_t *
372 371 sadb_makelarvalassoc(uint32_t spi, uint32_t *src, uint32_t *dst, int addrfam,
373 372 netstack_t *ns)
374 373 {
375 374 ipsa_t *newbie;
376 375
377 376 /*
378 377 * Allocate...
379 378 */
380 379
381 380 newbie = (ipsa_t *)kmem_zalloc(sizeof (ipsa_t), KM_NOSLEEP);
382 381 if (newbie == NULL) {
383 382 /* Can't make new larval SA. */
384 383 return (NULL);
385 384 }
386 385
387 386 /* Assigned requested SPI, assume caller does SPI allocation magic. */
388 387 newbie->ipsa_spi = spi;
389 388 newbie->ipsa_netstack = ns; /* No netstack_hold */
390 389
391 390 /*
392 391 * Copy addresses...
393 392 */
394 393
395 394 IPSA_COPY_ADDR(newbie->ipsa_srcaddr, src, addrfam);
396 395 IPSA_COPY_ADDR(newbie->ipsa_dstaddr, dst, addrfam);
397 396
398 397 newbie->ipsa_addrfam = addrfam;
399 398
400 399 /*
401 400 * Set common initialization values, including refcnt.
402 401 */
403 402 mutex_init(&newbie->ipsa_lock, NULL, MUTEX_DEFAULT, NULL);
404 403 newbie->ipsa_state = IPSA_STATE_LARVAL;
405 404 newbie->ipsa_refcnt = 1;
406 405 newbie->ipsa_freefunc = sadb_freeassoc;
407 406
408 407 /*
409 408 * There aren't a lot of other common initialization values, as
410 409 * they are copied in from the PF_KEY message.
411 410 */
412 411
413 412 return (newbie);
414 413 }
415 414
416 415 /*
417 416 * Call me to initialize a security association fanout.
418 417 */
419 418 static int
420 419 sadb_init_fanout(isaf_t **tablep, uint_t size, int kmflag)
421 420 {
422 421 isaf_t *table;
423 422 int i;
424 423
425 424 table = (isaf_t *)kmem_alloc(size * sizeof (*table), kmflag);
426 425 *tablep = table;
427 426
428 427 if (table == NULL)
429 428 return (ENOMEM);
430 429
431 430 for (i = 0; i < size; i++) {
432 431 mutex_init(&(table[i].isaf_lock), NULL, MUTEX_DEFAULT, NULL);
433 432 table[i].isaf_ipsa = NULL;
434 433 table[i].isaf_gen = 0;
435 434 }
436 435
437 436 return (0);
438 437 }
439 438
440 439 /*
441 440 * Call me to initialize an acquire fanout
442 441 */
443 442 static int
444 443 sadb_init_acfanout(iacqf_t **tablep, uint_t size, int kmflag)
445 444 {
446 445 iacqf_t *table;
447 446 int i;
448 447
449 448 table = (iacqf_t *)kmem_alloc(size * sizeof (*table), kmflag);
450 449 *tablep = table;
451 450
452 451 if (table == NULL)
453 452 return (ENOMEM);
454 453
455 454 for (i = 0; i < size; i++) {
456 455 mutex_init(&(table[i].iacqf_lock), NULL, MUTEX_DEFAULT, NULL);
457 456 table[i].iacqf_ipsacq = NULL;
458 457 }
459 458
460 459 return (0);
461 460 }
462 461
463 462 /*
464 463 * Attempt to initialize an SADB instance. On failure, return ENOMEM;
465 464 * caller must clean up partial allocations.
466 465 */
467 466 static int
468 467 sadb_init_trial(sadb_t *sp, uint_t size, int kmflag)
469 468 {
470 469 ASSERT(sp->sdb_of == NULL);
471 470 ASSERT(sp->sdb_if == NULL);
472 471 ASSERT(sp->sdb_acq == NULL);
473 472
474 473 sp->sdb_hashsize = size;
475 474 if (sadb_init_fanout(&sp->sdb_of, size, kmflag) != 0)
476 475 return (ENOMEM);
477 476 if (sadb_init_fanout(&sp->sdb_if, size, kmflag) != 0)
478 477 return (ENOMEM);
479 478 if (sadb_init_acfanout(&sp->sdb_acq, size, kmflag) != 0)
480 479 return (ENOMEM);
481 480
482 481 return (0);
483 482 }
484 483
485 484 /*
486 485 * Call me to initialize an SADB instance; fall back to default size on failure.
487 486 */
488 487 static void
489 488 sadb_init(const char *name, sadb_t *sp, uint_t size, uint_t ver,
490 489 netstack_t *ns)
491 490 {
492 491 ASSERT(sp->sdb_of == NULL);
493 492 ASSERT(sp->sdb_if == NULL);
494 493 ASSERT(sp->sdb_acq == NULL);
495 494
496 495 if (size < IPSEC_DEFAULT_HASH_SIZE)
497 496 size = IPSEC_DEFAULT_HASH_SIZE;
498 497
499 498 if (sadb_init_trial(sp, size, KM_NOSLEEP) != 0) {
500 499
501 500 cmn_err(CE_WARN,
502 501 "Unable to allocate %u entry IPv%u %s SADB hash table",
503 502 size, ver, name);
504 503
505 504 sadb_destroy(sp, ns);
506 505 size = IPSEC_DEFAULT_HASH_SIZE;
507 506 cmn_err(CE_WARN, "Falling back to %d entries", size);
508 507 (void) sadb_init_trial(sp, size, KM_SLEEP);
509 508 }
510 509 }
511 510
512 511
513 512 /*
514 513 * Initialize an SADB-pair.
515 514 */
516 515 void
517 516 sadbp_init(const char *name, sadbp_t *sp, int type, int size, netstack_t *ns)
518 517 {
519 518 sadb_init(name, &sp->s_v4, size, 4, ns);
520 519 sadb_init(name, &sp->s_v6, size, 6, ns);
521 520
522 521 sp->s_satype = type;
523 522
524 523 ASSERT((type == SADB_SATYPE_AH) || (type == SADB_SATYPE_ESP));
525 524 if (type == SADB_SATYPE_AH) {
526 525 ipsec_stack_t *ipss = ns->netstack_ipsec;
527 526
528 527 ip_drop_register(&ipss->ipsec_sadb_dropper, "IPsec SADB");
529 528 sp->s_addflags = AH_ADD_SETTABLE_FLAGS;
530 529 sp->s_updateflags = AH_UPDATE_SETTABLE_FLAGS;
531 530 } else {
532 531 sp->s_addflags = ESP_ADD_SETTABLE_FLAGS;
533 532 sp->s_updateflags = ESP_UPDATE_SETTABLE_FLAGS;
534 533 }
535 534 }
536 535
537 536 /*
538 537 * Deliver a single SADB_DUMP message representing a single SA. This is
539 538 * called many times by sadb_dump().
540 539 *
541 540 * If the return value of this is ENOBUFS (not the same as ENOMEM), then
542 541 * the caller should take that as a hint that dupb() on the "original answer"
543 542 * failed, and that perhaps the caller should try again with a copyb()ed
544 543 * "original answer".
545 544 */
546 545 static int
547 546 sadb_dump_deliver(queue_t *pfkey_q, mblk_t *original_answer, ipsa_t *ipsa,
548 547 sadb_msg_t *samsg)
549 548 {
550 549 mblk_t *answer;
551 550
552 551 answer = dupb(original_answer);
553 552 if (answer == NULL)
554 553 return (ENOBUFS);
555 554 answer->b_cont = sadb_sa2msg(ipsa, samsg);
556 555 if (answer->b_cont == NULL) {
557 556 freeb(answer);
558 557 return (ENOMEM);
559 558 }
560 559
561 560 /* Just do a putnext, and let keysock deal with flow control. */
562 561 putnext(pfkey_q, answer);
563 562 return (0);
564 563 }
565 564
566 565 /*
567 566 * Common function to allocate and prepare a keysock_out_t M_CTL message.
568 567 */
569 568 mblk_t *
570 569 sadb_keysock_out(minor_t serial)
571 570 {
572 571 mblk_t *mp;
573 572 keysock_out_t *kso;
574 573
575 574 mp = allocb(sizeof (ipsec_info_t), BPRI_HI);
576 575 if (mp != NULL) {
577 576 mp->b_datap->db_type = M_CTL;
578 577 mp->b_wptr += sizeof (ipsec_info_t);
579 578 kso = (keysock_out_t *)mp->b_rptr;
580 579 kso->ks_out_type = KEYSOCK_OUT;
581 580 kso->ks_out_len = sizeof (*kso);
582 581 kso->ks_out_serial = serial;
583 582 }
584 583
585 584 return (mp);
586 585 }
587 586
588 587 /*
589 588 * Perform an SADB_DUMP, spewing out every SA in an array of SA fanouts
590 589 * to keysock.
591 590 */
592 591 static int
593 592 sadb_dump_fanout(queue_t *pfkey_q, mblk_t *mp, minor_t serial, isaf_t *fanout,
594 593 int num_entries, boolean_t do_peers, time_t active_time)
595 594 {
596 595 int i, error = 0;
597 596 mblk_t *original_answer;
598 597 ipsa_t *walker;
599 598 sadb_msg_t *samsg;
600 599 time_t current;
601 600
602 601 /*
603 602 * For each IPSA hash bucket do:
604 603 * - Hold the mutex
605 604 * - Walk each entry, doing an sadb_dump_deliver() on it.
606 605 */
607 606 ASSERT(mp->b_cont != NULL);
608 607 samsg = (sadb_msg_t *)mp->b_cont->b_rptr;
609 608
610 609 original_answer = sadb_keysock_out(serial);
611 610 if (original_answer == NULL)
612 611 return (ENOMEM);
613 612
614 613 current = gethrestime_sec();
615 614 for (i = 0; i < num_entries; i++) {
616 615 mutex_enter(&fanout[i].isaf_lock);
617 616 for (walker = fanout[i].isaf_ipsa; walker != NULL;
618 617 walker = walker->ipsa_next) {
619 618 if (!do_peers && walker->ipsa_haspeer)
620 619 continue;
621 620 if ((active_time != 0) &&
622 621 ((current - walker->ipsa_lastuse) > active_time))
623 622 continue;
624 623 error = sadb_dump_deliver(pfkey_q, original_answer,
625 624 walker, samsg);
626 625 if (error == ENOBUFS) {
627 626 mblk_t *new_original_answer;
628 627
629 628 /* Ran out of dupb's. Try a copyb. */
630 629 new_original_answer = copyb(original_answer);
631 630 if (new_original_answer == NULL) {
632 631 error = ENOMEM;
633 632 } else {
634 633 freeb(original_answer);
635 634 original_answer = new_original_answer;
636 635 error = sadb_dump_deliver(pfkey_q,
637 636 original_answer, walker, samsg);
638 637 }
639 638 }
640 639 if (error != 0)
641 640 break; /* out of for loop. */
642 641 }
643 642 mutex_exit(&fanout[i].isaf_lock);
644 643 if (error != 0)
645 644 break; /* out of for loop. */
646 645 }
647 646
648 647 freeb(original_answer);
649 648 return (error);
650 649 }
651 650
652 651 /*
653 652 * Dump an entire SADB; outbound first, then inbound.
654 653 */
655 654
656 655 int
657 656 sadb_dump(queue_t *pfkey_q, mblk_t *mp, keysock_in_t *ksi, sadb_t *sp)
658 657 {
659 658 int error;
660 659 time_t active_time = 0;
661 660 sadb_x_edump_t *edump =
662 661 (sadb_x_edump_t *)ksi->ks_in_extv[SADB_X_EXT_EDUMP];
663 662
664 663 if (edump != NULL) {
665 664 active_time = edump->sadb_x_edump_timeout;
666 665 }
667 666
668 667 /* Dump outbound */
669 668 error = sadb_dump_fanout(pfkey_q, mp, ksi->ks_in_serial, sp->sdb_of,
670 669 sp->sdb_hashsize, B_TRUE, active_time);
671 670 if (error)
672 671 return (error);
673 672
674 673 /* Dump inbound */
675 674 return sadb_dump_fanout(pfkey_q, mp, ksi->ks_in_serial, sp->sdb_if,
676 675 sp->sdb_hashsize, B_FALSE, active_time);
677 676 }
678 677
679 678 /*
680 679 * Generic sadb table walker.
681 680 *
682 681 * Call "walkfn" for each SA in each bucket in "table"; pass the
683 682 * bucket, the entry and "cookie" to the callback function.
684 683 * Take care to ensure that walkfn can delete the SA without screwing
685 684 * up our traverse.
686 685 *
687 686 * The bucket is locked for the duration of the callback, both so that the
688 687 * callback can just call sadb_unlinkassoc() when it wants to delete something,
689 688 * and so that no new entries are added while we're walking the list.
690 689 */
691 690 static void
692 691 sadb_walker(isaf_t *table, uint_t numentries,
693 692 void (*walkfn)(isaf_t *head, ipsa_t *entry, void *cookie),
694 693 void *cookie)
695 694 {
696 695 int i;
697 696 for (i = 0; i < numentries; i++) {
698 697 ipsa_t *entry, *next;
699 698
700 699 mutex_enter(&table[i].isaf_lock);
701 700
702 701 for (entry = table[i].isaf_ipsa; entry != NULL;
703 702 entry = next) {
704 703 next = entry->ipsa_next;
705 704 (*walkfn)(&table[i], entry, cookie);
706 705 }
707 706 mutex_exit(&table[i].isaf_lock);
708 707 }
709 708 }
710 709
711 710 /*
712 711 * Call me to free up a security association fanout. Use the forever
713 712 * variable to indicate freeing up the SAs (forever == B_FALSE, e.g.
714 713 * an SADB_FLUSH message), or destroying everything (forever == B_TRUE,
715 714 * when a module is unloaded).
716 715 */
717 716 static void
718 717 sadb_destroyer(isaf_t **tablep, uint_t numentries, boolean_t forever,
719 718 boolean_t inbound)
720 719 {
721 720 int i;
722 721 isaf_t *table = *tablep;
723 722 uint8_t protocol;
724 723 ipsa_t *sa;
725 724 netstackid_t sid;
726 725
727 726 if (table == NULL)
728 727 return;
729 728
730 729 for (i = 0; i < numentries; i++) {
731 730 mutex_enter(&table[i].isaf_lock);
732 731 while ((sa = table[i].isaf_ipsa) != NULL) {
733 732 if (inbound && cl_inet_deletespi &&
734 733 (sa->ipsa_state != IPSA_STATE_ACTIVE_ELSEWHERE) &&
735 734 (sa->ipsa_state != IPSA_STATE_IDLE)) {
736 735 protocol = (sa->ipsa_type == SADB_SATYPE_AH) ?
737 736 IPPROTO_AH : IPPROTO_ESP;
738 737 sid = sa->ipsa_netstack->netstack_stackid;
739 738 cl_inet_deletespi(sid, protocol, sa->ipsa_spi,
740 739 NULL);
741 740 }
742 741 sadb_unlinkassoc(sa);
743 742 }
744 743 table[i].isaf_gen++;
745 744 mutex_exit(&table[i].isaf_lock);
746 745 if (forever)
747 746 mutex_destroy(&(table[i].isaf_lock));
748 747 }
749 748
750 749 if (forever) {
751 750 *tablep = NULL;
752 751 kmem_free(table, numentries * sizeof (*table));
753 752 }
754 753 }
755 754
756 755 /*
757 756 * Entry points to sadb_destroyer().
758 757 */
759 758 static void
760 759 sadb_flush(sadb_t *sp, netstack_t *ns)
761 760 {
762 761 /*
763 762 * Flush out each bucket, one at a time. Were it not for keysock's
764 763 * enforcement, there would be a subtlety where I could add on the
765 764 * heels of a flush. With keysock's enforcement, however, this
766 765 * makes ESP's job easy.
767 766 */
768 767 sadb_destroyer(&sp->sdb_of, sp->sdb_hashsize, B_FALSE, B_FALSE);
769 768 sadb_destroyer(&sp->sdb_if, sp->sdb_hashsize, B_FALSE, B_TRUE);
770 769
771 770 /* For each acquire, destroy it; leave the bucket mutex alone. */
772 771 sadb_destroy_acqlist(&sp->sdb_acq, sp->sdb_hashsize, B_FALSE, ns);
773 772 }
774 773
775 774 static void
776 775 sadb_destroy(sadb_t *sp, netstack_t *ns)
777 776 {
778 777 sadb_destroyer(&sp->sdb_of, sp->sdb_hashsize, B_TRUE, B_FALSE);
779 778 sadb_destroyer(&sp->sdb_if, sp->sdb_hashsize, B_TRUE, B_TRUE);
780 779
781 780 /* For each acquire, destroy it, including the bucket mutex. */
782 781 sadb_destroy_acqlist(&sp->sdb_acq, sp->sdb_hashsize, B_TRUE, ns);
783 782
784 783 ASSERT(sp->sdb_of == NULL);
785 784 ASSERT(sp->sdb_if == NULL);
786 785 ASSERT(sp->sdb_acq == NULL);
787 786 }
788 787
789 788 void
790 789 sadbp_flush(sadbp_t *spp, netstack_t *ns)
791 790 {
792 791 sadb_flush(&spp->s_v4, ns);
793 792 sadb_flush(&spp->s_v6, ns);
794 793 }
795 794
796 795 void
797 796 sadbp_destroy(sadbp_t *spp, netstack_t *ns)
798 797 {
799 798 sadb_destroy(&spp->s_v4, ns);
800 799 sadb_destroy(&spp->s_v6, ns);
801 800
802 801 if (spp->s_satype == SADB_SATYPE_AH) {
803 802 ipsec_stack_t *ipss = ns->netstack_ipsec;
804 803
805 804 ip_drop_unregister(&ipss->ipsec_sadb_dropper);
806 805 }
807 806 }
808 807
809 808
810 809 /*
811 810 * Check hard vs. soft lifetimes. If there's a reality mismatch (e.g.
812 811 * soft lifetimes > hard lifetimes) return an appropriate diagnostic for
813 812 * EINVAL.
814 813 */
815 814 int
816 815 sadb_hardsoftchk(sadb_lifetime_t *hard, sadb_lifetime_t *soft,
817 816 sadb_lifetime_t *idle)
818 817 {
819 818 if (hard == NULL || soft == NULL)
820 819 return (0);
821 820
822 821 if (hard->sadb_lifetime_allocations != 0 &&
823 822 soft->sadb_lifetime_allocations != 0 &&
824 823 hard->sadb_lifetime_allocations < soft->sadb_lifetime_allocations)
825 824 return (SADB_X_DIAGNOSTIC_ALLOC_HSERR);
826 825
827 826 if (hard->sadb_lifetime_bytes != 0 &&
828 827 soft->sadb_lifetime_bytes != 0 &&
829 828 hard->sadb_lifetime_bytes < soft->sadb_lifetime_bytes)
830 829 return (SADB_X_DIAGNOSTIC_BYTES_HSERR);
831 830
832 831 if (hard->sadb_lifetime_addtime != 0 &&
833 832 soft->sadb_lifetime_addtime != 0 &&
834 833 hard->sadb_lifetime_addtime < soft->sadb_lifetime_addtime)
835 834 return (SADB_X_DIAGNOSTIC_ADDTIME_HSERR);
836 835
837 836 if (hard->sadb_lifetime_usetime != 0 &&
838 837 soft->sadb_lifetime_usetime != 0 &&
839 838 hard->sadb_lifetime_usetime < soft->sadb_lifetime_usetime)
840 839 return (SADB_X_DIAGNOSTIC_USETIME_HSERR);
841 840
842 841 if (idle != NULL) {
843 842 if (hard->sadb_lifetime_addtime != 0 &&
844 843 idle->sadb_lifetime_addtime != 0 &&
845 844 hard->sadb_lifetime_addtime < idle->sadb_lifetime_addtime)
846 845 return (SADB_X_DIAGNOSTIC_ADDTIME_HSERR);
847 846
848 847 if (soft->sadb_lifetime_addtime != 0 &&
849 848 idle->sadb_lifetime_addtime != 0 &&
850 849 soft->sadb_lifetime_addtime < idle->sadb_lifetime_addtime)
851 850 return (SADB_X_DIAGNOSTIC_ADDTIME_HSERR);
852 851
853 852 if (hard->sadb_lifetime_usetime != 0 &&
854 853 idle->sadb_lifetime_usetime != 0 &&
855 854 hard->sadb_lifetime_usetime < idle->sadb_lifetime_usetime)
856 855 return (SADB_X_DIAGNOSTIC_USETIME_HSERR);
857 856
858 857 if (soft->sadb_lifetime_usetime != 0 &&
859 858 idle->sadb_lifetime_usetime != 0 &&
860 859 soft->sadb_lifetime_usetime < idle->sadb_lifetime_usetime)
861 860 return (SADB_X_DIAGNOSTIC_USETIME_HSERR);
862 861 }
863 862
864 863 return (0);
865 864 }
866 865
867 866 /*
868 867 * Sanity check sensitivity labels.
869 868 *
870 869 * For now, just reject labels on unlabeled systems.
871 870 */
872 871 int
873 872 sadb_labelchk(keysock_in_t *ksi)
874 873 {
875 874 if (!is_system_labeled()) {
876 875 if (ksi->ks_in_extv[SADB_EXT_SENSITIVITY] != NULL)
877 876 return (SADB_X_DIAGNOSTIC_BAD_LABEL);
878 877
879 878 if (ksi->ks_in_extv[SADB_X_EXT_OUTER_SENS] != NULL)
880 879 return (SADB_X_DIAGNOSTIC_BAD_LABEL);
881 880 }
882 881
883 882 return (0);
884 883 }
885 884
886 885 /*
887 886 * Clone a security association for the purposes of inserting a single SA
888 887 * into inbound and outbound tables respectively. This function should only
889 888 * be called from sadb_common_add().
890 889 */
891 890 static ipsa_t *
892 891 sadb_cloneassoc(ipsa_t *ipsa)
893 892 {
894 893 ipsa_t *newbie;
895 894 boolean_t error = B_FALSE;
896 895
897 896 ASSERT(MUTEX_NOT_HELD(&(ipsa->ipsa_lock)));
898 897
899 898 newbie = kmem_alloc(sizeof (ipsa_t), KM_NOSLEEP);
900 899 if (newbie == NULL)
901 900 return (NULL);
902 901
903 902 /* Copy over what we can. */
904 903 *newbie = *ipsa;
905 904
906 905 /* bzero and initialize locks, in case *_init() allocates... */
907 906 mutex_init(&newbie->ipsa_lock, NULL, MUTEX_DEFAULT, NULL);
908 907
909 908 if (newbie->ipsa_tsl != NULL)
910 909 label_hold(newbie->ipsa_tsl);
911 910
912 911 if (newbie->ipsa_otsl != NULL)
913 912 label_hold(newbie->ipsa_otsl);
914 913
915 914 /*
916 915 * While somewhat dain-bramaged, the most graceful way to
917 916 * recover from errors is to keep plowing through the
918 917 * allocations, and getting what I can. It's easier to call
919 918 * sadb_freeassoc() on the stillborn clone when all the
920 919 * pointers aren't pointing to the parent's data.
921 920 */
922 921
923 922 if (ipsa->ipsa_authkey != NULL) {
924 923 newbie->ipsa_authkey = kmem_alloc(newbie->ipsa_authkeylen,
925 924 KM_NOSLEEP);
926 925 if (newbie->ipsa_authkey == NULL) {
927 926 error = B_TRUE;
928 927 } else {
929 928 bcopy(ipsa->ipsa_authkey, newbie->ipsa_authkey,
930 929 newbie->ipsa_authkeylen);
931 930
932 931 newbie->ipsa_kcfauthkey.ck_data =
933 932 newbie->ipsa_authkey;
934 933 }
935 934
936 935 if (newbie->ipsa_amech.cm_param != NULL) {
937 936 newbie->ipsa_amech.cm_param =
938 937 (char *)&newbie->ipsa_mac_len;
939 938 }
940 939 }
941 940
942 941 if (ipsa->ipsa_encrkey != NULL) {
943 942 newbie->ipsa_encrkey = kmem_alloc(newbie->ipsa_encrkeylen,
944 943 KM_NOSLEEP);
945 944 if (newbie->ipsa_encrkey == NULL) {
946 945 error = B_TRUE;
947 946 } else {
948 947 bcopy(ipsa->ipsa_encrkey, newbie->ipsa_encrkey,
949 948 newbie->ipsa_encrkeylen);
950 949
951 950 newbie->ipsa_kcfencrkey.ck_data =
952 951 newbie->ipsa_encrkey;
953 952 }
954 953 }
955 954
956 955 newbie->ipsa_authtmpl = NULL;
957 956 newbie->ipsa_encrtmpl = NULL;
958 957 newbie->ipsa_haspeer = B_TRUE;
959 958
960 959 if (ipsa->ipsa_src_cid != NULL) {
961 960 newbie->ipsa_src_cid = ipsa->ipsa_src_cid;
962 961 IPSID_REFHOLD(ipsa->ipsa_src_cid);
963 962 }
964 963
965 964 if (ipsa->ipsa_dst_cid != NULL) {
966 965 newbie->ipsa_dst_cid = ipsa->ipsa_dst_cid;
967 966 IPSID_REFHOLD(ipsa->ipsa_dst_cid);
968 967 }
969 968
970 969 if (error) {
971 970 sadb_freeassoc(newbie);
972 971 return (NULL);
973 972 }
974 973
975 974 return (newbie);
976 975 }
977 976
978 977 /*
979 978 * Initialize a SADB address extension at the address specified by addrext.
980 979 * Return a pointer to the end of the new address extension.
981 980 */
982 981 static uint8_t *
983 982 sadb_make_addr_ext(uint8_t *start, uint8_t *end, uint16_t exttype,
984 983 sa_family_t af, uint32_t *addr, uint16_t port, uint8_t proto, int prefix)
985 984 {
986 985 struct sockaddr_in *sin;
987 986 struct sockaddr_in6 *sin6;
988 987 uint8_t *cur = start;
989 988 int addrext_len;
990 989 int sin_len;
991 990 sadb_address_t *addrext = (sadb_address_t *)cur;
992 991
993 992 if (cur == NULL)
994 993 return (NULL);
995 994
996 995 cur += sizeof (*addrext);
997 996 if (cur > end)
998 997 return (NULL);
999 998
1000 999 addrext->sadb_address_proto = proto;
1001 1000 addrext->sadb_address_prefixlen = prefix;
1002 1001 addrext->sadb_address_reserved = 0;
1003 1002 addrext->sadb_address_exttype = exttype;
1004 1003
1005 1004 switch (af) {
1006 1005 case AF_INET:
1007 1006 sin = (struct sockaddr_in *)cur;
1008 1007 sin_len = sizeof (*sin);
1009 1008 cur += sin_len;
1010 1009 if (cur > end)
1011 1010 return (NULL);
1012 1011
1013 1012 sin->sin_family = af;
1014 1013 bzero(sin->sin_zero, sizeof (sin->sin_zero));
1015 1014 sin->sin_port = port;
1016 1015 IPSA_COPY_ADDR(&sin->sin_addr, addr, af);
1017 1016 break;
1018 1017 case AF_INET6:
1019 1018 sin6 = (struct sockaddr_in6 *)cur;
1020 1019 sin_len = sizeof (*sin6);
1021 1020 cur += sin_len;
1022 1021 if (cur > end)
1023 1022 return (NULL);
1024 1023
1025 1024 bzero(sin6, sizeof (*sin6));
1026 1025 sin6->sin6_family = af;
1027 1026 sin6->sin6_port = port;
1028 1027 IPSA_COPY_ADDR(&sin6->sin6_addr, addr, af);
1029 1028 break;
1030 1029 }
1031 1030
1032 1031 addrext_len = roundup(cur - start, sizeof (uint64_t));
1033 1032 addrext->sadb_address_len = SADB_8TO64(addrext_len);
1034 1033
1035 1034 cur = start + addrext_len;
1036 1035 if (cur > end)
1037 1036 cur = NULL;
1038 1037
1039 1038 return (cur);
1040 1039 }
1041 1040
1042 1041 /*
1043 1042 * Construct a key management cookie extension.
1044 1043 */
1045 1044
1046 1045 static uint8_t *
1047 1046 sadb_make_kmc_ext(uint8_t *cur, uint8_t *end, uint32_t kmp, uint32_t kmc)
1048 1047 {
1049 1048 sadb_x_kmc_t *kmcext = (sadb_x_kmc_t *)cur;
1050 1049
1051 1050 if (cur == NULL)
1052 1051 return (NULL);
1053 1052
1054 1053 cur += sizeof (*kmcext);
1055 1054
1056 1055 if (cur > end)
1057 1056 return (NULL);
1058 1057
1059 1058 kmcext->sadb_x_kmc_len = SADB_8TO64(sizeof (*kmcext));
1060 1059 kmcext->sadb_x_kmc_exttype = SADB_X_EXT_KM_COOKIE;
1061 1060 kmcext->sadb_x_kmc_proto = kmp;
1062 1061 kmcext->sadb_x_kmc_cookie = kmc;
1063 1062 kmcext->sadb_x_kmc_reserved = 0;
1064 1063
1065 1064 return (cur);
1066 1065 }
1067 1066
1068 1067 /*
1069 1068 * Given an original message header with sufficient space following it, and an
1070 1069 * SA, construct a full PF_KEY message with all of the relevant extensions.
1071 1070 * This is mostly used for SADB_GET, and SADB_DUMP.
1072 1071 */
1073 1072 static mblk_t *
1074 1073 sadb_sa2msg(ipsa_t *ipsa, sadb_msg_t *samsg)
1075 1074 {
1076 1075 int alloclen, addrsize, paddrsize, authsize, encrsize;
1077 1076 int srcidsize, dstidsize, senslen, osenslen;
1078 1077 sa_family_t fam, pfam; /* Address family for SADB_EXT_ADDRESS */
1079 1078 /* src/dst and proxy sockaddrs. */
1080 1079 /*
1081 1080 * The following are pointers into the PF_KEY message this PF_KEY
1082 1081 * message creates.
1083 1082 */
1084 1083 sadb_msg_t *newsamsg;
1085 1084 sadb_sa_t *assoc;
1086 1085 sadb_lifetime_t *lt;
1087 1086 sadb_key_t *key;
1088 1087 sadb_ident_t *ident;
1089 1088 sadb_sens_t *sens;
1090 1089 sadb_ext_t *walker; /* For when we need a generic ext. pointer. */
1091 1090 sadb_x_replay_ctr_t *repl_ctr;
1092 1091 sadb_x_pair_t *pair_ext;
1093 1092
1094 1093 mblk_t *mp;
1095 1094 uint8_t *cur, *end;
1096 1095 /* These indicate the presence of the above extension fields. */
1097 1096 boolean_t soft = B_FALSE, hard = B_FALSE;
1098 1097 boolean_t isrc = B_FALSE, idst = B_FALSE;
1099 1098 boolean_t auth = B_FALSE, encr = B_FALSE;
1100 1099 boolean_t sensinteg = B_FALSE, osensinteg = B_FALSE;
1101 1100 boolean_t srcid = B_FALSE, dstid = B_FALSE;
1102 1101 boolean_t idle;
1103 1102 boolean_t paired;
1104 1103 uint32_t otherspi;
1105 1104
1106 1105 /* First off, figure out the allocation length for this message. */
1107 1106 /*
1108 1107 * Constant stuff. This includes base, SA, address (src, dst),
1109 1108 * and lifetime (current).
1110 1109 */
1111 1110 alloclen = sizeof (sadb_msg_t) + sizeof (sadb_sa_t) +
1112 1111 sizeof (sadb_lifetime_t);
1113 1112
1114 1113 fam = ipsa->ipsa_addrfam;
1115 1114 switch (fam) {
1116 1115 case AF_INET:
1117 1116 addrsize = roundup(sizeof (struct sockaddr_in) +
1118 1117 sizeof (sadb_address_t), sizeof (uint64_t));
1119 1118 break;
1120 1119 case AF_INET6:
1121 1120 addrsize = roundup(sizeof (struct sockaddr_in6) +
1122 1121 sizeof (sadb_address_t), sizeof (uint64_t));
1123 1122 break;
1124 1123 default:
1125 1124 return (NULL);
1126 1125 }
1127 1126 /*
1128 1127 * Allocate TWO address extensions, for source and destination.
1129 1128 * (Thus, the * 2.)
1130 1129 */
1131 1130 alloclen += addrsize * 2;
1132 1131 if (ipsa->ipsa_flags & IPSA_F_NATT_REM)
1133 1132 alloclen += addrsize;
1134 1133 if (ipsa->ipsa_flags & IPSA_F_NATT_LOC)
1135 1134 alloclen += addrsize;
1136 1135
1137 1136 if (ipsa->ipsa_flags & IPSA_F_PAIRED) {
1138 1137 paired = B_TRUE;
1139 1138 alloclen += sizeof (sadb_x_pair_t);
1140 1139 otherspi = ipsa->ipsa_otherspi;
1141 1140 } else {
1142 1141 paired = B_FALSE;
1143 1142 }
1144 1143
1145 1144 /* How 'bout other lifetimes? */
1146 1145 if (ipsa->ipsa_softaddlt != 0 || ipsa->ipsa_softuselt != 0 ||
1147 1146 ipsa->ipsa_softbyteslt != 0 || ipsa->ipsa_softalloc != 0) {
1148 1147 alloclen += sizeof (sadb_lifetime_t);
1149 1148 soft = B_TRUE;
1150 1149 }
1151 1150
1152 1151 if (ipsa->ipsa_hardaddlt != 0 || ipsa->ipsa_harduselt != 0 ||
1153 1152 ipsa->ipsa_hardbyteslt != 0 || ipsa->ipsa_hardalloc != 0) {
1154 1153 alloclen += sizeof (sadb_lifetime_t);
1155 1154 hard = B_TRUE;
1156 1155 }
1157 1156
1158 1157 if (ipsa->ipsa_idleaddlt != 0 || ipsa->ipsa_idleuselt != 0) {
1159 1158 alloclen += sizeof (sadb_lifetime_t);
1160 1159 idle = B_TRUE;
1161 1160 } else {
1162 1161 idle = B_FALSE;
1163 1162 }
1164 1163
1165 1164 /* Inner addresses. */
1166 1165 if (ipsa->ipsa_innerfam != 0) {
1167 1166 pfam = ipsa->ipsa_innerfam;
1168 1167 switch (pfam) {
1169 1168 case AF_INET6:
1170 1169 paddrsize = roundup(sizeof (struct sockaddr_in6) +
1171 1170 sizeof (sadb_address_t), sizeof (uint64_t));
1172 1171 break;
1173 1172 case AF_INET:
1174 1173 paddrsize = roundup(sizeof (struct sockaddr_in) +
1175 1174 sizeof (sadb_address_t), sizeof (uint64_t));
1176 1175 break;
1177 1176 default:
1178 1177 cmn_err(CE_PANIC,
1179 1178 "IPsec SADB: Proxy length failure.\n");
1180 1179 break;
1181 1180 }
1182 1181 isrc = B_TRUE;
1183 1182 idst = B_TRUE;
1184 1183 alloclen += 2 * paddrsize;
1185 1184 }
1186 1185
1187 1186 /* For the following fields, assume that length != 0 ==> stuff */
1188 1187 if (ipsa->ipsa_authkeylen != 0) {
1189 1188 authsize = roundup(sizeof (sadb_key_t) + ipsa->ipsa_authkeylen,
1190 1189 sizeof (uint64_t));
1191 1190 alloclen += authsize;
1192 1191 auth = B_TRUE;
1193 1192 }
1194 1193
1195 1194 if (ipsa->ipsa_encrkeylen != 0) {
1196 1195 encrsize = roundup(sizeof (sadb_key_t) + ipsa->ipsa_encrkeylen +
1197 1196 ipsa->ipsa_nonce_len, sizeof (uint64_t));
1198 1197 alloclen += encrsize;
1199 1198 encr = B_TRUE;
1200 1199 } else {
1201 1200 encr = B_FALSE;
1202 1201 }
1203 1202
1204 1203 if (ipsa->ipsa_tsl != NULL) {
1205 1204 senslen = sadb_sens_len_from_label(ipsa->ipsa_tsl);
1206 1205 alloclen += senslen;
1207 1206 sensinteg = B_TRUE;
1208 1207 }
1209 1208
1210 1209 if (ipsa->ipsa_otsl != NULL) {
1211 1210 osenslen = sadb_sens_len_from_label(ipsa->ipsa_otsl);
1212 1211 alloclen += osenslen;
1213 1212 osensinteg = B_TRUE;
1214 1213 }
1215 1214
1216 1215 /*
1217 1216 * Must use strlen() here for lengths. Identities use NULL
1218 1217 * pointers to indicate their nonexistence.
1219 1218 */
1220 1219 if (ipsa->ipsa_src_cid != NULL) {
1221 1220 srcidsize = roundup(sizeof (sadb_ident_t) +
1222 1221 strlen(ipsa->ipsa_src_cid->ipsid_cid) + 1,
1223 1222 sizeof (uint64_t));
1224 1223 alloclen += srcidsize;
1225 1224 srcid = B_TRUE;
1226 1225 }
1227 1226
1228 1227 if (ipsa->ipsa_dst_cid != NULL) {
1229 1228 dstidsize = roundup(sizeof (sadb_ident_t) +
1230 1229 strlen(ipsa->ipsa_dst_cid->ipsid_cid) + 1,
1231 1230 sizeof (uint64_t));
1232 1231 alloclen += dstidsize;
1233 1232 dstid = B_TRUE;
1234 1233 }
1235 1234
1236 1235 if ((ipsa->ipsa_kmp != 0) || (ipsa->ipsa_kmc != 0))
1237 1236 alloclen += sizeof (sadb_x_kmc_t);
1238 1237
1239 1238 if (ipsa->ipsa_replay != 0) {
1240 1239 alloclen += sizeof (sadb_x_replay_ctr_t);
1241 1240 }
1242 1241
1243 1242 /* Make sure the allocation length is a multiple of 8 bytes. */
1244 1243 ASSERT((alloclen & 0x7) == 0);
1245 1244
1246 1245 /* XXX Possibly make it esballoc, with a bzero-ing free_ftn. */
1247 1246 mp = allocb(alloclen, BPRI_HI);
1248 1247 if (mp == NULL)
1249 1248 return (NULL);
1250 1249 bzero(mp->b_rptr, alloclen);
1251 1250
1252 1251 mp->b_wptr += alloclen;
1253 1252 end = mp->b_wptr;
1254 1253 newsamsg = (sadb_msg_t *)mp->b_rptr;
1255 1254 *newsamsg = *samsg;
1256 1255 newsamsg->sadb_msg_len = (uint16_t)SADB_8TO64(alloclen);
1257 1256
1258 1257 mutex_enter(&ipsa->ipsa_lock); /* Since I'm grabbing SA fields... */
1259 1258
1260 1259 newsamsg->sadb_msg_satype = ipsa->ipsa_type;
1261 1260
1262 1261 assoc = (sadb_sa_t *)(newsamsg + 1);
1263 1262 assoc->sadb_sa_len = SADB_8TO64(sizeof (*assoc));
1264 1263 assoc->sadb_sa_exttype = SADB_EXT_SA;
1265 1264 assoc->sadb_sa_spi = ipsa->ipsa_spi;
1266 1265 assoc->sadb_sa_replay = ipsa->ipsa_replay_wsize;
1267 1266 assoc->sadb_sa_state = ipsa->ipsa_state;
1268 1267 assoc->sadb_sa_auth = ipsa->ipsa_auth_alg;
1269 1268 assoc->sadb_sa_encrypt = ipsa->ipsa_encr_alg;
1270 1269 assoc->sadb_sa_flags = ipsa->ipsa_flags;
1271 1270
1272 1271 lt = (sadb_lifetime_t *)(assoc + 1);
1273 1272 lt->sadb_lifetime_len = SADB_8TO64(sizeof (*lt));
1274 1273 lt->sadb_lifetime_exttype = SADB_EXT_LIFETIME_CURRENT;
1275 1274 /* We do not support the concept. */
1276 1275 lt->sadb_lifetime_allocations = 0;
1277 1276 lt->sadb_lifetime_bytes = ipsa->ipsa_bytes;
1278 1277 lt->sadb_lifetime_addtime = ipsa->ipsa_addtime;
1279 1278 lt->sadb_lifetime_usetime = ipsa->ipsa_usetime;
1280 1279
1281 1280 if (hard) {
1282 1281 lt++;
1283 1282 lt->sadb_lifetime_len = SADB_8TO64(sizeof (*lt));
1284 1283 lt->sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD;
1285 1284 lt->sadb_lifetime_allocations = ipsa->ipsa_hardalloc;
1286 1285 lt->sadb_lifetime_bytes = ipsa->ipsa_hardbyteslt;
1287 1286 lt->sadb_lifetime_addtime = ipsa->ipsa_hardaddlt;
1288 1287 lt->sadb_lifetime_usetime = ipsa->ipsa_harduselt;
1289 1288 }
1290 1289
1291 1290 if (soft) {
1292 1291 lt++;
1293 1292 lt->sadb_lifetime_len = SADB_8TO64(sizeof (*lt));
1294 1293 lt->sadb_lifetime_exttype = SADB_EXT_LIFETIME_SOFT;
1295 1294 lt->sadb_lifetime_allocations = ipsa->ipsa_softalloc;
1296 1295 lt->sadb_lifetime_bytes = ipsa->ipsa_softbyteslt;
1297 1296 lt->sadb_lifetime_addtime = ipsa->ipsa_softaddlt;
1298 1297 lt->sadb_lifetime_usetime = ipsa->ipsa_softuselt;
1299 1298 }
1300 1299
1301 1300 if (idle) {
1302 1301 lt++;
1303 1302 lt->sadb_lifetime_len = SADB_8TO64(sizeof (*lt));
1304 1303 lt->sadb_lifetime_exttype = SADB_X_EXT_LIFETIME_IDLE;
1305 1304 lt->sadb_lifetime_addtime = ipsa->ipsa_idleaddlt;
1306 1305 lt->sadb_lifetime_usetime = ipsa->ipsa_idleuselt;
1307 1306 }
1308 1307
1309 1308 cur = (uint8_t *)(lt + 1);
1310 1309
1311 1310 /* NOTE: Don't fill in ports here if we are a tunnel-mode SA. */
1312 1311 cur = sadb_make_addr_ext(cur, end, SADB_EXT_ADDRESS_SRC, fam,
1313 1312 ipsa->ipsa_srcaddr, (!isrc && !idst) ? SA_SRCPORT(ipsa) : 0,
1314 1313 SA_PROTO(ipsa), 0);
1315 1314 if (cur == NULL) {
1316 1315 freemsg(mp);
1317 1316 mp = NULL;
1318 1317 goto bail;
1319 1318 }
1320 1319
1321 1320 cur = sadb_make_addr_ext(cur, end, SADB_EXT_ADDRESS_DST, fam,
1322 1321 ipsa->ipsa_dstaddr, (!isrc && !idst) ? SA_DSTPORT(ipsa) : 0,
1323 1322 SA_PROTO(ipsa), 0);
1324 1323 if (cur == NULL) {
1325 1324 freemsg(mp);
1326 1325 mp = NULL;
1327 1326 goto bail;
1328 1327 }
1329 1328
1330 1329 if (ipsa->ipsa_flags & IPSA_F_NATT_LOC) {
1331 1330 cur = sadb_make_addr_ext(cur, end, SADB_X_EXT_ADDRESS_NATT_LOC,
1332 1331 fam, &ipsa->ipsa_natt_addr_loc, ipsa->ipsa_local_nat_port,
1333 1332 IPPROTO_UDP, 0);
1334 1333 if (cur == NULL) {
1335 1334 freemsg(mp);
1336 1335 mp = NULL;
1337 1336 goto bail;
1338 1337 }
1339 1338 }
1340 1339
1341 1340 if (ipsa->ipsa_flags & IPSA_F_NATT_REM) {
1342 1341 cur = sadb_make_addr_ext(cur, end, SADB_X_EXT_ADDRESS_NATT_REM,
1343 1342 fam, &ipsa->ipsa_natt_addr_rem, ipsa->ipsa_remote_nat_port,
1344 1343 IPPROTO_UDP, 0);
1345 1344 if (cur == NULL) {
1346 1345 freemsg(mp);
1347 1346 mp = NULL;
1348 1347 goto bail;
1349 1348 }
1350 1349 }
1351 1350
1352 1351 /* If we are a tunnel-mode SA, fill in the inner-selectors. */
1353 1352 if (isrc) {
1354 1353 cur = sadb_make_addr_ext(cur, end, SADB_X_EXT_ADDRESS_INNER_SRC,
1355 1354 pfam, ipsa->ipsa_innersrc, SA_SRCPORT(ipsa),
1356 1355 SA_IPROTO(ipsa), ipsa->ipsa_innersrcpfx);
1357 1356 if (cur == NULL) {
1358 1357 freemsg(mp);
1359 1358 mp = NULL;
1360 1359 goto bail;
1361 1360 }
1362 1361 }
1363 1362
1364 1363 if (idst) {
1365 1364 cur = sadb_make_addr_ext(cur, end, SADB_X_EXT_ADDRESS_INNER_DST,
1366 1365 pfam, ipsa->ipsa_innerdst, SA_DSTPORT(ipsa),
1367 1366 SA_IPROTO(ipsa), ipsa->ipsa_innerdstpfx);
1368 1367 if (cur == NULL) {
1369 1368 freemsg(mp);
1370 1369 mp = NULL;
1371 1370 goto bail;
1372 1371 }
1373 1372 }
1374 1373
1375 1374 if ((ipsa->ipsa_kmp != 0) || (ipsa->ipsa_kmc != 0)) {
1376 1375 cur = sadb_make_kmc_ext(cur, end,
1377 1376 ipsa->ipsa_kmp, ipsa->ipsa_kmc);
1378 1377 if (cur == NULL) {
1379 1378 freemsg(mp);
1380 1379 mp = NULL;
1381 1380 goto bail;
1382 1381 }
1383 1382 }
1384 1383
1385 1384 walker = (sadb_ext_t *)cur;
1386 1385 if (auth) {
1387 1386 key = (sadb_key_t *)walker;
1388 1387 key->sadb_key_len = SADB_8TO64(authsize);
1389 1388 key->sadb_key_exttype = SADB_EXT_KEY_AUTH;
1390 1389 key->sadb_key_bits = ipsa->ipsa_authkeybits;
1391 1390 key->sadb_key_reserved = 0;
1392 1391 bcopy(ipsa->ipsa_authkey, key + 1, ipsa->ipsa_authkeylen);
1393 1392 walker = (sadb_ext_t *)((uint64_t *)walker +
1394 1393 walker->sadb_ext_len);
1395 1394 }
1396 1395
1397 1396 if (encr) {
1398 1397 uint8_t *buf_ptr;
1399 1398 key = (sadb_key_t *)walker;
1400 1399 key->sadb_key_len = SADB_8TO64(encrsize);
1401 1400 key->sadb_key_exttype = SADB_EXT_KEY_ENCRYPT;
1402 1401 key->sadb_key_bits = ipsa->ipsa_encrkeybits;
1403 1402 key->sadb_key_reserved = ipsa->ipsa_saltbits;
1404 1403 buf_ptr = (uint8_t *)(key + 1);
1405 1404 bcopy(ipsa->ipsa_encrkey, buf_ptr, ipsa->ipsa_encrkeylen);
1406 1405 if (ipsa->ipsa_salt != NULL) {
1407 1406 buf_ptr += ipsa->ipsa_encrkeylen;
1408 1407 bcopy(ipsa->ipsa_salt, buf_ptr, ipsa->ipsa_saltlen);
1409 1408 }
1410 1409 walker = (sadb_ext_t *)((uint64_t *)walker +
1411 1410 walker->sadb_ext_len);
1412 1411 }
1413 1412
1414 1413 if (srcid) {
1415 1414 ident = (sadb_ident_t *)walker;
1416 1415 ident->sadb_ident_len = SADB_8TO64(srcidsize);
1417 1416 ident->sadb_ident_exttype = SADB_EXT_IDENTITY_SRC;
1418 1417 ident->sadb_ident_type = ipsa->ipsa_src_cid->ipsid_type;
1419 1418 ident->sadb_ident_id = 0;
1420 1419 ident->sadb_ident_reserved = 0;
1421 1420 (void) strcpy((char *)(ident + 1),
1422 1421 ipsa->ipsa_src_cid->ipsid_cid);
1423 1422 walker = (sadb_ext_t *)((uint64_t *)walker +
1424 1423 walker->sadb_ext_len);
1425 1424 }
1426 1425
1427 1426 if (dstid) {
1428 1427 ident = (sadb_ident_t *)walker;
1429 1428 ident->sadb_ident_len = SADB_8TO64(dstidsize);
1430 1429 ident->sadb_ident_exttype = SADB_EXT_IDENTITY_DST;
1431 1430 ident->sadb_ident_type = ipsa->ipsa_dst_cid->ipsid_type;
1432 1431 ident->sadb_ident_id = 0;
1433 1432 ident->sadb_ident_reserved = 0;
1434 1433 (void) strcpy((char *)(ident + 1),
1435 1434 ipsa->ipsa_dst_cid->ipsid_cid);
1436 1435 walker = (sadb_ext_t *)((uint64_t *)walker +
1437 1436 walker->sadb_ext_len);
1438 1437 }
1439 1438
1440 1439 if (sensinteg) {
1441 1440 sens = (sadb_sens_t *)walker;
1442 1441 sadb_sens_from_label(sens, SADB_EXT_SENSITIVITY,
1443 1442 ipsa->ipsa_tsl, senslen);
1444 1443
1445 1444 walker = (sadb_ext_t *)((uint64_t *)walker +
1446 1445 walker->sadb_ext_len);
1447 1446 }
1448 1447
1449 1448 if (osensinteg) {
1450 1449 sens = (sadb_sens_t *)walker;
1451 1450
1452 1451 sadb_sens_from_label(sens, SADB_X_EXT_OUTER_SENS,
1453 1452 ipsa->ipsa_otsl, osenslen);
1454 1453 if (ipsa->ipsa_mac_exempt)
1455 1454 sens->sadb_x_sens_flags = SADB_X_SENS_IMPLICIT;
1456 1455
1457 1456 walker = (sadb_ext_t *)((uint64_t *)walker +
1458 1457 walker->sadb_ext_len);
1459 1458 }
1460 1459
1461 1460 if (paired) {
1462 1461 pair_ext = (sadb_x_pair_t *)walker;
1463 1462
1464 1463 pair_ext->sadb_x_pair_len = SADB_8TO64(sizeof (sadb_x_pair_t));
1465 1464 pair_ext->sadb_x_pair_exttype = SADB_X_EXT_PAIR;
1466 1465 pair_ext->sadb_x_pair_spi = otherspi;
1467 1466
1468 1467 walker = (sadb_ext_t *)((uint64_t *)walker +
1469 1468 walker->sadb_ext_len);
1470 1469 }
1471 1470
1472 1471 if (ipsa->ipsa_replay != 0) {
1473 1472 repl_ctr = (sadb_x_replay_ctr_t *)walker;
1474 1473 repl_ctr->sadb_x_rc_len = SADB_8TO64(sizeof (*repl_ctr));
1475 1474 repl_ctr->sadb_x_rc_exttype = SADB_X_EXT_REPLAY_VALUE;
1476 1475 repl_ctr->sadb_x_rc_replay32 = ipsa->ipsa_replay;
1477 1476 repl_ctr->sadb_x_rc_replay64 = 0;
1478 1477 walker = (sadb_ext_t *)(repl_ctr + 1);
1479 1478 }
1480 1479
1481 1480 bail:
1482 1481 /* Pardon any delays... */
1483 1482 mutex_exit(&ipsa->ipsa_lock);
1484 1483
1485 1484 return (mp);
1486 1485 }
1487 1486
1488 1487 /*
1489 1488 * Strip out key headers or unmarked headers (SADB_EXT_KEY_*, SADB_EXT_UNKNOWN)
1490 1489 * and adjust base message accordingly.
1491 1490 *
1492 1491 * Assume message is pulled up in one piece of contiguous memory.
1493 1492 *
1494 1493 * Say if we start off with:
1495 1494 *
1496 1495 * +------+----+-------------+-----------+---------------+---------------+
1497 1496 * | base | SA | source addr | dest addr | rsrvd. or key | soft lifetime |
1498 1497 * +------+----+-------------+-----------+---------------+---------------+
1499 1498 *
1500 1499 * we will end up with
1501 1500 *
1502 1501 * +------+----+-------------+-----------+---------------+
1503 1502 * | base | SA | source addr | dest addr | soft lifetime |
1504 1503 * +------+----+-------------+-----------+---------------+
1505 1504 */
1506 1505 static void
1507 1506 sadb_strip(sadb_msg_t *samsg)
1508 1507 {
1509 1508 sadb_ext_t *ext;
1510 1509 uint8_t *target = NULL;
1511 1510 uint8_t *msgend;
1512 1511 int sofar = SADB_8TO64(sizeof (*samsg));
1513 1512 int copylen;
1514 1513
1515 1514 ext = (sadb_ext_t *)(samsg + 1);
1516 1515 msgend = (uint8_t *)samsg;
1517 1516 msgend += SADB_64TO8(samsg->sadb_msg_len);
1518 1517 while ((uint8_t *)ext < msgend) {
1519 1518 if (ext->sadb_ext_type == SADB_EXT_RESERVED ||
1520 1519 ext->sadb_ext_type == SADB_EXT_KEY_AUTH ||
1521 1520 ext->sadb_ext_type == SADB_X_EXT_EDUMP ||
1522 1521 ext->sadb_ext_type == SADB_EXT_KEY_ENCRYPT) {
1523 1522 /*
1524 1523 * Aha! I found a header to be erased.
1525 1524 */
1526 1525
1527 1526 if (target != NULL) {
1528 1527 /*
1529 1528 * If I had a previous header to be erased,
1530 1529 * copy over it. I can get away with just
1531 1530 * copying backwards because the target will
1532 1531 * always be 8 bytes behind the source.
1533 1532 */
1534 1533 copylen = ((uint8_t *)ext) - (target +
1535 1534 SADB_64TO8(
1536 1535 ((sadb_ext_t *)target)->sadb_ext_len));
1537 1536 ovbcopy(((uint8_t *)ext - copylen), target,
1538 1537 copylen);
1539 1538 target += copylen;
1540 1539 ((sadb_ext_t *)target)->sadb_ext_len =
1541 1540 SADB_8TO64(((uint8_t *)ext) - target +
1542 1541 SADB_64TO8(ext->sadb_ext_len));
1543 1542 } else {
1544 1543 target = (uint8_t *)ext;
1545 1544 }
1546 1545 } else {
1547 1546 sofar += ext->sadb_ext_len;
1548 1547 }
1549 1548
1550 1549 ext = (sadb_ext_t *)(((uint64_t *)ext) + ext->sadb_ext_len);
1551 1550 }
1552 1551
1553 1552 ASSERT((uint8_t *)ext == msgend);
1554 1553
1555 1554 if (target != NULL) {
1556 1555 copylen = ((uint8_t *)ext) - (target +
1557 1556 SADB_64TO8(((sadb_ext_t *)target)->sadb_ext_len));
1558 1557 if (copylen != 0)
1559 1558 ovbcopy(((uint8_t *)ext - copylen), target, copylen);
1560 1559 }
1561 1560
1562 1561 /* Adjust samsg. */
1563 1562 samsg->sadb_msg_len = (uint16_t)sofar;
1564 1563
1565 1564 /* Assume all of the rest is cleared by caller in sadb_pfkey_echo(). */
1566 1565 }
1567 1566
1568 1567 /*
1569 1568 * AH needs to send an error to PF_KEY. Assume mp points to an M_CTL
1570 1569 * followed by an M_DATA with a PF_KEY message in it. The serial of
1571 1570 * the sending keysock instance is included.
1572 1571 */
1573 1572 void
1574 1573 sadb_pfkey_error(queue_t *pfkey_q, mblk_t *mp, int error, int diagnostic,
1575 1574 uint_t serial)
1576 1575 {
1577 1576 mblk_t *msg = mp->b_cont;
1578 1577 sadb_msg_t *samsg;
1579 1578 keysock_out_t *kso;
1580 1579
1581 1580 /*
1582 1581 * Enough functions call this to merit a NULL queue check.
1583 1582 */
1584 1583 if (pfkey_q == NULL) {
1585 1584 freemsg(mp);
1586 1585 return;
1587 1586 }
1588 1587
1589 1588 ASSERT(msg != NULL);
1590 1589 ASSERT((mp->b_wptr - mp->b_rptr) == sizeof (ipsec_info_t));
1591 1590 ASSERT((msg->b_wptr - msg->b_rptr) >= sizeof (sadb_msg_t));
1592 1591 samsg = (sadb_msg_t *)msg->b_rptr;
1593 1592 kso = (keysock_out_t *)mp->b_rptr;
1594 1593
1595 1594 kso->ks_out_type = KEYSOCK_OUT;
1596 1595 kso->ks_out_len = sizeof (*kso);
1597 1596 kso->ks_out_serial = serial;
1598 1597
1599 1598 /*
1600 1599 * Only send the base message up in the event of an error.
1601 1600 * Don't worry about bzero()-ing, because it was probably bogus
1602 1601 * anyway.
1603 1602 */
1604 1603 msg->b_wptr = msg->b_rptr + sizeof (*samsg);
1605 1604 samsg = (sadb_msg_t *)msg->b_rptr;
1606 1605 samsg->sadb_msg_len = SADB_8TO64(sizeof (*samsg));
1607 1606 samsg->sadb_msg_errno = (uint8_t)error;
1608 1607 if (diagnostic != SADB_X_DIAGNOSTIC_PRESET)
1609 1608 samsg->sadb_x_msg_diagnostic = (uint16_t)diagnostic;
1610 1609
1611 1610 putnext(pfkey_q, mp);
1612 1611 }
1613 1612
1614 1613 /*
1615 1614 * Send a successful return packet back to keysock via the queue in pfkey_q.
1616 1615 *
1617 1616 * Often, an SA is associated with the reply message, it's passed in if needed,
1618 1617 * and NULL if not. BTW, that ipsa will have its refcnt appropriately held,
1619 1618 * and the caller will release said refcnt.
1620 1619 */
1621 1620 void
1622 1621 sadb_pfkey_echo(queue_t *pfkey_q, mblk_t *mp, sadb_msg_t *samsg,
1623 1622 keysock_in_t *ksi, ipsa_t *ipsa)
1624 1623 {
1625 1624 keysock_out_t *kso;
1626 1625 mblk_t *mp1;
1627 1626 sadb_msg_t *newsamsg;
1628 1627 uint8_t *oldend;
1629 1628
1630 1629 ASSERT((mp->b_cont != NULL) &&
1631 1630 ((void *)samsg == (void *)mp->b_cont->b_rptr) &&
1632 1631 ((void *)mp->b_rptr == (void *)ksi));
1633 1632
1634 1633 switch (samsg->sadb_msg_type) {
1635 1634 case SADB_ADD:
1636 1635 case SADB_UPDATE:
1637 1636 case SADB_X_UPDATEPAIR:
1638 1637 case SADB_X_DELPAIR_STATE:
1639 1638 case SADB_FLUSH:
1640 1639 case SADB_DUMP:
1641 1640 /*
1642 1641 * I have all of the message already. I just need to strip
1643 1642 * out the keying material and echo the message back.
1644 1643 *
1645 1644 * NOTE: for SADB_DUMP, the function sadb_dump() did the
1646 1645 * work. When DUMP reaches here, it should only be a base
1647 1646 * message.
1648 1647 */
1649 1648 justecho:
1650 1649 if (ksi->ks_in_extv[SADB_EXT_KEY_AUTH] != NULL ||
1651 1650 ksi->ks_in_extv[SADB_EXT_KEY_ENCRYPT] != NULL ||
1652 1651 ksi->ks_in_extv[SADB_X_EXT_EDUMP] != NULL) {
1653 1652 sadb_strip(samsg);
1654 1653 /* Assume PF_KEY message is contiguous. */
1655 1654 ASSERT(mp->b_cont->b_cont == NULL);
1656 1655 oldend = mp->b_cont->b_wptr;
1657 1656 mp->b_cont->b_wptr = mp->b_cont->b_rptr +
1658 1657 SADB_64TO8(samsg->sadb_msg_len);
1659 1658 bzero(mp->b_cont->b_wptr, oldend - mp->b_cont->b_wptr);
1660 1659 }
1661 1660 break;
1662 1661 case SADB_GET:
1663 1662 /*
1664 1663 * Do a lot of work here, because of the ipsa I just found.
1665 1664 * First construct the new PF_KEY message, then abandon
1666 1665 * the old one.
1667 1666 */
1668 1667 mp1 = sadb_sa2msg(ipsa, samsg);
1669 1668 if (mp1 == NULL) {
1670 1669 sadb_pfkey_error(pfkey_q, mp, ENOMEM,
1671 1670 SADB_X_DIAGNOSTIC_NONE, ksi->ks_in_serial);
1672 1671 return;
1673 1672 }
1674 1673 freemsg(mp->b_cont);
1675 1674 mp->b_cont = mp1;
1676 1675 break;
1677 1676 case SADB_DELETE:
1678 1677 case SADB_X_DELPAIR:
1679 1678 if (ipsa == NULL)
1680 1679 goto justecho;
1681 1680 /*
1682 1681 * Because listening KMds may require more info, treat
1683 1682 * DELETE like a special case of GET.
1684 1683 */
1685 1684 mp1 = sadb_sa2msg(ipsa, samsg);
1686 1685 if (mp1 == NULL) {
1687 1686 sadb_pfkey_error(pfkey_q, mp, ENOMEM,
1688 1687 SADB_X_DIAGNOSTIC_NONE, ksi->ks_in_serial);
1689 1688 return;
1690 1689 }
1691 1690 newsamsg = (sadb_msg_t *)mp1->b_rptr;
1692 1691 sadb_strip(newsamsg);
1693 1692 oldend = mp1->b_wptr;
1694 1693 mp1->b_wptr = mp1->b_rptr + SADB_64TO8(newsamsg->sadb_msg_len);
1695 1694 bzero(mp1->b_wptr, oldend - mp1->b_wptr);
1696 1695 freemsg(mp->b_cont);
1697 1696 mp->b_cont = mp1;
1698 1697 break;
1699 1698 default:
1700 1699 if (mp != NULL)
1701 1700 freemsg(mp);
1702 1701 return;
1703 1702 }
1704 1703
1705 1704 /* ksi is now null and void. */
1706 1705 kso = (keysock_out_t *)ksi;
1707 1706 kso->ks_out_type = KEYSOCK_OUT;
1708 1707 kso->ks_out_len = sizeof (*kso);
1709 1708 kso->ks_out_serial = ksi->ks_in_serial;
1710 1709 /* We're ready to send... */
1711 1710 putnext(pfkey_q, mp);
1712 1711 }
1713 1712
1714 1713 /*
1715 1714 * Set up a global pfkey_q instance for AH, ESP, or some other consumer.
1716 1715 */
1717 1716 void
1718 1717 sadb_keysock_hello(queue_t **pfkey_qp, queue_t *q, mblk_t *mp,
1719 1718 void (*ager)(void *), void *agerarg, timeout_id_t *top, int satype)
1720 1719 {
1721 1720 keysock_hello_ack_t *kha;
1722 1721 queue_t *oldq;
1723 1722
1724 1723 ASSERT(OTHERQ(q) != NULL);
1725 1724
1726 1725 /*
1727 1726 * First, check atomically that I'm the first and only keysock
1728 1727 * instance.
1729 1728 *
1730 1729 * Use OTHERQ(q), because qreply(q, mp) == putnext(OTHERQ(q), mp),
1731 1730 * and I want this module to say putnext(*_pfkey_q, mp) for PF_KEY
1732 1731 * messages.
1733 1732 */
1734 1733
1735 1734 oldq = atomic_cas_ptr((void **)pfkey_qp, NULL, OTHERQ(q));
1736 1735 if (oldq != NULL) {
1737 1736 ASSERT(oldq != q);
1738 1737 cmn_err(CE_WARN, "Danger! Multiple keysocks on top of %s.\n",
1739 1738 (satype == SADB_SATYPE_ESP)? "ESP" : "AH or other");
1740 1739 freemsg(mp);
1741 1740 return;
1742 1741 }
1743 1742
1744 1743 kha = (keysock_hello_ack_t *)mp->b_rptr;
1745 1744 kha->ks_hello_len = sizeof (keysock_hello_ack_t);
1746 1745 kha->ks_hello_type = KEYSOCK_HELLO_ACK;
1747 1746 kha->ks_hello_satype = (uint8_t)satype;
1748 1747
1749 1748 /*
1750 1749 * If we made it past the atomic_cas_ptr, then we have "exclusive"
1751 1750 * access to the timeout handle. Fire it off after the default ager
1752 1751 * interval.
1753 1752 */
1754 1753 *top = qtimeout(*pfkey_qp, ager, agerarg,
1755 1754 drv_usectohz(SADB_AGE_INTERVAL_DEFAULT * 1000));
1756 1755
1757 1756 putnext(*pfkey_qp, mp);
1758 1757 }
1759 1758
1760 1759 /*
1761 1760 * Normalize IPv4-mapped IPv6 addresses (and prefixes) as appropriate.
1762 1761 *
1763 1762 * Check addresses themselves for wildcard or multicast.
1764 1763 * Check ire table for local/non-local/broadcast.
1765 1764 */
1766 1765 int
1767 1766 sadb_addrcheck(queue_t *pfkey_q, mblk_t *mp, sadb_ext_t *ext, uint_t serial,
1768 1767 netstack_t *ns)
1769 1768 {
1770 1769 sadb_address_t *addr = (sadb_address_t *)ext;
1771 1770 struct sockaddr_in *sin;
1772 1771 struct sockaddr_in6 *sin6;
1773 1772 int diagnostic, type;
1774 1773 boolean_t normalized = B_FALSE;
1775 1774
1776 1775 ASSERT(ext != NULL);
1777 1776 ASSERT((ext->sadb_ext_type == SADB_EXT_ADDRESS_SRC) ||
1778 1777 (ext->sadb_ext_type == SADB_EXT_ADDRESS_DST) ||
1779 1778 (ext->sadb_ext_type == SADB_X_EXT_ADDRESS_INNER_SRC) ||
1780 1779 (ext->sadb_ext_type == SADB_X_EXT_ADDRESS_INNER_DST) ||
1781 1780 (ext->sadb_ext_type == SADB_X_EXT_ADDRESS_NATT_LOC) ||
1782 1781 (ext->sadb_ext_type == SADB_X_EXT_ADDRESS_NATT_REM));
1783 1782
1784 1783 /* Assign both sockaddrs, the compiler will do the right thing. */
1785 1784 sin = (struct sockaddr_in *)(addr + 1);
1786 1785 sin6 = (struct sockaddr_in6 *)(addr + 1);
1787 1786
1788 1787 if (sin6->sin6_family == AF_INET6) {
1789 1788 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
1790 1789 /*
1791 1790 * Convert to an AF_INET sockaddr. This means the
1792 1791 * return messages will have the extra space, but have
1793 1792 * AF_INET sockaddrs instead of AF_INET6.
1794 1793 *
1795 1794 * Yes, RFC 2367 isn't clear on what to do here w.r.t.
1796 1795 * mapped addresses, but since AF_INET6 ::ffff:<v4> is
1797 1796 * equal to AF_INET <v4>, it shouldnt be a huge
1798 1797 * problem.
1799 1798 */
1800 1799 sin->sin_family = AF_INET;
1801 1800 IN6_V4MAPPED_TO_INADDR(&sin6->sin6_addr,
1802 1801 &sin->sin_addr);
1803 1802 bzero(&sin->sin_zero, sizeof (sin->sin_zero));
1804 1803 normalized = B_TRUE;
1805 1804 }
1806 1805 } else if (sin->sin_family != AF_INET) {
1807 1806 switch (ext->sadb_ext_type) {
1808 1807 case SADB_EXT_ADDRESS_SRC:
1809 1808 diagnostic = SADB_X_DIAGNOSTIC_BAD_SRC_AF;
1810 1809 break;
1811 1810 case SADB_EXT_ADDRESS_DST:
1812 1811 diagnostic = SADB_X_DIAGNOSTIC_BAD_DST_AF;
1813 1812 break;
1814 1813 case SADB_X_EXT_ADDRESS_INNER_SRC:
1815 1814 diagnostic = SADB_X_DIAGNOSTIC_BAD_PROXY_AF;
1816 1815 break;
1817 1816 case SADB_X_EXT_ADDRESS_INNER_DST:
1818 1817 diagnostic = SADB_X_DIAGNOSTIC_BAD_INNER_DST_AF;
1819 1818 break;
1820 1819 case SADB_X_EXT_ADDRESS_NATT_LOC:
1821 1820 diagnostic = SADB_X_DIAGNOSTIC_BAD_NATT_LOC_AF;
1822 1821 break;
1823 1822 case SADB_X_EXT_ADDRESS_NATT_REM:
1824 1823 diagnostic = SADB_X_DIAGNOSTIC_BAD_NATT_REM_AF;
1825 1824 break;
1826 1825 /* There is no default, see above ASSERT. */
1827 1826 }
1828 1827 bail:
1829 1828 if (pfkey_q != NULL) {
1830 1829 sadb_pfkey_error(pfkey_q, mp, EINVAL, diagnostic,
1831 1830 serial);
1832 1831 } else {
1833 1832 /*
1834 1833 * Scribble in sadb_msg that we got passed in.
1835 1834 * Overload "mp" to be an sadb_msg pointer.
1836 1835 */
1837 1836 sadb_msg_t *samsg = (sadb_msg_t *)mp;
1838 1837
1839 1838 samsg->sadb_msg_errno = EINVAL;
1840 1839 samsg->sadb_x_msg_diagnostic = diagnostic;
1841 1840 }
1842 1841 return (KS_IN_ADDR_UNKNOWN);
1843 1842 }
1844 1843
1845 1844 if (ext->sadb_ext_type == SADB_X_EXT_ADDRESS_INNER_SRC ||
1846 1845 ext->sadb_ext_type == SADB_X_EXT_ADDRESS_INNER_DST) {
1847 1846 /*
1848 1847 * We need only check for prefix issues.
1849 1848 */
1850 1849
1851 1850 /* Set diagnostic now, in case we need it later. */
1852 1851 diagnostic =
1853 1852 (ext->sadb_ext_type == SADB_X_EXT_ADDRESS_INNER_SRC) ?
1854 1853 SADB_X_DIAGNOSTIC_PREFIX_INNER_SRC :
1855 1854 SADB_X_DIAGNOSTIC_PREFIX_INNER_DST;
1856 1855
1857 1856 if (normalized)
1858 1857 addr->sadb_address_prefixlen -= 96;
1859 1858
1860 1859 /*
1861 1860 * Verify and mask out inner-addresses based on prefix length.
1862 1861 */
1863 1862 if (sin->sin_family == AF_INET) {
1864 1863 if (addr->sadb_address_prefixlen > 32)
1865 1864 goto bail;
1866 1865 sin->sin_addr.s_addr &=
1867 1866 ip_plen_to_mask(addr->sadb_address_prefixlen);
1868 1867 } else {
1869 1868 in6_addr_t mask;
1870 1869
1871 1870 ASSERT(sin->sin_family == AF_INET6);
1872 1871 /*
1873 1872 * ip_plen_to_mask_v6() returns NULL if the value in
1874 1873 * question is out of range.
1875 1874 */
1876 1875 if (ip_plen_to_mask_v6(addr->sadb_address_prefixlen,
1877 1876 &mask) == NULL)
1878 1877 goto bail;
1879 1878 sin6->sin6_addr.s6_addr32[0] &= mask.s6_addr32[0];
1880 1879 sin6->sin6_addr.s6_addr32[1] &= mask.s6_addr32[1];
1881 1880 sin6->sin6_addr.s6_addr32[2] &= mask.s6_addr32[2];
1882 1881 sin6->sin6_addr.s6_addr32[3] &= mask.s6_addr32[3];
1883 1882 }
1884 1883
1885 1884 /* We don't care in these cases. */
1886 1885 return (KS_IN_ADDR_DONTCARE);
1887 1886 }
1888 1887
1889 1888 if (sin->sin_family == AF_INET6) {
1890 1889 /* Check the easy ones now. */
1891 1890 if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
1892 1891 return (KS_IN_ADDR_MBCAST);
1893 1892 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))
1894 1893 return (KS_IN_ADDR_UNSPEC);
1895 1894 /*
1896 1895 * At this point, we're a unicast IPv6 address.
1897 1896 *
1898 1897 * XXX Zones alert -> me/notme decision needs to be tempered
1899 1898 * by what zone we're in when we go to zone-aware IPsec.
1900 1899 */
1901 1900 if (ip_type_v6(&sin6->sin6_addr, ns->netstack_ip) ==
1902 1901 IRE_LOCAL) {
1903 1902 /* Hey hey, it's local. */
1904 1903 return (KS_IN_ADDR_ME);
1905 1904 }
1906 1905 } else {
1907 1906 ASSERT(sin->sin_family == AF_INET);
1908 1907 if (sin->sin_addr.s_addr == INADDR_ANY)
1909 1908 return (KS_IN_ADDR_UNSPEC);
1910 1909 if (CLASSD(sin->sin_addr.s_addr))
1911 1910 return (KS_IN_ADDR_MBCAST);
1912 1911 /*
1913 1912 * At this point we're a unicast or broadcast IPv4 address.
1914 1913 *
1915 1914 * Check if the address is IRE_BROADCAST or IRE_LOCAL.
1916 1915 *
1917 1916 * XXX Zones alert -> me/notme decision needs to be tempered
1918 1917 * by what zone we're in when we go to zone-aware IPsec.
1919 1918 */
1920 1919 type = ip_type_v4(sin->sin_addr.s_addr, ns->netstack_ip);
1921 1920 switch (type) {
1922 1921 case IRE_LOCAL:
1923 1922 return (KS_IN_ADDR_ME);
1924 1923 case IRE_BROADCAST:
1925 1924 return (KS_IN_ADDR_MBCAST);
1926 1925 }
1927 1926 }
1928 1927
1929 1928 return (KS_IN_ADDR_NOTME);
1930 1929 }
1931 1930
1932 1931 /*
1933 1932 * Address normalizations and reality checks for inbound PF_KEY messages.
1934 1933 *
1935 1934 * For the case of src == unspecified AF_INET6, and dst == AF_INET, convert
1936 1935 * the source to AF_INET. Do the same for the inner sources.
1937 1936 */
1938 1937 boolean_t
1939 1938 sadb_addrfix(keysock_in_t *ksi, queue_t *pfkey_q, mblk_t *mp, netstack_t *ns)
1940 1939 {
1941 1940 struct sockaddr_in *src, *isrc;
1942 1941 struct sockaddr_in6 *dst, *idst;
1943 1942 sadb_address_t *srcext, *dstext;
1944 1943 uint16_t sport;
1945 1944 sadb_ext_t **extv = ksi->ks_in_extv;
1946 1945 int rc;
1947 1946
1948 1947 if (extv[SADB_EXT_ADDRESS_SRC] != NULL) {
1949 1948 rc = sadb_addrcheck(pfkey_q, mp, extv[SADB_EXT_ADDRESS_SRC],
1950 1949 ksi->ks_in_serial, ns);
1951 1950 if (rc == KS_IN_ADDR_UNKNOWN)
1952 1951 return (B_FALSE);
1953 1952 if (rc == KS_IN_ADDR_MBCAST) {
1954 1953 sadb_pfkey_error(pfkey_q, mp, EINVAL,
1955 1954 SADB_X_DIAGNOSTIC_BAD_SRC, ksi->ks_in_serial);
1956 1955 return (B_FALSE);
1957 1956 }
1958 1957 ksi->ks_in_srctype = rc;
1959 1958 }
1960 1959
1961 1960 if (extv[SADB_EXT_ADDRESS_DST] != NULL) {
1962 1961 rc = sadb_addrcheck(pfkey_q, mp, extv[SADB_EXT_ADDRESS_DST],
1963 1962 ksi->ks_in_serial, ns);
1964 1963 if (rc == KS_IN_ADDR_UNKNOWN)
1965 1964 return (B_FALSE);
1966 1965 if (rc == KS_IN_ADDR_UNSPEC) {
1967 1966 sadb_pfkey_error(pfkey_q, mp, EINVAL,
1968 1967 SADB_X_DIAGNOSTIC_BAD_DST, ksi->ks_in_serial);
1969 1968 return (B_FALSE);
1970 1969 }
1971 1970 ksi->ks_in_dsttype = rc;
1972 1971 }
1973 1972
1974 1973 /*
1975 1974 * NAT-Traversal addrs are simple enough to not require all of
1976 1975 * the checks in sadb_addrcheck(). Just normalize or reject if not
1977 1976 * AF_INET.
1978 1977 */
1979 1978 if (extv[SADB_X_EXT_ADDRESS_NATT_LOC] != NULL) {
1980 1979 rc = sadb_addrcheck(pfkey_q, mp,
1981 1980 extv[SADB_X_EXT_ADDRESS_NATT_LOC], ksi->ks_in_serial, ns);
1982 1981
1983 1982 /*
1984 1983 * Local NAT-T addresses never use an IRE_LOCAL, so it should
1985 1984 * always be NOTME, or UNSPEC (to handle both tunnel mode
1986 1985 * AND local-port flexibility).
1987 1986 */
1988 1987 if (rc != KS_IN_ADDR_NOTME && rc != KS_IN_ADDR_UNSPEC) {
1989 1988 sadb_pfkey_error(pfkey_q, mp, EINVAL,
1990 1989 SADB_X_DIAGNOSTIC_MALFORMED_NATT_LOC,
1991 1990 ksi->ks_in_serial);
1992 1991 return (B_FALSE);
1993 1992 }
1994 1993 src = (struct sockaddr_in *)
1995 1994 (((sadb_address_t *)extv[SADB_X_EXT_ADDRESS_NATT_LOC]) + 1);
1996 1995 if (src->sin_family != AF_INET) {
1997 1996 sadb_pfkey_error(pfkey_q, mp, EINVAL,
1998 1997 SADB_X_DIAGNOSTIC_BAD_NATT_LOC_AF,
1999 1998 ksi->ks_in_serial);
2000 1999 return (B_FALSE);
2001 2000 }
2002 2001 }
2003 2002
2004 2003 if (extv[SADB_X_EXT_ADDRESS_NATT_REM] != NULL) {
2005 2004 rc = sadb_addrcheck(pfkey_q, mp,
2006 2005 extv[SADB_X_EXT_ADDRESS_NATT_REM], ksi->ks_in_serial, ns);
2007 2006
2008 2007 /*
2009 2008 * Remote NAT-T addresses never use an IRE_LOCAL, so it should
2010 2009 * always be NOTME, or UNSPEC if it's a tunnel-mode SA.
2011 2010 */
2012 2011 if (rc != KS_IN_ADDR_NOTME &&
2013 2012 !(extv[SADB_X_EXT_ADDRESS_INNER_SRC] != NULL &&
2014 2013 rc == KS_IN_ADDR_UNSPEC)) {
2015 2014 sadb_pfkey_error(pfkey_q, mp, EINVAL,
2016 2015 SADB_X_DIAGNOSTIC_MALFORMED_NATT_REM,
2017 2016 ksi->ks_in_serial);
2018 2017 return (B_FALSE);
2019 2018 }
2020 2019 src = (struct sockaddr_in *)
2021 2020 (((sadb_address_t *)extv[SADB_X_EXT_ADDRESS_NATT_REM]) + 1);
2022 2021 if (src->sin_family != AF_INET) {
2023 2022 sadb_pfkey_error(pfkey_q, mp, EINVAL,
2024 2023 SADB_X_DIAGNOSTIC_BAD_NATT_REM_AF,
2025 2024 ksi->ks_in_serial);
2026 2025 return (B_FALSE);
2027 2026 }
2028 2027 }
2029 2028
2030 2029 if (extv[SADB_X_EXT_ADDRESS_INNER_SRC] != NULL) {
2031 2030 if (extv[SADB_X_EXT_ADDRESS_INNER_DST] == NULL) {
2032 2031 sadb_pfkey_error(pfkey_q, mp, EINVAL,
2033 2032 SADB_X_DIAGNOSTIC_MISSING_INNER_DST,
2034 2033 ksi->ks_in_serial);
2035 2034 return (B_FALSE);
2036 2035 }
2037 2036
2038 2037 if (sadb_addrcheck(pfkey_q, mp,
2039 2038 extv[SADB_X_EXT_ADDRESS_INNER_DST], ksi->ks_in_serial, ns)
2040 2039 == KS_IN_ADDR_UNKNOWN ||
2041 2040 sadb_addrcheck(pfkey_q, mp,
2042 2041 extv[SADB_X_EXT_ADDRESS_INNER_SRC], ksi->ks_in_serial, ns)
2043 2042 == KS_IN_ADDR_UNKNOWN)
2044 2043 return (B_FALSE);
2045 2044
2046 2045 isrc = (struct sockaddr_in *)
2047 2046 (((sadb_address_t *)extv[SADB_X_EXT_ADDRESS_INNER_SRC]) +
2048 2047 1);
2049 2048 idst = (struct sockaddr_in6 *)
2050 2049 (((sadb_address_t *)extv[SADB_X_EXT_ADDRESS_INNER_DST]) +
2051 2050 1);
2052 2051 if (isrc->sin_family != idst->sin6_family) {
2053 2052 sadb_pfkey_error(pfkey_q, mp, EINVAL,
2054 2053 SADB_X_DIAGNOSTIC_INNER_AF_MISMATCH,
2055 2054 ksi->ks_in_serial);
2056 2055 return (B_FALSE);
2057 2056 }
2058 2057 } else if (extv[SADB_X_EXT_ADDRESS_INNER_DST] != NULL) {
2059 2058 sadb_pfkey_error(pfkey_q, mp, EINVAL,
2060 2059 SADB_X_DIAGNOSTIC_MISSING_INNER_SRC,
2061 2060 ksi->ks_in_serial);
2062 2061 return (B_FALSE);
2063 2062 } else {
2064 2063 isrc = NULL; /* For inner/outer port check below. */
2065 2064 }
2066 2065
2067 2066 dstext = (sadb_address_t *)extv[SADB_EXT_ADDRESS_DST];
2068 2067 srcext = (sadb_address_t *)extv[SADB_EXT_ADDRESS_SRC];
2069 2068
2070 2069 if (dstext == NULL || srcext == NULL)
2071 2070 return (B_TRUE);
2072 2071
2073 2072 dst = (struct sockaddr_in6 *)(dstext + 1);
2074 2073 src = (struct sockaddr_in *)(srcext + 1);
2075 2074
2076 2075 if (isrc != NULL &&
2077 2076 (isrc->sin_port != 0 || idst->sin6_port != 0) &&
2078 2077 (src->sin_port != 0 || dst->sin6_port != 0)) {
2079 2078 /* Can't set inner and outer ports in one SA. */
2080 2079 sadb_pfkey_error(pfkey_q, mp, EINVAL,
2081 2080 SADB_X_DIAGNOSTIC_DUAL_PORT_SETS,
2082 2081 ksi->ks_in_serial);
2083 2082 return (B_FALSE);
2084 2083 }
2085 2084
2086 2085 if (dst->sin6_family == src->sin_family)
2087 2086 return (B_TRUE);
2088 2087
2089 2088 if (srcext->sadb_address_proto != dstext->sadb_address_proto) {
2090 2089 if (srcext->sadb_address_proto == 0) {
2091 2090 srcext->sadb_address_proto = dstext->sadb_address_proto;
2092 2091 } else if (dstext->sadb_address_proto == 0) {
2093 2092 dstext->sadb_address_proto = srcext->sadb_address_proto;
2094 2093 } else {
2095 2094 /* Inequal protocols, neither were 0. Report error. */
2096 2095 sadb_pfkey_error(pfkey_q, mp, EINVAL,
2097 2096 SADB_X_DIAGNOSTIC_PROTO_MISMATCH,
2098 2097 ksi->ks_in_serial);
2099 2098 return (B_FALSE);
2100 2099 }
2101 2100 }
2102 2101
2103 2102 /*
2104 2103 * With the exception of an unspec IPv6 source and an IPv4
2105 2104 * destination, address families MUST me matched.
2106 2105 */
2107 2106 if (src->sin_family == AF_INET ||
2108 2107 ksi->ks_in_srctype != KS_IN_ADDR_UNSPEC) {
2109 2108 sadb_pfkey_error(pfkey_q, mp, EINVAL,
2110 2109 SADB_X_DIAGNOSTIC_AF_MISMATCH, ksi->ks_in_serial);
2111 2110 return (B_FALSE);
2112 2111 }
2113 2112
2114 2113 /*
2115 2114 * Convert "src" to AF_INET INADDR_ANY. We rely on sin_port being
2116 2115 * in the same place for sockaddr_in and sockaddr_in6.
2117 2116 */
2118 2117 sport = src->sin_port;
2119 2118 bzero(src, sizeof (*src));
2120 2119 src->sin_family = AF_INET;
2121 2120 src->sin_port = sport;
2122 2121
2123 2122 return (B_TRUE);
2124 2123 }
2125 2124
2126 2125 /*
2127 2126 * Set the results in "addrtype", given an IRE as requested by
2128 2127 * sadb_addrcheck().
2129 2128 */
2130 2129 int
2131 2130 sadb_addrset(ire_t *ire)
2132 2131 {
2133 2132 if ((ire->ire_type & IRE_BROADCAST) ||
2134 2133 (ire->ire_ipversion == IPV4_VERSION && CLASSD(ire->ire_addr)) ||
2135 2134 (ire->ire_ipversion == IPV6_VERSION &&
2136 2135 IN6_IS_ADDR_MULTICAST(&(ire->ire_addr_v6))))
2137 2136 return (KS_IN_ADDR_MBCAST);
2138 2137 if (ire->ire_type & (IRE_LOCAL | IRE_LOOPBACK))
2139 2138 return (KS_IN_ADDR_ME);
2140 2139 return (KS_IN_ADDR_NOTME);
2141 2140 }
2142 2141
2143 2142 /*
2144 2143 * Match primitives..
2145 2144 * !!! TODO: short term: inner selectors
2146 2145 * ipv6 scope id (ifindex)
2147 2146 * longer term: zone id. sensitivity label. uid.
2148 2147 */
2149 2148 boolean_t
2150 2149 sadb_match_spi(ipsa_query_t *sq, ipsa_t *sa)
2151 2150 {
2152 2151 return (sq->spi == sa->ipsa_spi);
2153 2152 }
2154 2153
2155 2154 boolean_t
2156 2155 sadb_match_dst_v6(ipsa_query_t *sq, ipsa_t *sa)
2157 2156 {
2158 2157 return (IPSA_ARE_ADDR_EQUAL(sa->ipsa_dstaddr, sq->dstaddr, AF_INET6));
2159 2158 }
2160 2159
2161 2160 boolean_t
2162 2161 sadb_match_src_v6(ipsa_query_t *sq, ipsa_t *sa)
2163 2162 {
2164 2163 return (IPSA_ARE_ADDR_EQUAL(sa->ipsa_srcaddr, sq->srcaddr, AF_INET6));
2165 2164 }
2166 2165
2167 2166 boolean_t
2168 2167 sadb_match_dst_v4(ipsa_query_t *sq, ipsa_t *sa)
2169 2168 {
2170 2169 return (sq->dstaddr[0] == sa->ipsa_dstaddr[0]);
2171 2170 }
2172 2171
2173 2172 boolean_t
2174 2173 sadb_match_src_v4(ipsa_query_t *sq, ipsa_t *sa)
2175 2174 {
2176 2175 return (sq->srcaddr[0] == sa->ipsa_srcaddr[0]);
2177 2176 }
2178 2177
2179 2178 boolean_t
2180 2179 sadb_match_dstid(ipsa_query_t *sq, ipsa_t *sa)
2181 2180 {
2182 2181 return ((sa->ipsa_dst_cid != NULL) &&
2183 2182 (sq->didtype == sa->ipsa_dst_cid->ipsid_type) &&
2184 2183 (strcmp(sq->didstr, sa->ipsa_dst_cid->ipsid_cid) == 0));
2185 2184
2186 2185 }
2187 2186 boolean_t
2188 2187 sadb_match_srcid(ipsa_query_t *sq, ipsa_t *sa)
2189 2188 {
2190 2189 return ((sa->ipsa_src_cid != NULL) &&
2191 2190 (sq->sidtype == sa->ipsa_src_cid->ipsid_type) &&
2192 2191 (strcmp(sq->sidstr, sa->ipsa_src_cid->ipsid_cid) == 0));
2193 2192 }
2194 2193
2195 2194 boolean_t
2196 2195 sadb_match_kmc(ipsa_query_t *sq, ipsa_t *sa)
2197 2196 {
2198 2197 #define M(a, b) (((a) == 0) || ((b) == 0) || ((a) == (b)))
2199 2198
2200 2199 return (M(sq->kmc, sa->ipsa_kmc) && M(sq->kmp, sa->ipsa_kmp));
2201 2200
2202 2201 #undef M
2203 2202 }
2204 2203
2205 2204 /*
2206 2205 * Common function which extracts several PF_KEY extensions for ease of
2207 2206 * SADB matching.
2208 2207 *
2209 2208 * XXX TODO: weed out ipsa_query_t fields not used during matching
2210 2209 * or afterwards?
2211 2210 */
2212 2211 int
2213 2212 sadb_form_query(keysock_in_t *ksi, uint32_t req, uint32_t match,
2214 2213 ipsa_query_t *sq, int *diagnostic)
2215 2214 {
2216 2215 int i;
2217 2216 ipsa_match_fn_t *mfpp = &(sq->matchers[0]);
2218 2217
2219 2218 for (i = 0; i < IPSA_NMATCH; i++)
2220 2219 sq->matchers[i] = NULL;
2221 2220
2222 2221 ASSERT((req & ~match) == 0);
2223 2222
2224 2223 sq->req = req;
2225 2224 sq->dstext = (sadb_address_t *)ksi->ks_in_extv[SADB_EXT_ADDRESS_DST];
2226 2225 sq->srcext = (sadb_address_t *)ksi->ks_in_extv[SADB_EXT_ADDRESS_SRC];
2227 2226 sq->assoc = (sadb_sa_t *)ksi->ks_in_extv[SADB_EXT_SA];
2228 2227
2229 2228 if ((req & IPSA_Q_DST) && (sq->dstext == NULL)) {
2230 2229 *diagnostic = SADB_X_DIAGNOSTIC_MISSING_DST;
2231 2230 return (EINVAL);
2232 2231 }
2233 2232 if ((req & IPSA_Q_SRC) && (sq->srcext == NULL)) {
2234 2233 *diagnostic = SADB_X_DIAGNOSTIC_MISSING_SRC;
2235 2234 return (EINVAL);
2236 2235 }
2237 2236 if ((req & IPSA_Q_SA) && (sq->assoc == NULL)) {
2238 2237 *diagnostic = SADB_X_DIAGNOSTIC_MISSING_SA;
2239 2238 return (EINVAL);
2240 2239 }
2241 2240
2242 2241 if (match & IPSA_Q_SA) {
2243 2242 *mfpp++ = sadb_match_spi;
2244 2243 sq->spi = sq->assoc->sadb_sa_spi;
2245 2244 }
2246 2245
2247 2246 if (sq->dstext != NULL)
2248 2247 sq->dst = (struct sockaddr_in *)(sq->dstext + 1);
2249 2248 else {
2250 2249 sq->dst = NULL;
2251 2250 sq->dst6 = NULL;
2252 2251 sq->dstaddr = NULL;
2253 2252 }
2254 2253
2255 2254 if (sq->srcext != NULL)
2256 2255 sq->src = (struct sockaddr_in *)(sq->srcext + 1);
2257 2256 else {
2258 2257 sq->src = NULL;
2259 2258 sq->src6 = NULL;
2260 2259 sq->srcaddr = NULL;
2261 2260 }
2262 2261
2263 2262 if (sq->dst != NULL)
2264 2263 sq->af = sq->dst->sin_family;
2265 2264 else if (sq->src != NULL)
2266 2265 sq->af = sq->src->sin_family;
2267 2266 else
2268 2267 sq->af = AF_INET;
2269 2268
2270 2269 if (sq->af == AF_INET6) {
2271 2270 if ((match & IPSA_Q_DST) && (sq->dstext != NULL)) {
2272 2271 *mfpp++ = sadb_match_dst_v6;
2273 2272 sq->dst6 = (struct sockaddr_in6 *)sq->dst;
2274 2273 sq->dstaddr = (uint32_t *)&(sq->dst6->sin6_addr);
2275 2274 } else {
2276 2275 match &= ~IPSA_Q_DST;
2277 2276 sq->dstaddr = ALL_ZEROES_PTR;
2278 2277 }
2279 2278
2280 2279 if ((match & IPSA_Q_SRC) && (sq->srcext != NULL)) {
2281 2280 sq->src6 = (struct sockaddr_in6 *)(sq->srcext + 1);
2282 2281 sq->srcaddr = (uint32_t *)&sq->src6->sin6_addr;
2283 2282 if (sq->src6->sin6_family != AF_INET6) {
2284 2283 *diagnostic = SADB_X_DIAGNOSTIC_AF_MISMATCH;
2285 2284 return (EINVAL);
2286 2285 }
2287 2286 *mfpp++ = sadb_match_src_v6;
2288 2287 } else {
2289 2288 match &= ~IPSA_Q_SRC;
2290 2289 sq->srcaddr = ALL_ZEROES_PTR;
2291 2290 }
2292 2291 } else {
2293 2292 sq->src6 = sq->dst6 = NULL;
2294 2293 if ((match & IPSA_Q_DST) && (sq->dstext != NULL)) {
2295 2294 *mfpp++ = sadb_match_dst_v4;
2296 2295 sq->dstaddr = (uint32_t *)&sq->dst->sin_addr;
2297 2296 } else {
2298 2297 match &= ~IPSA_Q_DST;
2299 2298 sq->dstaddr = ALL_ZEROES_PTR;
2300 2299 }
2301 2300 if ((match & IPSA_Q_SRC) && (sq->srcext != NULL)) {
2302 2301 sq->srcaddr = (uint32_t *)&sq->src->sin_addr;
2303 2302 if (sq->src->sin_family != AF_INET) {
2304 2303 *diagnostic = SADB_X_DIAGNOSTIC_AF_MISMATCH;
2305 2304 return (EINVAL);
2306 2305 }
2307 2306 *mfpp++ = sadb_match_src_v4;
2308 2307 } else {
2309 2308 match &= ~IPSA_Q_SRC;
2310 2309 sq->srcaddr = ALL_ZEROES_PTR;
2311 2310 }
2312 2311 }
2313 2312
2314 2313 sq->dstid = (sadb_ident_t *)ksi->ks_in_extv[SADB_EXT_IDENTITY_DST];
2315 2314 if ((match & IPSA_Q_DSTID) && (sq->dstid != NULL)) {
2316 2315 sq->didstr = (char *)(sq->dstid + 1);
2317 2316 sq->didtype = sq->dstid->sadb_ident_type;
2318 2317 *mfpp++ = sadb_match_dstid;
2319 2318 }
2320 2319
2321 2320 sq->srcid = (sadb_ident_t *)ksi->ks_in_extv[SADB_EXT_IDENTITY_SRC];
2322 2321
2323 2322 if ((match & IPSA_Q_SRCID) && (sq->srcid != NULL)) {
2324 2323 sq->sidstr = (char *)(sq->srcid + 1);
2325 2324 sq->sidtype = sq->srcid->sadb_ident_type;
2326 2325 *mfpp++ = sadb_match_srcid;
2327 2326 }
2328 2327
2329 2328 sq->kmcext = (sadb_x_kmc_t *)ksi->ks_in_extv[SADB_X_EXT_KM_COOKIE];
2330 2329 sq->kmc = 0;
2331 2330 sq->kmp = 0;
2332 2331
2333 2332 if ((match & IPSA_Q_KMC) && (sq->kmcext)) {
2334 2333 sq->kmc = sq->kmcext->sadb_x_kmc_cookie;
2335 2334 sq->kmp = sq->kmcext->sadb_x_kmc_proto;
2336 2335 *mfpp++ = sadb_match_kmc;
2337 2336 }
2338 2337
2339 2338 if (match & (IPSA_Q_INBOUND|IPSA_Q_OUTBOUND)) {
2340 2339 if (sq->af == AF_INET6)
2341 2340 sq->sp = &sq->spp->s_v6;
2342 2341 else
2343 2342 sq->sp = &sq->spp->s_v4;
2344 2343 } else {
2345 2344 sq->sp = NULL;
2346 2345 }
2347 2346
2348 2347 if (match & IPSA_Q_INBOUND) {
2349 2348 sq->inhash = INBOUND_HASH(sq->sp, sq->assoc->sadb_sa_spi);
2350 2349 sq->inbound = &sq->sp->sdb_if[sq->inhash];
2351 2350 } else {
2352 2351 sq->inhash = 0;
2353 2352 sq->inbound = NULL;
2354 2353 }
2355 2354
2356 2355 if (match & IPSA_Q_OUTBOUND) {
2357 2356 if (sq->af == AF_INET6) {
2358 2357 sq->outhash = OUTBOUND_HASH_V6(sq->sp, *(sq->dstaddr));
2359 2358 } else {
2360 2359 sq->outhash = OUTBOUND_HASH_V4(sq->sp, *(sq->dstaddr));
2361 2360 }
2362 2361 sq->outbound = &sq->sp->sdb_of[sq->outhash];
2363 2362 } else {
2364 2363 sq->outhash = 0;
2365 2364 sq->outbound = NULL;
2366 2365 }
2367 2366 sq->match = match;
2368 2367 return (0);
2369 2368 }
2370 2369
2371 2370 /*
2372 2371 * Match an initialized query structure with a security association;
2373 2372 * return B_TRUE on a match, B_FALSE on a miss.
2374 2373 * Applies match functions set up by sadb_form_query() until one returns false.
2375 2374 */
2376 2375 boolean_t
2377 2376 sadb_match_query(ipsa_query_t *sq, ipsa_t *sa)
2378 2377 {
2379 2378 ipsa_match_fn_t *mfpp = &(sq->matchers[0]);
2380 2379 ipsa_match_fn_t mfp;
2381 2380
2382 2381 for (mfp = *mfpp++; mfp != NULL; mfp = *mfpp++) {
2383 2382 if (!mfp(sq, sa))
2384 2383 return (B_FALSE);
2385 2384 }
2386 2385 return (B_TRUE);
2387 2386 }
2388 2387
2389 2388 /*
2390 2389 * Walker callback function to delete sa's based on src/dst address.
2391 2390 * Assumes that we're called with *head locked, no other locks held;
2392 2391 * Conveniently, and not coincidentally, this is both what sadb_walker
2393 2392 * gives us and also what sadb_unlinkassoc expects.
2394 2393 */
2395 2394 struct sadb_purge_state
2396 2395 {
2397 2396 ipsa_query_t sq;
2398 2397 boolean_t inbnd;
2399 2398 uint8_t sadb_sa_state;
2400 2399 };
2401 2400
2402 2401 static void
2403 2402 sadb_purge_cb(isaf_t *head, ipsa_t *entry, void *cookie)
2404 2403 {
2405 2404 struct sadb_purge_state *ps = (struct sadb_purge_state *)cookie;
2406 2405
2407 2406 ASSERT(MUTEX_HELD(&head->isaf_lock));
2408 2407
2409 2408 mutex_enter(&entry->ipsa_lock);
2410 2409
2411 2410 if (entry->ipsa_state == IPSA_STATE_LARVAL ||
2412 2411 !sadb_match_query(&ps->sq, entry)) {
2413 2412 mutex_exit(&entry->ipsa_lock);
2414 2413 return;
2415 2414 }
2416 2415
2417 2416 if (ps->inbnd) {
2418 2417 sadb_delete_cluster(entry);
2419 2418 }
2420 2419 entry->ipsa_state = IPSA_STATE_DEAD;
2421 2420 (void) sadb_torch_assoc(head, entry);
2422 2421 }
2423 2422
2424 2423 /*
2425 2424 * Common code to purge an SA with a matching src or dst address.
2426 2425 * Don't kill larval SA's in such a purge.
2427 2426 */
2428 2427 int
2429 2428 sadb_purge_sa(mblk_t *mp, keysock_in_t *ksi, sadb_t *sp,
2430 2429 int *diagnostic, queue_t *pfkey_q)
2431 2430 {
2432 2431 struct sadb_purge_state ps;
2433 2432 int error = sadb_form_query(ksi, 0,
2434 2433 IPSA_Q_SRC|IPSA_Q_DST|IPSA_Q_SRCID|IPSA_Q_DSTID|IPSA_Q_KMC,
2435 2434 &ps.sq, diagnostic);
2436 2435
2437 2436 if (error != 0)
2438 2437 return (error);
2439 2438
2440 2439 /*
2441 2440 * This is simple, crude, and effective.
2442 2441 * Unimplemented optimizations (TBD):
2443 2442 * - we can limit how many places we search based on where we
2444 2443 * think the SA is filed.
2445 2444 * - if we get a dst address, we can hash based on dst addr to find
2446 2445 * the correct bucket in the outbound table.
2447 2446 */
2448 2447 ps.inbnd = B_TRUE;
2449 2448 sadb_walker(sp->sdb_if, sp->sdb_hashsize, sadb_purge_cb, &ps);
2450 2449 ps.inbnd = B_FALSE;
2451 2450 sadb_walker(sp->sdb_of, sp->sdb_hashsize, sadb_purge_cb, &ps);
2452 2451
2453 2452 ASSERT(mp->b_cont != NULL);
2454 2453 sadb_pfkey_echo(pfkey_q, mp, (sadb_msg_t *)mp->b_cont->b_rptr, ksi,
2455 2454 NULL);
2456 2455 return (0);
2457 2456 }
2458 2457
2459 2458 static void
2460 2459 sadb_delpair_state_one(isaf_t *head, ipsa_t *entry, void *cookie)
2461 2460 {
2462 2461 struct sadb_purge_state *ps = (struct sadb_purge_state *)cookie;
2463 2462 isaf_t *inbound_bucket;
2464 2463 ipsa_t *peer_assoc;
2465 2464 ipsa_query_t *sq = &ps->sq;
2466 2465
2467 2466 ASSERT(MUTEX_HELD(&head->isaf_lock));
2468 2467
2469 2468 mutex_enter(&entry->ipsa_lock);
2470 2469
2471 2470 if ((entry->ipsa_state != ps->sadb_sa_state) ||
2472 2471 ((sq->srcaddr != NULL) &&
2473 2472 !IPSA_ARE_ADDR_EQUAL(entry->ipsa_srcaddr, sq->srcaddr, sq->af))) {
2474 2473 mutex_exit(&entry->ipsa_lock);
2475 2474 return;
2476 2475 }
2477 2476
2478 2477 /*
2479 2478 * The isaf_t *, which is passed in , is always an outbound bucket,
2480 2479 * and we are preserving the outbound-then-inbound hash-bucket lock
2481 2480 * ordering. The sadb_walker() which triggers this function is called
2482 2481 * only on the outbound fanout, and the corresponding inbound bucket
2483 2482 * lock is safe to acquire here.
2484 2483 */
2485 2484
2486 2485 if (entry->ipsa_haspeer) {
2487 2486 inbound_bucket = INBOUND_BUCKET(sq->sp, entry->ipsa_spi);
2488 2487 mutex_enter(&inbound_bucket->isaf_lock);
2489 2488 peer_assoc = ipsec_getassocbyspi(inbound_bucket,
2490 2489 entry->ipsa_spi, entry->ipsa_srcaddr,
2491 2490 entry->ipsa_dstaddr, entry->ipsa_addrfam);
2492 2491 } else {
2493 2492 inbound_bucket = INBOUND_BUCKET(sq->sp, entry->ipsa_otherspi);
2494 2493 mutex_enter(&inbound_bucket->isaf_lock);
2495 2494 peer_assoc = ipsec_getassocbyspi(inbound_bucket,
2496 2495 entry->ipsa_otherspi, entry->ipsa_dstaddr,
2497 2496 entry->ipsa_srcaddr, entry->ipsa_addrfam);
2498 2497 }
2499 2498
2500 2499 entry->ipsa_state = IPSA_STATE_DEAD;
2501 2500 (void) sadb_torch_assoc(head, entry);
2502 2501 if (peer_assoc != NULL) {
2503 2502 mutex_enter(&peer_assoc->ipsa_lock);
2504 2503 peer_assoc->ipsa_state = IPSA_STATE_DEAD;
2505 2504 (void) sadb_torch_assoc(inbound_bucket, peer_assoc);
2506 2505 }
2507 2506 mutex_exit(&inbound_bucket->isaf_lock);
2508 2507 }
2509 2508
2510 2509 static int
2511 2510 sadb_delpair_state(mblk_t *mp, keysock_in_t *ksi, sadbp_t *spp,
2512 2511 int *diagnostic, queue_t *pfkey_q)
2513 2512 {
2514 2513 sadb_sa_t *assoc = (sadb_sa_t *)ksi->ks_in_extv[SADB_EXT_SA];
2515 2514 struct sadb_purge_state ps;
2516 2515 int error;
2517 2516
2518 2517 ps.sq.spp = spp; /* XXX param */
2519 2518
2520 2519 error = sadb_form_query(ksi, IPSA_Q_DST|IPSA_Q_SRC,
2521 2520 IPSA_Q_SRC|IPSA_Q_DST|IPSA_Q_SRCID|IPSA_Q_DSTID|IPSA_Q_KMC,
2522 2521 &ps.sq, diagnostic);
2523 2522 if (error != 0)
2524 2523 return (error);
2525 2524
2526 2525 ps.inbnd = B_FALSE;
2527 2526 ps.sadb_sa_state = assoc->sadb_sa_state;
2528 2527 sadb_walker(ps.sq.sp->sdb_of, ps.sq.sp->sdb_hashsize,
2529 2528 sadb_delpair_state_one, &ps);
2530 2529
2531 2530 ASSERT(mp->b_cont != NULL);
2532 2531 sadb_pfkey_echo(pfkey_q, mp, (sadb_msg_t *)mp->b_cont->b_rptr,
2533 2532 ksi, NULL);
2534 2533 return (0);
2535 2534 }
2536 2535
2537 2536 /*
2538 2537 * Common code to delete/get an SA.
2539 2538 */
2540 2539 int
2541 2540 sadb_delget_sa(mblk_t *mp, keysock_in_t *ksi, sadbp_t *spp,
2542 2541 int *diagnostic, queue_t *pfkey_q, uint8_t sadb_msg_type)
2543 2542 {
2544 2543 ipsa_query_t sq;
2545 2544 ipsa_t *echo_target = NULL;
2546 2545 ipsap_t ipsapp;
2547 2546 uint_t error = 0;
2548 2547
2549 2548 if (sadb_msg_type == SADB_X_DELPAIR_STATE)
2550 2549 return (sadb_delpair_state(mp, ksi, spp, diagnostic, pfkey_q));
2551 2550
2552 2551 sq.spp = spp; /* XXX param */
2553 2552 error = sadb_form_query(ksi, IPSA_Q_DST|IPSA_Q_SA,
2554 2553 IPSA_Q_SRC|IPSA_Q_DST|IPSA_Q_SA|IPSA_Q_INBOUND|IPSA_Q_OUTBOUND,
2555 2554 &sq, diagnostic);
2556 2555 if (error != 0)
2557 2556 return (error);
2558 2557
2559 2558 error = get_ipsa_pair(&sq, &ipsapp, diagnostic);
2560 2559 if (error != 0) {
2561 2560 return (error);
2562 2561 }
2563 2562
2564 2563 echo_target = ipsapp.ipsap_sa_ptr;
2565 2564 if (echo_target == NULL)
2566 2565 echo_target = ipsapp.ipsap_psa_ptr;
2567 2566
2568 2567 if (sadb_msg_type == SADB_DELETE || sadb_msg_type == SADB_X_DELPAIR) {
2569 2568 /*
2570 2569 * Bucket locks will be required if SA is actually unlinked.
2571 2570 * get_ipsa_pair() returns valid hash bucket pointers even
2572 2571 * if it can't find a pair SA pointer. To prevent a potential
2573 2572 * deadlock, always lock the outbound bucket before the inbound.
2574 2573 */
2575 2574 if (ipsapp.in_inbound_table) {
2576 2575 mutex_enter(&ipsapp.ipsap_pbucket->isaf_lock);
2577 2576 mutex_enter(&ipsapp.ipsap_bucket->isaf_lock);
2578 2577 } else {
2579 2578 mutex_enter(&ipsapp.ipsap_bucket->isaf_lock);
2580 2579 mutex_enter(&ipsapp.ipsap_pbucket->isaf_lock);
2581 2580 }
2582 2581
2583 2582 if (ipsapp.ipsap_sa_ptr != NULL) {
2584 2583 mutex_enter(&ipsapp.ipsap_sa_ptr->ipsa_lock);
2585 2584 if (ipsapp.ipsap_sa_ptr->ipsa_flags & IPSA_F_INBOUND) {
2586 2585 sadb_delete_cluster(ipsapp.ipsap_sa_ptr);
2587 2586 }
2588 2587 ipsapp.ipsap_sa_ptr->ipsa_state = IPSA_STATE_DEAD;
2589 2588 (void) sadb_torch_assoc(ipsapp.ipsap_bucket,
2590 2589 ipsapp.ipsap_sa_ptr);
2591 2590 /*
2592 2591 * sadb_torch_assoc() releases the ipsa_lock
2593 2592 * and calls sadb_unlinkassoc() which does a
2594 2593 * IPSA_REFRELE.
2595 2594 */
2596 2595 }
2597 2596 if (ipsapp.ipsap_psa_ptr != NULL) {
2598 2597 mutex_enter(&ipsapp.ipsap_psa_ptr->ipsa_lock);
2599 2598 if (sadb_msg_type == SADB_X_DELPAIR ||
2600 2599 ipsapp.ipsap_psa_ptr->ipsa_haspeer) {
2601 2600 if (ipsapp.ipsap_psa_ptr->ipsa_flags &
2602 2601 IPSA_F_INBOUND) {
2603 2602 sadb_delete_cluster
2604 2603 (ipsapp.ipsap_psa_ptr);
2605 2604 }
2606 2605 ipsapp.ipsap_psa_ptr->ipsa_state =
2607 2606 IPSA_STATE_DEAD;
2608 2607 (void) sadb_torch_assoc(ipsapp.ipsap_pbucket,
2609 2608 ipsapp.ipsap_psa_ptr);
2610 2609 } else {
2611 2610 /*
2612 2611 * Only half of the "pair" has been deleted.
2613 2612 * Update the remaining SA and remove references
2614 2613 * to its pair SA, which is now gone.
2615 2614 */
2616 2615 ipsapp.ipsap_psa_ptr->ipsa_otherspi = 0;
2617 2616 ipsapp.ipsap_psa_ptr->ipsa_flags &=
2618 2617 ~IPSA_F_PAIRED;
2619 2618 mutex_exit(&ipsapp.ipsap_psa_ptr->ipsa_lock);
2620 2619 }
2621 2620 } else if (sadb_msg_type == SADB_X_DELPAIR) {
2622 2621 *diagnostic = SADB_X_DIAGNOSTIC_PAIR_SA_NOTFOUND;
2623 2622 error = ESRCH;
2624 2623 }
2625 2624 mutex_exit(&ipsapp.ipsap_bucket->isaf_lock);
2626 2625 mutex_exit(&ipsapp.ipsap_pbucket->isaf_lock);
2627 2626 }
2628 2627
2629 2628 ASSERT(mp->b_cont != NULL);
2630 2629
2631 2630 if (error == 0)
2632 2631 sadb_pfkey_echo(pfkey_q, mp, (sadb_msg_t *)
2633 2632 mp->b_cont->b_rptr, ksi, echo_target);
2634 2633
2635 2634 destroy_ipsa_pair(&ipsapp);
2636 2635
2637 2636 return (error);
2638 2637 }
2639 2638
2640 2639 /*
2641 2640 * This function takes a sadb_sa_t and finds the ipsa_t structure
2642 2641 * and the isaf_t (hash bucket) that its stored under. If the security
2643 2642 * association has a peer, the ipsa_t structure and bucket for that security
2644 2643 * association are also searched for. The "pair" of ipsa_t's and isaf_t's
2645 2644 * are returned as a ipsap_t.
2646 2645 *
2647 2646 * The hash buckets are returned for convenience, if the calling function
2648 2647 * needs to use the hash bucket locks, say to remove the SA's, it should
2649 2648 * take care to observe the convention of locking outbound bucket then
2650 2649 * inbound bucket. The flag in_inbound_table provides direction.
2651 2650 *
2652 2651 * Note that a "pair" is defined as one (but not both) of the following:
2653 2652 *
2654 2653 * A security association which has a soft reference to another security
2655 2654 * association via its SPI.
2656 2655 *
2657 2656 * A security association that is not obviously "inbound" or "outbound" so
2658 2657 * it appears in both hash tables, the "peer" being the same security
2659 2658 * association in the other hash table.
2660 2659 *
2661 2660 * This function will return NULL if the ipsa_t can't be found in the
2662 2661 * inbound or outbound hash tables (not found). If only one ipsa_t is
2663 2662 * found, the pair ipsa_t will be NULL. Both isaf_t values are valid
2664 2663 * provided at least one ipsa_t is found.
2665 2664 */
2666 2665 static int
2667 2666 get_ipsa_pair(ipsa_query_t *sq, ipsap_t *ipsapp, int *diagnostic)
2668 2667 {
2669 2668 uint32_t pair_srcaddr[IPSA_MAX_ADDRLEN];
2670 2669 uint32_t pair_dstaddr[IPSA_MAX_ADDRLEN];
2671 2670 uint32_t pair_spi;
2672 2671
2673 2672 init_ipsa_pair(ipsapp);
2674 2673
2675 2674 ipsapp->in_inbound_table = B_FALSE;
2676 2675
2677 2676 /* Lock down both buckets. */
2678 2677 mutex_enter(&sq->outbound->isaf_lock);
2679 2678 mutex_enter(&sq->inbound->isaf_lock);
2680 2679
2681 2680 if (sq->assoc->sadb_sa_flags & IPSA_F_INBOUND) {
2682 2681 ipsapp->ipsap_sa_ptr = ipsec_getassocbyspi(sq->inbound,
2683 2682 sq->assoc->sadb_sa_spi, sq->srcaddr, sq->dstaddr, sq->af);
2684 2683 if (ipsapp->ipsap_sa_ptr != NULL) {
2685 2684 ipsapp->ipsap_bucket = sq->inbound;
2686 2685 ipsapp->ipsap_pbucket = sq->outbound;
2687 2686 ipsapp->in_inbound_table = B_TRUE;
2688 2687 } else {
2689 2688 ipsapp->ipsap_sa_ptr = ipsec_getassocbyspi(sq->outbound,
2690 2689 sq->assoc->sadb_sa_spi, sq->srcaddr, sq->dstaddr,
2691 2690 sq->af);
2692 2691 ipsapp->ipsap_bucket = sq->outbound;
2693 2692 ipsapp->ipsap_pbucket = sq->inbound;
2694 2693 }
2695 2694 } else {
2696 2695 /* IPSA_F_OUTBOUND is set *or* no directions flags set. */
2697 2696 ipsapp->ipsap_sa_ptr =
2698 2697 ipsec_getassocbyspi(sq->outbound,
2699 2698 sq->assoc->sadb_sa_spi, sq->srcaddr, sq->dstaddr, sq->af);
2700 2699 if (ipsapp->ipsap_sa_ptr != NULL) {
2701 2700 ipsapp->ipsap_bucket = sq->outbound;
2702 2701 ipsapp->ipsap_pbucket = sq->inbound;
2703 2702 } else {
2704 2703 ipsapp->ipsap_sa_ptr = ipsec_getassocbyspi(sq->inbound,
2705 2704 sq->assoc->sadb_sa_spi, sq->srcaddr, sq->dstaddr,
2706 2705 sq->af);
2707 2706 ipsapp->ipsap_bucket = sq->inbound;
2708 2707 ipsapp->ipsap_pbucket = sq->outbound;
2709 2708 if (ipsapp->ipsap_sa_ptr != NULL)
2710 2709 ipsapp->in_inbound_table = B_TRUE;
2711 2710 }
2712 2711 }
2713 2712
2714 2713 if (ipsapp->ipsap_sa_ptr == NULL) {
2715 2714 mutex_exit(&sq->outbound->isaf_lock);
2716 2715 mutex_exit(&sq->inbound->isaf_lock);
2717 2716 *diagnostic = SADB_X_DIAGNOSTIC_SA_NOTFOUND;
2718 2717 return (ESRCH);
2719 2718 }
2720 2719
2721 2720 if ((ipsapp->ipsap_sa_ptr->ipsa_state == IPSA_STATE_LARVAL) &&
2722 2721 ipsapp->in_inbound_table) {
2723 2722 mutex_exit(&sq->outbound->isaf_lock);
2724 2723 mutex_exit(&sq->inbound->isaf_lock);
2725 2724 return (0);
2726 2725 }
2727 2726
2728 2727 mutex_enter(&ipsapp->ipsap_sa_ptr->ipsa_lock);
2729 2728 if (ipsapp->ipsap_sa_ptr->ipsa_haspeer) {
2730 2729 /*
2731 2730 * haspeer implies no sa_pairing, look for same spi
2732 2731 * in other hashtable.
2733 2732 */
2734 2733 ipsapp->ipsap_psa_ptr =
2735 2734 ipsec_getassocbyspi(ipsapp->ipsap_pbucket,
2736 2735 sq->assoc->sadb_sa_spi, sq->srcaddr, sq->dstaddr, sq->af);
2737 2736 mutex_exit(&ipsapp->ipsap_sa_ptr->ipsa_lock);
2738 2737 mutex_exit(&sq->outbound->isaf_lock);
2739 2738 mutex_exit(&sq->inbound->isaf_lock);
2740 2739 return (0);
2741 2740 }
2742 2741 pair_spi = ipsapp->ipsap_sa_ptr->ipsa_otherspi;
2743 2742 IPSA_COPY_ADDR(&pair_srcaddr,
2744 2743 ipsapp->ipsap_sa_ptr->ipsa_srcaddr, sq->af);
2745 2744 IPSA_COPY_ADDR(&pair_dstaddr,
2746 2745 ipsapp->ipsap_sa_ptr->ipsa_dstaddr, sq->af);
2747 2746 mutex_exit(&ipsapp->ipsap_sa_ptr->ipsa_lock);
2748 2747 mutex_exit(&sq->inbound->isaf_lock);
2749 2748 mutex_exit(&sq->outbound->isaf_lock);
2750 2749
2751 2750 if (pair_spi == 0) {
2752 2751 ASSERT(ipsapp->ipsap_bucket != NULL);
2753 2752 ASSERT(ipsapp->ipsap_pbucket != NULL);
2754 2753 return (0);
2755 2754 }
2756 2755
2757 2756 /* found sa in outbound sadb, peer should be inbound */
2758 2757
2759 2758 if (ipsapp->in_inbound_table) {
2760 2759 /* Found SA in inbound table, pair will be in outbound. */
2761 2760 if (sq->af == AF_INET6) {
2762 2761 ipsapp->ipsap_pbucket = OUTBOUND_BUCKET_V6(sq->sp,
2763 2762 *(uint32_t *)pair_srcaddr);
2764 2763 } else {
2765 2764 ipsapp->ipsap_pbucket = OUTBOUND_BUCKET_V4(sq->sp,
2766 2765 *(uint32_t *)pair_srcaddr);
2767 2766 }
2768 2767 } else {
2769 2768 ipsapp->ipsap_pbucket = INBOUND_BUCKET(sq->sp, pair_spi);
2770 2769 }
2771 2770 mutex_enter(&ipsapp->ipsap_pbucket->isaf_lock);
2772 2771 ipsapp->ipsap_psa_ptr = ipsec_getassocbyspi(ipsapp->ipsap_pbucket,
2773 2772 pair_spi, pair_dstaddr, pair_srcaddr, sq->af);
2774 2773 mutex_exit(&ipsapp->ipsap_pbucket->isaf_lock);
2775 2774 ASSERT(ipsapp->ipsap_bucket != NULL);
2776 2775 ASSERT(ipsapp->ipsap_pbucket != NULL);
2777 2776 return (0);
2778 2777 }
2779 2778
2780 2779 /*
2781 2780 * Perform NAT-traversal cached checksum offset calculations here.
2782 2781 */
2783 2782 static void
2784 2783 sadb_nat_calculations(ipsa_t *newbie, sadb_address_t *natt_loc_ext,
2785 2784 sadb_address_t *natt_rem_ext, uint32_t *src_addr_ptr,
2786 2785 uint32_t *dst_addr_ptr)
2787 2786 {
2788 2787 struct sockaddr_in *natt_loc, *natt_rem;
2789 2788 uint32_t *natt_loc_ptr = NULL, *natt_rem_ptr = NULL;
2790 2789 uint32_t running_sum = 0;
2791 2790
2792 2791 #define DOWN_SUM(x) (x) = ((x) & 0xFFFF) + ((x) >> 16)
2793 2792
2794 2793 if (natt_rem_ext != NULL) {
2795 2794 uint32_t l_src;
2796 2795 uint32_t l_rem;
2797 2796
2798 2797 natt_rem = (struct sockaddr_in *)(natt_rem_ext + 1);
2799 2798
2800 2799 /* Ensured by sadb_addrfix(). */
2801 2800 ASSERT(natt_rem->sin_family == AF_INET);
2802 2801
2803 2802 natt_rem_ptr = (uint32_t *)(&natt_rem->sin_addr);
2804 2803 newbie->ipsa_remote_nat_port = natt_rem->sin_port;
2805 2804 l_src = *src_addr_ptr;
2806 2805 l_rem = *natt_rem_ptr;
2807 2806
2808 2807 /* Instead of IPSA_COPY_ADDR(), just copy first 32 bits. */
2809 2808 newbie->ipsa_natt_addr_rem = *natt_rem_ptr;
2810 2809
2811 2810 l_src = ntohl(l_src);
2812 2811 DOWN_SUM(l_src);
2813 2812 DOWN_SUM(l_src);
2814 2813 l_rem = ntohl(l_rem);
2815 2814 DOWN_SUM(l_rem);
2816 2815 DOWN_SUM(l_rem);
2817 2816
2818 2817 /*
2819 2818 * We're 1's complement for checksums, so check for wraparound
2820 2819 * here.
2821 2820 */
2822 2821 if (l_rem > l_src)
2823 2822 l_src--;
2824 2823
2825 2824 running_sum += l_src - l_rem;
2826 2825
2827 2826 DOWN_SUM(running_sum);
2828 2827 DOWN_SUM(running_sum);
2829 2828 }
2830 2829
2831 2830 if (natt_loc_ext != NULL) {
2832 2831 natt_loc = (struct sockaddr_in *)(natt_loc_ext + 1);
2833 2832
2834 2833 /* Ensured by sadb_addrfix(). */
2835 2834 ASSERT(natt_loc->sin_family == AF_INET);
2836 2835
2837 2836 natt_loc_ptr = (uint32_t *)(&natt_loc->sin_addr);
2838 2837 newbie->ipsa_local_nat_port = natt_loc->sin_port;
2839 2838
2840 2839 /* Instead of IPSA_COPY_ADDR(), just copy first 32 bits. */
2841 2840 newbie->ipsa_natt_addr_loc = *natt_loc_ptr;
2842 2841
2843 2842 /*
2844 2843 * NAT-T port agility means we may have natt_loc_ext, but
2845 2844 * only for a local-port change.
2846 2845 */
2847 2846 if (natt_loc->sin_addr.s_addr != INADDR_ANY) {
2848 2847 uint32_t l_dst = ntohl(*dst_addr_ptr);
2849 2848 uint32_t l_loc = ntohl(*natt_loc_ptr);
2850 2849
2851 2850 DOWN_SUM(l_loc);
2852 2851 DOWN_SUM(l_loc);
2853 2852 DOWN_SUM(l_dst);
2854 2853 DOWN_SUM(l_dst);
2855 2854
2856 2855 /*
2857 2856 * We're 1's complement for checksums, so check for
2858 2857 * wraparound here.
2859 2858 */
2860 2859 if (l_loc > l_dst)
2861 2860 l_dst--;
2862 2861
2863 2862 running_sum += l_dst - l_loc;
2864 2863 DOWN_SUM(running_sum);
2865 2864 DOWN_SUM(running_sum);
2866 2865 }
2867 2866 }
2868 2867
2869 2868 newbie->ipsa_inbound_cksum = running_sum;
2870 2869 #undef DOWN_SUM
2871 2870 }
2872 2871
2873 2872 /*
2874 2873 * This function is called from consumers that need to insert a fully-grown
2875 2874 * security association into its tables. This function takes into account that
2876 2875 * SAs can be "inbound", "outbound", or "both". The "primary" and "secondary"
2877 2876 * hash bucket parameters are set in order of what the SA will be most of the
2878 2877 * time. (For example, an SA with an unspecified source, and a multicast
2879 2878 * destination will primarily be an outbound SA. OTOH, if that destination
2880 2879 * is unicast for this node, then the SA will primarily be inbound.)
2881 2880 *
2882 2881 * It takes a lot of parameters because even if clone is B_FALSE, this needs
2883 2882 * to check both buckets for purposes of collision.
2884 2883 *
2885 2884 * Return 0 upon success. Return various errnos (ENOMEM, EEXIST) for
2886 2885 * various error conditions. We may need to set samsg->sadb_x_msg_diagnostic
2887 2886 * with additional diagnostic information because there is at least one EINVAL
2888 2887 * case here.
2889 2888 */
2890 2889 int
2891 2890 sadb_common_add(queue_t *pfkey_q, mblk_t *mp, sadb_msg_t *samsg,
2892 2891 keysock_in_t *ksi, isaf_t *primary, isaf_t *secondary,
2893 2892 ipsa_t *newbie, boolean_t clone, boolean_t is_inbound, int *diagnostic,
2894 2893 netstack_t *ns, sadbp_t *spp)
2895 2894 {
2896 2895 ipsa_t *newbie_clone = NULL, *scratch;
2897 2896 ipsap_t ipsapp;
2898 2897 sadb_sa_t *assoc = (sadb_sa_t *)ksi->ks_in_extv[SADB_EXT_SA];
2899 2898 sadb_address_t *srcext =
2900 2899 (sadb_address_t *)ksi->ks_in_extv[SADB_EXT_ADDRESS_SRC];
2901 2900 sadb_address_t *dstext =
2902 2901 (sadb_address_t *)ksi->ks_in_extv[SADB_EXT_ADDRESS_DST];
2903 2902 sadb_address_t *isrcext =
2904 2903 (sadb_address_t *)ksi->ks_in_extv[SADB_X_EXT_ADDRESS_INNER_SRC];
2905 2904 sadb_address_t *idstext =
2906 2905 (sadb_address_t *)ksi->ks_in_extv[SADB_X_EXT_ADDRESS_INNER_DST];
2907 2906 sadb_x_kmc_t *kmcext =
2908 2907 (sadb_x_kmc_t *)ksi->ks_in_extv[SADB_X_EXT_KM_COOKIE];
2909 2908 sadb_key_t *akey = (sadb_key_t *)ksi->ks_in_extv[SADB_EXT_KEY_AUTH];
2910 2909 sadb_key_t *ekey = (sadb_key_t *)ksi->ks_in_extv[SADB_EXT_KEY_ENCRYPT];
2911 2910 sadb_sens_t *sens =
2912 2911 (sadb_sens_t *)ksi->ks_in_extv[SADB_EXT_SENSITIVITY];
2913 2912 sadb_sens_t *osens =
2914 2913 (sadb_sens_t *)ksi->ks_in_extv[SADB_X_EXT_OUTER_SENS];
2915 2914 sadb_x_pair_t *pair_ext =
2916 2915 (sadb_x_pair_t *)ksi->ks_in_extv[SADB_X_EXT_PAIR];
2917 2916 sadb_x_replay_ctr_t *replayext =
2918 2917 (sadb_x_replay_ctr_t *)ksi->ks_in_extv[SADB_X_EXT_REPLAY_VALUE];
2919 2918 uint8_t protocol =
2920 2919 (samsg->sadb_msg_satype == SADB_SATYPE_AH) ? IPPROTO_AH:IPPROTO_ESP;
2921 2920 int salt_offset;
2922 2921 uint8_t *buf_ptr;
2923 2922 struct sockaddr_in *src, *dst, *isrc, *idst;
2924 2923 struct sockaddr_in6 *src6, *dst6, *isrc6, *idst6;
2925 2924 sadb_lifetime_t *soft =
2926 2925 (sadb_lifetime_t *)ksi->ks_in_extv[SADB_EXT_LIFETIME_SOFT];
2927 2926 sadb_lifetime_t *hard =
2928 2927 (sadb_lifetime_t *)ksi->ks_in_extv[SADB_EXT_LIFETIME_HARD];
2929 2928 sadb_lifetime_t *idle =
2930 2929 (sadb_lifetime_t *)ksi->ks_in_extv[SADB_X_EXT_LIFETIME_IDLE];
2931 2930 sa_family_t af;
2932 2931 int error = 0;
2933 2932 boolean_t isupdate = (newbie != NULL);
2934 2933 uint32_t *src_addr_ptr, *dst_addr_ptr, *isrc_addr_ptr, *idst_addr_ptr;
2935 2934 ipsec_stack_t *ipss = ns->netstack_ipsec;
2936 2935 ip_stack_t *ipst = ns->netstack_ip;
2937 2936 ipsec_alginfo_t *alg;
2938 2937 int rcode;
2939 2938 boolean_t async = B_FALSE;
2940 2939
2941 2940 init_ipsa_pair(&ipsapp);
2942 2941
2943 2942 if (srcext == NULL) {
2944 2943 *diagnostic = SADB_X_DIAGNOSTIC_MISSING_SRC;
2945 2944 return (EINVAL);
2946 2945 }
2947 2946 if (dstext == NULL) {
2948 2947 *diagnostic = SADB_X_DIAGNOSTIC_MISSING_DST;
2949 2948 return (EINVAL);
2950 2949 }
2951 2950 if (assoc == NULL) {
2952 2951 *diagnostic = SADB_X_DIAGNOSTIC_MISSING_SA;
2953 2952 return (EINVAL);
2954 2953 }
2955 2954
2956 2955 src = (struct sockaddr_in *)(srcext + 1);
2957 2956 src6 = (struct sockaddr_in6 *)(srcext + 1);
2958 2957 dst = (struct sockaddr_in *)(dstext + 1);
2959 2958 dst6 = (struct sockaddr_in6 *)(dstext + 1);
2960 2959 if (isrcext != NULL) {
2961 2960 isrc = (struct sockaddr_in *)(isrcext + 1);
2962 2961 isrc6 = (struct sockaddr_in6 *)(isrcext + 1);
2963 2962 ASSERT(idstext != NULL);
2964 2963 idst = (struct sockaddr_in *)(idstext + 1);
2965 2964 idst6 = (struct sockaddr_in6 *)(idstext + 1);
2966 2965 } else {
2967 2966 isrc = NULL;
2968 2967 isrc6 = NULL;
2969 2968 }
2970 2969
2971 2970 af = src->sin_family;
2972 2971
2973 2972 if (af == AF_INET) {
2974 2973 src_addr_ptr = (uint32_t *)&src->sin_addr;
2975 2974 dst_addr_ptr = (uint32_t *)&dst->sin_addr;
2976 2975 } else {
2977 2976 ASSERT(af == AF_INET6);
2978 2977 src_addr_ptr = (uint32_t *)&src6->sin6_addr;
2979 2978 dst_addr_ptr = (uint32_t *)&dst6->sin6_addr;
2980 2979 }
2981 2980
2982 2981 if (!isupdate && (clone == B_TRUE || is_inbound == B_TRUE) &&
2983 2982 cl_inet_checkspi &&
2984 2983 (assoc->sadb_sa_state != SADB_X_SASTATE_ACTIVE_ELSEWHERE)) {
2985 2984 rcode = cl_inet_checkspi(ns->netstack_stackid, protocol,
2986 2985 assoc->sadb_sa_spi, NULL);
2987 2986 if (rcode == -1) {
2988 2987 return (EEXIST);
2989 2988 }
2990 2989 }
2991 2990
2992 2991 /*
2993 2992 * Check to see if the new SA will be cloned AND paired. The
2994 2993 * reason a SA will be cloned is the source or destination addresses
2995 2994 * are not specific enough to determine if the SA goes in the outbound
2996 2995 * or the inbound hash table, so its cloned and put in both. If
2997 2996 * the SA is paired, it's soft linked to another SA for the other
2998 2997 * direction. Keeping track and looking up SA's that are direction
2999 2998 * unspecific and linked is too hard.
3000 2999 */
3001 3000 if (clone && (pair_ext != NULL)) {
3002 3001 *diagnostic = SADB_X_DIAGNOSTIC_PAIR_INAPPROPRIATE;
3003 3002 return (EINVAL);
3004 3003 }
3005 3004
3006 3005 if (!isupdate) {
3007 3006 newbie = sadb_makelarvalassoc(assoc->sadb_sa_spi,
3008 3007 src_addr_ptr, dst_addr_ptr, af, ns);
3009 3008 if (newbie == NULL)
3010 3009 return (ENOMEM);
3011 3010 }
3012 3011
3013 3012 mutex_enter(&newbie->ipsa_lock);
3014 3013
3015 3014 if (isrc != NULL) {
3016 3015 if (isrc->sin_family == AF_INET) {
3017 3016 if (srcext->sadb_address_proto != IPPROTO_ENCAP) {
3018 3017 if (srcext->sadb_address_proto != 0) {
3019 3018 /*
3020 3019 * Mismatched outer-packet protocol
3021 3020 * and inner-packet address family.
3022 3021 */
3023 3022 mutex_exit(&newbie->ipsa_lock);
3024 3023 error = EPROTOTYPE;
3025 3024 *diagnostic =
3026 3025 SADB_X_DIAGNOSTIC_INNER_AF_MISMATCH;
3027 3026 goto error;
3028 3027 } else {
3029 3028 /* Fill in with explicit protocol. */
3030 3029 srcext->sadb_address_proto =
3031 3030 IPPROTO_ENCAP;
3032 3031 dstext->sadb_address_proto =
3033 3032 IPPROTO_ENCAP;
3034 3033 }
3035 3034 }
3036 3035 isrc_addr_ptr = (uint32_t *)&isrc->sin_addr;
3037 3036 idst_addr_ptr = (uint32_t *)&idst->sin_addr;
3038 3037 } else {
3039 3038 ASSERT(isrc->sin_family == AF_INET6);
3040 3039 if (srcext->sadb_address_proto != IPPROTO_IPV6) {
3041 3040 if (srcext->sadb_address_proto != 0) {
3042 3041 /*
3043 3042 * Mismatched outer-packet protocol
3044 3043 * and inner-packet address family.
3045 3044 */
3046 3045 mutex_exit(&newbie->ipsa_lock);
3047 3046 error = EPROTOTYPE;
3048 3047 *diagnostic =
3049 3048 SADB_X_DIAGNOSTIC_INNER_AF_MISMATCH;
3050 3049 goto error;
3051 3050 } else {
3052 3051 /* Fill in with explicit protocol. */
3053 3052 srcext->sadb_address_proto =
3054 3053 IPPROTO_IPV6;
3055 3054 dstext->sadb_address_proto =
3056 3055 IPPROTO_IPV6;
3057 3056 }
3058 3057 }
3059 3058 isrc_addr_ptr = (uint32_t *)&isrc6->sin6_addr;
3060 3059 idst_addr_ptr = (uint32_t *)&idst6->sin6_addr;
3061 3060 }
3062 3061 newbie->ipsa_innerfam = isrc->sin_family;
3063 3062
3064 3063 IPSA_COPY_ADDR(newbie->ipsa_innersrc, isrc_addr_ptr,
3065 3064 newbie->ipsa_innerfam);
3066 3065 IPSA_COPY_ADDR(newbie->ipsa_innerdst, idst_addr_ptr,
3067 3066 newbie->ipsa_innerfam);
3068 3067 newbie->ipsa_innersrcpfx = isrcext->sadb_address_prefixlen;
3069 3068 newbie->ipsa_innerdstpfx = idstext->sadb_address_prefixlen;
3070 3069
3071 3070 /* Unique value uses inner-ports for Tunnel Mode... */
3072 3071 newbie->ipsa_unique_id = SA_UNIQUE_ID(isrc->sin_port,
3073 3072 idst->sin_port, dstext->sadb_address_proto,
3074 3073 idstext->sadb_address_proto);
3075 3074 newbie->ipsa_unique_mask = SA_UNIQUE_MASK(isrc->sin_port,
3076 3075 idst->sin_port, dstext->sadb_address_proto,
3077 3076 idstext->sadb_address_proto);
3078 3077 } else {
3079 3078 /* ... and outer-ports for Transport Mode. */
3080 3079 newbie->ipsa_unique_id = SA_UNIQUE_ID(src->sin_port,
3081 3080 dst->sin_port, dstext->sadb_address_proto, 0);
3082 3081 newbie->ipsa_unique_mask = SA_UNIQUE_MASK(src->sin_port,
3083 3082 dst->sin_port, dstext->sadb_address_proto, 0);
3084 3083 }
3085 3084 if (newbie->ipsa_unique_mask != (uint64_t)0)
3086 3085 newbie->ipsa_flags |= IPSA_F_UNIQUE;
3087 3086
3088 3087 sadb_nat_calculations(newbie,
3089 3088 (sadb_address_t *)ksi->ks_in_extv[SADB_X_EXT_ADDRESS_NATT_LOC],
3090 3089 (sadb_address_t *)ksi->ks_in_extv[SADB_X_EXT_ADDRESS_NATT_REM],
3091 3090 src_addr_ptr, dst_addr_ptr);
3092 3091
3093 3092 newbie->ipsa_type = samsg->sadb_msg_satype;
3094 3093
3095 3094 ASSERT((assoc->sadb_sa_state == SADB_SASTATE_MATURE) ||
3096 3095 (assoc->sadb_sa_state == SADB_X_SASTATE_ACTIVE_ELSEWHERE));
3097 3096 newbie->ipsa_auth_alg = assoc->sadb_sa_auth;
3098 3097 newbie->ipsa_encr_alg = assoc->sadb_sa_encrypt;
3099 3098
3100 3099 newbie->ipsa_flags |= assoc->sadb_sa_flags;
3101 3100 if (newbie->ipsa_flags & SADB_X_SAFLAGS_NATT_LOC &&
3102 3101 ksi->ks_in_extv[SADB_X_EXT_ADDRESS_NATT_LOC] == NULL) {
3103 3102 mutex_exit(&newbie->ipsa_lock);
3104 3103 *diagnostic = SADB_X_DIAGNOSTIC_MISSING_NATT_LOC;
3105 3104 error = EINVAL;
3106 3105 goto error;
3107 3106 }
3108 3107 if (newbie->ipsa_flags & SADB_X_SAFLAGS_NATT_REM &&
3109 3108 ksi->ks_in_extv[SADB_X_EXT_ADDRESS_NATT_REM] == NULL) {
3110 3109 mutex_exit(&newbie->ipsa_lock);
3111 3110 *diagnostic = SADB_X_DIAGNOSTIC_MISSING_NATT_REM;
3112 3111 error = EINVAL;
3113 3112 goto error;
3114 3113 }
3115 3114 if (newbie->ipsa_flags & SADB_X_SAFLAGS_TUNNEL &&
3116 3115 ksi->ks_in_extv[SADB_X_EXT_ADDRESS_INNER_SRC] == NULL) {
3117 3116 mutex_exit(&newbie->ipsa_lock);
3118 3117 *diagnostic = SADB_X_DIAGNOSTIC_MISSING_INNER_SRC;
3119 3118 error = EINVAL;
3120 3119 goto error;
3121 3120 }
3122 3121 /*
3123 3122 * If unspecified source address, force replay_wsize to 0.
3124 3123 * This is because an SA that has multiple sources of secure
3125 3124 * traffic cannot enforce a replay counter w/o synchronizing the
3126 3125 * senders.
3127 3126 */
3128 3127 if (ksi->ks_in_srctype != KS_IN_ADDR_UNSPEC)
3129 3128 newbie->ipsa_replay_wsize = assoc->sadb_sa_replay;
3130 3129 else
3131 3130 newbie->ipsa_replay_wsize = 0;
3132 3131
3133 3132 newbie->ipsa_addtime = gethrestime_sec();
3134 3133
3135 3134 if (kmcext != NULL) {
3136 3135 newbie->ipsa_kmp = kmcext->sadb_x_kmc_proto;
3137 3136 newbie->ipsa_kmc = kmcext->sadb_x_kmc_cookie;
3138 3137 }
3139 3138
3140 3139 /*
3141 3140 * XXX CURRENT lifetime checks MAY BE needed for an UPDATE.
3142 3141 * The spec says that one can update current lifetimes, but
3143 3142 * that seems impractical, especially in the larval-to-mature
3144 3143 * update that this function performs.
3145 3144 */
3146 3145 if (soft != NULL) {
3147 3146 newbie->ipsa_softaddlt = soft->sadb_lifetime_addtime;
3148 3147 newbie->ipsa_softuselt = soft->sadb_lifetime_usetime;
3149 3148 newbie->ipsa_softbyteslt = soft->sadb_lifetime_bytes;
3150 3149 newbie->ipsa_softalloc = soft->sadb_lifetime_allocations;
3151 3150 SET_EXPIRE(newbie, softaddlt, softexpiretime);
3152 3151 }
3153 3152 if (hard != NULL) {
3154 3153 newbie->ipsa_hardaddlt = hard->sadb_lifetime_addtime;
3155 3154 newbie->ipsa_harduselt = hard->sadb_lifetime_usetime;
3156 3155 newbie->ipsa_hardbyteslt = hard->sadb_lifetime_bytes;
3157 3156 newbie->ipsa_hardalloc = hard->sadb_lifetime_allocations;
3158 3157 SET_EXPIRE(newbie, hardaddlt, hardexpiretime);
3159 3158 }
3160 3159 if (idle != NULL) {
3161 3160 newbie->ipsa_idleaddlt = idle->sadb_lifetime_addtime;
3162 3161 newbie->ipsa_idleuselt = idle->sadb_lifetime_usetime;
3163 3162 newbie->ipsa_idleexpiretime = newbie->ipsa_addtime +
3164 3163 newbie->ipsa_idleaddlt;
3165 3164 newbie->ipsa_idletime = newbie->ipsa_idleaddlt;
3166 3165 }
3167 3166
3168 3167 newbie->ipsa_authtmpl = NULL;
3169 3168 newbie->ipsa_encrtmpl = NULL;
3170 3169
3171 3170 #ifdef IPSEC_LATENCY_TEST
3172 3171 if (akey != NULL && newbie->ipsa_auth_alg != SADB_AALG_NONE) {
3173 3172 #else
3174 3173 if (akey != NULL) {
3175 3174 #endif
3176 3175 async = (ipss->ipsec_algs_exec_mode[IPSEC_ALG_AUTH] ==
3177 3176 IPSEC_ALGS_EXEC_ASYNC);
3178 3177
3179 3178 newbie->ipsa_authkeybits = akey->sadb_key_bits;
3180 3179 newbie->ipsa_authkeylen = SADB_1TO8(akey->sadb_key_bits);
3181 3180 /* In case we have to round up to the next byte... */
3182 3181 if ((akey->sadb_key_bits & 0x7) != 0)
3183 3182 newbie->ipsa_authkeylen++;
3184 3183 newbie->ipsa_authkey = kmem_alloc(newbie->ipsa_authkeylen,
3185 3184 KM_NOSLEEP);
3186 3185 if (newbie->ipsa_authkey == NULL) {
3187 3186 error = ENOMEM;
3188 3187 mutex_exit(&newbie->ipsa_lock);
3189 3188 goto error;
3190 3189 }
3191 3190 bcopy(akey + 1, newbie->ipsa_authkey, newbie->ipsa_authkeylen);
3192 3191 bzero(akey + 1, newbie->ipsa_authkeylen);
3193 3192
3194 3193 /*
3195 3194 * Pre-initialize the kernel crypto framework key
3196 3195 * structure.
3197 3196 */
3198 3197 newbie->ipsa_kcfauthkey.ck_format = CRYPTO_KEY_RAW;
3199 3198 newbie->ipsa_kcfauthkey.ck_length = newbie->ipsa_authkeybits;
3200 3199 newbie->ipsa_kcfauthkey.ck_data = newbie->ipsa_authkey;
3201 3200
3202 3201 rw_enter(&ipss->ipsec_alg_lock, RW_READER);
3203 3202 alg = ipss->ipsec_alglists[IPSEC_ALG_AUTH]
3204 3203 [newbie->ipsa_auth_alg];
3205 3204 if (alg != NULL && ALG_VALID(alg)) {
3206 3205 newbie->ipsa_amech.cm_type = alg->alg_mech_type;
3207 3206 newbie->ipsa_amech.cm_param =
3208 3207 (char *)&newbie->ipsa_mac_len;
3209 3208 newbie->ipsa_amech.cm_param_len = sizeof (size_t);
3210 3209 newbie->ipsa_mac_len = (size_t)alg->alg_datalen;
3211 3210 } else {
3212 3211 newbie->ipsa_amech.cm_type = CRYPTO_MECHANISM_INVALID;
3213 3212 }
3214 3213 error = ipsec_create_ctx_tmpl(newbie, IPSEC_ALG_AUTH);
3215 3214 rw_exit(&ipss->ipsec_alg_lock);
3216 3215 if (error != 0) {
3217 3216 mutex_exit(&newbie->ipsa_lock);
3218 3217 /*
3219 3218 * An error here indicates that alg is the wrong type
3220 3219 * (IE: not authentication) or its not in the alg tables
3221 3220 * created by ipsecalgs(1m), or Kcf does not like the
3222 3221 * parameters passed in with this algorithm, which is
3223 3222 * probably a coding error!
3224 3223 */
3225 3224 *diagnostic = SADB_X_DIAGNOSTIC_BAD_CTX;
3226 3225
3227 3226 goto error;
3228 3227 }
3229 3228 }
3230 3229
3231 3230 if (ekey != NULL) {
3232 3231 rw_enter(&ipss->ipsec_alg_lock, RW_READER);
3233 3232 async = async || (ipss->ipsec_algs_exec_mode[IPSEC_ALG_ENCR] ==
3234 3233 IPSEC_ALGS_EXEC_ASYNC);
3235 3234 alg = ipss->ipsec_alglists[IPSEC_ALG_ENCR]
3236 3235 [newbie->ipsa_encr_alg];
3237 3236
3238 3237 if (alg != NULL && ALG_VALID(alg)) {
3239 3238 newbie->ipsa_emech.cm_type = alg->alg_mech_type;
3240 3239 newbie->ipsa_datalen = alg->alg_datalen;
3241 3240 if (alg->alg_flags & ALG_FLAG_COUNTERMODE)
3242 3241 newbie->ipsa_flags |= IPSA_F_COUNTERMODE;
3243 3242
3244 3243 if (alg->alg_flags & ALG_FLAG_COMBINED) {
3245 3244 newbie->ipsa_flags |= IPSA_F_COMBINED;
3246 3245 newbie->ipsa_mac_len = alg->alg_icvlen;
3247 3246 }
3248 3247
3249 3248 if (alg->alg_flags & ALG_FLAG_CCM)
3250 3249 newbie->ipsa_noncefunc = ccm_params_init;
3251 3250 else if (alg->alg_flags & ALG_FLAG_GCM)
3252 3251 newbie->ipsa_noncefunc = gcm_params_init;
3253 3252 else newbie->ipsa_noncefunc = cbc_params_init;
3254 3253
3255 3254 newbie->ipsa_saltlen = alg->alg_saltlen;
3256 3255 newbie->ipsa_saltbits = SADB_8TO1(newbie->ipsa_saltlen);
3257 3256 newbie->ipsa_iv_len = alg->alg_ivlen;
3258 3257 newbie->ipsa_nonce_len = newbie->ipsa_saltlen +
3259 3258 newbie->ipsa_iv_len;
3260 3259 newbie->ipsa_emech.cm_param = NULL;
3261 3260 newbie->ipsa_emech.cm_param_len = 0;
3262 3261 } else {
3263 3262 newbie->ipsa_emech.cm_type = CRYPTO_MECHANISM_INVALID;
3264 3263 }
3265 3264 rw_exit(&ipss->ipsec_alg_lock);
3266 3265
3267 3266 /*
3268 3267 * The byte stream following the sadb_key_t is made up of:
3269 3268 * key bytes, [salt bytes], [IV initial value]
3270 3269 * All of these have variable length. The IV is typically
3271 3270 * randomly generated by this function and not passed in.
3272 3271 * By supporting the injection of a known IV, the whole
3273 3272 * IPsec subsystem and the underlying crypto subsystem
3274 3273 * can be tested with known test vectors.
3275 3274 *
3276 3275 * The keying material has been checked by ext_check()
3277 3276 * and ipsec_valid_key_size(), after removing salt/IV
3278 3277 * bits, whats left is the encryption key. If this is too
3279 3278 * short, ipsec_create_ctx_tmpl() will fail and the SA
3280 3279 * won't get created.
3281 3280 *
3282 3281 * set ipsa_encrkeylen to length of key only.
3283 3282 */
3284 3283 newbie->ipsa_encrkeybits = ekey->sadb_key_bits;
3285 3284 newbie->ipsa_encrkeybits -= ekey->sadb_key_reserved;
3286 3285 newbie->ipsa_encrkeybits -= newbie->ipsa_saltbits;
3287 3286 newbie->ipsa_encrkeylen = SADB_1TO8(newbie->ipsa_encrkeybits);
3288 3287
3289 3288 /* In case we have to round up to the next byte... */
3290 3289 if ((ekey->sadb_key_bits & 0x7) != 0)
3291 3290 newbie->ipsa_encrkeylen++;
3292 3291
3293 3292 newbie->ipsa_encrkey = kmem_alloc(newbie->ipsa_encrkeylen,
3294 3293 KM_NOSLEEP);
3295 3294 if (newbie->ipsa_encrkey == NULL) {
3296 3295 error = ENOMEM;
3297 3296 mutex_exit(&newbie->ipsa_lock);
3298 3297 goto error;
3299 3298 }
3300 3299
3301 3300 buf_ptr = (uint8_t *)(ekey + 1);
3302 3301 bcopy(buf_ptr, newbie->ipsa_encrkey, newbie->ipsa_encrkeylen);
3303 3302
3304 3303 if (newbie->ipsa_flags & IPSA_F_COMBINED) {
3305 3304 /*
3306 3305 * Combined mode algs need a nonce. Copy the salt and
3307 3306 * IV into a buffer. The ipsa_nonce is a pointer into
3308 3307 * this buffer, some bytes at the start of the buffer
3309 3308 * may be unused, depends on the salt length. The IV
3310 3309 * is 64 bit aligned so it can be incremented as a
3311 3310 * uint64_t. Zero out key in samsg_t before freeing.
3312 3311 */
3313 3312
3314 3313 newbie->ipsa_nonce_buf = kmem_alloc(
3315 3314 sizeof (ipsec_nonce_t), KM_NOSLEEP);
3316 3315 if (newbie->ipsa_nonce_buf == NULL) {
3317 3316 error = ENOMEM;
3318 3317 mutex_exit(&newbie->ipsa_lock);
3319 3318 goto error;
3320 3319 }
3321 3320 /*
3322 3321 * Initialize nonce and salt pointers to point
3323 3322 * to the nonce buffer. This is just in case we get
3324 3323 * bad data, the pointers will be valid, the data
3325 3324 * won't be.
3326 3325 *
3327 3326 * See sadb.h for layout of nonce.
3328 3327 */
3329 3328 newbie->ipsa_iv = &newbie->ipsa_nonce_buf->iv;
3330 3329 newbie->ipsa_salt = (uint8_t *)newbie->ipsa_nonce_buf;
3331 3330 newbie->ipsa_nonce = newbie->ipsa_salt;
3332 3331 if (newbie->ipsa_saltlen != 0) {
3333 3332 salt_offset = MAXSALTSIZE -
3334 3333 newbie->ipsa_saltlen;
3335 3334 newbie->ipsa_salt = (uint8_t *)
3336 3335 &newbie->ipsa_nonce_buf->salt[salt_offset];
3337 3336 newbie->ipsa_nonce = newbie->ipsa_salt;
3338 3337 buf_ptr += newbie->ipsa_encrkeylen;
3339 3338 bcopy(buf_ptr, newbie->ipsa_salt,
3340 3339 newbie->ipsa_saltlen);
3341 3340 }
3342 3341 /*
3343 3342 * The IV for CCM/GCM mode increments, it should not
3344 3343 * repeat. Get a random value for the IV, make a
3345 3344 * copy, the SA will expire when/if the IV ever
3346 3345 * wraps back to the initial value. If an Initial IV
3347 3346 * is passed in via PF_KEY, save this in the SA.
3348 3347 * Initialising IV for inbound is pointless as its
3349 3348 * taken from the inbound packet.
3350 3349 */
3351 3350 if (!is_inbound) {
3352 3351 if (ekey->sadb_key_reserved != 0) {
3353 3352 buf_ptr += newbie->ipsa_saltlen;
3354 3353 bcopy(buf_ptr, (uint8_t *)newbie->
3355 3354 ipsa_iv, SADB_1TO8(ekey->
3356 3355 sadb_key_reserved));
3357 3356 } else {
3358 3357 (void) random_get_pseudo_bytes(
3359 3358 (uint8_t *)newbie->ipsa_iv,
3360 3359 newbie->ipsa_iv_len);
3361 3360 }
3362 3361 newbie->ipsa_iv_softexpire =
3363 3362 (*newbie->ipsa_iv) << 9;
3364 3363 newbie->ipsa_iv_hardexpire = *newbie->ipsa_iv;
3365 3364 }
3366 3365 }
3367 3366 bzero((ekey + 1), SADB_1TO8(ekey->sadb_key_bits));
3368 3367
3369 3368 /*
3370 3369 * Pre-initialize the kernel crypto framework key
3371 3370 * structure.
3372 3371 */
3373 3372 newbie->ipsa_kcfencrkey.ck_format = CRYPTO_KEY_RAW;
3374 3373 newbie->ipsa_kcfencrkey.ck_length = newbie->ipsa_encrkeybits;
3375 3374 newbie->ipsa_kcfencrkey.ck_data = newbie->ipsa_encrkey;
3376 3375
3377 3376 rw_enter(&ipss->ipsec_alg_lock, RW_READER);
3378 3377 error = ipsec_create_ctx_tmpl(newbie, IPSEC_ALG_ENCR);
3379 3378 rw_exit(&ipss->ipsec_alg_lock);
3380 3379 if (error != 0) {
3381 3380 mutex_exit(&newbie->ipsa_lock);
3382 3381 /* See above for error explanation. */
3383 3382 *diagnostic = SADB_X_DIAGNOSTIC_BAD_CTX;
3384 3383 goto error;
3385 3384 }
3386 3385 }
3387 3386
3388 3387 if (async)
3389 3388 newbie->ipsa_flags |= IPSA_F_ASYNC;
3390 3389
3391 3390 /*
3392 3391 * Ptrs to processing functions.
3393 3392 */
3394 3393 if (newbie->ipsa_type == SADB_SATYPE_ESP)
3395 3394 ipsecesp_init_funcs(newbie);
3396 3395 else
3397 3396 ipsecah_init_funcs(newbie);
3398 3397 ASSERT(newbie->ipsa_output_func != NULL &&
3399 3398 newbie->ipsa_input_func != NULL);
3400 3399
3401 3400 /*
3402 3401 * Certificate ID stuff.
3403 3402 */
3404 3403 if (ksi->ks_in_extv[SADB_EXT_IDENTITY_SRC] != NULL) {
3405 3404 sadb_ident_t *id =
3406 3405 (sadb_ident_t *)ksi->ks_in_extv[SADB_EXT_IDENTITY_SRC];
3407 3406
3408 3407 /*
3409 3408 * Can assume strlen() will return okay because ext_check() in
3410 3409 * keysock.c prepares the string for us.
3411 3410 */
3412 3411 newbie->ipsa_src_cid = ipsid_lookup(id->sadb_ident_type,
3413 3412 (char *)(id+1), ns);
3414 3413 if (newbie->ipsa_src_cid == NULL) {
3415 3414 error = ENOMEM;
3416 3415 mutex_exit(&newbie->ipsa_lock);
3417 3416 goto error;
3418 3417 }
3419 3418 }
3420 3419
3421 3420 if (ksi->ks_in_extv[SADB_EXT_IDENTITY_DST] != NULL) {
3422 3421 sadb_ident_t *id =
3423 3422 (sadb_ident_t *)ksi->ks_in_extv[SADB_EXT_IDENTITY_DST];
3424 3423
3425 3424 /*
3426 3425 * Can assume strlen() will return okay because ext_check() in
3427 3426 * keysock.c prepares the string for us.
3428 3427 */
3429 3428 newbie->ipsa_dst_cid = ipsid_lookup(id->sadb_ident_type,
3430 3429 (char *)(id+1), ns);
3431 3430 if (newbie->ipsa_dst_cid == NULL) {
3432 3431 error = ENOMEM;
3433 3432 mutex_exit(&newbie->ipsa_lock);
3434 3433 goto error;
3435 3434 }
3436 3435 }
3437 3436
3438 3437 /*
3439 3438 * sensitivity label handling code:
3440 3439 * Convert sens + bitmap into cred_t, and associate it
3441 3440 * with the new SA.
3442 3441 */
3443 3442 if (sens != NULL) {
3444 3443 uint64_t *bitmap = (uint64_t *)(sens + 1);
3445 3444
3446 3445 newbie->ipsa_tsl = sadb_label_from_sens(sens, bitmap);
3447 3446 }
3448 3447
3449 3448 /*
3450 3449 * Likewise for outer sensitivity.
3451 3450 */
3452 3451 if (osens != NULL) {
3453 3452 uint64_t *bitmap = (uint64_t *)(osens + 1);
3454 3453 ts_label_t *tsl, *effective_tsl;
3455 3454 uint32_t *peer_addr_ptr;
3456 3455 zoneid_t zoneid = GLOBAL_ZONEID;
3457 3456 zone_t *zone;
3458 3457
3459 3458 peer_addr_ptr = is_inbound ? src_addr_ptr : dst_addr_ptr;
3460 3459
3461 3460 tsl = sadb_label_from_sens(osens, bitmap);
3462 3461 newbie->ipsa_mac_exempt = CONN_MAC_DEFAULT;
3463 3462
3464 3463 if (osens->sadb_x_sens_flags & SADB_X_SENS_IMPLICIT) {
3465 3464 newbie->ipsa_mac_exempt = CONN_MAC_IMPLICIT;
3466 3465 }
3467 3466
3468 3467 error = tsol_check_dest(tsl, peer_addr_ptr,
3469 3468 (af == AF_INET6)?IPV6_VERSION:IPV4_VERSION,
3470 3469 newbie->ipsa_mac_exempt, B_TRUE, &effective_tsl);
3471 3470 if (error != 0) {
3472 3471 label_rele(tsl);
3473 3472 mutex_exit(&newbie->ipsa_lock);
3474 3473 goto error;
3475 3474 }
3476 3475
3477 3476 if (effective_tsl != NULL) {
3478 3477 label_rele(tsl);
3479 3478 tsl = effective_tsl;
3480 3479 }
3481 3480
3482 3481 newbie->ipsa_otsl = tsl;
3483 3482
3484 3483 zone = zone_find_by_label(tsl);
3485 3484 if (zone != NULL) {
3486 3485 zoneid = zone->zone_id;
3487 3486 zone_rele(zone);
3488 3487 }
3489 3488 /*
3490 3489 * For exclusive stacks we set the zoneid to zero to operate
3491 3490 * as if in the global zone for tsol_compute_label_v4/v6
3492 3491 */
3493 3492 if (ipst->ips_netstack->netstack_stackid != GLOBAL_NETSTACKID)
3494 3493 zoneid = GLOBAL_ZONEID;
3495 3494
3496 3495 if (af == AF_INET6) {
3497 3496 error = tsol_compute_label_v6(tsl, zoneid,
3498 3497 (in6_addr_t *)peer_addr_ptr,
3499 3498 newbie->ipsa_opt_storage, ipst);
3500 3499 } else {
3501 3500 error = tsol_compute_label_v4(tsl, zoneid,
3502 3501 *peer_addr_ptr, newbie->ipsa_opt_storage, ipst);
3503 3502 }
3504 3503 if (error != 0) {
3505 3504 mutex_exit(&newbie->ipsa_lock);
3506 3505 goto error;
3507 3506 }
3508 3507 }
3509 3508
3510 3509
3511 3510 if (replayext != NULL) {
3512 3511 if ((replayext->sadb_x_rc_replay32 == 0) &&
3513 3512 (replayext->sadb_x_rc_replay64 != 0)) {
3514 3513 error = EOPNOTSUPP;
3515 3514 *diagnostic = SADB_X_DIAGNOSTIC_INVALID_REPLAY;
3516 3515 mutex_exit(&newbie->ipsa_lock);
3517 3516 goto error;
3518 3517 }
3519 3518 newbie->ipsa_replay = replayext->sadb_x_rc_replay32;
3520 3519 }
3521 3520
3522 3521 /* now that the SA has been updated, set its new state */
3523 3522 newbie->ipsa_state = assoc->sadb_sa_state;
3524 3523
3525 3524 if (clone) {
3526 3525 newbie->ipsa_haspeer = B_TRUE;
3527 3526 } else {
3528 3527 if (!is_inbound) {
3529 3528 lifetime_fuzz(newbie);
3530 3529 }
3531 3530 }
3532 3531 /*
3533 3532 * The less locks I hold when doing an insertion and possible cloning,
3534 3533 * the better!
3535 3534 */
3536 3535 mutex_exit(&newbie->ipsa_lock);
3537 3536
3538 3537 if (clone) {
3539 3538 newbie_clone = sadb_cloneassoc(newbie);
3540 3539
3541 3540 if (newbie_clone == NULL) {
3542 3541 error = ENOMEM;
3543 3542 goto error;
3544 3543 }
3545 3544 }
3546 3545
3547 3546 /*
3548 3547 * Enter the bucket locks. The order of entry is outbound,
3549 3548 * inbound. We map "primary" and "secondary" into outbound and inbound
3550 3549 * based on the destination address type. If the destination address
3551 3550 * type is for a node that isn't mine (or potentially mine), the
3552 3551 * "primary" bucket is the outbound one.
3553 3552 */
3554 3553 if (!is_inbound) {
3555 3554 /* primary == outbound */
3556 3555 mutex_enter(&primary->isaf_lock);
3557 3556 mutex_enter(&secondary->isaf_lock);
3558 3557 } else {
3559 3558 /* primary == inbound */
3560 3559 mutex_enter(&secondary->isaf_lock);
3561 3560 mutex_enter(&primary->isaf_lock);
3562 3561 }
3563 3562
3564 3563 /*
3565 3564 * sadb_insertassoc() doesn't increment the reference
3566 3565 * count. We therefore have to increment the
3567 3566 * reference count one more time to reflect the
3568 3567 * pointers of the table that reference this SA.
3569 3568 */
3570 3569 IPSA_REFHOLD(newbie);
3571 3570
3572 3571 if (isupdate) {
3573 3572 /*
3574 3573 * Unlink from larval holding cell in the "inbound" fanout.
3575 3574 */
3576 3575 ASSERT(newbie->ipsa_linklock == &primary->isaf_lock ||
3577 3576 newbie->ipsa_linklock == &secondary->isaf_lock);
3578 3577 sadb_unlinkassoc(newbie);
3579 3578 }
3580 3579
3581 3580 mutex_enter(&newbie->ipsa_lock);
3582 3581 error = sadb_insertassoc(newbie, primary);
3583 3582 mutex_exit(&newbie->ipsa_lock);
3584 3583
3585 3584 if (error != 0) {
3586 3585 /*
3587 3586 * Since sadb_insertassoc() failed, we must decrement the
3588 3587 * refcount again so the cleanup code will actually free
3589 3588 * the offending SA.
3590 3589 */
3591 3590 IPSA_REFRELE(newbie);
3592 3591 goto error_unlock;
3593 3592 }
3594 3593
3595 3594 if (newbie_clone != NULL) {
3596 3595 mutex_enter(&newbie_clone->ipsa_lock);
3597 3596 error = sadb_insertassoc(newbie_clone, secondary);
3598 3597 mutex_exit(&newbie_clone->ipsa_lock);
3599 3598 if (error != 0) {
3600 3599 /* Collision in secondary table. */
3601 3600 sadb_unlinkassoc(newbie); /* This does REFRELE. */
3602 3601 goto error_unlock;
3603 3602 }
3604 3603 IPSA_REFHOLD(newbie_clone);
3605 3604 } else {
3606 3605 ASSERT(primary != secondary);
3607 3606 scratch = ipsec_getassocbyspi(secondary, newbie->ipsa_spi,
3608 3607 ALL_ZEROES_PTR, newbie->ipsa_dstaddr, af);
3609 3608 if (scratch != NULL) {
3610 3609 /* Collision in secondary table. */
3611 3610 sadb_unlinkassoc(newbie); /* This does REFRELE. */
3612 3611 /* Set the error, since ipsec_getassocbyspi() can't. */
3613 3612 error = EEXIST;
3614 3613 goto error_unlock;
3615 3614 }
3616 3615 }
3617 3616
3618 3617 /* OKAY! So let's do some reality check assertions. */
3619 3618
3620 3619 ASSERT(MUTEX_NOT_HELD(&newbie->ipsa_lock));
3621 3620 ASSERT(newbie_clone == NULL ||
3622 3621 (MUTEX_NOT_HELD(&newbie_clone->ipsa_lock)));
3623 3622
3624 3623 error_unlock:
3625 3624
3626 3625 /*
3627 3626 * We can exit the locks in any order. Only entrance needs to
3628 3627 * follow any protocol.
3629 3628 */
3630 3629 mutex_exit(&secondary->isaf_lock);
3631 3630 mutex_exit(&primary->isaf_lock);
3632 3631
3633 3632 if (pair_ext != NULL && error == 0) {
3634 3633 /* update pair_spi if it exists. */
3635 3634 ipsa_query_t sq;
3636 3635
3637 3636 sq.spp = spp; /* XXX param */
3638 3637 error = sadb_form_query(ksi, IPSA_Q_DST, IPSA_Q_SRC|IPSA_Q_DST|
3639 3638 IPSA_Q_SA|IPSA_Q_INBOUND|IPSA_Q_OUTBOUND, &sq, diagnostic);
3640 3639 if (error)
3641 3640 return (error);
3642 3641
3643 3642 error = get_ipsa_pair(&sq, &ipsapp, diagnostic);
3644 3643
3645 3644 if (error != 0)
3646 3645 goto error;
3647 3646
3648 3647 if (ipsapp.ipsap_psa_ptr != NULL) {
3649 3648 *diagnostic = SADB_X_DIAGNOSTIC_PAIR_ALREADY;
3650 3649 error = EINVAL;
3651 3650 } else {
3652 3651 /* update_pairing() sets diagnostic */
3653 3652 error = update_pairing(&ipsapp, &sq, ksi, diagnostic);
3654 3653 }
3655 3654 }
3656 3655 /* Common error point for this routine. */
3657 3656 error:
3658 3657 if (newbie != NULL) {
3659 3658 if (error != 0) {
3660 3659 /* This SA is broken, let the reaper clean up. */
3661 3660 mutex_enter(&newbie->ipsa_lock);
3662 3661 newbie->ipsa_state = IPSA_STATE_DEAD;
3663 3662 newbie->ipsa_hardexpiretime = 1;
3664 3663 mutex_exit(&newbie->ipsa_lock);
3665 3664 }
3666 3665 IPSA_REFRELE(newbie);
3667 3666 }
3668 3667 if (newbie_clone != NULL) {
3669 3668 IPSA_REFRELE(newbie_clone);
3670 3669 }
3671 3670
3672 3671 if (error == 0) {
3673 3672 /*
3674 3673 * Construct favorable PF_KEY return message and send to
3675 3674 * keysock. Update the flags in the original keysock message
3676 3675 * to reflect the actual flags in the new SA.
3677 3676 * (Q: Do I need to pass "newbie"? If I do,
3678 3677 * make sure to REFHOLD, call, then REFRELE.)
3679 3678 */
3680 3679 assoc->sadb_sa_flags = newbie->ipsa_flags;
3681 3680 sadb_pfkey_echo(pfkey_q, mp, samsg, ksi, NULL);
3682 3681 }
3683 3682
3684 3683 destroy_ipsa_pair(&ipsapp);
3685 3684 return (error);
3686 3685 }
3687 3686
3688 3687 /*
3689 3688 * Set the time of first use for a security association. Update any
3690 3689 * expiration times as a result.
3691 3690 */
3692 3691 void
3693 3692 sadb_set_usetime(ipsa_t *assoc)
3694 3693 {
3695 3694 time_t snapshot = gethrestime_sec();
3696 3695
3697 3696 mutex_enter(&assoc->ipsa_lock);
3698 3697 assoc->ipsa_lastuse = snapshot;
3699 3698 assoc->ipsa_idleexpiretime = snapshot + assoc->ipsa_idletime;
3700 3699
3701 3700 /*
3702 3701 * Caller does check usetime before calling me usually, and
3703 3702 * double-checking is better than a mutex_enter/exit hit.
3704 3703 */
3705 3704 if (assoc->ipsa_usetime == 0) {
3706 3705 /*
3707 3706 * This is redundant for outbound SA's, as
3708 3707 * ipsec_getassocbyconn() sets the IPSA_F_USED flag already.
3709 3708 * Inbound SAs, however, have no such protection.
3710 3709 */
3711 3710 assoc->ipsa_flags |= IPSA_F_USED;
3712 3711 assoc->ipsa_usetime = snapshot;
3713 3712
3714 3713 /*
3715 3714 * After setting the use time, see if we have a use lifetime
3716 3715 * that would cause the actual SA expiration time to shorten.
3717 3716 */
3718 3717 UPDATE_EXPIRE(assoc, softuselt, softexpiretime);
3719 3718 UPDATE_EXPIRE(assoc, harduselt, hardexpiretime);
3720 3719 }
3721 3720 mutex_exit(&assoc->ipsa_lock);
3722 3721 }
3723 3722
3724 3723 /*
3725 3724 * Send up a PF_KEY expire message for this association.
3726 3725 */
3727 3726 static void
3728 3727 sadb_expire_assoc(queue_t *pfkey_q, ipsa_t *assoc)
3729 3728 {
3730 3729 mblk_t *mp, *mp1;
3731 3730 int alloclen, af;
3732 3731 sadb_msg_t *samsg;
3733 3732 sadb_lifetime_t *current, *expire;
3734 3733 sadb_sa_t *saext;
3735 3734 uint8_t *end;
3736 3735 boolean_t tunnel_mode;
3737 3736
3738 3737 ASSERT(MUTEX_HELD(&assoc->ipsa_lock));
3739 3738
3740 3739 /* Don't bother sending if there's no queue. */
3741 3740 if (pfkey_q == NULL)
3742 3741 return;
3743 3742
3744 3743 mp = sadb_keysock_out(0);
3745 3744 if (mp == NULL) {
3746 3745 /* cmn_err(CE_WARN, */
3747 3746 /* "sadb_expire_assoc: Can't allocate KEYSOCK_OUT.\n"); */
3748 3747 return;
3749 3748 }
3750 3749
3751 3750 alloclen = sizeof (*samsg) + sizeof (*current) + sizeof (*expire) +
3752 3751 2 * sizeof (sadb_address_t) + sizeof (*saext);
3753 3752
3754 3753 af = assoc->ipsa_addrfam;
3755 3754 switch (af) {
3756 3755 case AF_INET:
3757 3756 alloclen += 2 * sizeof (struct sockaddr_in);
3758 3757 break;
3759 3758 case AF_INET6:
3760 3759 alloclen += 2 * sizeof (struct sockaddr_in6);
3761 3760 break;
3762 3761 default:
3763 3762 /* Won't happen unless there's a kernel bug. */
3764 3763 freeb(mp);
3765 3764 cmn_err(CE_WARN,
3766 3765 "sadb_expire_assoc: Unknown address length.\n");
3767 3766 return;
3768 3767 }
3769 3768
3770 3769 tunnel_mode = (assoc->ipsa_flags & IPSA_F_TUNNEL);
3771 3770 if (tunnel_mode) {
3772 3771 alloclen += 2 * sizeof (sadb_address_t);
3773 3772 switch (assoc->ipsa_innerfam) {
3774 3773 case AF_INET:
3775 3774 alloclen += 2 * sizeof (struct sockaddr_in);
3776 3775 break;
3777 3776 case AF_INET6:
3778 3777 alloclen += 2 * sizeof (struct sockaddr_in6);
3779 3778 break;
3780 3779 default:
3781 3780 /* Won't happen unless there's a kernel bug. */
3782 3781 freeb(mp);
3783 3782 cmn_err(CE_WARN, "sadb_expire_assoc: "
3784 3783 "Unknown inner address length.\n");
3785 3784 return;
3786 3785 }
3787 3786 }
3788 3787
3789 3788 mp->b_cont = allocb(alloclen, BPRI_HI);
3790 3789 if (mp->b_cont == NULL) {
3791 3790 freeb(mp);
3792 3791 /* cmn_err(CE_WARN, */
3793 3792 /* "sadb_expire_assoc: Can't allocate message.\n"); */
3794 3793 return;
3795 3794 }
3796 3795
3797 3796 mp1 = mp;
3798 3797 mp = mp->b_cont;
3799 3798 end = mp->b_wptr + alloclen;
3800 3799
3801 3800 samsg = (sadb_msg_t *)mp->b_wptr;
3802 3801 mp->b_wptr += sizeof (*samsg);
3803 3802 samsg->sadb_msg_version = PF_KEY_V2;
3804 3803 samsg->sadb_msg_type = SADB_EXPIRE;
3805 3804 samsg->sadb_msg_errno = 0;
3806 3805 samsg->sadb_msg_satype = assoc->ipsa_type;
3807 3806 samsg->sadb_msg_len = SADB_8TO64(alloclen);
3808 3807 samsg->sadb_msg_reserved = 0;
3809 3808 samsg->sadb_msg_seq = 0;
3810 3809 samsg->sadb_msg_pid = 0;
3811 3810
3812 3811 saext = (sadb_sa_t *)mp->b_wptr;
3813 3812 mp->b_wptr += sizeof (*saext);
3814 3813 saext->sadb_sa_len = SADB_8TO64(sizeof (*saext));
3815 3814 saext->sadb_sa_exttype = SADB_EXT_SA;
3816 3815 saext->sadb_sa_spi = assoc->ipsa_spi;
3817 3816 saext->sadb_sa_replay = assoc->ipsa_replay_wsize;
3818 3817 saext->sadb_sa_state = assoc->ipsa_state;
3819 3818 saext->sadb_sa_auth = assoc->ipsa_auth_alg;
3820 3819 saext->sadb_sa_encrypt = assoc->ipsa_encr_alg;
3821 3820 saext->sadb_sa_flags = assoc->ipsa_flags;
3822 3821
3823 3822 current = (sadb_lifetime_t *)mp->b_wptr;
3824 3823 mp->b_wptr += sizeof (sadb_lifetime_t);
3825 3824 current->sadb_lifetime_len = SADB_8TO64(sizeof (*current));
3826 3825 current->sadb_lifetime_exttype = SADB_EXT_LIFETIME_CURRENT;
3827 3826 /* We do not support the concept. */
3828 3827 current->sadb_lifetime_allocations = 0;
3829 3828 current->sadb_lifetime_bytes = assoc->ipsa_bytes;
3830 3829 current->sadb_lifetime_addtime = assoc->ipsa_addtime;
3831 3830 current->sadb_lifetime_usetime = assoc->ipsa_usetime;
3832 3831
3833 3832 expire = (sadb_lifetime_t *)mp->b_wptr;
3834 3833 mp->b_wptr += sizeof (*expire);
3835 3834 expire->sadb_lifetime_len = SADB_8TO64(sizeof (*expire));
3836 3835
3837 3836 if (assoc->ipsa_state == IPSA_STATE_DEAD) {
3838 3837 expire->sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD;
3839 3838 expire->sadb_lifetime_allocations = assoc->ipsa_hardalloc;
3840 3839 expire->sadb_lifetime_bytes = assoc->ipsa_hardbyteslt;
3841 3840 expire->sadb_lifetime_addtime = assoc->ipsa_hardaddlt;
3842 3841 expire->sadb_lifetime_usetime = assoc->ipsa_harduselt;
3843 3842 } else if (assoc->ipsa_state == IPSA_STATE_DYING) {
3844 3843 expire->sadb_lifetime_exttype = SADB_EXT_LIFETIME_SOFT;
3845 3844 expire->sadb_lifetime_allocations = assoc->ipsa_softalloc;
3846 3845 expire->sadb_lifetime_bytes = assoc->ipsa_softbyteslt;
3847 3846 expire->sadb_lifetime_addtime = assoc->ipsa_softaddlt;
3848 3847 expire->sadb_lifetime_usetime = assoc->ipsa_softuselt;
3849 3848 } else {
3850 3849 ASSERT(assoc->ipsa_state == IPSA_STATE_MATURE);
3851 3850 expire->sadb_lifetime_exttype = SADB_X_EXT_LIFETIME_IDLE;
3852 3851 expire->sadb_lifetime_allocations = 0;
3853 3852 expire->sadb_lifetime_bytes = 0;
3854 3853 expire->sadb_lifetime_addtime = assoc->ipsa_idleaddlt;
3855 3854 expire->sadb_lifetime_usetime = assoc->ipsa_idleuselt;
3856 3855 }
3857 3856
3858 3857 mp->b_wptr = sadb_make_addr_ext(mp->b_wptr, end, SADB_EXT_ADDRESS_SRC,
3859 3858 af, assoc->ipsa_srcaddr, tunnel_mode ? 0 : SA_SRCPORT(assoc),
3860 3859 SA_PROTO(assoc), 0);
3861 3860 ASSERT(mp->b_wptr != NULL);
3862 3861
3863 3862 mp->b_wptr = sadb_make_addr_ext(mp->b_wptr, end, SADB_EXT_ADDRESS_DST,
3864 3863 af, assoc->ipsa_dstaddr, tunnel_mode ? 0 : SA_DSTPORT(assoc),
3865 3864 SA_PROTO(assoc), 0);
3866 3865 ASSERT(mp->b_wptr != NULL);
3867 3866
3868 3867 if (tunnel_mode) {
3869 3868 mp->b_wptr = sadb_make_addr_ext(mp->b_wptr, end,
3870 3869 SADB_X_EXT_ADDRESS_INNER_SRC, assoc->ipsa_innerfam,
3871 3870 assoc->ipsa_innersrc, SA_SRCPORT(assoc), SA_IPROTO(assoc),
3872 3871 assoc->ipsa_innersrcpfx);
3873 3872 ASSERT(mp->b_wptr != NULL);
3874 3873 mp->b_wptr = sadb_make_addr_ext(mp->b_wptr, end,
3875 3874 SADB_X_EXT_ADDRESS_INNER_DST, assoc->ipsa_innerfam,
3876 3875 assoc->ipsa_innerdst, SA_DSTPORT(assoc), SA_IPROTO(assoc),
3877 3876 assoc->ipsa_innerdstpfx);
3878 3877 ASSERT(mp->b_wptr != NULL);
3879 3878 }
3880 3879
3881 3880 /* Can just putnext, we're ready to go! */
3882 3881 putnext(pfkey_q, mp1);
3883 3882 }
3884 3883
3885 3884 /*
3886 3885 * "Age" the SA with the number of bytes that was used to protect traffic.
3887 3886 * Send an SADB_EXPIRE message if appropriate. Return B_TRUE if there was
3888 3887 * enough "charge" left in the SA to protect the data. Return B_FALSE
3889 3888 * otherwise. (If B_FALSE is returned, the association either was, or became
3890 3889 * DEAD.)
3891 3890 */
3892 3891 boolean_t
3893 3892 sadb_age_bytes(queue_t *pfkey_q, ipsa_t *assoc, uint64_t bytes,
3894 3893 boolean_t sendmsg)
3895 3894 {
3896 3895 boolean_t rc = B_TRUE;
3897 3896 uint64_t newtotal;
3898 3897
3899 3898 mutex_enter(&assoc->ipsa_lock);
3900 3899 newtotal = assoc->ipsa_bytes + bytes;
3901 3900 if (assoc->ipsa_hardbyteslt != 0 &&
3902 3901 newtotal >= assoc->ipsa_hardbyteslt) {
3903 3902 if (assoc->ipsa_state != IPSA_STATE_DEAD) {
3904 3903 sadb_delete_cluster(assoc);
3905 3904 /*
3906 3905 * Send EXPIRE message to PF_KEY. May wish to pawn
3907 3906 * this off on another non-interrupt thread. Also
3908 3907 * unlink this SA immediately.
3909 3908 */
3910 3909 assoc->ipsa_state = IPSA_STATE_DEAD;
3911 3910 if (sendmsg)
3912 3911 sadb_expire_assoc(pfkey_q, assoc);
3913 3912 /*
3914 3913 * Set non-zero expiration time so sadb_age_assoc()
3915 3914 * will work when reaping.
3916 3915 */
3917 3916 assoc->ipsa_hardexpiretime = (time_t)1;
3918 3917 } /* Else someone beat me to it! */
3919 3918 rc = B_FALSE;
3920 3919 } else if (assoc->ipsa_softbyteslt != 0 &&
3921 3920 (newtotal >= assoc->ipsa_softbyteslt)) {
3922 3921 if (assoc->ipsa_state < IPSA_STATE_DYING) {
3923 3922 /*
3924 3923 * Send EXPIRE message to PF_KEY. May wish to pawn
3925 3924 * this off on another non-interrupt thread.
3926 3925 */
3927 3926 assoc->ipsa_state = IPSA_STATE_DYING;
3928 3927 assoc->ipsa_bytes = newtotal;
3929 3928 if (sendmsg)
3930 3929 sadb_expire_assoc(pfkey_q, assoc);
3931 3930 } /* Else someone beat me to it! */
3932 3931 }
3933 3932 if (rc == B_TRUE)
3934 3933 assoc->ipsa_bytes = newtotal;
3935 3934 mutex_exit(&assoc->ipsa_lock);
3936 3935 return (rc);
3937 3936 }
3938 3937
3939 3938 /*
3940 3939 * "Torch" an individual SA. Returns NULL, so it can be tail-called from
3941 3940 * sadb_age_assoc().
3942 3941 */
3943 3942 static ipsa_t *
3944 3943 sadb_torch_assoc(isaf_t *head, ipsa_t *sa)
3945 3944 {
3946 3945 ASSERT(MUTEX_HELD(&head->isaf_lock));
3947 3946 ASSERT(MUTEX_HELD(&sa->ipsa_lock));
3948 3947 ASSERT(sa->ipsa_state == IPSA_STATE_DEAD);
3949 3948
3950 3949 /*
3951 3950 * Force cached SAs to be revalidated..
3952 3951 */
3953 3952 head->isaf_gen++;
3954 3953
3955 3954 mutex_exit(&sa->ipsa_lock);
3956 3955 sadb_unlinkassoc(sa);
3957 3956
3958 3957 return (NULL);
3959 3958 }
3960 3959
3961 3960 /*
3962 3961 * Do various SA-is-idle activities depending on delta (the number of idle
3963 3962 * seconds on the SA) and/or other properties of the SA.
3964 3963 *
3965 3964 * Return B_TRUE if I've sent a packet, because I have to drop the
3966 3965 * association's mutex before sending a packet out the wire.
3967 3966 */
3968 3967 /* ARGSUSED */
3969 3968 static boolean_t
3970 3969 sadb_idle_activities(ipsa_t *assoc, time_t delta, boolean_t inbound)
3971 3970 {
3972 3971 ipsecesp_stack_t *espstack = assoc->ipsa_netstack->netstack_ipsecesp;
3973 3972 int nat_t_interval = espstack->ipsecesp_nat_keepalive_interval;
3974 3973
3975 3974 ASSERT(MUTEX_HELD(&assoc->ipsa_lock));
3976 3975
3977 3976 if (!inbound && (assoc->ipsa_flags & IPSA_F_NATT_LOC) &&
3978 3977 delta >= nat_t_interval &&
3979 3978 gethrestime_sec() - assoc->ipsa_last_nat_t_ka >= nat_t_interval) {
3980 3979 ASSERT(assoc->ipsa_type == SADB_SATYPE_ESP);
3981 3980 assoc->ipsa_last_nat_t_ka = gethrestime_sec();
3982 3981 mutex_exit(&assoc->ipsa_lock);
3983 3982 ipsecesp_send_keepalive(assoc);
3984 3983 return (B_TRUE);
3985 3984 }
3986 3985 return (B_FALSE);
3987 3986 }
3988 3987
3989 3988 /*
3990 3989 * Return "assoc" if haspeer is true and I send an expire. This allows
3991 3990 * the consumers' aging functions to tidy up an expired SA's peer.
3992 3991 */
3993 3992 static ipsa_t *
3994 3993 sadb_age_assoc(isaf_t *head, queue_t *pfkey_q, ipsa_t *assoc,
3995 3994 time_t current, int reap_delay, boolean_t inbound)
3996 3995 {
3997 3996 ipsa_t *retval = NULL;
3998 3997 boolean_t dropped_mutex = B_FALSE;
3999 3998
4000 3999 ASSERT(MUTEX_HELD(&head->isaf_lock));
4001 4000
4002 4001 mutex_enter(&assoc->ipsa_lock);
4003 4002
4004 4003 if (((assoc->ipsa_state == IPSA_STATE_LARVAL) ||
4005 4004 ((assoc->ipsa_state == IPSA_STATE_IDLE) ||
4006 4005 (assoc->ipsa_state == IPSA_STATE_ACTIVE_ELSEWHERE) &&
4007 4006 (assoc->ipsa_hardexpiretime != 0))) &&
4008 4007 (assoc->ipsa_hardexpiretime <= current)) {
4009 4008 assoc->ipsa_state = IPSA_STATE_DEAD;
4010 4009 return (sadb_torch_assoc(head, assoc));
4011 4010 }
4012 4011
4013 4012 /*
4014 4013 * Check lifetimes. Fortunately, SA setup is done
4015 4014 * such that there are only two times to look at,
4016 4015 * softexpiretime, and hardexpiretime.
4017 4016 *
4018 4017 * Check hard first.
4019 4018 */
4020 4019
4021 4020 if (assoc->ipsa_hardexpiretime != 0 &&
4022 4021 assoc->ipsa_hardexpiretime <= current) {
4023 4022 if (assoc->ipsa_state == IPSA_STATE_DEAD)
4024 4023 return (sadb_torch_assoc(head, assoc));
4025 4024
4026 4025 if (inbound) {
4027 4026 sadb_delete_cluster(assoc);
4028 4027 }
4029 4028
4030 4029 /*
4031 4030 * Send SADB_EXPIRE with hard lifetime, delay for unlinking.
4032 4031 */
4033 4032 assoc->ipsa_state = IPSA_STATE_DEAD;
4034 4033 if (assoc->ipsa_haspeer || assoc->ipsa_otherspi != 0) {
4035 4034 /*
4036 4035 * If the SA is paired or peered with another, put
4037 4036 * a copy on a list which can be processed later, the
4038 4037 * pair/peer SA needs to be updated so the both die
4039 4038 * at the same time.
4040 4039 *
4041 4040 * If I return assoc, I have to bump up its reference
4042 4041 * count to keep with the ipsa_t reference count
4043 4042 * semantics.
4044 4043 */
4045 4044 IPSA_REFHOLD(assoc);
4046 4045 retval = assoc;
4047 4046 }
4048 4047 sadb_expire_assoc(pfkey_q, assoc);
4049 4048 assoc->ipsa_hardexpiretime = current + reap_delay;
4050 4049 } else if (assoc->ipsa_softexpiretime != 0 &&
4051 4050 assoc->ipsa_softexpiretime <= current &&
4052 4051 assoc->ipsa_state < IPSA_STATE_DYING) {
4053 4052 /*
4054 4053 * Send EXPIRE message to PF_KEY. May wish to pawn
4055 4054 * this off on another non-interrupt thread.
4056 4055 */
4057 4056 assoc->ipsa_state = IPSA_STATE_DYING;
4058 4057 if (assoc->ipsa_haspeer) {
4059 4058 /*
4060 4059 * If the SA has a peer, update the peer's state
4061 4060 * on SOFT_EXPIRE, this is mostly to prevent two
4062 4061 * expire messages from effectively the same SA.
4063 4062 *
4064 4063 * Don't care about paired SA's, then can (and should)
4065 4064 * be able to soft expire at different times.
4066 4065 *
4067 4066 * If I return assoc, I have to bump up its
4068 4067 * reference count to keep with the ipsa_t reference
4069 4068 * count semantics.
4070 4069 */
4071 4070 IPSA_REFHOLD(assoc);
4072 4071 retval = assoc;
4073 4072 }
4074 4073 sadb_expire_assoc(pfkey_q, assoc);
4075 4074 } else if (assoc->ipsa_idletime != 0 &&
4076 4075 assoc->ipsa_idleexpiretime <= current) {
4077 4076 if (assoc->ipsa_state == IPSA_STATE_ACTIVE_ELSEWHERE) {
4078 4077 assoc->ipsa_state = IPSA_STATE_IDLE;
4079 4078 }
4080 4079
4081 4080 /*
4082 4081 * Need to handle Mature case
4083 4082 */
4084 4083 if (assoc->ipsa_state == IPSA_STATE_MATURE) {
4085 4084 sadb_expire_assoc(pfkey_q, assoc);
4086 4085 }
4087 4086 } else {
4088 4087 /* Check idle time activities. */
4089 4088 dropped_mutex = sadb_idle_activities(assoc,
4090 4089 current - assoc->ipsa_lastuse, inbound);
4091 4090 }
4092 4091
4093 4092 if (!dropped_mutex)
4094 4093 mutex_exit(&assoc->ipsa_lock);
4095 4094 return (retval);
4096 4095 }
4097 4096
4098 4097 /*
4099 4098 * Called by a consumer protocol to do ther dirty work of reaping dead
4100 4099 * Security Associations.
4101 4100 *
4102 4101 * NOTE: sadb_age_assoc() marks expired SA's as DEAD but only removed
4103 4102 * SA's that are already marked DEAD, so expired SA's are only reaped
4104 4103 * the second time sadb_ager() runs.
4105 4104 */
4106 4105 void
4107 4106 sadb_ager(sadb_t *sp, queue_t *pfkey_q, int reap_delay, netstack_t *ns)
4108 4107 {
4109 4108 int i;
4110 4109 isaf_t *bucket;
4111 4110 ipsa_t *assoc, *spare;
4112 4111 iacqf_t *acqlist;
4113 4112 ipsacq_t *acqrec, *spareacq;
4114 4113 templist_t *haspeerlist, *newbie;
4115 4114 /* Snapshot current time now. */
4116 4115 time_t current = gethrestime_sec();
4117 4116 haspeerlist = NULL;
4118 4117
4119 4118 /*
4120 4119 * Do my dirty work. This includes aging real entries, aging
4121 4120 * larvals, and aging outstanding ACQUIREs.
4122 4121 *
4123 4122 * I hope I don't tie up resources for too long.
4124 4123 */
4125 4124
4126 4125 /* Age acquires. */
4127 4126
4128 4127 for (i = 0; i < sp->sdb_hashsize; i++) {
4129 4128 acqlist = &sp->sdb_acq[i];
4130 4129 mutex_enter(&acqlist->iacqf_lock);
4131 4130 for (acqrec = acqlist->iacqf_ipsacq; acqrec != NULL;
4132 4131 acqrec = spareacq) {
4133 4132 spareacq = acqrec->ipsacq_next;
4134 4133 if (current > acqrec->ipsacq_expire)
4135 4134 sadb_destroy_acquire(acqrec, ns);
4136 4135 }
4137 4136 mutex_exit(&acqlist->iacqf_lock);
4138 4137 }
4139 4138
4140 4139 /* Age inbound associations. */
4141 4140 for (i = 0; i < sp->sdb_hashsize; i++) {
4142 4141 bucket = &(sp->sdb_if[i]);
4143 4142 mutex_enter(&bucket->isaf_lock);
4144 4143 for (assoc = bucket->isaf_ipsa; assoc != NULL;
4145 4144 assoc = spare) {
4146 4145 spare = assoc->ipsa_next;
4147 4146 if (sadb_age_assoc(bucket, pfkey_q, assoc, current,
4148 4147 reap_delay, B_TRUE) != NULL) {
4149 4148 /*
4150 4149 * Put SA's which have a peer or SA's which
4151 4150 * are paired on a list for processing after
4152 4151 * all the hash tables have been walked.
4153 4152 *
4154 4153 * sadb_age_assoc() increments the refcnt,
4155 4154 * effectively doing an IPSA_REFHOLD().
4156 4155 */
4157 4156 newbie = kmem_alloc(sizeof (*newbie),
4158 4157 KM_NOSLEEP);
4159 4158 if (newbie == NULL) {
4160 4159 /*
4161 4160 * Don't forget to REFRELE().
4162 4161 */
4163 4162 IPSA_REFRELE(assoc);
4164 4163 continue; /* for loop... */
4165 4164 }
4166 4165 newbie->next = haspeerlist;
4167 4166 newbie->ipsa = assoc;
4168 4167 haspeerlist = newbie;
4169 4168 }
4170 4169 }
4171 4170 mutex_exit(&bucket->isaf_lock);
4172 4171 }
4173 4172
4174 4173 age_pair_peer_list(haspeerlist, sp, B_FALSE);
4175 4174 haspeerlist = NULL;
4176 4175
4177 4176 /* Age outbound associations. */
4178 4177 for (i = 0; i < sp->sdb_hashsize; i++) {
4179 4178 bucket = &(sp->sdb_of[i]);
4180 4179 mutex_enter(&bucket->isaf_lock);
4181 4180 for (assoc = bucket->isaf_ipsa; assoc != NULL;
4182 4181 assoc = spare) {
4183 4182 spare = assoc->ipsa_next;
4184 4183 if (sadb_age_assoc(bucket, pfkey_q, assoc, current,
4185 4184 reap_delay, B_FALSE) != NULL) {
4186 4185 /*
4187 4186 * sadb_age_assoc() increments the refcnt,
4188 4187 * effectively doing an IPSA_REFHOLD().
4189 4188 */
4190 4189 newbie = kmem_alloc(sizeof (*newbie),
4191 4190 KM_NOSLEEP);
4192 4191 if (newbie == NULL) {
4193 4192 /*
4194 4193 * Don't forget to REFRELE().
4195 4194 */
4196 4195 IPSA_REFRELE(assoc);
4197 4196 continue; /* for loop... */
4198 4197 }
4199 4198 newbie->next = haspeerlist;
4200 4199 newbie->ipsa = assoc;
4201 4200 haspeerlist = newbie;
4202 4201 }
4203 4202 }
4204 4203 mutex_exit(&bucket->isaf_lock);
4205 4204 }
4206 4205
4207 4206 age_pair_peer_list(haspeerlist, sp, B_TRUE);
4208 4207
4209 4208 /*
4210 4209 * Run a GC pass to clean out dead identities.
4211 4210 */
4212 4211 ipsid_gc(ns);
4213 4212 }
4214 4213
4215 4214 /*
4216 4215 * Figure out when to reschedule the ager.
4217 4216 */
4218 4217 timeout_id_t
4219 4218 sadb_retimeout(hrtime_t begin, queue_t *pfkey_q, void (*ager)(void *),
4220 4219 void *agerarg, uint_t *intp, uint_t intmax, short mid)
4221 4220 {
4222 4221 hrtime_t end = gethrtime();
4223 4222 uint_t interval = *intp; /* "interval" is in ms. */
4224 4223
4225 4224 /*
4226 4225 * See how long this took. If it took too long, increase the
4227 4226 * aging interval.
4228 4227 */
4229 4228 if ((end - begin) > MSEC2NSEC(interval)) {
4230 4229 if (interval >= intmax) {
4231 4230 /* XXX Rate limit this? Or recommend flush? */
4232 4231 (void) strlog(mid, 0, 0, SL_ERROR | SL_WARN,
4233 4232 "Too many SA's to age out in %d msec.\n",
4234 4233 intmax);
4235 4234 } else {
4236 4235 /* Double by shifting by one bit. */
4237 4236 interval <<= 1;
4238 4237 interval = min(interval, intmax);
4239 4238 }
4240 4239 } else if ((end - begin) <= (MSEC2NSEC(interval) / 2) &&
4241 4240 interval > SADB_AGE_INTERVAL_DEFAULT) {
4242 4241 /*
4243 4242 * If I took less than half of the interval, then I should
4244 4243 * ratchet the interval back down. Never automatically
4245 4244 * shift below the default aging interval.
4246 4245 *
4247 4246 * NOTE:This even overrides manual setting of the age
4248 4247 * interval using NDD to lower the setting past the
4249 4248 * default. In other words, if you set the interval
4250 4249 * lower than the default, and your SADB gets too big,
4251 4250 * the interval will only self-lower back to the default.
4252 4251 */
4253 4252 /* Halve by shifting one bit. */
4254 4253 interval >>= 1;
4255 4254 interval = max(interval, SADB_AGE_INTERVAL_DEFAULT);
4256 4255 }
4257 4256 *intp = interval;
4258 4257 return (qtimeout(pfkey_q, ager, agerarg,
4259 4258 drv_usectohz(interval * (MICROSEC / MILLISEC))));
4260 4259 }
4261 4260
4262 4261
4263 4262 /*
4264 4263 * Update the lifetime values of an SA. This is the path an SADB_UPDATE
4265 4264 * message takes when updating a MATURE or DYING SA.
4266 4265 */
4267 4266 static void
4268 4267 sadb_update_lifetimes(ipsa_t *assoc, sadb_lifetime_t *hard,
4269 4268 sadb_lifetime_t *soft, sadb_lifetime_t *idle, boolean_t outbound)
4270 4269 {
4271 4270 mutex_enter(&assoc->ipsa_lock);
4272 4271
4273 4272 /*
4274 4273 * XXX RFC 2367 mentions how an SADB_EXT_LIFETIME_CURRENT can be
4275 4274 * passed in during an update message. We currently don't handle
4276 4275 * these.
4277 4276 */
4278 4277
4279 4278 if (hard != NULL) {
4280 4279 if (hard->sadb_lifetime_bytes != 0)
4281 4280 assoc->ipsa_hardbyteslt = hard->sadb_lifetime_bytes;
4282 4281 if (hard->sadb_lifetime_usetime != 0)
4283 4282 assoc->ipsa_harduselt = hard->sadb_lifetime_usetime;
4284 4283 if (hard->sadb_lifetime_addtime != 0)
4285 4284 assoc->ipsa_hardaddlt = hard->sadb_lifetime_addtime;
4286 4285 if (assoc->ipsa_hardaddlt != 0) {
4287 4286 assoc->ipsa_hardexpiretime =
4288 4287 assoc->ipsa_addtime + assoc->ipsa_hardaddlt;
4289 4288 }
4290 4289 if (assoc->ipsa_harduselt != 0 &&
4291 4290 assoc->ipsa_flags & IPSA_F_USED) {
4292 4291 UPDATE_EXPIRE(assoc, harduselt, hardexpiretime);
4293 4292 }
4294 4293 if (hard->sadb_lifetime_allocations != 0)
4295 4294 assoc->ipsa_hardalloc = hard->sadb_lifetime_allocations;
4296 4295 }
4297 4296
4298 4297 if (soft != NULL) {
4299 4298 if (soft->sadb_lifetime_bytes != 0) {
4300 4299 if (soft->sadb_lifetime_bytes >
4301 4300 assoc->ipsa_hardbyteslt) {
4302 4301 assoc->ipsa_softbyteslt =
4303 4302 assoc->ipsa_hardbyteslt;
4304 4303 } else {
4305 4304 assoc->ipsa_softbyteslt =
4306 4305 soft->sadb_lifetime_bytes;
4307 4306 }
4308 4307 }
4309 4308 if (soft->sadb_lifetime_usetime != 0) {
4310 4309 if (soft->sadb_lifetime_usetime >
4311 4310 assoc->ipsa_harduselt) {
4312 4311 assoc->ipsa_softuselt =
4313 4312 assoc->ipsa_harduselt;
4314 4313 } else {
4315 4314 assoc->ipsa_softuselt =
4316 4315 soft->sadb_lifetime_usetime;
4317 4316 }
4318 4317 }
4319 4318 if (soft->sadb_lifetime_addtime != 0) {
4320 4319 if (soft->sadb_lifetime_addtime >
4321 4320 assoc->ipsa_hardexpiretime) {
4322 4321 assoc->ipsa_softexpiretime =
4323 4322 assoc->ipsa_hardexpiretime;
4324 4323 } else {
4325 4324 assoc->ipsa_softaddlt =
4326 4325 soft->sadb_lifetime_addtime;
4327 4326 }
4328 4327 }
4329 4328 if (assoc->ipsa_softaddlt != 0) {
4330 4329 assoc->ipsa_softexpiretime =
4331 4330 assoc->ipsa_addtime + assoc->ipsa_softaddlt;
4332 4331 }
4333 4332 if (assoc->ipsa_softuselt != 0 &&
4334 4333 assoc->ipsa_flags & IPSA_F_USED) {
4335 4334 UPDATE_EXPIRE(assoc, softuselt, softexpiretime);
4336 4335 }
4337 4336 if (outbound && assoc->ipsa_softexpiretime != 0) {
4338 4337 if (assoc->ipsa_state == IPSA_STATE_MATURE)
4339 4338 lifetime_fuzz(assoc);
4340 4339 }
4341 4340
4342 4341 if (soft->sadb_lifetime_allocations != 0)
4343 4342 assoc->ipsa_softalloc = soft->sadb_lifetime_allocations;
4344 4343 }
4345 4344
4346 4345 if (idle != NULL) {
4347 4346 time_t current = gethrestime_sec();
4348 4347 if ((assoc->ipsa_idleexpiretime <= current) &&
4349 4348 (assoc->ipsa_idleaddlt == idle->sadb_lifetime_addtime)) {
4350 4349 assoc->ipsa_idleexpiretime =
4351 4350 current + assoc->ipsa_idleaddlt;
4352 4351 }
4353 4352 if (idle->sadb_lifetime_addtime != 0)
4354 4353 assoc->ipsa_idleaddlt = idle->sadb_lifetime_addtime;
4355 4354 if (idle->sadb_lifetime_usetime != 0)
4356 4355 assoc->ipsa_idleuselt = idle->sadb_lifetime_usetime;
4357 4356 if (assoc->ipsa_idleaddlt != 0) {
4358 4357 assoc->ipsa_idleexpiretime =
4359 4358 current + idle->sadb_lifetime_addtime;
4360 4359 assoc->ipsa_idletime = idle->sadb_lifetime_addtime;
4361 4360 }
4362 4361 if (assoc->ipsa_idleuselt != 0) {
4363 4362 if (assoc->ipsa_idletime != 0) {
4364 4363 assoc->ipsa_idletime = min(assoc->ipsa_idletime,
4365 4364 assoc->ipsa_idleuselt);
4366 4365 assoc->ipsa_idleexpiretime =
4367 4366 current + assoc->ipsa_idletime;
4368 4367 } else {
4369 4368 assoc->ipsa_idleexpiretime =
4370 4369 current + assoc->ipsa_idleuselt;
4371 4370 assoc->ipsa_idletime = assoc->ipsa_idleuselt;
4372 4371 }
4373 4372 }
4374 4373 }
4375 4374 mutex_exit(&assoc->ipsa_lock);
4376 4375 }
4377 4376
4378 4377 static int
4379 4378 sadb_update_state(ipsa_t *assoc, uint_t new_state, mblk_t **ipkt_lst)
4380 4379 {
4381 4380 int rcode = 0;
4382 4381 time_t current = gethrestime_sec();
4383 4382
4384 4383 mutex_enter(&assoc->ipsa_lock);
4385 4384
4386 4385 switch (new_state) {
4387 4386 case SADB_X_SASTATE_ACTIVE_ELSEWHERE:
4388 4387 if (assoc->ipsa_state == SADB_X_SASTATE_IDLE) {
4389 4388 assoc->ipsa_state = IPSA_STATE_ACTIVE_ELSEWHERE;
4390 4389 assoc->ipsa_idleexpiretime =
4391 4390 current + assoc->ipsa_idletime;
4392 4391 }
4393 4392 break;
4394 4393 case SADB_X_SASTATE_IDLE:
4395 4394 if (assoc->ipsa_state == SADB_X_SASTATE_ACTIVE_ELSEWHERE) {
4396 4395 assoc->ipsa_state = IPSA_STATE_IDLE;
4397 4396 assoc->ipsa_idleexpiretime =
4398 4397 current + assoc->ipsa_idletime;
4399 4398 } else {
4400 4399 rcode = EINVAL;
4401 4400 }
4402 4401 break;
4403 4402
4404 4403 case SADB_X_SASTATE_ACTIVE:
4405 4404 if (assoc->ipsa_state != SADB_X_SASTATE_IDLE) {
4406 4405 rcode = EINVAL;
4407 4406 break;
4408 4407 }
4409 4408 assoc->ipsa_state = IPSA_STATE_MATURE;
4410 4409 assoc->ipsa_idleexpiretime = current + assoc->ipsa_idletime;
4411 4410
4412 4411 if (ipkt_lst == NULL) {
4413 4412 break;
4414 4413 }
4415 4414
4416 4415 if (assoc->ipsa_bpkt_head != NULL) {
4417 4416 *ipkt_lst = assoc->ipsa_bpkt_head;
4418 4417 assoc->ipsa_bpkt_head = assoc->ipsa_bpkt_tail = NULL;
4419 4418 assoc->ipsa_mblkcnt = 0;
4420 4419 } else {
4421 4420 *ipkt_lst = NULL;
4422 4421 }
4423 4422 break;
4424 4423 default:
4425 4424 rcode = EINVAL;
4426 4425 break;
4427 4426 }
4428 4427
4429 4428 mutex_exit(&assoc->ipsa_lock);
4430 4429 return (rcode);
4431 4430 }
4432 4431
4433 4432 /*
4434 4433 * Check a proposed KMC update for sanity.
4435 4434 */
4436 4435 static int
4437 4436 sadb_check_kmc(ipsa_query_t *sq, ipsa_t *sa, int *diagnostic)
4438 4437 {
4439 4438 uint32_t kmp = sq->kmp;
4440 4439 uint32_t kmc = sq->kmc;
4441 4440
4442 4441 if (sa == NULL)
4443 4442 return (0);
4444 4443
4445 4444 if (sa->ipsa_state == IPSA_STATE_DEAD)
4446 4445 return (ESRCH); /* DEAD == Not there, in this case. */
4447 4446
4448 4447 if ((kmp != 0) && ((sa->ipsa_kmp != 0) || (sa->ipsa_kmp != kmp))) {
4449 4448 *diagnostic = SADB_X_DIAGNOSTIC_DUPLICATE_KMP;
4450 4449 return (EINVAL);
4451 4450 }
4452 4451
4453 4452 if ((kmc != 0) && ((sa->ipsa_kmc != 0) || (sa->ipsa_kmc != kmc))) {
4454 4453 *diagnostic = SADB_X_DIAGNOSTIC_DUPLICATE_KMC;
4455 4454 return (EINVAL);
4456 4455 }
4457 4456
4458 4457 return (0);
4459 4458 }
4460 4459
4461 4460 /*
4462 4461 * Actually update the KMC info.
4463 4462 */
4464 4463 static void
4465 4464 sadb_update_kmc(ipsa_query_t *sq, ipsa_t *sa)
4466 4465 {
4467 4466 uint32_t kmp = sq->kmp;
4468 4467 uint32_t kmc = sq->kmc;
4469 4468
4470 4469 if (kmp != 0)
4471 4470 sa->ipsa_kmp = kmp;
4472 4471 if (kmc != 0)
4473 4472 sa->ipsa_kmc = kmc;
4474 4473 }
4475 4474
4476 4475 /*
4477 4476 * Common code to update an SA.
4478 4477 */
4479 4478
4480 4479 int
4481 4480 sadb_update_sa(mblk_t *mp, keysock_in_t *ksi, mblk_t **ipkt_lst,
4482 4481 sadbp_t *spp, int *diagnostic, queue_t *pfkey_q,
4483 4482 int (*add_sa_func)(mblk_t *, keysock_in_t *, int *, netstack_t *),
4484 4483 netstack_t *ns, uint8_t sadb_msg_type)
4485 4484 {
4486 4485 sadb_key_t *akey = (sadb_key_t *)ksi->ks_in_extv[SADB_EXT_KEY_AUTH];
4487 4486 sadb_key_t *ekey = (sadb_key_t *)ksi->ks_in_extv[SADB_EXT_KEY_ENCRYPT];
4488 4487 sadb_x_replay_ctr_t *replext =
4489 4488 (sadb_x_replay_ctr_t *)ksi->ks_in_extv[SADB_X_EXT_REPLAY_VALUE];
4490 4489 sadb_lifetime_t *soft =
4491 4490 (sadb_lifetime_t *)ksi->ks_in_extv[SADB_EXT_LIFETIME_SOFT];
4492 4491 sadb_lifetime_t *hard =
4493 4492 (sadb_lifetime_t *)ksi->ks_in_extv[SADB_EXT_LIFETIME_HARD];
4494 4493 sadb_lifetime_t *idle =
4495 4494 (sadb_lifetime_t *)ksi->ks_in_extv[SADB_X_EXT_LIFETIME_IDLE];
4496 4495 sadb_x_pair_t *pair_ext =
4497 4496 (sadb_x_pair_t *)ksi->ks_in_extv[SADB_X_EXT_PAIR];
4498 4497 ipsa_t *echo_target = NULL;
4499 4498 ipsap_t ipsapp;
4500 4499 ipsa_query_t sq;
4501 4500 time_t current = gethrestime_sec();
4502 4501
4503 4502 sq.spp = spp; /* XXX param */
4504 4503 int error = sadb_form_query(ksi, IPSA_Q_SRC|IPSA_Q_DST|IPSA_Q_SA,
4505 4504 IPSA_Q_SRC|IPSA_Q_DST|IPSA_Q_SA|IPSA_Q_INBOUND|IPSA_Q_OUTBOUND,
4506 4505 &sq, diagnostic);
4507 4506
4508 4507 if (error != 0)
4509 4508 return (error);
4510 4509
4511 4510 error = get_ipsa_pair(&sq, &ipsapp, diagnostic);
4512 4511 if (error != 0)
4513 4512 return (error);
4514 4513
4515 4514 if (ipsapp.ipsap_psa_ptr == NULL && ipsapp.ipsap_sa_ptr != NULL) {
4516 4515 if (ipsapp.ipsap_sa_ptr->ipsa_state == IPSA_STATE_LARVAL) {
4517 4516 /*
4518 4517 * REFRELE the target and let the add_sa_func()
4519 4518 * deal with updating a larval SA.
4520 4519 */
4521 4520 destroy_ipsa_pair(&ipsapp);
4522 4521 return (add_sa_func(mp, ksi, diagnostic, ns));
4523 4522 }
4524 4523 }
4525 4524
4526 4525 /*
4527 4526 * At this point we have an UPDATE to a MATURE SA. There should
4528 4527 * not be any keying material present.
4529 4528 */
4530 4529 if (akey != NULL) {
4531 4530 *diagnostic = SADB_X_DIAGNOSTIC_AKEY_PRESENT;
4532 4531 error = EINVAL;
4533 4532 goto bail;
4534 4533 }
4535 4534 if (ekey != NULL) {
4536 4535 *diagnostic = SADB_X_DIAGNOSTIC_EKEY_PRESENT;
4537 4536 error = EINVAL;
4538 4537 goto bail;
4539 4538 }
4540 4539
4541 4540 if (sq.assoc->sadb_sa_state == SADB_X_SASTATE_ACTIVE_ELSEWHERE) {
4542 4541 if (ipsapp.ipsap_sa_ptr != NULL &&
4543 4542 ipsapp.ipsap_sa_ptr->ipsa_state == IPSA_STATE_IDLE) {
4544 4543 if ((error = sadb_update_state(ipsapp.ipsap_sa_ptr,
4545 4544 sq.assoc->sadb_sa_state, NULL)) != 0) {
4546 4545 *diagnostic = SADB_X_DIAGNOSTIC_BAD_SASTATE;
4547 4546 goto bail;
4548 4547 }
4549 4548 }
4550 4549 if (ipsapp.ipsap_psa_ptr != NULL &&
4551 4550 ipsapp.ipsap_psa_ptr->ipsa_state == IPSA_STATE_IDLE) {
4552 4551 if ((error = sadb_update_state(ipsapp.ipsap_psa_ptr,
4553 4552 sq.assoc->sadb_sa_state, NULL)) != 0) {
4554 4553 *diagnostic = SADB_X_DIAGNOSTIC_BAD_SASTATE;
4555 4554 goto bail;
4556 4555 }
4557 4556 }
4558 4557 }
4559 4558 if (sq.assoc->sadb_sa_state == SADB_X_SASTATE_ACTIVE) {
4560 4559 if (ipsapp.ipsap_sa_ptr != NULL) {
4561 4560 error = sadb_update_state(ipsapp.ipsap_sa_ptr,
4562 4561 sq.assoc->sadb_sa_state,
4563 4562 (ipsapp.ipsap_sa_ptr->ipsa_flags &
4564 4563 IPSA_F_INBOUND) ? ipkt_lst : NULL);
4565 4564 if (error) {
4566 4565 *diagnostic = SADB_X_DIAGNOSTIC_BAD_SASTATE;
4567 4566 goto bail;
4568 4567 }
4569 4568 }
4570 4569 if (ipsapp.ipsap_psa_ptr != NULL) {
4571 4570 error = sadb_update_state(ipsapp.ipsap_psa_ptr,
4572 4571 sq.assoc->sadb_sa_state,
4573 4572 (ipsapp.ipsap_psa_ptr->ipsa_flags &
4574 4573 IPSA_F_INBOUND) ? ipkt_lst : NULL);
4575 4574 if (error) {
4576 4575 *diagnostic = SADB_X_DIAGNOSTIC_BAD_SASTATE;
4577 4576 goto bail;
4578 4577 }
4579 4578 }
4580 4579 sadb_pfkey_echo(pfkey_q, mp, (sadb_msg_t *)mp->b_cont->b_rptr,
4581 4580 ksi, echo_target);
4582 4581 goto bail;
4583 4582 }
4584 4583
4585 4584 /*
4586 4585 * Reality checks for updates of active associations.
4587 4586 * Sundry first-pass UPDATE-specific reality checks.
4588 4587 * Have to do the checks here, because it's after the add_sa code.
4589 4588 * XXX STATS : logging/stats here?
4590 4589 */
4591 4590
4592 4591 if (!((sq.assoc->sadb_sa_state == SADB_SASTATE_MATURE) ||
4593 4592 (sq.assoc->sadb_sa_state == SADB_X_SASTATE_ACTIVE_ELSEWHERE))) {
4594 4593 *diagnostic = SADB_X_DIAGNOSTIC_BAD_SASTATE;
4595 4594 error = EINVAL;
4596 4595 goto bail;
4597 4596 }
4598 4597 if (sq.assoc->sadb_sa_flags & ~spp->s_updateflags) {
4599 4598 *diagnostic = SADB_X_DIAGNOSTIC_BAD_SAFLAGS;
4600 4599 error = EINVAL;
4601 4600 goto bail;
4602 4601 }
4603 4602 if (ksi->ks_in_extv[SADB_EXT_LIFETIME_CURRENT] != NULL) {
4604 4603 *diagnostic = SADB_X_DIAGNOSTIC_MISSING_LIFETIME;
4605 4604 error = EOPNOTSUPP;
4606 4605 goto bail;
4607 4606 }
4608 4607
4609 4608 if ((*diagnostic = sadb_hardsoftchk(hard, soft, idle)) != 0) {
4610 4609 error = EINVAL;
4611 4610 goto bail;
4612 4611 }
4613 4612
4614 4613 if ((*diagnostic = sadb_labelchk(ksi)) != 0)
4615 4614 return (EINVAL);
4616 4615
4617 4616 error = sadb_check_kmc(&sq, ipsapp.ipsap_sa_ptr, diagnostic);
4618 4617 if (error != 0)
4619 4618 goto bail;
4620 4619
4621 4620 error = sadb_check_kmc(&sq, ipsapp.ipsap_psa_ptr, diagnostic);
4622 4621 if (error != 0)
4623 4622 goto bail;
4624 4623
4625 4624
4626 4625 if (ipsapp.ipsap_sa_ptr != NULL) {
4627 4626 /*
4628 4627 * Do not allow replay value change for MATURE or LARVAL SA.
4629 4628 */
4630 4629
4631 4630 if ((replext != NULL) &&
4632 4631 ((ipsapp.ipsap_sa_ptr->ipsa_state == IPSA_STATE_LARVAL) ||
4633 4632 (ipsapp.ipsap_sa_ptr->ipsa_state == IPSA_STATE_MATURE))) {
4634 4633 *diagnostic = SADB_X_DIAGNOSTIC_BAD_SASTATE;
4635 4634 error = EINVAL;
4636 4635 goto bail;
4637 4636 }
4638 4637 }
4639 4638
4640 4639
4641 4640 if (ipsapp.ipsap_sa_ptr != NULL) {
4642 4641 sadb_update_lifetimes(ipsapp.ipsap_sa_ptr, hard, soft,
4643 4642 idle, B_TRUE);
4644 4643 sadb_update_kmc(&sq, ipsapp.ipsap_sa_ptr);
4645 4644 if ((replext != NULL) &&
4646 4645 (ipsapp.ipsap_sa_ptr->ipsa_replay_wsize != 0)) {
4647 4646 /*
4648 4647 * If an inbound SA, update the replay counter
4649 4648 * and check off all the other sequence number
4650 4649 */
4651 4650 if (ksi->ks_in_dsttype == KS_IN_ADDR_ME) {
4652 4651 if (!sadb_replay_check(ipsapp.ipsap_sa_ptr,
4653 4652 replext->sadb_x_rc_replay32)) {
4654 4653 *diagnostic =
4655 4654 SADB_X_DIAGNOSTIC_INVALID_REPLAY;
4656 4655 error = EINVAL;
4657 4656 goto bail;
4658 4657 }
4659 4658 mutex_enter(&ipsapp.ipsap_sa_ptr->ipsa_lock);
4660 4659 ipsapp.ipsap_sa_ptr->ipsa_idleexpiretime =
4661 4660 current +
4662 4661 ipsapp.ipsap_sa_ptr->ipsa_idletime;
4663 4662 mutex_exit(&ipsapp.ipsap_sa_ptr->ipsa_lock);
4664 4663 } else {
4665 4664 mutex_enter(&ipsapp.ipsap_sa_ptr->ipsa_lock);
4666 4665 ipsapp.ipsap_sa_ptr->ipsa_replay =
4667 4666 replext->sadb_x_rc_replay32;
4668 4667 ipsapp.ipsap_sa_ptr->ipsa_idleexpiretime =
4669 4668 current +
4670 4669 ipsapp.ipsap_sa_ptr->ipsa_idletime;
4671 4670 mutex_exit(&ipsapp.ipsap_sa_ptr->ipsa_lock);
4672 4671 }
4673 4672 }
4674 4673 }
4675 4674
4676 4675 if (sadb_msg_type == SADB_X_UPDATEPAIR) {
4677 4676 if (ipsapp.ipsap_psa_ptr != NULL) {
4678 4677 sadb_update_lifetimes(ipsapp.ipsap_psa_ptr, hard, soft,
4679 4678 idle, B_FALSE);
4680 4679 sadb_update_kmc(&sq, ipsapp.ipsap_psa_ptr);
4681 4680 } else {
4682 4681 *diagnostic = SADB_X_DIAGNOSTIC_PAIR_SA_NOTFOUND;
4683 4682 error = ESRCH;
4684 4683 goto bail;
4685 4684 }
4686 4685 }
4687 4686
4688 4687 if (pair_ext != NULL)
4689 4688 error = update_pairing(&ipsapp, &sq, ksi, diagnostic);
4690 4689
4691 4690 if (error == 0)
4692 4691 sadb_pfkey_echo(pfkey_q, mp, (sadb_msg_t *)mp->b_cont->b_rptr,
4693 4692 ksi, echo_target);
4694 4693 bail:
4695 4694
4696 4695 destroy_ipsa_pair(&ipsapp);
4697 4696
4698 4697 return (error);
4699 4698 }
4700 4699
4701 4700
4702 4701 static int
4703 4702 update_pairing(ipsap_t *ipsapp, ipsa_query_t *sq, keysock_in_t *ksi,
4704 4703 int *diagnostic)
4705 4704 {
4706 4705 sadb_sa_t *assoc = (sadb_sa_t *)ksi->ks_in_extv[SADB_EXT_SA];
4707 4706 sadb_x_pair_t *pair_ext =
4708 4707 (sadb_x_pair_t *)ksi->ks_in_extv[SADB_X_EXT_PAIR];
4709 4708 int error = 0;
4710 4709 ipsap_t oipsapp;
4711 4710 boolean_t undo_pair = B_FALSE;
4712 4711 uint32_t ipsa_flags;
4713 4712
4714 4713 if (pair_ext->sadb_x_pair_spi == 0 || pair_ext->sadb_x_pair_spi ==
4715 4714 assoc->sadb_sa_spi) {
4716 4715 *diagnostic = SADB_X_DIAGNOSTIC_PAIR_INAPPROPRIATE;
4717 4716 return (EINVAL);
4718 4717 }
4719 4718
4720 4719 /*
4721 4720 * Assume for now that the spi value provided in the SADB_UPDATE
4722 4721 * message was valid, update the SA with its pair spi value.
4723 4722 * If the spi turns out to be bogus or the SA no longer exists
4724 4723 * then this will be detected when the reverse update is made
4725 4724 * below.
4726 4725 */
4727 4726 mutex_enter(&ipsapp->ipsap_sa_ptr->ipsa_lock);
4728 4727 ipsapp->ipsap_sa_ptr->ipsa_flags |= IPSA_F_PAIRED;
4729 4728 ipsapp->ipsap_sa_ptr->ipsa_otherspi = pair_ext->sadb_x_pair_spi;
4730 4729 mutex_exit(&ipsapp->ipsap_sa_ptr->ipsa_lock);
4731 4730
4732 4731 /*
4733 4732 * After updating the ipsa_otherspi element of the SA, get_ipsa_pair()
4734 4733 * should now return pointers to the SA *AND* its pair, if this is not
4735 4734 * the case, the "otherspi" either did not exist or was deleted. Also
4736 4735 * check that "otherspi" is not already paired. If everything looks
4737 4736 * good, complete the update. IPSA_REFRELE the first pair_pointer
4738 4737 * after this update to ensure its not deleted until we are done.
4739 4738 */
4740 4739 error = get_ipsa_pair(sq, &oipsapp, diagnostic);
4741 4740 if (error != 0) {
4742 4741 /*
4743 4742 * This should never happen, calling function still has
4744 4743 * IPSA_REFHELD on the SA we just updated.
4745 4744 */
4746 4745 return (error); /* XXX EINVAL instead of ESRCH? */
4747 4746 }
4748 4747
4749 4748 if (oipsapp.ipsap_psa_ptr == NULL) {
4750 4749 *diagnostic = SADB_X_DIAGNOSTIC_PAIR_INAPPROPRIATE;
4751 4750 error = EINVAL;
4752 4751 undo_pair = B_TRUE;
4753 4752 } else {
4754 4753 ipsa_flags = oipsapp.ipsap_psa_ptr->ipsa_flags;
4755 4754 if ((oipsapp.ipsap_psa_ptr->ipsa_state == IPSA_STATE_DEAD) ||
4756 4755 (oipsapp.ipsap_psa_ptr->ipsa_state == IPSA_STATE_DYING)) {
4757 4756 /* Its dead Jim! */
4758 4757 *diagnostic = SADB_X_DIAGNOSTIC_PAIR_INAPPROPRIATE;
4759 4758 undo_pair = B_TRUE;
4760 4759 } else if ((ipsa_flags & (IPSA_F_OUTBOUND | IPSA_F_INBOUND)) ==
4761 4760 (IPSA_F_OUTBOUND | IPSA_F_INBOUND)) {
4762 4761 /* This SA is in both hashtables. */
4763 4762 *diagnostic = SADB_X_DIAGNOSTIC_PAIR_INAPPROPRIATE;
4764 4763 undo_pair = B_TRUE;
4765 4764 } else if (ipsa_flags & IPSA_F_PAIRED) {
4766 4765 /* This SA is already paired with another. */
4767 4766 *diagnostic = SADB_X_DIAGNOSTIC_PAIR_ALREADY;
4768 4767 undo_pair = B_TRUE;
4769 4768 }
4770 4769 }
4771 4770
4772 4771 if (undo_pair) {
4773 4772 /* The pair SA does not exist. */
4774 4773 mutex_enter(&ipsapp->ipsap_sa_ptr->ipsa_lock);
4775 4774 ipsapp->ipsap_sa_ptr->ipsa_flags &= ~IPSA_F_PAIRED;
4776 4775 ipsapp->ipsap_sa_ptr->ipsa_otherspi = 0;
4777 4776 mutex_exit(&ipsapp->ipsap_sa_ptr->ipsa_lock);
4778 4777 } else {
4779 4778 mutex_enter(&oipsapp.ipsap_psa_ptr->ipsa_lock);
4780 4779 oipsapp.ipsap_psa_ptr->ipsa_otherspi = assoc->sadb_sa_spi;
4781 4780 oipsapp.ipsap_psa_ptr->ipsa_flags |= IPSA_F_PAIRED;
4782 4781 mutex_exit(&oipsapp.ipsap_psa_ptr->ipsa_lock);
4783 4782 }
4784 4783
4785 4784 destroy_ipsa_pair(&oipsapp);
4786 4785 return (error);
4787 4786 }
4788 4787
4789 4788 /*
4790 4789 * The following functions deal with ACQUIRE LISTS. An ACQUIRE list is
4791 4790 * a list of outstanding SADB_ACQUIRE messages. If ipsec_getassocbyconn() fails
4792 4791 * for an outbound datagram, that datagram is queued up on an ACQUIRE record,
4793 4792 * and an SADB_ACQUIRE message is sent up. Presumably, a user-space key
4794 4793 * management daemon will process the ACQUIRE, use a SADB_GETSPI to reserve
4795 4794 * an SPI value and a larval SA, then SADB_UPDATE the larval SA, and ADD the
4796 4795 * other direction's SA.
4797 4796 */
4798 4797
4799 4798 /*
4800 4799 * Check the ACQUIRE lists. If there's an existing ACQUIRE record,
4801 4800 * grab it, lock it, and return it. Otherwise return NULL.
4802 4801 *
4803 4802 * XXX MLS number of arguments getting unwieldy here
4804 4803 */
4805 4804 static ipsacq_t *
4806 4805 sadb_checkacquire(iacqf_t *bucket, ipsec_action_t *ap, ipsec_policy_t *pp,
4807 4806 uint32_t *src, uint32_t *dst, uint32_t *isrc, uint32_t *idst,
4808 4807 uint64_t unique_id, ts_label_t *tsl)
4809 4808 {
4810 4809 ipsacq_t *walker;
4811 4810 sa_family_t fam;
4812 4811 uint32_t blank_address[4] = {0, 0, 0, 0};
4813 4812
4814 4813 if (isrc == NULL) {
4815 4814 ASSERT(idst == NULL);
4816 4815 isrc = idst = blank_address;
4817 4816 }
4818 4817
4819 4818 /*
4820 4819 * Scan list for duplicates. Check for UNIQUE, src/dest, policy.
4821 4820 *
4822 4821 * XXX May need search for duplicates based on other things too!
4823 4822 */
4824 4823 for (walker = bucket->iacqf_ipsacq; walker != NULL;
4825 4824 walker = walker->ipsacq_next) {
4826 4825 mutex_enter(&walker->ipsacq_lock);
4827 4826 fam = walker->ipsacq_addrfam;
4828 4827 if (IPSA_ARE_ADDR_EQUAL(dst, walker->ipsacq_dstaddr, fam) &&
4829 4828 IPSA_ARE_ADDR_EQUAL(src, walker->ipsacq_srcaddr, fam) &&
4830 4829 ip_addr_match((uint8_t *)isrc, walker->ipsacq_innersrcpfx,
4831 4830 (in6_addr_t *)walker->ipsacq_innersrc) &&
4832 4831 ip_addr_match((uint8_t *)idst, walker->ipsacq_innerdstpfx,
4833 4832 (in6_addr_t *)walker->ipsacq_innerdst) &&
4834 4833 (ap == walker->ipsacq_act) &&
4835 4834 (pp == walker->ipsacq_policy) &&
4836 4835 /* XXX do deep compares of ap/pp? */
|
↓ open down ↓ |
4740 lines elided |
↑ open up ↑ |
4837 4836 (unique_id == walker->ipsacq_unique_id) &&
4838 4837 (ipsec_label_match(tsl, walker->ipsacq_tsl)))
4839 4838 break; /* everything matched */
4840 4839 mutex_exit(&walker->ipsacq_lock);
4841 4840 }
4842 4841
4843 4842 return (walker);
4844 4843 }
4845 4844
4846 4845 /*
4846 + * Generate an SADB_ACQUIRE base message mblk, including KEYSOCK_OUT metadata.
4847 + * In other words, this will return, upon success, a two-mblk chain.
4848 + */
4849 +static inline mblk_t *
4850 +sadb_acquire_msg_base(minor_t serial, uint8_t satype, uint32_t seq, pid_t pid)
4851 +{
4852 + mblk_t *mp;
4853 + sadb_msg_t *samsg;
4854 +
4855 + mp = sadb_keysock_out(serial);
4856 + if (mp == NULL)
4857 + return (NULL);
4858 + mp->b_cont = allocb(sizeof (sadb_msg_t), BPRI_HI);
4859 + if (mp->b_cont == NULL) {
4860 + freeb(mp);
4861 + return (NULL);
4862 + }
4863 +
4864 + samsg = (sadb_msg_t *)mp->b_cont->b_rptr;
4865 + mp->b_cont->b_wptr += sizeof (*samsg);
4866 + samsg->sadb_msg_version = PF_KEY_V2;
4867 + samsg->sadb_msg_type = SADB_ACQUIRE;
4868 + samsg->sadb_msg_errno = 0;
4869 + samsg->sadb_msg_reserved = 0;
4870 + samsg->sadb_msg_satype = satype;
4871 + samsg->sadb_msg_seq = seq;
4872 + samsg->sadb_msg_pid = pid;
4873 +
4874 + return (mp);
4875 +}
4876 +
4877 +/*
4878 + * Generate address and TX/MLS sensitivity label PF_KEY extensions that are
4879 + * common to both regular and extended ACQUIREs.
4880 + */
4881 +static mblk_t *
4882 +sadb_acquire_msg_common(ipsec_selector_t *sel, ipsec_policy_t *pp,
4883 + ipsec_action_t *ap, boolean_t tunnel_mode, ts_label_t *tsl,
4884 + sadb_sens_t *sens)
4885 +{
4886 + size_t len;
4887 + mblk_t *mp;
4888 + uint8_t *start, *cur, *end;
4889 + uint32_t *saddrptr, *daddrptr;
4890 + sa_family_t af;
4891 + ipsec_action_t *oldap;
4892 + ipsec_selkey_t *ipsl;
4893 + uint8_t proto, pfxlen;
4894 + uint16_t lport, rport;
4895 + int senslen = 0;
4896 +
4897 + /*
4898 + * Get action pointer set if it isn't already.
4899 + */
4900 + oldap = ap;
4901 + if (pp != NULL) {
4902 + ap = pp->ipsp_act;
4903 + if (ap == NULL)
4904 + ap = oldap;
4905 + }
4906 +
4907 + /*
4908 + * Biggest-case scenario:
4909 + * 4x (sadb_address_t + struct sockaddr_in6)
4910 + * (src, dst, isrc, idst)
4911 + * (COMING SOON, 6x, because of triggering-packet contents.)
4912 + * sadb_x_kmc_t
4913 + * sadb_sens_t
4914 + * And wiggle room for label bitvectors. Luckily there are
4915 + * programmatic ways to find it.
4916 + */
4917 + len = 4 * (sizeof (sadb_address_t) + sizeof (struct sockaddr_in6));
4918 +
4919 + /* Figure out full and proper length of sensitivity labels. */
4920 + if (sens != NULL) {
4921 + ASSERT(tsl == NULL);
4922 + senslen = SADB_64TO8(sens->sadb_sens_len);
4923 + } else if (tsl != NULL) {
4924 + senslen = sadb_sens_len_from_label(tsl);
4925 + }
4926 +#ifdef DEBUG
4927 + else {
4928 + ASSERT(senslen == 0);
4929 + }
4930 +#endif /* DEBUG */
4931 + len += senslen;
4932 +
4933 + mp = allocb(len, BPRI_HI);
4934 + if (mp == NULL)
4935 + return (NULL);
4936 +
4937 + start = mp->b_rptr;
4938 + end = start + len;
4939 + cur = start;
4940 +
4941 + /*
4942 + * Address extensions first, from most-recently-defined to least.
4943 + * (This should immediately trigger surprise or verify robustness on
4944 + * older apps, like in.iked.)
4945 + */
4946 + if (tunnel_mode) {
4947 + /*
4948 + * Form inner address extensions based NOT on the inner
4949 + * selectors (i.e. the packet data), but on the policy's
4950 + * selector key (i.e. the policy's selector information).
4951 + *
4952 + * NOTE: The position of IPv4 and IPv6 addresses is the
4953 + * same in ipsec_selkey_t (unless the compiler does very
4954 + * strange things with unions, consult your local C language
4955 + * lawyer for details).
4956 + */
4957 + ASSERT(pp != NULL);
4958 +
4959 + ipsl = &(pp->ipsp_sel->ipsl_key);
4960 + if (ipsl->ipsl_valid & IPSL_IPV4) {
4961 + af = AF_INET;
4962 + ASSERT(sel->ips_protocol == IPPROTO_ENCAP);
4963 + ASSERT(!(ipsl->ipsl_valid & IPSL_IPV6));
4964 + } else {
4965 + af = AF_INET6;
4966 + ASSERT(sel->ips_protocol == IPPROTO_IPV6);
4967 + ASSERT(ipsl->ipsl_valid & IPSL_IPV6);
4968 + }
4969 +
4970 + if (ipsl->ipsl_valid & IPSL_LOCAL_ADDR) {
4971 + saddrptr = (uint32_t *)(&ipsl->ipsl_local);
4972 + pfxlen = ipsl->ipsl_local_pfxlen;
4973 + } else {
4974 + saddrptr = (uint32_t *)(&ipv6_all_zeros);
4975 + pfxlen = 0;
4976 + }
4977 + /* XXX What about ICMP type/code? */
4978 + lport = (ipsl->ipsl_valid & IPSL_LOCAL_PORT) ?
4979 + ipsl->ipsl_lport : 0;
4980 + proto = (ipsl->ipsl_valid & IPSL_PROTOCOL) ?
4981 + ipsl->ipsl_proto : 0;
4982 +
4983 + cur = sadb_make_addr_ext(cur, end, SADB_X_EXT_ADDRESS_INNER_SRC,
4984 + af, saddrptr, lport, proto, pfxlen);
4985 + if (cur == NULL) {
4986 + freeb(mp);
4987 + return (NULL);
4988 + }
4989 +
4990 + if (ipsl->ipsl_valid & IPSL_REMOTE_ADDR) {
4991 + daddrptr = (uint32_t *)(&ipsl->ipsl_remote);
4992 + pfxlen = ipsl->ipsl_remote_pfxlen;
4993 + } else {
4994 + daddrptr = (uint32_t *)(&ipv6_all_zeros);
4995 + pfxlen = 0;
4996 + }
4997 + /* XXX What about ICMP type/code? */
4998 + rport = (ipsl->ipsl_valid & IPSL_REMOTE_PORT) ?
4999 + ipsl->ipsl_rport : 0;
5000 +
5001 + cur = sadb_make_addr_ext(cur, end, SADB_X_EXT_ADDRESS_INNER_DST,
5002 + af, daddrptr, rport, proto, pfxlen);
5003 + if (cur == NULL) {
5004 + freeb(mp);
5005 + return (NULL);
5006 + }
5007 + /*
5008 + * TODO - if we go to 3884's dream of transport mode IP-in-IP
5009 + * _with_ inner-packet address selectors, we'll need to further
5010 + * distinguish tunnel mode here. For now, having inner
5011 + * addresses and/or ports is sufficient.
5012 + *
5013 + * Meanwhile, whack proto/ports to reflect IP-in-IP for the
5014 + * outer addresses.
5015 + */
5016 + proto = sel->ips_protocol; /* Either _ENCAP or _IPV6 */
5017 + lport = rport = 0;
5018 + } else if ((ap != NULL) && (!ap->ipa_want_unique)) {
5019 + /*
5020 + * For cases when the policy calls out specific ports (or not).
5021 + */
5022 + proto = 0;
5023 + lport = 0;
5024 + rport = 0;
5025 + if (pp != NULL) {
5026 + ipsl = &(pp->ipsp_sel->ipsl_key);
5027 + if (ipsl->ipsl_valid & IPSL_PROTOCOL)
5028 + proto = ipsl->ipsl_proto;
5029 + if (ipsl->ipsl_valid & IPSL_REMOTE_PORT)
5030 + rport = ipsl->ipsl_rport;
5031 + if (ipsl->ipsl_valid & IPSL_LOCAL_PORT)
5032 + lport = ipsl->ipsl_lport;
5033 + }
5034 + } else {
5035 + /*
5036 + * For require-unique-SA policies.
5037 + */
5038 + proto = sel->ips_protocol;
5039 + lport = sel->ips_local_port;
5040 + rport = sel->ips_remote_port;
5041 + }
5042 +
5043 + /*
5044 + * Regular addresses. These are outer-packet ones for tunnel mode.
5045 + * Or for transport mode, the regulard address & port information.
5046 + */
5047 + af = sel->ips_isv4 ? AF_INET : AF_INET6;
5048 +
5049 + /*
5050 + * NOTE: The position of IPv4 and IPv6 addresses is the same in
5051 + * ipsec_selector_t.
5052 + */
5053 + cur = sadb_make_addr_ext(cur, end, SADB_EXT_ADDRESS_SRC, af,
5054 + (uint32_t *)(&sel->ips_local_addr_v6), lport, proto, 0);
5055 + if (cur == NULL) {
5056 + freeb(mp);
5057 + return (NULL);
5058 + }
5059 +
5060 + cur = sadb_make_addr_ext(cur, end, SADB_EXT_ADDRESS_DST, af,
5061 + (uint32_t *)(&sel->ips_remote_addr_v6), rport, proto, 0);
5062 + if (cur == NULL) {
5063 + freeb(mp);
5064 + return (NULL);
5065 + }
5066 +
5067 + /*
5068 + * If present, generate a sensitivity label.
5069 + */
5070 + if (cur + senslen > end) {
5071 + freeb(mp);
5072 + return (NULL);
5073 + }
5074 + if (sens != NULL) {
5075 + /* Explicit sadb_sens_t, usually from inverse-ACQUIRE. */
5076 + bcopy(sens, cur, senslen);
5077 + } else if (tsl != NULL) {
5078 + /* Generate sadb_sens_t from ACQUIRE source. */
5079 + sadb_sens_from_label((sadb_sens_t *)cur, SADB_EXT_SENSITIVITY,
5080 + tsl, senslen);
5081 + }
5082 +#ifdef DEBUG
5083 + else {
5084 + ASSERT(senslen == 0);
5085 + }
5086 +#endif /* DEBUG */
5087 + cur += senslen;
5088 + mp->b_wptr = cur;
5089 +
5090 + return (mp);
5091 +}
5092 +
5093 +/*
5094 + * Generate a regular ACQUIRE's proposal extension and KMC information..
5095 + */
5096 +static mblk_t *
5097 +sadb_acquire_prop(ipsec_action_t *ap, netstack_t *ns, boolean_t do_esp)
5098 +{
5099 + ipsec_stack_t *ipss = ns->netstack_ipsec;
5100 + ipsecesp_stack_t *espstack = ns->netstack_ipsecesp;
5101 + ipsecah_stack_t *ahstack = ns->netstack_ipsecah;
5102 + mblk_t *mp = NULL;
5103 + sadb_prop_t *prop;
5104 + sadb_comb_t *comb;
5105 + ipsec_action_t *walker;
5106 + int ncombs, allocsize, ealgid, aalgid, aminbits, amaxbits, eminbits,
5107 + emaxbits, replay;
5108 + uint64_t softbytes, hardbytes, softaddtime, hardaddtime, softusetime,
5109 + hardusetime;
5110 + uint32_t kmc = 0, kmp = 0;
5111 +
5112 + /*
5113 + * Since it's an rwlock read, AND writing to the IPsec algorithms is
5114 + * rare, just acquire it once up top, and drop it upon return.
5115 + */
5116 + rw_enter(&ipss->ipsec_alg_lock, RW_READER);
5117 + if (do_esp) {
5118 + uint64_t num_aalgs, num_ealgs;
5119 +
5120 + if (espstack->esp_kstats == NULL)
5121 + goto bail;
5122 +
5123 + num_aalgs = ipss->ipsec_nalgs[IPSEC_ALG_AUTH];
5124 + num_ealgs = ipss->ipsec_nalgs[IPSEC_ALG_ENCR];
5125 + if (num_ealgs == 0)
5126 + goto bail; /* IPsec not loaded yet, apparently. */
5127 + num_aalgs++; /* No-auth or self-auth-crypto ESP. */
5128 +
5129 + /* Use netstack's maximum loaded algorithms... */
5130 + ncombs = num_ealgs * num_aalgs;
5131 + replay = espstack->ipsecesp_replay_size;
5132 + } else {
5133 + if (ahstack->ah_kstats == NULL)
5134 + goto bail;
5135 +
5136 + ncombs = ipss->ipsec_nalgs[IPSEC_ALG_AUTH];
5137 +
5138 + if (ncombs == 0)
5139 + goto bail; /* IPsec not loaded yet, apparently. */
5140 + replay = ahstack->ipsecah_replay_size;
5141 + }
5142 +
5143 + allocsize = sizeof (*prop) + ncombs * sizeof (*comb) +
5144 + sizeof (sadb_x_kmc_t);
5145 + mp = allocb(allocsize, BPRI_HI);
5146 + if (mp == NULL)
5147 + goto bail;
5148 + prop = (sadb_prop_t *)mp->b_rptr;
5149 + mp->b_wptr += sizeof (*prop);
5150 + comb = (sadb_comb_t *)mp->b_wptr;
5151 + /* Decrement allocsize, if it goes to or below 0, stop. */
5152 + allocsize -= sizeof (*prop);
5153 + prop->sadb_prop_exttype = SADB_EXT_PROPOSAL;
5154 + prop->sadb_prop_len = SADB_8TO64(sizeof (*prop));
5155 + *(uint32_t *)(&prop->sadb_prop_replay) = 0; /* Quick zero-out! */
5156 + prop->sadb_prop_replay = replay;
5157 +
5158 + /*
5159 + * Based upon algorithm properties, and what-not, prioritize a
5160 + * proposal, based on the ordering of the ESP algorithms in the
5161 + * alternatives in the policy rule or socket that was placed
5162 + * in the acquire record.
5163 + *
5164 + * For each action in policy list
5165 + * Add combination.
5166 + * I should not hit it, but if I've hit limit, return.
5167 + */
5168 +
5169 + for (walker = ap; walker != NULL; walker = walker->ipa_next) {
5170 + ipsec_alginfo_t *ealg, *aalg;
5171 + ipsec_prot_t *prot;
5172 +
5173 + if (walker->ipa_act.ipa_type != IPSEC_POLICY_APPLY)
5174 + continue;
5175 +
5176 + prot = &walker->ipa_act.ipa_apply;
5177 + if (walker->ipa_act.ipa_apply.ipp_km_proto != 0)
5178 + kmp = walker->ipa_act.ipa_apply.ipp_km_proto;
5179 + if (walker->ipa_act.ipa_apply.ipp_km_cookie != 0)
5180 + kmc = walker->ipa_act.ipa_apply.ipp_km_cookie;
5181 + if (walker->ipa_act.ipa_apply.ipp_replay_depth) {
5182 + prop->sadb_prop_replay =
5183 + walker->ipa_act.ipa_apply.ipp_replay_depth;
5184 + }
5185 +
5186 + if (do_esp) {
5187 + if (!prot->ipp_use_esp)
5188 + continue;
5189 +
5190 + if (prot->ipp_esp_auth_alg != 0) {
5191 + aalg = ipss->ipsec_alglists[IPSEC_ALG_AUTH]
5192 + [prot->ipp_esp_auth_alg];
5193 + if (aalg == NULL || !ALG_VALID(aalg))
5194 + continue;
5195 + } else
5196 + aalg = NULL;
5197 +
5198 + ASSERT(prot->ipp_encr_alg > 0);
5199 + ealg = ipss->ipsec_alglists[IPSEC_ALG_ENCR]
5200 + [prot->ipp_encr_alg];
5201 + if (ealg == NULL || !ALG_VALID(ealg))
5202 + continue;
5203 +
5204 + /*
5205 + * These may want to come from policy rule..
5206 + */
5207 + softbytes = espstack->ipsecesp_default_soft_bytes;
5208 + hardbytes = espstack->ipsecesp_default_hard_bytes;
5209 + softaddtime = espstack->ipsecesp_default_soft_addtime;
5210 + hardaddtime = espstack->ipsecesp_default_hard_addtime;
5211 + softusetime = espstack->ipsecesp_default_soft_usetime;
5212 + hardusetime = espstack->ipsecesp_default_hard_usetime;
5213 + } else {
5214 + if (!prot->ipp_use_ah)
5215 + continue;
5216 + ealg = NULL;
5217 + aalg = ipss->ipsec_alglists[IPSEC_ALG_AUTH]
5218 + [prot->ipp_auth_alg];
5219 + if (aalg == NULL || !ALG_VALID(aalg))
5220 + continue;
5221 +
5222 + /*
5223 + * These may want to come from policy rule..
5224 + */
5225 + softbytes = ahstack->ipsecah_default_soft_bytes;
5226 + hardbytes = ahstack->ipsecah_default_hard_bytes;
5227 + softaddtime = ahstack->ipsecah_default_soft_addtime;
5228 + hardaddtime = ahstack->ipsecah_default_hard_addtime;
5229 + softusetime = ahstack->ipsecah_default_soft_usetime;
5230 + hardusetime = ahstack->ipsecah_default_hard_usetime;
5231 + }
5232 +
5233 + if (ealg == NULL) {
5234 + ealgid = eminbits = emaxbits = 0;
5235 + } else {
5236 + ealgid = ealg->alg_id;
5237 + eminbits =
5238 + MAX(prot->ipp_espe_minbits, ealg->alg_ef_minbits);
5239 + emaxbits =
5240 + MIN(prot->ipp_espe_maxbits, ealg->alg_ef_maxbits);
5241 + }
5242 +
5243 + if (aalg == NULL) {
5244 + aalgid = aminbits = amaxbits = 0;
5245 + } else {
5246 + aalgid = aalg->alg_id;
5247 + aminbits = MAX(prot->ipp_espa_minbits,
5248 + aalg->alg_ef_minbits);
5249 + amaxbits = MIN(prot->ipp_espa_maxbits,
5250 + aalg->alg_ef_maxbits);
5251 + }
5252 +
5253 + comb->sadb_comb_flags = 0;
5254 + comb->sadb_comb_reserved = 0;
5255 + comb->sadb_comb_encrypt = ealgid;
5256 + comb->sadb_comb_encrypt_minbits = eminbits;
5257 + comb->sadb_comb_encrypt_maxbits = emaxbits;
5258 + comb->sadb_comb_auth = aalgid;
5259 + comb->sadb_comb_auth_minbits = aminbits;
5260 + comb->sadb_comb_auth_maxbits = amaxbits;
5261 + comb->sadb_comb_soft_allocations = 0;
5262 + comb->sadb_comb_hard_allocations = 0;
5263 + comb->sadb_comb_soft_bytes = softbytes;
5264 + comb->sadb_comb_hard_bytes = hardbytes;
5265 + comb->sadb_comb_soft_addtime = softaddtime;
5266 + comb->sadb_comb_hard_addtime = hardaddtime;
5267 + comb->sadb_comb_soft_usetime = softusetime;
5268 + comb->sadb_comb_hard_usetime = hardusetime;
5269 +
5270 + prop->sadb_prop_len += SADB_8TO64(sizeof (*comb));
5271 + mp->b_wptr += sizeof (*comb);
5272 + allocsize -= sizeof (*comb);
5273 + /* Should never dip BELOW sizeof (KM cookie extension). */
5274 + ASSERT3S(allocsize, >=, sizeof (sadb_x_kmc_t));
5275 + if (allocsize <= sizeof (sadb_x_kmc_t))
5276 + break; /* out of space.. */
5277 + comb++;
5278 + }
5279 +
5280 + /* Don't include KMC extension if there's no room. */
5281 + if (((kmp != 0) || (kmc != 0)) && allocsize >= sizeof (sadb_x_kmc_t)) {
5282 + if (sadb_make_kmc_ext(mp->b_wptr,
5283 + mp->b_wptr + sizeof (sadb_x_kmc_t), kmp, kmc) == NULL) {
5284 + freeb(mp);
5285 + mp = NULL;
5286 + goto bail;
5287 + }
5288 + mp->b_wptr += sizeof (sadb_x_kmc_t);
5289 + prop->sadb_prop_len += SADB_8TO64(sizeof (sadb_x_kmc_t));
5290 + }
5291 +
5292 +bail:
5293 + rw_exit(&ipss->ipsec_alg_lock);
5294 + return (mp);
5295 +}
5296 +
5297 +/*
5298 + * Generate an extended ACQUIRE's extended-proposal extension.
5299 + */
5300 +/* ARGSUSED */
5301 +static mblk_t *
5302 +sadb_acquire_extended_prop(ipsec_action_t *ap, netstack_t *ns)
5303 +{
5304 + sadb_prop_t *eprop;
5305 + uint8_t *cur, *end;
5306 + mblk_t *mp;
5307 + int allocsize, numecombs = 0, numalgdescs = 0;
5308 + uint32_t kmc = 0, kmp = 0, replay = 0;
5309 + ipsec_action_t *walker;
5310 +
5311 + allocsize = sizeof (*eprop);
5312 +
5313 + /*
5314 + * Going to walk through the action list twice. Once for allocation
5315 + * measurement, and once for actual construction.
5316 + */
5317 + for (walker = ap; walker != NULL; walker = walker->ipa_next) {
5318 + ipsec_prot_t *ipp;
5319 +
5320 + /*
5321 + * Skip non-IPsec policies
5322 + */
5323 + if (walker->ipa_act.ipa_type != IPSEC_ACT_APPLY)
5324 + continue;
5325 +
5326 + ipp = &walker->ipa_act.ipa_apply;
5327 +
5328 + if (walker->ipa_act.ipa_apply.ipp_km_proto)
5329 + kmp = ipp->ipp_km_proto;
5330 + if (walker->ipa_act.ipa_apply.ipp_km_cookie)
5331 + kmc = ipp->ipp_km_cookie;
5332 + if (walker->ipa_act.ipa_apply.ipp_replay_depth)
5333 + replay = ipp->ipp_replay_depth;
5334 +
5335 + if (ipp->ipp_use_ah)
5336 + numalgdescs++;
5337 + if (ipp->ipp_use_esp) {
5338 + numalgdescs++;
5339 + if (ipp->ipp_use_espa)
5340 + numalgdescs++;
5341 + }
5342 +
5343 + numecombs++;
5344 + }
5345 + ASSERT(numecombs > 0);
5346 +
5347 + allocsize += numecombs * sizeof (sadb_x_ecomb_t) +
5348 + numalgdescs * sizeof (sadb_x_algdesc_t) + sizeof (sadb_x_kmc_t);
5349 + mp = allocb(allocsize, BPRI_HI);
5350 + if (mp == NULL)
5351 + return (NULL);
5352 + eprop = (sadb_prop_t *)mp->b_rptr;
5353 + end = mp->b_rptr + allocsize;
5354 + cur = mp->b_rptr + sizeof (*eprop);
5355 +
5356 + eprop->sadb_prop_exttype = SADB_X_EXT_EPROP;
5357 + eprop->sadb_x_prop_ereserved = 0;
5358 + eprop->sadb_x_prop_numecombs = 0;
5359 + *(uint32_t *)(&eprop->sadb_prop_replay) = 0; /* Quick zero-out! */
5360 + /* Pick ESP's replay default if need be. */
5361 + eprop->sadb_prop_replay = (replay == 0) ?
5362 + ns->netstack_ipsecesp->ipsecesp_replay_size : replay;
5363 +
5364 + /* This time, walk through and actually allocate. */
5365 + for (walker = ap; walker != NULL; walker = walker->ipa_next) {
5366 + /*
5367 + * Skip non-IPsec policies
5368 + */
5369 + if (walker->ipa_act.ipa_type != IPSEC_ACT_APPLY)
5370 + continue;
5371 + cur = sadb_action_to_ecomb(cur, end, walker, ns);
5372 + if (cur == NULL) {
5373 + /* NOTE: inverse-ACQUIRE should note this as ENOMEM. */
5374 + freeb(mp);
5375 + return (NULL);
5376 + }
5377 + eprop->sadb_x_prop_numecombs++;
5378 + }
5379 +
5380 + ASSERT(end - cur >= sizeof (sadb_x_kmc_t));
5381 + if ((kmp != 0) || (kmc != 0)) {
5382 + cur = sadb_make_kmc_ext(cur, end, kmp, kmc);
5383 + if (cur == NULL) {
5384 + freeb(mp);
5385 + return (NULL);
5386 + }
5387 + }
5388 + mp->b_wptr = cur;
5389 + eprop->sadb_prop_len = SADB_8TO64(cur - mp->b_rptr);
5390 +
5391 + return (mp);
5392 +}
5393 +
5394 +/*
4847 5395 * For this mblk, insert a new acquire record. Assume bucket contains addrs
4848 5396 * of all of the same length. Give up (and drop) if memory
4849 5397 * cannot be allocated for a new one; otherwise, invoke callback to
4850 5398 * send the acquire up..
4851 5399 *
4852 5400 * In cases where we need both AH and ESP, add the SA to the ESP ACQUIRE
4853 5401 * list. The ah_add_sa_finish() routines can look at the packet's attached
4854 5402 * attributes and handle this case specially.
4855 5403 */
4856 5404 void
4857 5405 sadb_acquire(mblk_t *datamp, ip_xmit_attr_t *ixa, boolean_t need_ah,
4858 5406 boolean_t need_esp)
4859 5407 {
4860 - mblk_t *asyncmp;
5408 + mblk_t *asyncmp, *regular, *extended, *common, *prop, *eprop;
4861 5409 sadbp_t *spp;
4862 5410 sadb_t *sp;
4863 5411 ipsacq_t *newbie;
4864 5412 iacqf_t *bucket;
4865 - mblk_t *extended;
4866 5413 ipha_t *ipha = (ipha_t *)datamp->b_rptr;
4867 5414 ip6_t *ip6h = (ip6_t *)datamp->b_rptr;
4868 5415 uint32_t *src, *dst, *isrc, *idst;
4869 5416 ipsec_policy_t *pp = ixa->ixa_ipsec_policy;
4870 5417 ipsec_action_t *ap = ixa->ixa_ipsec_action;
4871 5418 sa_family_t af;
4872 5419 int hashoffset;
4873 5420 uint32_t seq;
4874 5421 uint64_t unique_id = 0;
4875 - ipsec_selector_t sel;
4876 5422 boolean_t tunnel_mode = (ixa->ixa_flags & IXAF_IPSEC_TUNNEL) != 0;
4877 - ts_label_t *tsl = NULL;
5423 + ts_label_t *tsl;
4878 5424 netstack_t *ns = ixa->ixa_ipst->ips_netstack;
4879 5425 ipsec_stack_t *ipss = ns->netstack_ipsec;
4880 - sadb_sens_t *sens = NULL;
4881 - int sens_len;
5426 + ipsecesp_stack_t *espstack = ns->netstack_ipsecesp;
5427 + ipsecah_stack_t *ahstack = ns->netstack_ipsecah;
5428 + ipsec_selector_t sel;
5429 + queue_t *q;
4882 5430
4883 5431 ASSERT((pp != NULL) || (ap != NULL));
4884 5432
4885 - ASSERT(need_ah != NULL || need_esp != NULL);
5433 + ASSERT(need_ah || need_esp);
4886 5434
4887 5435 /* Assign sadb pointers */
4888 - if (need_esp) { /* ESP for AH+ESP */
4889 - ipsecesp_stack_t *espstack = ns->netstack_ipsecesp;
4890 -
5436 + if (need_esp) {
5437 + /*
5438 + * ESP happens first if we need both AH and ESP.
5439 + */
4891 5440 spp = &espstack->esp_sadb;
4892 5441 } else {
4893 - ipsecah_stack_t *ahstack = ns->netstack_ipsecah;
4894 -
4895 5442 spp = &ahstack->ah_sadb;
4896 5443 }
4897 5444 sp = (ixa->ixa_flags & IXAF_IS_IPV4) ? &spp->s_v4 : &spp->s_v6;
4898 5445
4899 5446 if (is_system_labeled())
4900 5447 tsl = ixa->ixa_tsl;
5448 + else
5449 + tsl = NULL;
4901 5450
4902 5451 if (ap == NULL)
4903 5452 ap = pp->ipsp_act;
4904 -
4905 5453 ASSERT(ap != NULL);
4906 5454
4907 5455 if (ap->ipa_act.ipa_apply.ipp_use_unique || tunnel_mode)
4908 5456 unique_id = SA_FORM_UNIQUE_ID(ixa);
4909 5457
4910 5458 /*
4911 5459 * Set up an ACQUIRE record.
4912 5460 *
4913 5461 * Immediately, make sure the ACQUIRE sequence number doesn't slip
4914 5462 * below the lowest point allowed in the kernel. (In other words,
4915 5463 * make sure the high bit on the sequence number is set.)
4916 5464 */
4917 5465
4918 5466 seq = keysock_next_seq(ns) | IACQF_LOWEST_SEQ;
4919 5467
4920 5468 if (IPH_HDR_VERSION(ipha) == IP_VERSION) {
4921 5469 src = (uint32_t *)&ipha->ipha_src;
4922 5470 dst = (uint32_t *)&ipha->ipha_dst;
4923 5471 af = AF_INET;
4924 5472 hashoffset = OUTBOUND_HASH_V4(sp, ipha->ipha_dst);
4925 5473 ASSERT(ixa->ixa_flags & IXAF_IS_IPV4);
4926 5474 } else {
4927 5475 ASSERT(IPH_HDR_VERSION(ipha) == IPV6_VERSION);
4928 5476 src = (uint32_t *)&ip6h->ip6_src;
4929 5477 dst = (uint32_t *)&ip6h->ip6_dst;
4930 5478 af = AF_INET6;
4931 5479 hashoffset = OUTBOUND_HASH_V6(sp, ip6h->ip6_dst);
4932 5480 ASSERT(!(ixa->ixa_flags & IXAF_IS_IPV4));
4933 5481 }
4934 5482
4935 5483 if (tunnel_mode) {
4936 5484 if (pp == NULL) {
4937 5485 /*
4938 5486 * Tunnel mode with no policy pointer means this is a
4939 5487 * reflected ICMP (like a ECHO REQUEST) that came in
4940 5488 * with self-encapsulated protection. Until we better
4941 5489 * support this, drop the packet.
4942 5490 */
4943 5491 ip_drop_packet(datamp, B_FALSE, NULL,
4944 5492 DROPPER(ipss, ipds_spd_got_selfencap),
4945 5493 &ipss->ipsec_spd_dropper);
4946 5494 return;
4947 5495 }
4948 5496 /* Snag inner addresses. */
4949 5497 isrc = ixa->ixa_ipsec_insrc;
4950 5498 idst = ixa->ixa_ipsec_indst;
4951 5499 } else {
4952 5500 isrc = idst = NULL;
4953 5501 }
4954 5502
4955 5503 /*
4956 5504 * Check buckets to see if there is an existing entry. If so,
4957 5505 * grab it. sadb_checkacquire locks newbie if found.
4958 5506 */
4959 5507 bucket = &(sp->sdb_acq[hashoffset]);
4960 5508 mutex_enter(&bucket->iacqf_lock);
4961 5509 newbie = sadb_checkacquire(bucket, ap, pp, src, dst, isrc, idst,
4962 5510 unique_id, tsl);
4963 5511
4964 5512 if (newbie == NULL) {
4965 5513 /*
4966 5514 * Otherwise, allocate a new one.
4967 5515 */
4968 5516 newbie = kmem_zalloc(sizeof (*newbie), KM_NOSLEEP);
4969 5517 if (newbie == NULL) {
4970 5518 mutex_exit(&bucket->iacqf_lock);
4971 5519 ip_drop_packet(datamp, B_FALSE, NULL,
4972 5520 DROPPER(ipss, ipds_sadb_acquire_nomem),
4973 5521 &ipss->ipsec_sadb_dropper);
4974 5522 return;
4975 5523 }
4976 5524 newbie->ipsacq_policy = pp;
4977 5525 if (pp != NULL) {
4978 5526 IPPOL_REFHOLD(pp);
4979 5527 }
4980 5528 IPACT_REFHOLD(ap);
4981 5529 newbie->ipsacq_act = ap;
4982 5530 newbie->ipsacq_linklock = &bucket->iacqf_lock;
4983 5531 newbie->ipsacq_next = bucket->iacqf_ipsacq;
4984 5532 newbie->ipsacq_ptpn = &bucket->iacqf_ipsacq;
4985 5533 if (newbie->ipsacq_next != NULL)
4986 5534 newbie->ipsacq_next->ipsacq_ptpn = &newbie->ipsacq_next;
4987 5535
4988 5536 bucket->iacqf_ipsacq = newbie;
4989 5537 mutex_init(&newbie->ipsacq_lock, NULL, MUTEX_DEFAULT, NULL);
4990 5538 mutex_enter(&newbie->ipsacq_lock);
4991 5539 }
4992 5540
4993 5541 /*
4994 5542 * XXX MLS does it actually help us to drop the bucket lock here?
4995 5543 * we have inserted a half-built, locked acquire record into the
4996 5544 * bucket. any competing thread will now be able to lock the bucket
4997 5545 * to scan it, but will immediately pile up on the new acquire
4998 5546 * record's lock; I don't think we gain anything here other than to
4999 5547 * disperse blame for lock contention.
5000 5548 *
5001 5549 * we might be able to dispense with acquire record locks entirely..
5002 5550 * just use the bucket locks..
5003 5551 */
5004 5552
5005 5553 mutex_exit(&bucket->iacqf_lock);
5006 5554
5007 5555 /*
5008 5556 * This assert looks silly for now, but we may need to enter newbie's
5009 5557 * mutex during a search.
5010 5558 */
5011 5559 ASSERT(MUTEX_HELD(&newbie->ipsacq_lock));
5012 5560
5013 5561 /*
5014 5562 * Make the ip_xmit_attr_t into something we can queue.
5015 5563 * If no memory it frees datamp.
5016 5564 */
5017 5565 asyncmp = ip_xmit_attr_to_mblk(ixa);
5018 5566 if (asyncmp != NULL)
5019 5567 linkb(asyncmp, datamp);
5020 5568
5021 5569 /* Queue up packet. Use b_next. */
5022 5570
5023 5571 if (asyncmp == NULL) {
|
↓ open down ↓ |
109 lines elided |
↑ open up ↑ |
5024 5572 /* Statistics for allocation failure */
5025 5573 if (ixa->ixa_flags & IXAF_IS_IPV4) {
5026 5574 BUMP_MIB(&ixa->ixa_ipst->ips_ip_mib,
5027 5575 ipIfStatsOutDiscards);
5028 5576 } else {
5029 5577 BUMP_MIB(&ixa->ixa_ipst->ips_ip6_mib,
5030 5578 ipIfStatsOutDiscards);
5031 5579 }
5032 5580 ip_drop_output("No memory for asyncmp", datamp, NULL);
5033 5581 freemsg(datamp);
5582 + /*
5583 + * The acquire record will be freed quickly if it's new
5584 + * (ipsacq_expire == 0), and will proceed as if no packet
5585 + * showed up if not.
5586 + */
5587 + mutex_exit(&newbie->ipsacq_lock);
5588 + return;
5034 5589 } else if (newbie->ipsacq_numpackets == 0) {
5035 5590 /* First one. */
5036 5591 newbie->ipsacq_mp = asyncmp;
5037 5592 newbie->ipsacq_numpackets = 1;
5038 5593 newbie->ipsacq_expire = gethrestime_sec();
5039 5594 /*
5040 5595 * Extended ACQUIRE with both AH+ESP will use ESP's timeout
5041 5596 * value.
5042 5597 */
5043 5598 newbie->ipsacq_expire += *spp->s_acquire_timeout;
5044 5599 newbie->ipsacq_seq = seq;
5045 5600 newbie->ipsacq_addrfam = af;
5046 5601
5047 5602 newbie->ipsacq_srcport = ixa->ixa_ipsec_src_port;
5048 5603 newbie->ipsacq_dstport = ixa->ixa_ipsec_dst_port;
5049 5604 newbie->ipsacq_icmp_type = ixa->ixa_ipsec_icmp_type;
5050 5605 newbie->ipsacq_icmp_code = ixa->ixa_ipsec_icmp_code;
5051 5606 if (tunnel_mode) {
5052 5607 newbie->ipsacq_inneraddrfam = ixa->ixa_ipsec_inaf;
5053 5608 newbie->ipsacq_proto = ixa->ixa_ipsec_inaf == AF_INET6 ?
5054 5609 IPPROTO_IPV6 : IPPROTO_ENCAP;
5055 5610 newbie->ipsacq_innersrcpfx = ixa->ixa_ipsec_insrcpfx;
|
↓ open down ↓ |
12 lines elided |
↑ open up ↑ |
5056 5611 newbie->ipsacq_innerdstpfx = ixa->ixa_ipsec_indstpfx;
5057 5612 IPSA_COPY_ADDR(newbie->ipsacq_innersrc,
5058 5613 ixa->ixa_ipsec_insrc, ixa->ixa_ipsec_inaf);
5059 5614 IPSA_COPY_ADDR(newbie->ipsacq_innerdst,
5060 5615 ixa->ixa_ipsec_indst, ixa->ixa_ipsec_inaf);
5061 5616 } else {
5062 5617 newbie->ipsacq_proto = ixa->ixa_ipsec_proto;
5063 5618 }
5064 5619 newbie->ipsacq_unique_id = unique_id;
5065 5620
5066 - if (ixa->ixa_tsl != NULL) {
5067 - label_hold(ixa->ixa_tsl);
5068 - newbie->ipsacq_tsl = ixa->ixa_tsl;
5621 + if (tsl != NULL) {
5622 + label_hold(tsl);
5623 + newbie->ipsacq_tsl = tsl;
5069 5624 }
5070 5625 } else {
5071 5626 /* Scan to the end of the list & insert. */
5072 5627 mblk_t *lastone = newbie->ipsacq_mp;
5073 5628
5074 5629 while (lastone->b_next != NULL)
5075 5630 lastone = lastone->b_next;
5076 5631 lastone->b_next = asyncmp;
5077 5632 if (newbie->ipsacq_numpackets++ == ipsacq_maxpackets) {
5078 5633 newbie->ipsacq_numpackets = ipsacq_maxpackets;
5079 5634 lastone = newbie->ipsacq_mp;
5080 5635 newbie->ipsacq_mp = lastone->b_next;
5081 5636 lastone->b_next = NULL;
5082 5637
5083 5638 /* Freeing the async message */
5084 5639 lastone = ip_xmit_attr_free_mblk(lastone);
5085 5640 ip_drop_packet(lastone, B_FALSE, NULL,
5086 5641 DROPPER(ipss, ipds_sadb_acquire_toofull),
5087 5642 &ipss->ipsec_sadb_dropper);
5088 5643 } else {
5089 5644 IP_ACQUIRE_STAT(ipss, qhiwater,
5090 5645 newbie->ipsacq_numpackets);
5091 5646 }
5092 5647 }
5093 5648
5094 5649 /*
5095 5650 * Reset addresses. Set them to the most recently added mblk chain,
5096 5651 * so that the address pointers in the acquire record will point
5097 5652 * at an mblk still attached to the acquire list.
5098 5653 */
5099 5654
5100 5655 newbie->ipsacq_srcaddr = src;
5101 5656 newbie->ipsacq_dstaddr = dst;
5102 5657
|
↓ open down ↓ |
24 lines elided |
↑ open up ↑ |
5103 5658 /*
5104 5659 * If the acquire record has more than one queued packet, we've
5105 5660 * already sent an ACQUIRE, and don't need to repeat ourself.
5106 5661 */
5107 5662 if (newbie->ipsacq_seq != seq || newbie->ipsacq_numpackets > 1) {
5108 5663 /* I have an acquire outstanding already! */
5109 5664 mutex_exit(&newbie->ipsacq_lock);
5110 5665 return;
5111 5666 }
5112 5667
5113 - if (!keysock_extended_reg(ns))
5114 - goto punt_extended;
5668 + if (need_esp) {
5669 + ESP_BUMP_STAT(espstack, acquire_requests);
5670 + q = espstack->esp_pfkey_q;
5671 + } else {
5672 + /*
5673 + * Two cases get us here:
5674 + * 1.) AH-only policy.
5675 + *
5676 + * 2.) A continuation of an AH+ESP policy, and this is the
5677 + * post-ESP, AH-needs-to-send-a-regular-ACQUIRE case.
5678 + * (i.e. called from esp_do_outbound_ah().)
5679 + */
5680 + AH_BUMP_STAT(ahstack, acquire_requests);
5681 + q = ahstack->ah_pfkey_q;
5682 + }
5683 +
5115 5684 /*
5116 - * Construct an extended ACQUIRE. There are logging
5117 - * opportunities here in failure cases.
5685 + * Get selectors and other policy-expression bits needed for an
5686 + * ACQUIRE.
5118 5687 */
5119 5688 bzero(&sel, sizeof (sel));
5120 5689 sel.ips_isv4 = (ixa->ixa_flags & IXAF_IS_IPV4) != 0;
5121 5690 if (tunnel_mode) {
5122 5691 sel.ips_protocol = (ixa->ixa_ipsec_inaf == AF_INET) ?
5123 5692 IPPROTO_ENCAP : IPPROTO_IPV6;
5124 5693 } else {
5125 5694 sel.ips_protocol = ixa->ixa_ipsec_proto;
5126 5695 sel.ips_local_port = ixa->ixa_ipsec_src_port;
5127 5696 sel.ips_remote_port = ixa->ixa_ipsec_dst_port;
5128 5697 }
5129 5698 sel.ips_icmp_type = ixa->ixa_ipsec_icmp_type;
|
↓ open down ↓ |
2 lines elided |
↑ open up ↑ |
5130 5699 sel.ips_icmp_code = ixa->ixa_ipsec_icmp_code;
5131 5700 sel.ips_is_icmp_inv_acq = 0;
5132 5701 if (af == AF_INET) {
5133 5702 sel.ips_local_addr_v4 = ipha->ipha_src;
5134 5703 sel.ips_remote_addr_v4 = ipha->ipha_dst;
5135 5704 } else {
5136 5705 sel.ips_local_addr_v6 = ip6h->ip6_src;
5137 5706 sel.ips_remote_addr_v6 = ip6h->ip6_dst;
5138 5707 }
5139 5708
5140 - extended = sadb_keysock_out(0);
5141 - if (extended == NULL)
5142 - goto punt_extended;
5143 5709
5144 - if (ixa->ixa_tsl != NULL) {
5145 - /*
5146 - * XXX MLS correct condition here?
5147 - * XXX MLS other credential attributes in acquire?
5148 - * XXX malloc failure? don't fall back to original?
5149 - */
5150 - sens = sadb_make_sens_ext(ixa->ixa_tsl, &sens_len);
5710 + /*
5711 + * 1. Generate addresses, kmc, and sensitivity. These are "common"
5712 + * and should be an mblk pointed to by common. TBD -- eventually it
5713 + * will include triggering packet contents as more address extensions.
5714 + *
5715 + * 2. Generate ACQUIRE & KEYSOCK_OUT and single-protocol proposal.
5716 + * These are "regular" and "prop". String regular->b_cont->b_cont =
5717 + * common, common->b_cont = prop.
5718 + *
5719 + * 3. If extended register got turned on, generate EXT_ACQUIRE &
5720 + * KEYSOCK_OUT and multi-protocol eprop. These are "extended" and
5721 + * "eprop". String extended->b_cont->b_cont = dupb(common) and
5722 + * extended->b_cont->b_cont->b_cont = prop.
5723 + *
5724 + * 4. Deliver: putnext(q, regular) and if there, putnext(q, extended).
5725 + */
5151 5726
5152 - if (sens == NULL) {
5153 - freeb(extended);
5154 - goto punt_extended;
5155 - }
5156 - }
5727 + regular = extended = prop = eprop = NULL;
5157 5728
5158 - extended->b_cont = sadb_extended_acquire(&sel, pp, ap, tunnel_mode,
5159 - seq, 0, sens, ns);
5729 + common = sadb_acquire_msg_common(&sel, pp, ap, tunnel_mode, tsl, NULL);
5730 + if (common == NULL)
5731 + goto bail;
5160 5732
5161 - if (sens != NULL)
5162 - kmem_free(sens, sens_len);
5733 + regular = sadb_acquire_msg_base(0, (need_esp ?
5734 + SADB_SATYPE_ESP : SADB_SATYPE_AH), newbie->ipsacq_seq, 0);
5735 + if (regular == NULL)
5736 + goto bail;
5163 5737
5164 - if (extended->b_cont == NULL) {
5165 - freeb(extended);
5166 - goto punt_extended;
5167 - }
5738 + /*
5739 + * Pardon the boolean cleverness. At least one of need_* must be true.
5740 + * If they are equal, it's an AH & ESP policy and ESP needs to go
5741 + * first. If they aren't, just check the contents of need_esp.
5742 + */
5743 + prop = sadb_acquire_prop(ap, ns, need_esp);
5744 + if (prop == NULL)
5745 + goto bail;
5168 5746
5747 + /* Link the parts together. */
5748 + regular->b_cont->b_cont = common;
5749 + common->b_cont = prop;
5169 5750 /*
5170 - * Send an ACQUIRE message (and possible an extended ACQUIRE) based on
5171 - * this new record. The send-acquire callback assumes that acqrec is
5172 - * already locked.
5751 + * Prop is now linked, so don't freemsg() it if the extended
5752 + * construction goes off the rails.
5173 5753 */
5174 - (*spp->s_acqfn)(newbie, extended, ns);
5754 + prop = NULL;
5755 +
5756 + ((sadb_msg_t *)(regular->b_cont->b_rptr))->sadb_msg_len =
5757 + SADB_8TO64(msgsize(regular->b_cont));
5758 +
5759 + /*
5760 + * If we need an extended ACQUIRE, build it here.
5761 + */
5762 + if (keysock_extended_reg(ns)) {
5763 + /* NOTE: "common" still points to what we need. */
5764 + extended = sadb_acquire_msg_base(0, 0, newbie->ipsacq_seq, 0);
5765 + if (extended == NULL) {
5766 + common = NULL;
5767 + goto bail;
5768 + }
5769 +
5770 + extended->b_cont->b_cont = dupb(common);
5771 + common = NULL;
5772 + if (extended->b_cont->b_cont == NULL)
5773 + goto bail;
5774 +
5775 + eprop = sadb_acquire_extended_prop(ap, ns);
5776 + if (eprop == NULL)
5777 + goto bail;
5778 + extended->b_cont->b_cont->b_cont = eprop;
5779 +
5780 + ((sadb_msg_t *)(extended->b_cont->b_rptr))->sadb_msg_len =
5781 + SADB_8TO64(msgsize(extended->b_cont));
5782 + }
5783 +
5784 + /* So we don't hold a lock across putnext()... */
5785 + mutex_exit(&newbie->ipsacq_lock);
5786 +
5787 + if (extended != NULL)
5788 + putnext(q, extended);
5789 + ASSERT(regular != NULL);
5790 + putnext(q, regular);
5175 5791 return;
5176 5792
5177 -punt_extended:
5178 - (*spp->s_acqfn)(newbie, NULL, ns);
5793 +bail:
5794 + /* Make this acquire record go away quickly... */
5795 + newbie->ipsacq_expire = 0;
5796 + /* Exploit freemsg(NULL) being legal for fun & profit. */
5797 + freemsg(common);
5798 + freemsg(prop);
5799 + freemsg(extended);
5800 + freemsg(regular);
5801 + mutex_exit(&newbie->ipsacq_lock);
5179 5802 }
5180 5803
5181 5804 /*
5182 5805 * Unlink and free an acquire record.
5183 5806 */
5184 5807 void
5185 5808 sadb_destroy_acquire(ipsacq_t *acqrec, netstack_t *ns)
5186 5809 {
5187 5810 mblk_t *mp;
5188 5811 ipsec_stack_t *ipss = ns->netstack_ipsec;
5189 5812
5190 5813 ASSERT(MUTEX_HELD(acqrec->ipsacq_linklock));
5191 5814
5192 5815 if (acqrec->ipsacq_policy != NULL) {
5193 5816 IPPOL_REFRELE(acqrec->ipsacq_policy);
5194 5817 }
5195 5818 if (acqrec->ipsacq_act != NULL) {
5196 5819 IPACT_REFRELE(acqrec->ipsacq_act);
5197 5820 }
5198 5821
5199 5822 /* Unlink */
5200 5823 *(acqrec->ipsacq_ptpn) = acqrec->ipsacq_next;
5201 5824 if (acqrec->ipsacq_next != NULL)
5202 5825 acqrec->ipsacq_next->ipsacq_ptpn = acqrec->ipsacq_ptpn;
5203 5826
5204 5827 if (acqrec->ipsacq_tsl != NULL) {
5205 5828 label_rele(acqrec->ipsacq_tsl);
5206 5829 acqrec->ipsacq_tsl = NULL;
5207 5830 }
5208 5831
5209 5832 /*
5210 5833 * Free hanging mp's.
5211 5834 *
5212 5835 * XXX Instead of freemsg(), perhaps use IPSEC_REQ_FAILED.
5213 5836 */
5214 5837
5215 5838 mutex_enter(&acqrec->ipsacq_lock);
5216 5839 while (acqrec->ipsacq_mp != NULL) {
5217 5840 mp = acqrec->ipsacq_mp;
5218 5841 acqrec->ipsacq_mp = mp->b_next;
5219 5842 mp->b_next = NULL;
5220 5843 /* Freeing the async message */
5221 5844 mp = ip_xmit_attr_free_mblk(mp);
5222 5845 ip_drop_packet(mp, B_FALSE, NULL,
5223 5846 DROPPER(ipss, ipds_sadb_acquire_timeout),
5224 5847 &ipss->ipsec_sadb_dropper);
5225 5848 }
5226 5849 mutex_exit(&acqrec->ipsacq_lock);
5227 5850
5228 5851 /* Free */
5229 5852 mutex_destroy(&acqrec->ipsacq_lock);
5230 5853 kmem_free(acqrec, sizeof (*acqrec));
5231 5854 }
5232 5855
5233 5856 /*
5234 5857 * Destroy an acquire list fanout.
5235 5858 */
5236 5859 static void
5237 5860 sadb_destroy_acqlist(iacqf_t **listp, uint_t numentries, boolean_t forever,
5238 5861 netstack_t *ns)
5239 5862 {
5240 5863 int i;
5241 5864 iacqf_t *list = *listp;
5242 5865
5243 5866 if (list == NULL)
5244 5867 return;
5245 5868
5246 5869 for (i = 0; i < numentries; i++) {
5247 5870 mutex_enter(&(list[i].iacqf_lock));
5248 5871 while (list[i].iacqf_ipsacq != NULL)
5249 5872 sadb_destroy_acquire(list[i].iacqf_ipsacq, ns);
5250 5873 mutex_exit(&(list[i].iacqf_lock));
5251 5874 if (forever)
5252 5875 mutex_destroy(&(list[i].iacqf_lock));
5253 5876 }
5254 5877
5255 5878 if (forever) {
5256 5879 *listp = NULL;
5257 5880 kmem_free(list, numentries * sizeof (*list));
5258 5881 }
5259 5882 }
5260 5883
5261 5884 /*
5262 5885 * Create an algorithm descriptor for an extended ACQUIRE. Filter crypto
5263 5886 * framework's view of reality vs. IPsec's. EF's wins, BTW.
5264 5887 */
5265 5888 static uint8_t *
5266 5889 sadb_new_algdesc(uint8_t *start, uint8_t *limit,
5267 5890 sadb_x_ecomb_t *ecomb, uint8_t satype, uint8_t algtype,
5268 5891 uint8_t alg, uint16_t minbits, uint16_t maxbits, ipsec_stack_t *ipss)
5269 5892 {
5270 5893 uint8_t *cur = start;
5271 5894 ipsec_alginfo_t *algp;
5272 5895 sadb_x_algdesc_t *algdesc = (sadb_x_algdesc_t *)cur;
5273 5896
5274 5897 cur += sizeof (*algdesc);
5275 5898 if (cur >= limit)
5276 5899 return (NULL);
5277 5900
5278 5901 ecomb->sadb_x_ecomb_numalgs++;
5279 5902
5280 5903 /*
5281 5904 * Normalize vs. crypto framework's limits. This way, you can specify
5282 5905 * a stronger policy, and when the framework loads a stronger version,
5283 5906 * you can just keep plowing w/o rewhacking your SPD.
5284 5907 */
5285 5908 rw_enter(&ipss->ipsec_alg_lock, RW_READER);
5286 5909 algp = ipss->ipsec_alglists[(algtype == SADB_X_ALGTYPE_AUTH) ?
5287 5910 IPSEC_ALG_AUTH : IPSEC_ALG_ENCR][alg];
5288 5911 if (algp == NULL) {
5289 5912 rw_exit(&ipss->ipsec_alg_lock);
5290 5913 return (NULL); /* Algorithm doesn't exist. Fail gracefully. */
5291 5914 }
5292 5915 if (minbits < algp->alg_ef_minbits)
5293 5916 minbits = algp->alg_ef_minbits;
5294 5917 if (maxbits > algp->alg_ef_maxbits)
5295 5918 maxbits = algp->alg_ef_maxbits;
5296 5919 rw_exit(&ipss->ipsec_alg_lock);
5297 5920
5298 5921 algdesc->sadb_x_algdesc_reserved = SADB_8TO1(algp->alg_saltlen);
5299 5922 algdesc->sadb_x_algdesc_satype = satype;
5300 5923 algdesc->sadb_x_algdesc_algtype = algtype;
5301 5924 algdesc->sadb_x_algdesc_alg = alg;
5302 5925 algdesc->sadb_x_algdesc_minbits = minbits;
5303 5926 algdesc->sadb_x_algdesc_maxbits = maxbits;
5304 5927
5305 5928 return (cur);
5306 5929 }
5307 5930
5308 5931 /*
5309 5932 * Convert the given ipsec_action_t into an ecomb starting at *ecomb
5310 5933 * which must fit before *limit
5311 5934 *
5312 5935 * return NULL if we ran out of room or a pointer to the end of the ecomb.
5313 5936 */
5314 5937 static uint8_t *
5315 5938 sadb_action_to_ecomb(uint8_t *start, uint8_t *limit, ipsec_action_t *act,
5316 5939 netstack_t *ns)
5317 5940 {
5318 5941 uint8_t *cur = start;
5319 5942 sadb_x_ecomb_t *ecomb = (sadb_x_ecomb_t *)cur;
5320 5943 ipsec_prot_t *ipp;
5321 5944 ipsec_stack_t *ipss = ns->netstack_ipsec;
5322 5945
5323 5946 cur += sizeof (*ecomb);
5324 5947 if (cur >= limit)
5325 5948 return (NULL);
5326 5949
5327 5950 ASSERT(act->ipa_act.ipa_type == IPSEC_ACT_APPLY);
5328 5951
5329 5952 ipp = &act->ipa_act.ipa_apply;
5330 5953
5331 5954 ecomb->sadb_x_ecomb_numalgs = 0;
5332 5955 ecomb->sadb_x_ecomb_reserved = 0;
5333 5956 ecomb->sadb_x_ecomb_reserved2 = 0;
5334 5957 /*
5335 5958 * No limits on allocations, since we really don't support that
5336 5959 * concept currently.
5337 5960 */
5338 5961 ecomb->sadb_x_ecomb_soft_allocations = 0;
5339 5962 ecomb->sadb_x_ecomb_hard_allocations = 0;
5340 5963
5341 5964 /*
5342 5965 * XXX TBD: Policy or global parameters will eventually be
5343 5966 * able to fill in some of these.
5344 5967 */
5345 5968 ecomb->sadb_x_ecomb_flags = 0;
5346 5969 ecomb->sadb_x_ecomb_soft_bytes = 0;
5347 5970 ecomb->sadb_x_ecomb_hard_bytes = 0;
5348 5971 ecomb->sadb_x_ecomb_soft_addtime = 0;
5349 5972 ecomb->sadb_x_ecomb_hard_addtime = 0;
5350 5973 ecomb->sadb_x_ecomb_soft_usetime = 0;
5351 5974 ecomb->sadb_x_ecomb_hard_usetime = 0;
5352 5975
5353 5976 if (ipp->ipp_use_ah) {
5354 5977 cur = sadb_new_algdesc(cur, limit, ecomb,
5355 5978 SADB_SATYPE_AH, SADB_X_ALGTYPE_AUTH, ipp->ipp_auth_alg,
5356 5979 ipp->ipp_ah_minbits, ipp->ipp_ah_maxbits, ipss);
5357 5980 if (cur == NULL)
5358 5981 return (NULL);
5359 5982 ipsecah_fill_defs(ecomb, ns);
5360 5983 }
5361 5984
5362 5985 if (ipp->ipp_use_esp) {
5363 5986 if (ipp->ipp_use_espa) {
5364 5987 cur = sadb_new_algdesc(cur, limit, ecomb,
5365 5988 SADB_SATYPE_ESP, SADB_X_ALGTYPE_AUTH,
5366 5989 ipp->ipp_esp_auth_alg,
5367 5990 ipp->ipp_espa_minbits,
5368 5991 ipp->ipp_espa_maxbits, ipss);
5369 5992 if (cur == NULL)
5370 5993 return (NULL);
5371 5994 }
5372 5995
5373 5996 cur = sadb_new_algdesc(cur, limit, ecomb,
5374 5997 SADB_SATYPE_ESP, SADB_X_ALGTYPE_CRYPT,
5375 5998 ipp->ipp_encr_alg,
5376 5999 ipp->ipp_espe_minbits,
5377 6000 ipp->ipp_espe_maxbits, ipss);
5378 6001 if (cur == NULL)
5379 6002 return (NULL);
5380 6003 /* Fill in lifetimes if and only if AH didn't already... */
5381 6004 if (!ipp->ipp_use_ah)
5382 6005 ipsecesp_fill_defs(ecomb, ns);
5383 6006 }
5384 6007
5385 6008 return (cur);
5386 6009 }
5387 6010
5388 6011 #include <sys/tsol/label_macro.h> /* XXX should not need this */
5389 6012
5390 6013 /*
5391 6014 * From a cred_t, construct a sensitivity label extension
5392 6015 *
5393 6016 * We send up a fixed-size sensitivity label bitmap, and are perhaps
5394 6017 * overly chummy with the underlying data structures here.
5395 6018 */
5396 6019
5397 6020 /* ARGSUSED */
5398 6021 int
5399 6022 sadb_sens_len_from_label(ts_label_t *tsl)
5400 6023 {
5401 6024 int baselen = sizeof (sadb_sens_t) + _C_LEN * 4;
5402 6025 return (roundup(baselen, sizeof (uint64_t)));
5403 6026 }
5404 6027
5405 6028 void
5406 6029 sadb_sens_from_label(sadb_sens_t *sens, int exttype, ts_label_t *tsl,
5407 6030 int senslen)
5408 6031 {
5409 6032 uint8_t *bitmap;
5410 6033 bslabel_t *sl;
5411 6034
5412 6035 /* LINTED */
5413 6036 ASSERT((_C_LEN & 1) == 0);
5414 6037 ASSERT((senslen & 7) == 0);
5415 6038
5416 6039 sl = label2bslabel(tsl);
5417 6040
5418 6041 sens->sadb_sens_exttype = exttype;
5419 6042 sens->sadb_sens_len = SADB_8TO64(senslen);
5420 6043
5421 6044 sens->sadb_sens_dpd = tsl->tsl_doi;
|
↓ open down ↓ |
233 lines elided |
↑ open up ↑ |
5422 6045 sens->sadb_sens_sens_level = LCLASS(sl);
5423 6046 sens->sadb_sens_integ_level = 0; /* TBD */
5424 6047 sens->sadb_sens_sens_len = _C_LEN >> 1;
5425 6048 sens->sadb_sens_integ_len = 0; /* TBD */
5426 6049 sens->sadb_x_sens_flags = 0;
5427 6050
5428 6051 bitmap = (uint8_t *)(sens + 1);
5429 6052 bcopy(&(((_bslabel_impl_t *)sl)->compartments), bitmap, _C_LEN * 4);
5430 6053 }
5431 6054
5432 -static sadb_sens_t *
5433 -sadb_make_sens_ext(ts_label_t *tsl, int *len)
5434 -{
5435 - /* XXX allocation failure? */
5436 - int sens_len = sadb_sens_len_from_label(tsl);
5437 -
5438 - sadb_sens_t *sens = kmem_alloc(sens_len, KM_SLEEP);
5439 -
5440 - sadb_sens_from_label(sens, SADB_EXT_SENSITIVITY, tsl, sens_len);
5441 -
5442 - *len = sens_len;
5443 -
5444 - return (sens);
5445 -}
5446 -
5447 6055 /*
5448 6056 * Okay, how do we report errors/invalid labels from this?
5449 6057 * With a special designated "not a label" cred_t ?
5450 6058 */
5451 6059 /* ARGSUSED */
5452 6060 ts_label_t *
5453 6061 sadb_label_from_sens(sadb_sens_t *sens, uint64_t *bitmap)
5454 6062 {
5455 6063 int bitmap_len = SADB_64TO8(sens->sadb_sens_sens_len);
5456 6064 bslabel_t sl;
5457 6065 ts_label_t *tsl;
5458 6066
5459 6067 if (sens->sadb_sens_integ_level != 0)
5460 6068 return (NULL);
5461 6069 if (sens->sadb_sens_integ_len != 0)
5462 6070 return (NULL);
5463 6071 if (bitmap_len > _C_LEN * 4)
5464 6072 return (NULL);
5465 6073
5466 6074 bsllow(&sl);
5467 6075 LCLASS_SET((_bslabel_impl_t *)&sl, sens->sadb_sens_sens_level);
5468 6076 bcopy(bitmap, &((_bslabel_impl_t *)&sl)->compartments,
5469 6077 bitmap_len);
5470 6078
5471 6079 tsl = labelalloc(&sl, sens->sadb_sens_dpd, KM_NOSLEEP);
5472 6080 if (tsl == NULL)
|
↓ open down ↓ |
16 lines elided |
↑ open up ↑ |
5473 6081 return (NULL);
5474 6082
5475 6083 if (sens->sadb_x_sens_flags & SADB_X_SENS_UNLABELED)
5476 6084 tsl->tsl_flags |= TSLF_UNLABELED;
5477 6085 return (tsl);
5478 6086 }
5479 6087
5480 6088 /* End XXX label-library-leakage */
5481 6089
5482 6090 /*
5483 - * Construct an extended ACQUIRE message based on a selector and the resulting
5484 - * IPsec action.
5485 - *
5486 - * NOTE: This is used by both inverse ACQUIRE and actual ACQUIRE
5487 - * generation. As a consequence, expect this function to evolve
5488 - * rapidly.
5489 - */
5490 -static mblk_t *
5491 -sadb_extended_acquire(ipsec_selector_t *sel, ipsec_policy_t *pol,
5492 - ipsec_action_t *act, boolean_t tunnel_mode, uint32_t seq, uint32_t pid,
5493 - sadb_sens_t *sens, netstack_t *ns)
5494 -{
5495 - mblk_t *mp;
5496 - sadb_msg_t *samsg;
5497 - uint8_t *start, *cur, *end;
5498 - uint32_t *saddrptr, *daddrptr;
5499 - sa_family_t af;
5500 - sadb_prop_t *eprop;
5501 - ipsec_action_t *ap, *an;
5502 - ipsec_selkey_t *ipsl;
5503 - uint8_t proto, pfxlen;
5504 - uint16_t lport, rport;
5505 - uint32_t kmp, kmc;
5506 -
5507 - /*
5508 - * Find the action we want sooner rather than later..
5509 - */
5510 - an = NULL;
5511 - if (pol == NULL) {
5512 - ap = act;
5513 - } else {
5514 - ap = pol->ipsp_act;
5515 -
5516 - if (ap != NULL)
5517 - an = ap->ipa_next;
5518 - }
5519 -
5520 - /*
5521 - * Just take a swag for the allocation for now. We can always
5522 - * alter it later.
5523 - */
5524 -#define SADB_EXTENDED_ACQUIRE_SIZE 4096
5525 - mp = allocb(SADB_EXTENDED_ACQUIRE_SIZE, BPRI_HI);
5526 - if (mp == NULL)
5527 - return (NULL);
5528 -
5529 - start = mp->b_rptr;
5530 - end = start + SADB_EXTENDED_ACQUIRE_SIZE;
5531 -
5532 - cur = start;
5533 -
5534 - samsg = (sadb_msg_t *)cur;
5535 - cur += sizeof (*samsg);
5536 -
5537 - samsg->sadb_msg_version = PF_KEY_V2;
5538 - samsg->sadb_msg_type = SADB_ACQUIRE;
5539 - samsg->sadb_msg_errno = 0;
5540 - samsg->sadb_msg_reserved = 0;
5541 - samsg->sadb_msg_satype = 0;
5542 - samsg->sadb_msg_seq = seq;
5543 - samsg->sadb_msg_pid = pid;
5544 -
5545 - if (tunnel_mode) {
5546 - /*
5547 - * Form inner address extensions based NOT on the inner
5548 - * selectors (i.e. the packet data), but on the policy's
5549 - * selector key (i.e. the policy's selector information).
5550 - *
5551 - * NOTE: The position of IPv4 and IPv6 addresses is the
5552 - * same in ipsec_selkey_t (unless the compiler does very
5553 - * strange things with unions, consult your local C language
5554 - * lawyer for details).
5555 - */
5556 - ASSERT(pol != NULL);
5557 -
5558 - ipsl = &(pol->ipsp_sel->ipsl_key);
5559 - if (ipsl->ipsl_valid & IPSL_IPV4) {
5560 - af = AF_INET;
5561 - ASSERT(sel->ips_protocol == IPPROTO_ENCAP);
5562 - ASSERT(!(ipsl->ipsl_valid & IPSL_IPV6));
5563 - } else {
5564 - af = AF_INET6;
5565 - ASSERT(sel->ips_protocol == IPPROTO_IPV6);
5566 - ASSERT(ipsl->ipsl_valid & IPSL_IPV6);
5567 - }
5568 -
5569 - if (ipsl->ipsl_valid & IPSL_LOCAL_ADDR) {
5570 - saddrptr = (uint32_t *)(&ipsl->ipsl_local);
5571 - pfxlen = ipsl->ipsl_local_pfxlen;
5572 - } else {
5573 - saddrptr = (uint32_t *)(&ipv6_all_zeros);
5574 - pfxlen = 0;
5575 - }
5576 - /* XXX What about ICMP type/code? */
5577 - lport = (ipsl->ipsl_valid & IPSL_LOCAL_PORT) ?
5578 - ipsl->ipsl_lport : 0;
5579 - proto = (ipsl->ipsl_valid & IPSL_PROTOCOL) ?
5580 - ipsl->ipsl_proto : 0;
5581 -
5582 - cur = sadb_make_addr_ext(cur, end, SADB_X_EXT_ADDRESS_INNER_SRC,
5583 - af, saddrptr, lport, proto, pfxlen);
5584 - if (cur == NULL) {
5585 - freeb(mp);
5586 - return (NULL);
5587 - }
5588 -
5589 - if (ipsl->ipsl_valid & IPSL_REMOTE_ADDR) {
5590 - daddrptr = (uint32_t *)(&ipsl->ipsl_remote);
5591 - pfxlen = ipsl->ipsl_remote_pfxlen;
5592 - } else {
5593 - daddrptr = (uint32_t *)(&ipv6_all_zeros);
5594 - pfxlen = 0;
5595 - }
5596 - /* XXX What about ICMP type/code? */
5597 - rport = (ipsl->ipsl_valid & IPSL_REMOTE_PORT) ?
5598 - ipsl->ipsl_rport : 0;
5599 -
5600 - cur = sadb_make_addr_ext(cur, end, SADB_X_EXT_ADDRESS_INNER_DST,
5601 - af, daddrptr, rport, proto, pfxlen);
5602 - if (cur == NULL) {
5603 - freeb(mp);
5604 - return (NULL);
5605 - }
5606 - /*
5607 - * TODO - if we go to 3408's dream of transport mode IP-in-IP
5608 - * _with_ inner-packet address selectors, we'll need to further
5609 - * distinguish tunnel mode here. For now, having inner
5610 - * addresses and/or ports is sufficient.
5611 - *
5612 - * Meanwhile, whack proto/ports to reflect IP-in-IP for the
5613 - * outer addresses.
5614 - */
5615 - proto = sel->ips_protocol; /* Either _ENCAP or _IPV6 */
5616 - lport = rport = 0;
5617 - } else if ((ap != NULL) && (!ap->ipa_want_unique)) {
5618 - proto = 0;
5619 - lport = 0;
5620 - rport = 0;
5621 - if (pol != NULL) {
5622 - ipsl = &(pol->ipsp_sel->ipsl_key);
5623 - if (ipsl->ipsl_valid & IPSL_PROTOCOL)
5624 - proto = ipsl->ipsl_proto;
5625 - if (ipsl->ipsl_valid & IPSL_REMOTE_PORT)
5626 - rport = ipsl->ipsl_rport;
5627 - if (ipsl->ipsl_valid & IPSL_LOCAL_PORT)
5628 - lport = ipsl->ipsl_lport;
5629 - }
5630 - } else {
5631 - proto = sel->ips_protocol;
5632 - lport = sel->ips_local_port;
5633 - rport = sel->ips_remote_port;
5634 - }
5635 -
5636 - af = sel->ips_isv4 ? AF_INET : AF_INET6;
5637 -
5638 - /*
5639 - * NOTE: The position of IPv4 and IPv6 addresses is the same in
5640 - * ipsec_selector_t.
5641 - */
5642 - cur = sadb_make_addr_ext(cur, end, SADB_EXT_ADDRESS_SRC, af,
5643 - (uint32_t *)(&sel->ips_local_addr_v6), lport, proto, 0);
5644 -
5645 - if (cur == NULL) {
5646 - freeb(mp);
5647 - return (NULL);
5648 - }
5649 -
5650 - cur = sadb_make_addr_ext(cur, end, SADB_EXT_ADDRESS_DST, af,
5651 - (uint32_t *)(&sel->ips_remote_addr_v6), rport, proto, 0);
5652 -
5653 - if (cur == NULL) {
5654 - freeb(mp);
5655 - return (NULL);
5656 - }
5657 -
5658 - if (sens != NULL) {
5659 - uint8_t *sensext = cur;
5660 - int senslen = SADB_64TO8(sens->sadb_sens_len);
5661 -
5662 - cur += senslen;
5663 - if (cur > end) {
5664 - freeb(mp);
5665 - return (NULL);
5666 - }
5667 - bcopy(sens, sensext, senslen);
5668 - }
5669 -
5670 - /*
5671 - * This section will change a lot as policy evolves.
5672 - * For now, it'll be relatively simple.
5673 - */
5674 - eprop = (sadb_prop_t *)cur;
5675 - cur += sizeof (*eprop);
5676 - if (cur > end) {
5677 - /* no space left */
5678 - freeb(mp);
5679 - return (NULL);
5680 - }
5681 -
5682 - eprop->sadb_prop_exttype = SADB_X_EXT_EPROP;
5683 - eprop->sadb_x_prop_ereserved = 0;
5684 - eprop->sadb_x_prop_numecombs = 0;
5685 - eprop->sadb_prop_replay = 32; /* default */
5686 -
5687 - kmc = kmp = 0;
5688 -
5689 - for (; ap != NULL; ap = an) {
5690 - an = (pol != NULL) ? ap->ipa_next : NULL;
5691 -
5692 - /*
5693 - * Skip non-IPsec policies
5694 - */
5695 - if (ap->ipa_act.ipa_type != IPSEC_ACT_APPLY)
5696 - continue;
5697 -
5698 - if (ap->ipa_act.ipa_apply.ipp_km_proto)
5699 - kmp = ap->ipa_act.ipa_apply.ipp_km_proto;
5700 - if (ap->ipa_act.ipa_apply.ipp_km_cookie)
5701 - kmc = ap->ipa_act.ipa_apply.ipp_km_cookie;
5702 - if (ap->ipa_act.ipa_apply.ipp_replay_depth) {
5703 - eprop->sadb_prop_replay =
5704 - ap->ipa_act.ipa_apply.ipp_replay_depth;
5705 - }
5706 -
5707 - cur = sadb_action_to_ecomb(cur, end, ap, ns);
5708 - if (cur == NULL) { /* no space */
5709 - freeb(mp);
5710 - return (NULL);
5711 - }
5712 - eprop->sadb_x_prop_numecombs++;
5713 - }
5714 -
5715 - if (eprop->sadb_x_prop_numecombs == 0) {
5716 - /*
5717 - * This will happen if we fail to find a policy
5718 - * allowing for IPsec processing.
5719 - * Construct an error message.
5720 - */
5721 - samsg->sadb_msg_len = SADB_8TO64(sizeof (*samsg));
5722 - samsg->sadb_msg_errno = ENOENT;
5723 - samsg->sadb_x_msg_diagnostic = 0;
5724 - return (mp);
5725 - }
5726 -
5727 - if ((kmp != 0) || (kmc != 0)) {
5728 - cur = sadb_make_kmc_ext(cur, end, kmp, kmc);
5729 - if (cur == NULL) {
5730 - freeb(mp);
5731 - return (NULL);
5732 - }
5733 - }
5734 -
5735 - eprop->sadb_prop_len = SADB_8TO64(cur - (uint8_t *)eprop);
5736 - samsg->sadb_msg_len = SADB_8TO64(cur - start);
5737 - mp->b_wptr = cur;
5738 -
5739 - return (mp);
5740 -}
5741 -
5742 -/*
5743 - * Generic setup of an RFC 2367 ACQUIRE message. Caller sets satype.
5744 - *
5745 - * NOTE: This function acquires alg_lock as a side-effect if-and-only-if we
5746 - * succeed (i.e. return non-NULL). Caller MUST release it. This is to
5747 - * maximize code consolidation while preventing algorithm changes from messing
5748 - * with the callers finishing touches on the ACQUIRE itself.
5749 - */
5750 -mblk_t *
5751 -sadb_setup_acquire(ipsacq_t *acqrec, uint8_t satype, ipsec_stack_t *ipss)
5752 -{
5753 - uint_t allocsize;
5754 - mblk_t *pfkeymp, *msgmp;
5755 - sa_family_t af;
5756 - uint8_t *cur, *end;
5757 - sadb_msg_t *samsg;
5758 - uint16_t sport_typecode;
5759 - uint16_t dport_typecode;
5760 - uint8_t check_proto;
5761 - boolean_t tunnel_mode = (acqrec->ipsacq_inneraddrfam != 0);
5762 -
5763 - ASSERT(MUTEX_HELD(&acqrec->ipsacq_lock));
5764 -
5765 - pfkeymp = sadb_keysock_out(0);
5766 - if (pfkeymp == NULL)
5767 - return (NULL);
5768 -
5769 - /*
5770 - * First, allocate a basic ACQUIRE message
5771 - */
5772 - allocsize = sizeof (sadb_msg_t) + sizeof (sadb_address_t) +
5773 - sizeof (sadb_address_t) + sizeof (sadb_prop_t);
5774 -
5775 - /* Make sure there's enough to cover both AF_INET and AF_INET6. */
5776 - allocsize += 2 * sizeof (struct sockaddr_in6);
5777 -
5778 - rw_enter(&ipss->ipsec_alg_lock, RW_READER);
5779 - /* NOTE: The lock is now held through to this function's return. */
5780 - allocsize += ipss->ipsec_nalgs[IPSEC_ALG_AUTH] *
5781 - ipss->ipsec_nalgs[IPSEC_ALG_ENCR] * sizeof (sadb_comb_t);
5782 -
5783 - if (tunnel_mode) {
5784 - /* Tunnel mode! */
5785 - allocsize += 2 * sizeof (sadb_address_t);
5786 - /* Enough to cover both AF_INET and AF_INET6. */
5787 - allocsize += 2 * sizeof (struct sockaddr_in6);
5788 - }
5789 -
5790 - msgmp = allocb(allocsize, BPRI_HI);
5791 - if (msgmp == NULL) {
5792 - freeb(pfkeymp);
5793 - rw_exit(&ipss->ipsec_alg_lock);
5794 - return (NULL);
5795 - }
5796 -
5797 - pfkeymp->b_cont = msgmp;
5798 - cur = msgmp->b_rptr;
5799 - end = cur + allocsize;
5800 - samsg = (sadb_msg_t *)cur;
5801 - cur += sizeof (sadb_msg_t);
5802 -
5803 - af = acqrec->ipsacq_addrfam;
5804 - switch (af) {
5805 - case AF_INET:
5806 - check_proto = IPPROTO_ICMP;
5807 - break;
5808 - case AF_INET6:
5809 - check_proto = IPPROTO_ICMPV6;
5810 - break;
5811 - default:
5812 - /* This should never happen unless we have kernel bugs. */
5813 - cmn_err(CE_WARN,
5814 - "sadb_setup_acquire: corrupt ACQUIRE record.\n");
5815 - ASSERT(0);
5816 - rw_exit(&ipss->ipsec_alg_lock);
5817 - return (NULL);
5818 - }
5819 -
5820 - samsg->sadb_msg_version = PF_KEY_V2;
5821 - samsg->sadb_msg_type = SADB_ACQUIRE;
5822 - samsg->sadb_msg_satype = satype;
5823 - samsg->sadb_msg_errno = 0;
5824 - samsg->sadb_msg_pid = 0;
5825 - samsg->sadb_msg_reserved = 0;
5826 - samsg->sadb_msg_seq = acqrec->ipsacq_seq;
5827 -
5828 - ASSERT(MUTEX_HELD(&acqrec->ipsacq_lock));
5829 -
5830 - if ((acqrec->ipsacq_proto == check_proto) || tunnel_mode) {
5831 - sport_typecode = dport_typecode = 0;
5832 - } else {
5833 - sport_typecode = acqrec->ipsacq_srcport;
5834 - dport_typecode = acqrec->ipsacq_dstport;
5835 - }
5836 -
5837 - cur = sadb_make_addr_ext(cur, end, SADB_EXT_ADDRESS_SRC, af,
5838 - acqrec->ipsacq_srcaddr, sport_typecode, acqrec->ipsacq_proto, 0);
5839 -
5840 - cur = sadb_make_addr_ext(cur, end, SADB_EXT_ADDRESS_DST, af,
5841 - acqrec->ipsacq_dstaddr, dport_typecode, acqrec->ipsacq_proto, 0);
5842 -
5843 - if (tunnel_mode) {
5844 - sport_typecode = acqrec->ipsacq_srcport;
5845 - dport_typecode = acqrec->ipsacq_dstport;
5846 - cur = sadb_make_addr_ext(cur, end, SADB_X_EXT_ADDRESS_INNER_SRC,
5847 - acqrec->ipsacq_inneraddrfam, acqrec->ipsacq_innersrc,
5848 - sport_typecode, acqrec->ipsacq_inner_proto,
5849 - acqrec->ipsacq_innersrcpfx);
5850 - cur = sadb_make_addr_ext(cur, end, SADB_X_EXT_ADDRESS_INNER_DST,
5851 - acqrec->ipsacq_inneraddrfam, acqrec->ipsacq_innerdst,
5852 - dport_typecode, acqrec->ipsacq_inner_proto,
5853 - acqrec->ipsacq_innerdstpfx);
5854 - }
5855 -
5856 - /* XXX Insert identity information here. */
5857 -
5858 - /* XXXMLS Insert sensitivity information here. */
5859 -
5860 - if (cur != NULL)
5861 - samsg->sadb_msg_len = SADB_8TO64(cur - msgmp->b_rptr);
5862 - else
5863 - rw_exit(&ipss->ipsec_alg_lock);
5864 -
5865 - return (pfkeymp);
5866 -}
5867 -
5868 -/*
5869 6091 * Given an SADB_GETSPI message, find an appropriately ranged SA and
5870 6092 * allocate an SA. If there are message improprieties, return (ipsa_t *)-1.
5871 6093 * If there was a memory allocation error, return NULL. (Assume NULL !=
5872 6094 * (ipsa_t *)-1).
5873 6095 *
5874 6096 * master_spi is passed in host order.
5875 6097 */
5876 6098 ipsa_t *
5877 6099 sadb_getspi(keysock_in_t *ksi, uint32_t master_spi, int *diagnostic,
5878 6100 netstack_t *ns, uint_t sa_type)
5879 6101 {
5880 6102 sadb_address_t *src =
5881 6103 (sadb_address_t *)ksi->ks_in_extv[SADB_EXT_ADDRESS_SRC],
5882 6104 *dst = (sadb_address_t *)ksi->ks_in_extv[SADB_EXT_ADDRESS_DST];
5883 6105 sadb_spirange_t *range =
5884 6106 (sadb_spirange_t *)ksi->ks_in_extv[SADB_EXT_SPIRANGE];
5885 6107 struct sockaddr_in *ssa, *dsa;
5886 6108 struct sockaddr_in6 *ssa6, *dsa6;
5887 6109 uint32_t *srcaddr, *dstaddr;
5888 6110 sa_family_t af;
5889 6111 uint32_t add, min, max;
5890 6112 uint8_t protocol =
5891 6113 (sa_type == SADB_SATYPE_AH) ? IPPROTO_AH : IPPROTO_ESP;
5892 6114
5893 6115 if (src == NULL) {
5894 6116 *diagnostic = SADB_X_DIAGNOSTIC_MISSING_SRC;
5895 6117 return ((ipsa_t *)-1);
5896 6118 }
5897 6119 if (dst == NULL) {
5898 6120 *diagnostic = SADB_X_DIAGNOSTIC_MISSING_DST;
5899 6121 return ((ipsa_t *)-1);
5900 6122 }
5901 6123 if (range == NULL) {
5902 6124 *diagnostic = SADB_X_DIAGNOSTIC_MISSING_RANGE;
5903 6125 return ((ipsa_t *)-1);
5904 6126 }
5905 6127
5906 6128 min = ntohl(range->sadb_spirange_min);
5907 6129 max = ntohl(range->sadb_spirange_max);
5908 6130 dsa = (struct sockaddr_in *)(dst + 1);
5909 6131 dsa6 = (struct sockaddr_in6 *)dsa;
5910 6132
5911 6133 ssa = (struct sockaddr_in *)(src + 1);
5912 6134 ssa6 = (struct sockaddr_in6 *)ssa;
5913 6135 ASSERT(dsa->sin_family == ssa->sin_family);
5914 6136
5915 6137 srcaddr = ALL_ZEROES_PTR;
5916 6138 af = dsa->sin_family;
5917 6139 switch (af) {
5918 6140 case AF_INET:
5919 6141 if (src != NULL)
5920 6142 srcaddr = (uint32_t *)(&ssa->sin_addr);
5921 6143 dstaddr = (uint32_t *)(&dsa->sin_addr);
5922 6144 break;
5923 6145 case AF_INET6:
5924 6146 if (src != NULL)
5925 6147 srcaddr = (uint32_t *)(&ssa6->sin6_addr);
5926 6148 dstaddr = (uint32_t *)(&dsa6->sin6_addr);
5927 6149 break;
5928 6150 default:
5929 6151 *diagnostic = SADB_X_DIAGNOSTIC_BAD_DST_AF;
5930 6152 return ((ipsa_t *)-1);
5931 6153 }
5932 6154
5933 6155 if (master_spi < min || master_spi > max) {
5934 6156 /* Return a random value in the range. */
5935 6157 if (cl_inet_getspi) {
5936 6158 cl_inet_getspi(ns->netstack_stackid, protocol,
5937 6159 (uint8_t *)&add, sizeof (add), NULL);
5938 6160 } else {
5939 6161 (void) random_get_pseudo_bytes((uint8_t *)&add,
5940 6162 sizeof (add));
5941 6163 }
5942 6164 master_spi = min + (add % (max - min + 1));
5943 6165 }
5944 6166
5945 6167 /*
5946 6168 * Since master_spi is passed in host order, we need to htonl() it
5947 6169 * for the purposes of creating a new SA.
5948 6170 */
5949 6171 return (sadb_makelarvalassoc(htonl(master_spi), srcaddr, dstaddr, af,
5950 6172 ns));
5951 6173 }
5952 6174
5953 6175 /*
5954 6176 *
5955 6177 * Locate an ACQUIRE and nuke it. If I have an samsg that's larger than the
5956 6178 * base header, just ignore it. Otherwise, lock down the whole ACQUIRE list
5957 6179 * and scan for the sequence number in question. I may wish to accept an
5958 6180 * address pair with it, for easier searching.
5959 6181 *
5960 6182 * Caller frees the message, so we don't have to here.
5961 6183 *
5962 6184 * NOTE: The pfkey_q parameter may be used in the future for ACQUIRE
5963 6185 * failures.
5964 6186 */
5965 6187 /* ARGSUSED */
5966 6188 void
5967 6189 sadb_in_acquire(sadb_msg_t *samsg, sadbp_t *sp, queue_t *pfkey_q,
5968 6190 netstack_t *ns)
5969 6191 {
5970 6192 int i;
5971 6193 ipsacq_t *acqrec;
5972 6194 iacqf_t *bucket;
5973 6195
5974 6196 /*
5975 6197 * I only accept the base header for this!
5976 6198 * Though to be honest, requiring the dst address would help
5977 6199 * immensely.
5978 6200 *
5979 6201 * XXX There are already cases where I can get the dst address.
5980 6202 */
5981 6203 if (samsg->sadb_msg_len > SADB_8TO64(sizeof (*samsg)))
5982 6204 return;
5983 6205
5984 6206 /*
5985 6207 * Using the samsg->sadb_msg_seq, find the ACQUIRE record, delete it,
5986 6208 * (and in the future send a message to IP with the appropriate error
5987 6209 * number).
5988 6210 *
5989 6211 * Q: Do I want to reject if pid != 0?
5990 6212 */
5991 6213
5992 6214 for (i = 0; i < sp->s_v4.sdb_hashsize; i++) {
5993 6215 bucket = &sp->s_v4.sdb_acq[i];
5994 6216 mutex_enter(&bucket->iacqf_lock);
5995 6217 for (acqrec = bucket->iacqf_ipsacq; acqrec != NULL;
5996 6218 acqrec = acqrec->ipsacq_next) {
5997 6219 if (samsg->sadb_msg_seq == acqrec->ipsacq_seq)
5998 6220 break; /* for acqrec... loop. */
5999 6221 }
6000 6222 if (acqrec != NULL)
6001 6223 break; /* for i = 0... loop. */
6002 6224
6003 6225 mutex_exit(&bucket->iacqf_lock);
6004 6226 }
6005 6227
6006 6228 if (acqrec == NULL) {
6007 6229 for (i = 0; i < sp->s_v6.sdb_hashsize; i++) {
6008 6230 bucket = &sp->s_v6.sdb_acq[i];
6009 6231 mutex_enter(&bucket->iacqf_lock);
6010 6232 for (acqrec = bucket->iacqf_ipsacq; acqrec != NULL;
6011 6233 acqrec = acqrec->ipsacq_next) {
6012 6234 if (samsg->sadb_msg_seq == acqrec->ipsacq_seq)
6013 6235 break; /* for acqrec... loop. */
6014 6236 }
6015 6237 if (acqrec != NULL)
6016 6238 break; /* for i = 0... loop. */
6017 6239
6018 6240 mutex_exit(&bucket->iacqf_lock);
6019 6241 }
6020 6242 }
6021 6243
6022 6244
6023 6245 if (acqrec == NULL)
6024 6246 return;
6025 6247
6026 6248 /*
6027 6249 * What do I do with the errno and IP? I may need mp's services a
6028 6250 * little more. See sadb_destroy_acquire() for future directions
6029 6251 * beyond free the mblk chain on the acquire record.
6030 6252 */
6031 6253
6032 6254 ASSERT(&bucket->iacqf_lock == acqrec->ipsacq_linklock);
6033 6255 sadb_destroy_acquire(acqrec, ns);
6034 6256 /* Have to exit mutex here, because of breaking out of for loop. */
6035 6257 mutex_exit(&bucket->iacqf_lock);
6036 6258 }
6037 6259
6038 6260 /*
6039 6261 * The following functions work with the replay windows of an SA. They assume
6040 6262 * the ipsa->ipsa_replay_arr is an array of uint64_t, and that the bit vector
6041 6263 * represents the highest sequence number packet received, and back
6042 6264 * (ipsa->ipsa_replay_wsize) packets.
6043 6265 */
6044 6266
6045 6267 /*
6046 6268 * Is the replay bit set?
6047 6269 */
6048 6270 static boolean_t
6049 6271 ipsa_is_replay_set(ipsa_t *ipsa, uint32_t offset)
6050 6272 {
6051 6273 uint64_t bit = (uint64_t)1 << (uint64_t)(offset & 63);
6052 6274
6053 6275 return ((bit & ipsa->ipsa_replay_arr[offset >> 6]) ? B_TRUE : B_FALSE);
6054 6276 }
6055 6277
6056 6278 /*
6057 6279 * Shift the bits of the replay window over.
6058 6280 */
6059 6281 static void
6060 6282 ipsa_shift_replay(ipsa_t *ipsa, uint32_t shift)
6061 6283 {
6062 6284 int i;
6063 6285 int jump = ((shift - 1) >> 6) + 1;
6064 6286
6065 6287 if (shift == 0)
6066 6288 return;
6067 6289
6068 6290 for (i = (ipsa->ipsa_replay_wsize - 1) >> 6; i >= 0; i--) {
6069 6291 if (i + jump <= (ipsa->ipsa_replay_wsize - 1) >> 6) {
6070 6292 ipsa->ipsa_replay_arr[i + jump] |=
6071 6293 ipsa->ipsa_replay_arr[i] >> (64 - (shift & 63));
6072 6294 }
6073 6295 ipsa->ipsa_replay_arr[i] <<= shift;
6074 6296 }
6075 6297 }
6076 6298
6077 6299 /*
6078 6300 * Set a bit in the bit vector.
6079 6301 */
6080 6302 static void
6081 6303 ipsa_set_replay(ipsa_t *ipsa, uint32_t offset)
6082 6304 {
6083 6305 uint64_t bit = (uint64_t)1 << (uint64_t)(offset & 63);
6084 6306
6085 6307 ipsa->ipsa_replay_arr[offset >> 6] |= bit;
6086 6308 }
6087 6309
6088 6310 #define SADB_MAX_REPLAY_VALUE 0xffffffff
6089 6311
6090 6312 /*
6091 6313 * Assume caller has NOT done ntohl() already on seq. Check to see
6092 6314 * if replay sequence number "seq" has been seen already.
6093 6315 */
6094 6316 boolean_t
6095 6317 sadb_replay_check(ipsa_t *ipsa, uint32_t seq)
6096 6318 {
6097 6319 boolean_t rc;
6098 6320 uint32_t diff;
6099 6321
6100 6322 if (ipsa->ipsa_replay_wsize == 0)
6101 6323 return (B_TRUE);
6102 6324
6103 6325 /*
6104 6326 * NOTE: I've already checked for 0 on the wire in sadb_replay_peek().
6105 6327 */
6106 6328
6107 6329 /* Convert sequence number into host order before holding the mutex. */
6108 6330 seq = ntohl(seq);
6109 6331
6110 6332 mutex_enter(&ipsa->ipsa_lock);
6111 6333
6112 6334 /* Initialize inbound SA's ipsa_replay field to last one received. */
6113 6335 if (ipsa->ipsa_replay == 0)
6114 6336 ipsa->ipsa_replay = 1;
6115 6337
6116 6338 if (seq > ipsa->ipsa_replay) {
6117 6339 /*
6118 6340 * I have received a new "highest value received". Shift
6119 6341 * the replay window over.
6120 6342 */
6121 6343 diff = seq - ipsa->ipsa_replay;
6122 6344 if (diff < ipsa->ipsa_replay_wsize) {
6123 6345 /* In replay window, shift bits over. */
6124 6346 ipsa_shift_replay(ipsa, diff);
6125 6347 } else {
6126 6348 /* WAY FAR AHEAD, clear bits and start again. */
6127 6349 bzero(ipsa->ipsa_replay_arr,
6128 6350 sizeof (ipsa->ipsa_replay_arr));
6129 6351 }
6130 6352 ipsa_set_replay(ipsa, 0);
6131 6353 ipsa->ipsa_replay = seq;
6132 6354 rc = B_TRUE;
6133 6355 goto done;
6134 6356 }
6135 6357 diff = ipsa->ipsa_replay - seq;
6136 6358 if (diff >= ipsa->ipsa_replay_wsize || ipsa_is_replay_set(ipsa, diff)) {
6137 6359 rc = B_FALSE;
6138 6360 goto done;
6139 6361 }
6140 6362 /* Set this packet as seen. */
6141 6363 ipsa_set_replay(ipsa, diff);
6142 6364
6143 6365 rc = B_TRUE;
6144 6366 done:
6145 6367 mutex_exit(&ipsa->ipsa_lock);
6146 6368 return (rc);
6147 6369 }
6148 6370
6149 6371 /*
6150 6372 * "Peek" and see if we should even bother going through the effort of
6151 6373 * running an authentication check on the sequence number passed in.
6152 6374 * this takes into account packets that are below the replay window,
6153 6375 * and collisions with already replayed packets. Return B_TRUE if it
6154 6376 * is okay to proceed, B_FALSE if this packet should be dropped immediately.
6155 6377 * Assume same byte-ordering as sadb_replay_check.
6156 6378 */
6157 6379 boolean_t
6158 6380 sadb_replay_peek(ipsa_t *ipsa, uint32_t seq)
6159 6381 {
6160 6382 boolean_t rc = B_FALSE;
6161 6383 uint32_t diff;
6162 6384
6163 6385 if (ipsa->ipsa_replay_wsize == 0)
6164 6386 return (B_TRUE);
6165 6387
6166 6388 /*
6167 6389 * 0 is 0, regardless of byte order... :)
6168 6390 *
6169 6391 * If I get 0 on the wire (and there is a replay window) then the
6170 6392 * sender most likely wrapped. This ipsa may need to be marked or
6171 6393 * something.
6172 6394 */
6173 6395 if (seq == 0)
6174 6396 return (B_FALSE);
6175 6397
6176 6398 seq = ntohl(seq);
6177 6399 mutex_enter(&ipsa->ipsa_lock);
6178 6400 if (seq < ipsa->ipsa_replay - ipsa->ipsa_replay_wsize &&
6179 6401 ipsa->ipsa_replay >= ipsa->ipsa_replay_wsize)
6180 6402 goto done;
6181 6403
6182 6404 /*
6183 6405 * If I've hit 0xffffffff, then quite honestly, I don't need to
6184 6406 * bother with formalities. I'm not accepting any more packets
6185 6407 * on this SA.
6186 6408 */
6187 6409 if (ipsa->ipsa_replay == SADB_MAX_REPLAY_VALUE) {
6188 6410 /*
6189 6411 * Since we're already holding the lock, update the
6190 6412 * expire time ala. sadb_replay_delete() and return.
6191 6413 */
6192 6414 ipsa->ipsa_hardexpiretime = (time_t)1;
6193 6415 goto done;
6194 6416 }
6195 6417
6196 6418 if (seq <= ipsa->ipsa_replay) {
6197 6419 /*
6198 6420 * This seq is in the replay window. I'm not below it,
6199 6421 * because I already checked for that above!
6200 6422 */
6201 6423 diff = ipsa->ipsa_replay - seq;
6202 6424 if (ipsa_is_replay_set(ipsa, diff))
6203 6425 goto done;
6204 6426 }
6205 6427 /* Else return B_TRUE, I'm going to advance the window. */
6206 6428
6207 6429 rc = B_TRUE;
6208 6430 done:
6209 6431 mutex_exit(&ipsa->ipsa_lock);
6210 6432 return (rc);
6211 6433 }
6212 6434
6213 6435 /*
6214 6436 * Delete a single SA.
6215 6437 *
6216 6438 * For now, use the quick-and-dirty trick of making the association's
6217 6439 * hard-expire lifetime (time_t)1, ensuring deletion by the *_ager().
6218 6440 */
6219 6441 void
6220 6442 sadb_replay_delete(ipsa_t *assoc)
6221 6443 {
6222 6444 mutex_enter(&assoc->ipsa_lock);
6223 6445 assoc->ipsa_hardexpiretime = (time_t)1;
6224 6446 mutex_exit(&assoc->ipsa_lock);
6225 6447 }
6226 6448
6227 6449 /*
6228 6450 * Special front-end to ipsec_rl_strlog() dealing with SA failure.
6229 6451 * this is designed to take only a format string with "* %x * %s *", so
6230 6452 * that "spi" is printed first, then "addr" is converted using inet_pton().
6231 6453 *
6232 6454 * This is abstracted out to save the stack space for only when inet_pton()
6233 6455 * is called. Make sure "spi" is in network order; it usually is when this
6234 6456 * would get called.
6235 6457 */
6236 6458 void
6237 6459 ipsec_assocfailure(short mid, short sid, char level, ushort_t sl, char *fmt,
6238 6460 uint32_t spi, void *addr, int af, netstack_t *ns)
6239 6461 {
6240 6462 char buf[INET6_ADDRSTRLEN];
6241 6463
6242 6464 ASSERT(af == AF_INET6 || af == AF_INET);
6243 6465
6244 6466 ipsec_rl_strlog(ns, mid, sid, level, sl, fmt, ntohl(spi),
6245 6467 inet_ntop(af, addr, buf, sizeof (buf)));
6246 6468 }
6247 6469
6248 6470 /*
6249 6471 * Fills in a reference to the policy, if any, from the conn, in *ppp
6250 6472 */
6251 6473 static void
6252 6474 ipsec_conn_pol(ipsec_selector_t *sel, conn_t *connp, ipsec_policy_t **ppp)
6253 6475 {
6254 6476 ipsec_policy_t *pp;
6255 6477 ipsec_latch_t *ipl = connp->conn_latch;
6256 6478
6257 6479 if ((ipl != NULL) && (connp->conn_ixa->ixa_ipsec_policy != NULL)) {
6258 6480 pp = connp->conn_ixa->ixa_ipsec_policy;
6259 6481 IPPOL_REFHOLD(pp);
6260 6482 } else {
6261 6483 pp = ipsec_find_policy(IPSEC_TYPE_OUTBOUND, connp, sel,
6262 6484 connp->conn_netstack);
6263 6485 }
6264 6486 *ppp = pp;
6265 6487 }
6266 6488
6267 6489 /*
6268 6490 * The following functions scan through active conn_t structures
6269 6491 * and return a reference to the best-matching policy it can find.
6270 6492 * Caller must release the reference.
6271 6493 */
6272 6494 static void
6273 6495 ipsec_udp_pol(ipsec_selector_t *sel, ipsec_policy_t **ppp, ip_stack_t *ipst)
6274 6496 {
6275 6497 connf_t *connfp;
6276 6498 conn_t *connp = NULL;
6277 6499 ipsec_selector_t portonly;
6278 6500
6279 6501 bzero((void *)&portonly, sizeof (portonly));
6280 6502
6281 6503 if (sel->ips_local_port == 0)
6282 6504 return;
6283 6505
6284 6506 connfp = &ipst->ips_ipcl_udp_fanout[IPCL_UDP_HASH(sel->ips_local_port,
6285 6507 ipst)];
6286 6508 mutex_enter(&connfp->connf_lock);
6287 6509
6288 6510 if (sel->ips_isv4) {
6289 6511 connp = connfp->connf_head;
6290 6512 while (connp != NULL) {
6291 6513 if (IPCL_UDP_MATCH(connp, sel->ips_local_port,
6292 6514 sel->ips_local_addr_v4, sel->ips_remote_port,
6293 6515 sel->ips_remote_addr_v4))
6294 6516 break;
6295 6517 connp = connp->conn_next;
6296 6518 }
6297 6519
6298 6520 if (connp == NULL) {
6299 6521 /* Try port-only match in IPv6. */
6300 6522 portonly.ips_local_port = sel->ips_local_port;
6301 6523 sel = &portonly;
6302 6524 }
6303 6525 }
6304 6526
6305 6527 if (connp == NULL) {
6306 6528 connp = connfp->connf_head;
6307 6529 while (connp != NULL) {
6308 6530 if (IPCL_UDP_MATCH_V6(connp, sel->ips_local_port,
6309 6531 sel->ips_local_addr_v6, sel->ips_remote_port,
6310 6532 sel->ips_remote_addr_v6))
6311 6533 break;
6312 6534 connp = connp->conn_next;
6313 6535 }
6314 6536
6315 6537 if (connp == NULL) {
6316 6538 mutex_exit(&connfp->connf_lock);
6317 6539 return;
6318 6540 }
6319 6541 }
6320 6542
6321 6543 CONN_INC_REF(connp);
6322 6544 mutex_exit(&connfp->connf_lock);
6323 6545
6324 6546 ipsec_conn_pol(sel, connp, ppp);
6325 6547 CONN_DEC_REF(connp);
6326 6548 }
6327 6549
6328 6550 static conn_t *
6329 6551 ipsec_find_listen_conn(uint16_t *pptr, ipsec_selector_t *sel, ip_stack_t *ipst)
6330 6552 {
6331 6553 connf_t *connfp;
6332 6554 conn_t *connp = NULL;
6333 6555 const in6_addr_t *v6addrmatch = &sel->ips_local_addr_v6;
6334 6556
6335 6557 if (sel->ips_local_port == 0)
6336 6558 return (NULL);
6337 6559
6338 6560 connfp = &ipst->ips_ipcl_bind_fanout[
6339 6561 IPCL_BIND_HASH(sel->ips_local_port, ipst)];
6340 6562 mutex_enter(&connfp->connf_lock);
6341 6563
6342 6564 if (sel->ips_isv4) {
6343 6565 connp = connfp->connf_head;
6344 6566 while (connp != NULL) {
6345 6567 if (IPCL_BIND_MATCH(connp, IPPROTO_TCP,
6346 6568 sel->ips_local_addr_v4, pptr[1]))
6347 6569 break;
6348 6570 connp = connp->conn_next;
6349 6571 }
6350 6572
6351 6573 if (connp == NULL) {
6352 6574 /* Match to all-zeroes. */
6353 6575 v6addrmatch = &ipv6_all_zeros;
6354 6576 }
6355 6577 }
6356 6578
6357 6579 if (connp == NULL) {
6358 6580 connp = connfp->connf_head;
6359 6581 while (connp != NULL) {
6360 6582 if (IPCL_BIND_MATCH_V6(connp, IPPROTO_TCP,
6361 6583 *v6addrmatch, pptr[1]))
6362 6584 break;
6363 6585 connp = connp->conn_next;
6364 6586 }
6365 6587
6366 6588 if (connp == NULL) {
6367 6589 mutex_exit(&connfp->connf_lock);
6368 6590 return (NULL);
6369 6591 }
6370 6592 }
6371 6593
6372 6594 CONN_INC_REF(connp);
6373 6595 mutex_exit(&connfp->connf_lock);
6374 6596 return (connp);
6375 6597 }
6376 6598
6377 6599 static void
6378 6600 ipsec_tcp_pol(ipsec_selector_t *sel, ipsec_policy_t **ppp, ip_stack_t *ipst)
6379 6601 {
6380 6602 connf_t *connfp;
6381 6603 conn_t *connp;
6382 6604 uint32_t ports;
6383 6605 uint16_t *pptr = (uint16_t *)&ports;
6384 6606
6385 6607 /*
6386 6608 * Find TCP state in the following order:
6387 6609 * 1.) Connected conns.
6388 6610 * 2.) Listeners.
6389 6611 *
6390 6612 * Even though #2 will be the common case for inbound traffic, only
6391 6613 * following this order insures correctness.
6392 6614 */
6393 6615
6394 6616 if (sel->ips_local_port == 0)
6395 6617 return;
6396 6618
6397 6619 /*
6398 6620 * 0 should be fport, 1 should be lport. SRC is the local one here.
6399 6621 * See ipsec_construct_inverse_acquire() for details.
6400 6622 */
6401 6623 pptr[0] = sel->ips_remote_port;
6402 6624 pptr[1] = sel->ips_local_port;
6403 6625
6404 6626 connfp = &ipst->ips_ipcl_conn_fanout[
6405 6627 IPCL_CONN_HASH(sel->ips_remote_addr_v4, ports, ipst)];
6406 6628 mutex_enter(&connfp->connf_lock);
6407 6629 connp = connfp->connf_head;
6408 6630
6409 6631 if (sel->ips_isv4) {
6410 6632 while (connp != NULL) {
6411 6633 if (IPCL_CONN_MATCH(connp, IPPROTO_TCP,
6412 6634 sel->ips_remote_addr_v4, sel->ips_local_addr_v4,
6413 6635 ports))
6414 6636 break;
6415 6637 connp = connp->conn_next;
6416 6638 }
6417 6639 } else {
6418 6640 while (connp != NULL) {
6419 6641 if (IPCL_CONN_MATCH_V6(connp, IPPROTO_TCP,
6420 6642 sel->ips_remote_addr_v6, sel->ips_local_addr_v6,
6421 6643 ports))
6422 6644 break;
6423 6645 connp = connp->conn_next;
6424 6646 }
6425 6647 }
6426 6648
6427 6649 if (connp != NULL) {
6428 6650 CONN_INC_REF(connp);
6429 6651 mutex_exit(&connfp->connf_lock);
6430 6652 } else {
6431 6653 mutex_exit(&connfp->connf_lock);
6432 6654
6433 6655 /* Try the listen hash. */
6434 6656 if ((connp = ipsec_find_listen_conn(pptr, sel, ipst)) == NULL)
6435 6657 return;
6436 6658 }
6437 6659
6438 6660 ipsec_conn_pol(sel, connp, ppp);
6439 6661 CONN_DEC_REF(connp);
6440 6662 }
6441 6663
6442 6664 static void
6443 6665 ipsec_sctp_pol(ipsec_selector_t *sel, ipsec_policy_t **ppp,
6444 6666 ip_stack_t *ipst)
6445 6667 {
6446 6668 conn_t *connp;
6447 6669 uint32_t ports;
6448 6670 uint16_t *pptr = (uint16_t *)&ports;
6449 6671
6450 6672 /*
6451 6673 * Find SCP state in the following order:
6452 6674 * 1.) Connected conns.
6453 6675 * 2.) Listeners.
6454 6676 *
6455 6677 * Even though #2 will be the common case for inbound traffic, only
6456 6678 * following this order insures correctness.
6457 6679 */
6458 6680
6459 6681 if (sel->ips_local_port == 0)
6460 6682 return;
6461 6683
6462 6684 /*
6463 6685 * 0 should be fport, 1 should be lport. SRC is the local one here.
6464 6686 * See ipsec_construct_inverse_acquire() for details.
6465 6687 */
6466 6688 pptr[0] = sel->ips_remote_port;
6467 6689 pptr[1] = sel->ips_local_port;
6468 6690
6469 6691 /*
6470 6692 * For labeled systems, there's no need to check the
6471 6693 * label here. It's known to be good as we checked
6472 6694 * before allowing the connection to become bound.
6473 6695 */
6474 6696 if (sel->ips_isv4) {
6475 6697 in6_addr_t src, dst;
6476 6698
6477 6699 IN6_IPADDR_TO_V4MAPPED(sel->ips_remote_addr_v4, &dst);
6478 6700 IN6_IPADDR_TO_V4MAPPED(sel->ips_local_addr_v4, &src);
6479 6701 connp = sctp_find_conn(&dst, &src, ports, ALL_ZONES,
6480 6702 0, ipst->ips_netstack->netstack_sctp);
6481 6703 } else {
6482 6704 connp = sctp_find_conn(&sel->ips_remote_addr_v6,
6483 6705 &sel->ips_local_addr_v6, ports, ALL_ZONES,
6484 6706 0, ipst->ips_netstack->netstack_sctp);
6485 6707 }
6486 6708 if (connp == NULL)
6487 6709 return;
6488 6710 ipsec_conn_pol(sel, connp, ppp);
6489 6711 CONN_DEC_REF(connp);
6490 6712 }
6491 6713
6492 6714 /*
6493 6715 * Fill in a query for the SPD (in "sel") using two PF_KEY address extensions.
6494 6716 * Returns 0 or errno, and always sets *diagnostic to something appropriate
6495 6717 * to PF_KEY.
6496 6718 *
6497 6719 * NOTE: For right now, this function (and ipsec_selector_t for that matter),
6498 6720 * ignore prefix lengths in the address extension. Since we match on first-
6499 6721 * entered policies, this shouldn't matter. Also, since we normalize prefix-
6500 6722 * set addresses to mask out the lower bits, we should get a suitable search
6501 6723 * key for the SPD anyway. This is the function to change if the assumption
6502 6724 * about suitable search keys is wrong.
6503 6725 */
6504 6726 static int
6505 6727 ipsec_get_inverse_acquire_sel(ipsec_selector_t *sel, sadb_address_t *srcext,
6506 6728 sadb_address_t *dstext, int *diagnostic)
6507 6729 {
6508 6730 struct sockaddr_in *src, *dst;
6509 6731 struct sockaddr_in6 *src6, *dst6;
6510 6732
6511 6733 *diagnostic = 0;
6512 6734
6513 6735 bzero(sel, sizeof (*sel));
6514 6736 sel->ips_protocol = srcext->sadb_address_proto;
6515 6737 dst = (struct sockaddr_in *)(dstext + 1);
6516 6738 if (dst->sin_family == AF_INET6) {
6517 6739 dst6 = (struct sockaddr_in6 *)dst;
6518 6740 src6 = (struct sockaddr_in6 *)(srcext + 1);
6519 6741 if (src6->sin6_family != AF_INET6) {
6520 6742 *diagnostic = SADB_X_DIAGNOSTIC_AF_MISMATCH;
6521 6743 return (EINVAL);
6522 6744 }
6523 6745 sel->ips_remote_addr_v6 = dst6->sin6_addr;
6524 6746 sel->ips_local_addr_v6 = src6->sin6_addr;
6525 6747 if (sel->ips_protocol == IPPROTO_ICMPV6) {
6526 6748 sel->ips_is_icmp_inv_acq = 1;
6527 6749 } else {
6528 6750 sel->ips_remote_port = dst6->sin6_port;
6529 6751 sel->ips_local_port = src6->sin6_port;
6530 6752 }
6531 6753 sel->ips_isv4 = B_FALSE;
6532 6754 } else {
6533 6755 src = (struct sockaddr_in *)(srcext + 1);
6534 6756 if (src->sin_family != AF_INET) {
6535 6757 *diagnostic = SADB_X_DIAGNOSTIC_AF_MISMATCH;
6536 6758 return (EINVAL);
6537 6759 }
6538 6760 sel->ips_remote_addr_v4 = dst->sin_addr.s_addr;
6539 6761 sel->ips_local_addr_v4 = src->sin_addr.s_addr;
6540 6762 if (sel->ips_protocol == IPPROTO_ICMP) {
6541 6763 sel->ips_is_icmp_inv_acq = 1;
6542 6764 } else {
6543 6765 sel->ips_remote_port = dst->sin_port;
6544 6766 sel->ips_local_port = src->sin_port;
6545 6767 }
6546 6768 sel->ips_isv4 = B_TRUE;
6547 6769 }
6548 6770 return (0);
6549 6771 }
6550 6772
6551 6773 /*
6552 6774 * We have encapsulation.
6553 6775 * - Lookup tun_t by address and look for an associated
6554 6776 * tunnel policy
6555 6777 * - If there are inner selectors
6556 6778 * - check ITPF_P_TUNNEL and ITPF_P_ACTIVE
6557 6779 * - Look up tunnel policy based on selectors
6558 6780 * - Else
6559 6781 * - Sanity check the negotation
6560 6782 * - If appropriate, fall through to global policy
6561 6783 */
6562 6784 static int
6563 6785 ipsec_tun_pol(ipsec_selector_t *sel, ipsec_policy_t **ppp,
6564 6786 sadb_address_t *innsrcext, sadb_address_t *inndstext, ipsec_tun_pol_t *itp,
6565 6787 int *diagnostic)
6566 6788 {
6567 6789 int err;
6568 6790 ipsec_policy_head_t *polhead;
6569 6791
6570 6792 *diagnostic = 0;
6571 6793
6572 6794 /* Check for inner selectors and act appropriately */
6573 6795
6574 6796 if (innsrcext != NULL) {
6575 6797 /* Inner selectors present */
6576 6798 ASSERT(inndstext != NULL);
6577 6799 if ((itp == NULL) ||
6578 6800 (itp->itp_flags & (ITPF_P_ACTIVE | ITPF_P_TUNNEL)) !=
6579 6801 (ITPF_P_ACTIVE | ITPF_P_TUNNEL)) {
6580 6802 /*
6581 6803 * If inner packet selectors, we must have negotiate
6582 6804 * tunnel and active policy. If the tunnel has
6583 6805 * transport-mode policy set on it, or has no policy,
6584 6806 * fail.
6585 6807 */
6586 6808 return (ENOENT);
6587 6809 } else {
6588 6810 /*
6589 6811 * Reset "sel" to indicate inner selectors. Pass
6590 6812 * inner PF_KEY address extensions for this to happen.
6591 6813 */
6592 6814 if ((err = ipsec_get_inverse_acquire_sel(sel,
6593 6815 innsrcext, inndstext, diagnostic)) != 0)
6594 6816 return (err);
6595 6817 /*
6596 6818 * Now look for a tunnel policy based on those inner
6597 6819 * selectors. (Common code is below.)
6598 6820 */
6599 6821 }
6600 6822 } else {
6601 6823 /* No inner selectors present */
6602 6824 if ((itp == NULL) || !(itp->itp_flags & ITPF_P_ACTIVE)) {
6603 6825 /*
6604 6826 * Transport mode negotiation with no tunnel policy
6605 6827 * configured - return to indicate a global policy
6606 6828 * check is needed.
6607 6829 */
6608 6830 return (0);
6609 6831 } else if (itp->itp_flags & ITPF_P_TUNNEL) {
6610 6832 /* Tunnel mode set with no inner selectors. */
6611 6833 return (ENOENT);
6612 6834 }
6613 6835 /*
6614 6836 * Else, this is a tunnel policy configured with ifconfig(1m)
6615 6837 * or "negotiate transport" with ipsecconf(1m). We have an
6616 6838 * itp with policy set based on any match, so don't bother
6617 6839 * changing fields in "sel".
6618 6840 */
6619 6841 }
6620 6842
6621 6843 ASSERT(itp != NULL);
6622 6844 polhead = itp->itp_policy;
6623 6845 ASSERT(polhead != NULL);
6624 6846 rw_enter(&polhead->iph_lock, RW_READER);
6625 6847 *ppp = ipsec_find_policy_head(NULL, polhead, IPSEC_TYPE_INBOUND, sel);
6626 6848 rw_exit(&polhead->iph_lock);
6627 6849
6628 6850 /*
6629 6851 * Don't default to global if we didn't find a matching policy entry.
6630 6852 * Instead, send ENOENT, just like if we hit a transport-mode tunnel.
6631 6853 */
6632 6854 if (*ppp == NULL)
6633 6855 return (ENOENT);
6634 6856
6635 6857 return (0);
6636 6858 }
6637 6859
6638 6860 /*
6639 6861 * For sctp conn_faddr is the primary address, hence this is of limited
6640 6862 * use for sctp.
6641 6863 */
6642 6864 static void
6643 6865 ipsec_oth_pol(ipsec_selector_t *sel, ipsec_policy_t **ppp,
6644 6866 ip_stack_t *ipst)
6645 6867 {
6646 6868 boolean_t isv4 = sel->ips_isv4;
6647 6869 connf_t *connfp;
6648 6870 conn_t *connp;
6649 6871
6650 6872 if (isv4) {
6651 6873 connfp = &ipst->ips_ipcl_proto_fanout_v4[sel->ips_protocol];
6652 6874 } else {
6653 6875 connfp = &ipst->ips_ipcl_proto_fanout_v6[sel->ips_protocol];
6654 6876 }
6655 6877
6656 6878 mutex_enter(&connfp->connf_lock);
6657 6879 for (connp = connfp->connf_head; connp != NULL;
6658 6880 connp = connp->conn_next) {
6659 6881 if (isv4) {
6660 6882 if ((connp->conn_laddr_v4 == INADDR_ANY ||
6661 6883 connp->conn_laddr_v4 == sel->ips_local_addr_v4) &&
6662 6884 (connp->conn_faddr_v4 == INADDR_ANY ||
6663 6885 connp->conn_faddr_v4 == sel->ips_remote_addr_v4))
6664 6886 break;
6665 6887 } else {
6666 6888 if ((IN6_IS_ADDR_UNSPECIFIED(&connp->conn_laddr_v6) ||
6667 6889 IN6_ARE_ADDR_EQUAL(&connp->conn_laddr_v6,
6668 6890 &sel->ips_local_addr_v6)) &&
6669 6891 (IN6_IS_ADDR_UNSPECIFIED(&connp->conn_faddr_v6) ||
6670 6892 IN6_ARE_ADDR_EQUAL(&connp->conn_faddr_v6,
6671 6893 &sel->ips_remote_addr_v6)))
6672 6894 break;
6673 6895 }
6674 6896 }
6675 6897 if (connp == NULL) {
6676 6898 mutex_exit(&connfp->connf_lock);
6677 6899 return;
6678 6900 }
6679 6901
6680 6902 CONN_INC_REF(connp);
6681 6903 mutex_exit(&connfp->connf_lock);
6682 6904
6683 6905 ipsec_conn_pol(sel, connp, ppp);
6684 6906 CONN_DEC_REF(connp);
6685 6907 }
6686 6908
6687 6909 /*
6688 6910 * Construct an inverse ACQUIRE reply based on:
6689 6911 *
6690 6912 * 1.) Current global policy.
6691 6913 * 2.) An conn_t match depending on what all was passed in the extv[].
6692 6914 * 3.) A tunnel's policy head.
6693 6915 * ...
6694 6916 * N.) Other stuff TBD (e.g. identities)
6695 6917 *
6696 6918 * If there is an error, set sadb_msg_errno and sadb_x_msg_diagnostic
6697 6919 * in this function so the caller can extract them where appropriately.
6698 6920 *
6699 6921 * The SRC address is the local one - just like an outbound ACQUIRE message.
6700 6922 *
6701 6923 * XXX MLS: key management supplies a label which we just reflect back up
6702 6924 * again. clearly we need to involve the label in the rest of the checks.
6703 6925 */
6704 6926 mblk_t *
6705 6927 ipsec_construct_inverse_acquire(sadb_msg_t *samsg, sadb_ext_t *extv[],
6706 6928 netstack_t *ns)
6707 6929 {
6708 6930 int err;
6709 6931 int diagnostic;
6710 6932 sadb_address_t *srcext = (sadb_address_t *)extv[SADB_EXT_ADDRESS_SRC],
6711 6933 *dstext = (sadb_address_t *)extv[SADB_EXT_ADDRESS_DST],
6712 6934 *innsrcext = (sadb_address_t *)extv[SADB_X_EXT_ADDRESS_INNER_SRC],
6713 6935 *inndstext = (sadb_address_t *)extv[SADB_X_EXT_ADDRESS_INNER_DST];
6714 6936 sadb_sens_t *sens = (sadb_sens_t *)extv[SADB_EXT_SENSITIVITY];
6715 6937 struct sockaddr_in6 *src, *dst;
6716 6938 struct sockaddr_in6 *isrc, *idst;
6717 6939 ipsec_tun_pol_t *itp = NULL;
6718 6940 ipsec_policy_t *pp = NULL;
6719 6941 ipsec_selector_t sel, isel;
6720 6942 mblk_t *retmp = NULL;
6721 6943 ip_stack_t *ipst = ns->netstack_ip;
6722 6944
6723 6945
6724 6946 /* Normalize addresses */
6725 6947 if (sadb_addrcheck(NULL, (mblk_t *)samsg, (sadb_ext_t *)srcext, 0, ns)
6726 6948 == KS_IN_ADDR_UNKNOWN) {
6727 6949 err = EINVAL;
6728 6950 diagnostic = SADB_X_DIAGNOSTIC_BAD_SRC;
6729 6951 goto bail;
6730 6952 }
6731 6953 src = (struct sockaddr_in6 *)(srcext + 1);
6732 6954 if (sadb_addrcheck(NULL, (mblk_t *)samsg, (sadb_ext_t *)dstext, 0, ns)
6733 6955 == KS_IN_ADDR_UNKNOWN) {
6734 6956 err = EINVAL;
6735 6957 diagnostic = SADB_X_DIAGNOSTIC_BAD_DST;
6736 6958 goto bail;
6737 6959 }
6738 6960 dst = (struct sockaddr_in6 *)(dstext + 1);
6739 6961 if (src->sin6_family != dst->sin6_family) {
6740 6962 err = EINVAL;
6741 6963 diagnostic = SADB_X_DIAGNOSTIC_AF_MISMATCH;
6742 6964 goto bail;
6743 6965 }
6744 6966
6745 6967 /* Check for tunnel mode and act appropriately */
6746 6968 if (innsrcext != NULL) {
6747 6969 if (inndstext == NULL) {
6748 6970 err = EINVAL;
6749 6971 diagnostic = SADB_X_DIAGNOSTIC_MISSING_INNER_DST;
6750 6972 goto bail;
6751 6973 }
6752 6974 if (sadb_addrcheck(NULL, (mblk_t *)samsg,
6753 6975 (sadb_ext_t *)innsrcext, 0, ns) == KS_IN_ADDR_UNKNOWN) {
6754 6976 err = EINVAL;
6755 6977 diagnostic = SADB_X_DIAGNOSTIC_MALFORMED_INNER_SRC;
6756 6978 goto bail;
6757 6979 }
6758 6980 isrc = (struct sockaddr_in6 *)(innsrcext + 1);
6759 6981 if (sadb_addrcheck(NULL, (mblk_t *)samsg,
6760 6982 (sadb_ext_t *)inndstext, 0, ns) == KS_IN_ADDR_UNKNOWN) {
6761 6983 err = EINVAL;
6762 6984 diagnostic = SADB_X_DIAGNOSTIC_MALFORMED_INNER_DST;
6763 6985 goto bail;
6764 6986 }
6765 6987 idst = (struct sockaddr_in6 *)(inndstext + 1);
6766 6988 if (isrc->sin6_family != idst->sin6_family) {
6767 6989 err = EINVAL;
6768 6990 diagnostic = SADB_X_DIAGNOSTIC_INNER_AF_MISMATCH;
6769 6991 goto bail;
6770 6992 }
6771 6993 if (isrc->sin6_family != AF_INET &&
6772 6994 isrc->sin6_family != AF_INET6) {
6773 6995 err = EINVAL;
6774 6996 diagnostic = SADB_X_DIAGNOSTIC_BAD_INNER_SRC_AF;
6775 6997 goto bail;
6776 6998 }
6777 6999 } else if (inndstext != NULL) {
6778 7000 err = EINVAL;
6779 7001 diagnostic = SADB_X_DIAGNOSTIC_MISSING_INNER_SRC;
6780 7002 goto bail;
6781 7003 }
6782 7004
6783 7005 /* Get selectors first, based on outer addresses */
6784 7006 err = ipsec_get_inverse_acquire_sel(&sel, srcext, dstext, &diagnostic);
6785 7007 if (err != 0)
6786 7008 goto bail;
6787 7009
6788 7010 /* Check for tunnel mode mismatches. */
6789 7011 if (innsrcext != NULL &&
6790 7012 ((isrc->sin6_family == AF_INET &&
6791 7013 sel.ips_protocol != IPPROTO_ENCAP && sel.ips_protocol != 0) ||
6792 7014 (isrc->sin6_family == AF_INET6 &&
6793 7015 sel.ips_protocol != IPPROTO_IPV6 && sel.ips_protocol != 0))) {
6794 7016 err = EPROTOTYPE;
6795 7017 goto bail;
6796 7018 }
6797 7019
6798 7020 /*
6799 7021 * Okay, we have the addresses and other selector information.
6800 7022 * Let's first find a conn...
6801 7023 */
6802 7024 pp = NULL;
6803 7025 switch (sel.ips_protocol) {
6804 7026 case IPPROTO_TCP:
6805 7027 ipsec_tcp_pol(&sel, &pp, ipst);
6806 7028 break;
6807 7029 case IPPROTO_UDP:
6808 7030 ipsec_udp_pol(&sel, &pp, ipst);
6809 7031 break;
6810 7032 case IPPROTO_SCTP:
6811 7033 ipsec_sctp_pol(&sel, &pp, ipst);
6812 7034 break;
6813 7035 case IPPROTO_ENCAP:
6814 7036 case IPPROTO_IPV6:
6815 7037 /*
6816 7038 * Assume sel.ips_remote_addr_* has the right address at
6817 7039 * that exact position.
6818 7040 */
6819 7041 itp = itp_get_byaddr((uint32_t *)(&sel.ips_local_addr_v6),
6820 7042 (uint32_t *)(&sel.ips_remote_addr_v6), src->sin6_family,
6821 7043 ipst);
6822 7044
6823 7045 if (innsrcext == NULL) {
6824 7046 /*
6825 7047 * Transport-mode tunnel, make sure we fake out isel
6826 7048 * to contain something based on the outer protocol.
6827 7049 */
6828 7050 bzero(&isel, sizeof (isel));
6829 7051 isel.ips_isv4 = (sel.ips_protocol == IPPROTO_ENCAP);
6830 7052 } /* Else isel is initialized by ipsec_tun_pol(). */
6831 7053 err = ipsec_tun_pol(&isel, &pp, innsrcext, inndstext, itp,
6832 7054 &diagnostic);
6833 7055 /*
6834 7056 * NOTE: isel isn't used for now, but in RFC 430x IPsec, it
6835 7057 * may be.
6836 7058 */
6837 7059 if (err != 0)
6838 7060 goto bail;
6839 7061 break;
6840 7062 default:
6841 7063 ipsec_oth_pol(&sel, &pp, ipst);
6842 7064 break;
6843 7065 }
6844 7066
6845 7067 /*
6846 7068 * If we didn't find a matching conn_t or other policy head, take a
6847 7069 * look in the global policy.
6848 7070 */
|
↓ open down ↓ |
970 lines elided |
↑ open up ↑ |
6849 7071 if (pp == NULL) {
6850 7072 pp = ipsec_find_policy(IPSEC_TYPE_OUTBOUND, NULL, &sel, ns);
6851 7073 if (pp == NULL) {
6852 7074 /* There's no global policy. */
6853 7075 err = ENOENT;
6854 7076 diagnostic = 0;
6855 7077 goto bail;
6856 7078 }
6857 7079 }
6858 7080
6859 - /*
6860 - * Now that we have a policy entry/widget, construct an ACQUIRE
6861 - * message based on that, fix fields where appropriate,
6862 - * and return the message.
6863 - */
6864 - retmp = sadb_extended_acquire(&sel, pp, NULL,
6865 - (itp != NULL && (itp->itp_flags & ITPF_P_TUNNEL)),
6866 - samsg->sadb_msg_seq, samsg->sadb_msg_pid, sens, ns);
7081 + ASSERT(pp != NULL);
7082 + retmp = sadb_acquire_msg_base(0, 0, samsg->sadb_msg_seq,
7083 + samsg->sadb_msg_pid);
7084 + if (retmp != NULL) {
7085 + /* Remove KEYSOCK_OUT, because caller constructs it instead. */
7086 + mblk_t *kso = retmp;
7087 +
7088 + retmp = retmp->b_cont;
7089 + freeb(kso);
7090 + /* Append addresses... */
7091 + retmp->b_cont = sadb_acquire_msg_common(&sel, pp, NULL,
7092 + (itp != NULL && (itp->itp_flags & ITPF_P_TUNNEL)), NULL,
7093 + sens);
7094 + if (retmp->b_cont == NULL) {
7095 + freemsg(retmp);
7096 + retmp = NULL;
7097 + }
7098 + /* And the policy result. */
7099 + retmp->b_cont->b_cont =
7100 + sadb_acquire_extended_prop(pp->ipsp_act, ns);
7101 + if (retmp->b_cont->b_cont == NULL) {
7102 + freemsg(retmp);
7103 + retmp = NULL;
7104 + }
7105 + ((sadb_msg_t *)retmp->b_rptr)->sadb_msg_len =
7106 + SADB_8TO64(msgsize(retmp));
7107 + }
7108 +
6867 7109 if (pp != NULL) {
6868 7110 IPPOL_REFRELE(pp);
6869 7111 }
6870 7112 ASSERT(err == 0 && diagnostic == 0);
6871 7113 if (retmp == NULL)
6872 7114 err = ENOMEM;
6873 7115 bail:
6874 7116 if (itp != NULL) {
6875 7117 ITP_REFRELE(itp, ns);
6876 7118 }
6877 7119 samsg->sadb_msg_errno = (uint8_t)err;
6878 7120 samsg->sadb_x_msg_diagnostic = (uint16_t)diagnostic;
6879 7121 return (retmp);
6880 7122 }
6881 7123
6882 7124 /*
6883 7125 * ipsa_lpkt is a one-element queue, only manipulated by the next two
6884 7126 * functions. They have to hold the ipsa_lock because of potential races
6885 7127 * between key management using SADB_UPDATE, and inbound packets that may
6886 7128 * queue up on the larval SA (hence the 'l' in "lpkt").
6887 7129 */
6888 7130
6889 7131 /*
6890 7132 * sadb_set_lpkt:
6891 7133 *
6892 7134 * Returns the passed-in packet if the SA is no longer larval.
6893 7135 *
6894 7136 * Returns NULL if the SA is larval, and needs to be swapped into the SA for
6895 7137 * processing after an SADB_UPDATE.
6896 7138 */
6897 7139 mblk_t *
6898 7140 sadb_set_lpkt(ipsa_t *ipsa, mblk_t *npkt, ip_recv_attr_t *ira)
6899 7141 {
6900 7142 mblk_t *opkt;
6901 7143
6902 7144 mutex_enter(&ipsa->ipsa_lock);
6903 7145 opkt = ipsa->ipsa_lpkt;
6904 7146 if (ipsa->ipsa_state == IPSA_STATE_LARVAL) {
6905 7147 /*
6906 7148 * Consume npkt and place it in the LARVAL SA's inbound
6907 7149 * packet slot.
6908 7150 */
6909 7151 mblk_t *attrmp;
6910 7152
6911 7153 attrmp = ip_recv_attr_to_mblk(ira);
6912 7154 if (attrmp == NULL) {
6913 7155 ill_t *ill = ira->ira_ill;
6914 7156
6915 7157 BUMP_MIB(ill->ill_ip_mib, ipIfStatsInDiscards);
6916 7158 ip_drop_input("ipIfStatsInDiscards", npkt, ill);
6917 7159 freemsg(npkt);
6918 7160 opkt = NULL;
6919 7161 } else {
6920 7162 ASSERT(attrmp->b_cont == NULL);
6921 7163 attrmp->b_cont = npkt;
6922 7164 ipsa->ipsa_lpkt = attrmp;
6923 7165 }
6924 7166 npkt = NULL;
6925 7167 } else {
6926 7168 /*
6927 7169 * If not larval, we lost the race. NOTE: ipsa_lpkt may still
6928 7170 * have been non-NULL in the non-larval case, because of
6929 7171 * inbound packets arriving prior to sadb_common_add()
6930 7172 * transferring the SA completely out of larval state, but
6931 7173 * after lpkt was grabbed by the AH/ESP-specific add routines.
6932 7174 * We should clear the old ipsa_lpkt in this case to make sure
6933 7175 * that it doesn't linger on the now-MATURE IPsec SA, or get
6934 7176 * picked up as an out-of-order packet.
6935 7177 */
6936 7178 ipsa->ipsa_lpkt = NULL;
6937 7179 }
6938 7180 mutex_exit(&ipsa->ipsa_lock);
6939 7181
6940 7182 if (opkt != NULL) {
6941 7183 ipsec_stack_t *ipss;
6942 7184
6943 7185 ipss = ira->ira_ill->ill_ipst->ips_netstack->netstack_ipsec;
6944 7186 opkt = ip_recv_attr_free_mblk(opkt);
6945 7187 ip_drop_packet(opkt, B_TRUE, ira->ira_ill,
6946 7188 DROPPER(ipss, ipds_sadb_inlarval_replace),
6947 7189 &ipss->ipsec_sadb_dropper);
6948 7190 }
6949 7191 return (npkt);
6950 7192 }
6951 7193
6952 7194 /*
6953 7195 * sadb_clear_lpkt: Atomically clear ipsa->ipsa_lpkt and return the
6954 7196 * previous value.
6955 7197 */
6956 7198 mblk_t *
6957 7199 sadb_clear_lpkt(ipsa_t *ipsa)
6958 7200 {
6959 7201 mblk_t *opkt;
6960 7202
6961 7203 mutex_enter(&ipsa->ipsa_lock);
6962 7204 opkt = ipsa->ipsa_lpkt;
6963 7205 ipsa->ipsa_lpkt = NULL;
6964 7206 mutex_exit(&ipsa->ipsa_lock);
6965 7207 return (opkt);
6966 7208 }
6967 7209
6968 7210 /*
6969 7211 * Buffer a packet that's in IDLE state as set by Solaris Clustering.
6970 7212 */
6971 7213 void
6972 7214 sadb_buf_pkt(ipsa_t *ipsa, mblk_t *bpkt, ip_recv_attr_t *ira)
6973 7215 {
6974 7216 netstack_t *ns = ira->ira_ill->ill_ipst->ips_netstack;
6975 7217 ipsec_stack_t *ipss = ns->netstack_ipsec;
6976 7218 in6_addr_t *srcaddr = (in6_addr_t *)(&ipsa->ipsa_srcaddr);
6977 7219 in6_addr_t *dstaddr = (in6_addr_t *)(&ipsa->ipsa_dstaddr);
6978 7220 mblk_t *mp;
6979 7221
6980 7222 ASSERT(ipsa->ipsa_state == IPSA_STATE_IDLE);
6981 7223
6982 7224 if (cl_inet_idlesa == NULL) {
6983 7225 ip_drop_packet(bpkt, B_TRUE, ira->ira_ill,
6984 7226 DROPPER(ipss, ipds_sadb_inidle_overflow),
6985 7227 &ipss->ipsec_sadb_dropper);
6986 7228 return;
6987 7229 }
6988 7230
6989 7231 cl_inet_idlesa(ns->netstack_stackid,
6990 7232 (ipsa->ipsa_type == SADB_SATYPE_AH) ? IPPROTO_AH : IPPROTO_ESP,
6991 7233 ipsa->ipsa_spi, ipsa->ipsa_addrfam, *srcaddr, *dstaddr, NULL);
6992 7234
6993 7235 mp = ip_recv_attr_to_mblk(ira);
6994 7236 if (mp == NULL) {
6995 7237 ip_drop_packet(bpkt, B_TRUE, ira->ira_ill,
6996 7238 DROPPER(ipss, ipds_sadb_inidle_overflow),
6997 7239 &ipss->ipsec_sadb_dropper);
6998 7240 return;
6999 7241 }
7000 7242 linkb(mp, bpkt);
7001 7243
7002 7244 mutex_enter(&ipsa->ipsa_lock);
7003 7245 ipsa->ipsa_mblkcnt++;
7004 7246 if (ipsa->ipsa_bpkt_head == NULL) {
7005 7247 ipsa->ipsa_bpkt_head = ipsa->ipsa_bpkt_tail = bpkt;
7006 7248 } else {
7007 7249 ipsa->ipsa_bpkt_tail->b_next = bpkt;
7008 7250 ipsa->ipsa_bpkt_tail = bpkt;
7009 7251 if (ipsa->ipsa_mblkcnt > SADB_MAX_IDLEPKTS) {
7010 7252 mblk_t *tmp;
7011 7253
7012 7254 tmp = ipsa->ipsa_bpkt_head;
7013 7255 ipsa->ipsa_bpkt_head = ipsa->ipsa_bpkt_head->b_next;
7014 7256 tmp = ip_recv_attr_free_mblk(tmp);
7015 7257 ip_drop_packet(tmp, B_TRUE, NULL,
7016 7258 DROPPER(ipss, ipds_sadb_inidle_overflow),
7017 7259 &ipss->ipsec_sadb_dropper);
7018 7260 ipsa->ipsa_mblkcnt --;
7019 7261 }
7020 7262 }
7021 7263 mutex_exit(&ipsa->ipsa_lock);
7022 7264 }
7023 7265
7024 7266 /*
7025 7267 * Stub function that taskq_dispatch() invokes to take the mblk (in arg)
7026 7268 * and put into STREAMS again.
7027 7269 */
7028 7270 void
7029 7271 sadb_clear_buf_pkt(void *ipkt)
7030 7272 {
7031 7273 mblk_t *tmp, *buf_pkt;
7032 7274 ip_recv_attr_t iras;
7033 7275
7034 7276 buf_pkt = (mblk_t *)ipkt;
7035 7277
7036 7278 while (buf_pkt != NULL) {
7037 7279 mblk_t *data_mp;
7038 7280
7039 7281 tmp = buf_pkt->b_next;
7040 7282 buf_pkt->b_next = NULL;
7041 7283
7042 7284 data_mp = buf_pkt->b_cont;
7043 7285 buf_pkt->b_cont = NULL;
7044 7286 if (!ip_recv_attr_from_mblk(buf_pkt, &iras)) {
7045 7287 /* The ill or ip_stack_t disappeared on us. */
7046 7288 ip_drop_input("ip_recv_attr_from_mblk", data_mp, NULL);
7047 7289 freemsg(data_mp);
7048 7290 } else {
7049 7291 ip_input_post_ipsec(data_mp, &iras);
7050 7292 }
7051 7293 ira_cleanup(&iras, B_TRUE);
7052 7294 buf_pkt = tmp;
7053 7295 }
7054 7296 }
7055 7297 /*
7056 7298 * Walker callback used by sadb_alg_update() to free/create crypto
7057 7299 * context template when a crypto software provider is removed or
7058 7300 * added.
7059 7301 */
7060 7302
7061 7303 struct sadb_update_alg_state {
7062 7304 ipsec_algtype_t alg_type;
7063 7305 uint8_t alg_id;
7064 7306 boolean_t is_added;
7065 7307 boolean_t async_auth;
7066 7308 boolean_t async_encr;
7067 7309 };
7068 7310
7069 7311 static void
7070 7312 sadb_alg_update_cb(isaf_t *head, ipsa_t *entry, void *cookie)
7071 7313 {
7072 7314 struct sadb_update_alg_state *update_state =
7073 7315 (struct sadb_update_alg_state *)cookie;
7074 7316 crypto_ctx_template_t *ctx_tmpl = NULL;
7075 7317
7076 7318 ASSERT(MUTEX_HELD(&head->isaf_lock));
7077 7319
7078 7320 if (entry->ipsa_state == IPSA_STATE_LARVAL)
7079 7321 return;
7080 7322
7081 7323 mutex_enter(&entry->ipsa_lock);
7082 7324
7083 7325 if ((entry->ipsa_encr_alg != SADB_EALG_NONE && entry->ipsa_encr_alg !=
7084 7326 SADB_EALG_NULL && update_state->async_encr) ||
7085 7327 (entry->ipsa_auth_alg != SADB_AALG_NONE &&
7086 7328 update_state->async_auth)) {
7087 7329 entry->ipsa_flags |= IPSA_F_ASYNC;
7088 7330 } else {
7089 7331 entry->ipsa_flags &= ~IPSA_F_ASYNC;
7090 7332 }
7091 7333
7092 7334 switch (update_state->alg_type) {
7093 7335 case IPSEC_ALG_AUTH:
7094 7336 if (entry->ipsa_auth_alg == update_state->alg_id)
7095 7337 ctx_tmpl = &entry->ipsa_authtmpl;
7096 7338 break;
7097 7339 case IPSEC_ALG_ENCR:
7098 7340 if (entry->ipsa_encr_alg == update_state->alg_id)
7099 7341 ctx_tmpl = &entry->ipsa_encrtmpl;
7100 7342 break;
7101 7343 default:
7102 7344 ctx_tmpl = NULL;
7103 7345 }
7104 7346
7105 7347 if (ctx_tmpl == NULL) {
7106 7348 mutex_exit(&entry->ipsa_lock);
7107 7349 return;
7108 7350 }
7109 7351
7110 7352 /*
7111 7353 * The context template of the SA may be affected by the change
7112 7354 * of crypto provider.
7113 7355 */
7114 7356 if (update_state->is_added) {
7115 7357 /* create the context template if not already done */
7116 7358 if (*ctx_tmpl == NULL) {
7117 7359 (void) ipsec_create_ctx_tmpl(entry,
7118 7360 update_state->alg_type);
7119 7361 }
7120 7362 } else {
7121 7363 /*
7122 7364 * The crypto provider was removed. If the context template
7123 7365 * exists but it is no longer valid, free it.
7124 7366 */
7125 7367 if (*ctx_tmpl != NULL)
7126 7368 ipsec_destroy_ctx_tmpl(entry, update_state->alg_type);
7127 7369 }
7128 7370
7129 7371 mutex_exit(&entry->ipsa_lock);
7130 7372 }
7131 7373
7132 7374 /*
7133 7375 * Invoked by IP when an software crypto provider has been updated, or if
7134 7376 * the crypto synchrony changes. The type and id of the corresponding
7135 7377 * algorithm is passed as argument. The type is set to ALL in the case of
7136 7378 * a synchrony change.
7137 7379 *
7138 7380 * is_added is B_TRUE if the provider was added, B_FALSE if it was
7139 7381 * removed. The function updates the SADB and free/creates the
7140 7382 * context templates associated with SAs if needed.
7141 7383 */
7142 7384
7143 7385 #define SADB_ALG_UPDATE_WALK(sadb, table) \
7144 7386 sadb_walker((sadb).table, (sadb).sdb_hashsize, sadb_alg_update_cb, \
7145 7387 &update_state)
7146 7388
7147 7389 void
7148 7390 sadb_alg_update(ipsec_algtype_t alg_type, uint8_t alg_id, boolean_t is_added,
7149 7391 netstack_t *ns)
7150 7392 {
7151 7393 struct sadb_update_alg_state update_state;
7152 7394 ipsecah_stack_t *ahstack = ns->netstack_ipsecah;
7153 7395 ipsecesp_stack_t *espstack = ns->netstack_ipsecesp;
7154 7396 ipsec_stack_t *ipss = ns->netstack_ipsec;
7155 7397
7156 7398 update_state.alg_type = alg_type;
7157 7399 update_state.alg_id = alg_id;
7158 7400 update_state.is_added = is_added;
7159 7401 update_state.async_auth = ipss->ipsec_algs_exec_mode[IPSEC_ALG_AUTH] ==
7160 7402 IPSEC_ALGS_EXEC_ASYNC;
7161 7403 update_state.async_encr = ipss->ipsec_algs_exec_mode[IPSEC_ALG_ENCR] ==
7162 7404 IPSEC_ALGS_EXEC_ASYNC;
7163 7405
7164 7406 if (alg_type == IPSEC_ALG_AUTH || alg_type == IPSEC_ALG_ALL) {
7165 7407 /* walk the AH tables only for auth. algorithm changes */
7166 7408 SADB_ALG_UPDATE_WALK(ahstack->ah_sadb.s_v4, sdb_of);
7167 7409 SADB_ALG_UPDATE_WALK(ahstack->ah_sadb.s_v4, sdb_if);
7168 7410 SADB_ALG_UPDATE_WALK(ahstack->ah_sadb.s_v6, sdb_of);
7169 7411 SADB_ALG_UPDATE_WALK(ahstack->ah_sadb.s_v6, sdb_if);
7170 7412 }
7171 7413
7172 7414 /* walk the ESP tables */
7173 7415 SADB_ALG_UPDATE_WALK(espstack->esp_sadb.s_v4, sdb_of);
7174 7416 SADB_ALG_UPDATE_WALK(espstack->esp_sadb.s_v4, sdb_if);
7175 7417 SADB_ALG_UPDATE_WALK(espstack->esp_sadb.s_v6, sdb_of);
7176 7418 SADB_ALG_UPDATE_WALK(espstack->esp_sadb.s_v6, sdb_if);
7177 7419 }
7178 7420
7179 7421 /*
7180 7422 * Creates a context template for the specified SA. This function
7181 7423 * is called when an SA is created and when a context template needs
7182 7424 * to be created due to a change of software provider.
7183 7425 */
7184 7426 int
7185 7427 ipsec_create_ctx_tmpl(ipsa_t *sa, ipsec_algtype_t alg_type)
7186 7428 {
7187 7429 ipsec_alginfo_t *alg;
7188 7430 crypto_mechanism_t mech;
7189 7431 crypto_key_t *key;
7190 7432 crypto_ctx_template_t *sa_tmpl;
7191 7433 int rv;
7192 7434 ipsec_stack_t *ipss = sa->ipsa_netstack->netstack_ipsec;
7193 7435
7194 7436 ASSERT(RW_READ_HELD(&ipss->ipsec_alg_lock));
7195 7437 ASSERT(MUTEX_HELD(&sa->ipsa_lock));
7196 7438
7197 7439 /* get pointers to the algorithm info, context template, and key */
7198 7440 switch (alg_type) {
7199 7441 case IPSEC_ALG_AUTH:
7200 7442 key = &sa->ipsa_kcfauthkey;
7201 7443 sa_tmpl = &sa->ipsa_authtmpl;
7202 7444 alg = ipss->ipsec_alglists[alg_type][sa->ipsa_auth_alg];
7203 7445 break;
7204 7446 case IPSEC_ALG_ENCR:
7205 7447 key = &sa->ipsa_kcfencrkey;
7206 7448 sa_tmpl = &sa->ipsa_encrtmpl;
7207 7449 alg = ipss->ipsec_alglists[alg_type][sa->ipsa_encr_alg];
7208 7450 break;
7209 7451 default:
7210 7452 alg = NULL;
7211 7453 }
7212 7454
7213 7455 if (alg == NULL || !ALG_VALID(alg))
7214 7456 return (EINVAL);
7215 7457
7216 7458 /* initialize the mech info structure for the framework */
7217 7459 ASSERT(alg->alg_mech_type != CRYPTO_MECHANISM_INVALID);
7218 7460 mech.cm_type = alg->alg_mech_type;
7219 7461 mech.cm_param = NULL;
7220 7462 mech.cm_param_len = 0;
7221 7463
7222 7464 /* create a new context template */
7223 7465 rv = crypto_create_ctx_template(&mech, key, sa_tmpl, KM_NOSLEEP);
7224 7466
7225 7467 /*
7226 7468 * CRYPTO_MECH_NOT_SUPPORTED can be returned if only hardware
7227 7469 * providers are available for that mechanism. In that case
7228 7470 * we don't fail, and will generate the context template from
7229 7471 * the framework callback when a software provider for that
7230 7472 * mechanism registers.
7231 7473 *
7232 7474 * The context template is assigned the special value
7233 7475 * IPSEC_CTX_TMPL_ALLOC if the allocation failed due to a
7234 7476 * lack of memory. No attempt will be made to use
7235 7477 * the context template if it is set to this value.
7236 7478 */
7237 7479 if (rv == CRYPTO_HOST_MEMORY) {
7238 7480 *sa_tmpl = IPSEC_CTX_TMPL_ALLOC;
7239 7481 } else if (rv != CRYPTO_SUCCESS) {
7240 7482 *sa_tmpl = NULL;
7241 7483 if (rv != CRYPTO_MECH_NOT_SUPPORTED)
7242 7484 return (EINVAL);
7243 7485 }
7244 7486
7245 7487 return (0);
7246 7488 }
7247 7489
7248 7490 /*
7249 7491 * Destroy the context template of the specified algorithm type
7250 7492 * of the specified SA. Must be called while holding the SA lock.
7251 7493 */
7252 7494 void
7253 7495 ipsec_destroy_ctx_tmpl(ipsa_t *sa, ipsec_algtype_t alg_type)
7254 7496 {
7255 7497 ASSERT(MUTEX_HELD(&sa->ipsa_lock));
7256 7498
7257 7499 if (alg_type == IPSEC_ALG_AUTH) {
7258 7500 if (sa->ipsa_authtmpl == IPSEC_CTX_TMPL_ALLOC)
7259 7501 sa->ipsa_authtmpl = NULL;
7260 7502 else if (sa->ipsa_authtmpl != NULL) {
7261 7503 crypto_destroy_ctx_template(sa->ipsa_authtmpl);
7262 7504 sa->ipsa_authtmpl = NULL;
7263 7505 }
7264 7506 } else {
7265 7507 ASSERT(alg_type == IPSEC_ALG_ENCR);
7266 7508 if (sa->ipsa_encrtmpl == IPSEC_CTX_TMPL_ALLOC)
7267 7509 sa->ipsa_encrtmpl = NULL;
7268 7510 else if (sa->ipsa_encrtmpl != NULL) {
7269 7511 crypto_destroy_ctx_template(sa->ipsa_encrtmpl);
7270 7512 sa->ipsa_encrtmpl = NULL;
7271 7513 }
7272 7514 }
7273 7515 }
7274 7516
7275 7517 /*
7276 7518 * Use the kernel crypto framework to check the validity of a key received
7277 7519 * via keysock. Returns 0 if the key is OK, -1 otherwise.
7278 7520 */
7279 7521 int
7280 7522 ipsec_check_key(crypto_mech_type_t mech_type, sadb_key_t *sadb_key,
7281 7523 boolean_t is_auth, int *diag)
7282 7524 {
7283 7525 crypto_mechanism_t mech;
7284 7526 crypto_key_t crypto_key;
7285 7527 int crypto_rc;
7286 7528
7287 7529 mech.cm_type = mech_type;
7288 7530 mech.cm_param = NULL;
7289 7531 mech.cm_param_len = 0;
7290 7532
7291 7533 crypto_key.ck_format = CRYPTO_KEY_RAW;
7292 7534 crypto_key.ck_data = sadb_key + 1;
7293 7535 crypto_key.ck_length = sadb_key->sadb_key_bits;
7294 7536
7295 7537 crypto_rc = crypto_key_check(&mech, &crypto_key);
7296 7538
7297 7539 switch (crypto_rc) {
7298 7540 case CRYPTO_SUCCESS:
7299 7541 return (0);
7300 7542 case CRYPTO_MECHANISM_INVALID:
7301 7543 case CRYPTO_MECH_NOT_SUPPORTED:
7302 7544 *diag = is_auth ? SADB_X_DIAGNOSTIC_BAD_AALG :
7303 7545 SADB_X_DIAGNOSTIC_BAD_EALG;
7304 7546 break;
7305 7547 case CRYPTO_KEY_SIZE_RANGE:
7306 7548 *diag = is_auth ? SADB_X_DIAGNOSTIC_BAD_AKEYBITS :
7307 7549 SADB_X_DIAGNOSTIC_BAD_EKEYBITS;
7308 7550 break;
7309 7551 case CRYPTO_WEAK_KEY:
7310 7552 *diag = is_auth ? SADB_X_DIAGNOSTIC_WEAK_AKEY :
7311 7553 SADB_X_DIAGNOSTIC_WEAK_EKEY;
7312 7554 break;
7313 7555 }
7314 7556
7315 7557 return (-1);
7316 7558 }
7317 7559
7318 7560 /*
7319 7561 * Whack options in the outer IP header when ipsec changes the outer label
7320 7562 *
7321 7563 * This is inelegant and really could use refactoring.
7322 7564 */
7323 7565 mblk_t *
7324 7566 sadb_whack_label_v4(mblk_t *mp, ipsa_t *assoc, kstat_named_t *counter,
7325 7567 ipdropper_t *dropper)
7326 7568 {
7327 7569 int delta;
7328 7570 int plen;
7329 7571 dblk_t *db;
7330 7572 int hlen;
7331 7573 uint8_t *opt_storage = assoc->ipsa_opt_storage;
7332 7574 ipha_t *ipha = (ipha_t *)mp->b_rptr;
7333 7575
7334 7576 plen = ntohs(ipha->ipha_length);
7335 7577
7336 7578 delta = tsol_remove_secopt(ipha, MBLKL(mp));
7337 7579 mp->b_wptr += delta;
7338 7580 plen += delta;
7339 7581
7340 7582 /* XXX XXX code copied from tsol_check_label */
7341 7583
7342 7584 /* Make sure we have room for the worst-case addition */
7343 7585 hlen = IPH_HDR_LENGTH(ipha) + opt_storage[IPOPT_OLEN];
7344 7586 hlen = (hlen + 3) & ~3;
7345 7587 if (hlen > IP_MAX_HDR_LENGTH)
7346 7588 hlen = IP_MAX_HDR_LENGTH;
7347 7589 hlen -= IPH_HDR_LENGTH(ipha);
7348 7590
7349 7591 db = mp->b_datap;
7350 7592 if ((db->db_ref != 1) || (mp->b_wptr + hlen > db->db_lim)) {
7351 7593 int copylen;
7352 7594 mblk_t *new_mp;
7353 7595
7354 7596 /* allocate enough to be meaningful, but not *too* much */
7355 7597 copylen = MBLKL(mp);
7356 7598 if (copylen > 256)
7357 7599 copylen = 256;
7358 7600 new_mp = allocb_tmpl(hlen + copylen +
7359 7601 (mp->b_rptr - mp->b_datap->db_base), mp);
7360 7602
7361 7603 if (new_mp == NULL) {
7362 7604 ip_drop_packet(mp, B_FALSE, NULL, counter, dropper);
7363 7605 return (NULL);
7364 7606 }
7365 7607
7366 7608 /* keep the bias */
7367 7609 new_mp->b_rptr += mp->b_rptr - mp->b_datap->db_base;
7368 7610 new_mp->b_wptr = new_mp->b_rptr + copylen;
7369 7611 bcopy(mp->b_rptr, new_mp->b_rptr, copylen);
7370 7612 new_mp->b_cont = mp;
7371 7613 if ((mp->b_rptr += copylen) >= mp->b_wptr) {
7372 7614 new_mp->b_cont = mp->b_cont;
7373 7615 freeb(mp);
7374 7616 }
7375 7617 mp = new_mp;
7376 7618 ipha = (ipha_t *)mp->b_rptr;
7377 7619 }
7378 7620
7379 7621 delta = tsol_prepend_option(assoc->ipsa_opt_storage, ipha, MBLKL(mp));
7380 7622
7381 7623 ASSERT(delta != -1);
7382 7624
7383 7625 plen += delta;
7384 7626 mp->b_wptr += delta;
7385 7627
7386 7628 /*
7387 7629 * Paranoia
7388 7630 */
7389 7631 db = mp->b_datap;
7390 7632
7391 7633 ASSERT3P(mp->b_wptr, <=, db->db_lim);
7392 7634 ASSERT3P(mp->b_rptr, <=, db->db_lim);
7393 7635
7394 7636 ASSERT3P(mp->b_wptr, >=, db->db_base);
7395 7637 ASSERT3P(mp->b_rptr, >=, db->db_base);
7396 7638 /* End paranoia */
7397 7639
7398 7640 ipha->ipha_length = htons(plen);
7399 7641
7400 7642 return (mp);
7401 7643 }
7402 7644
7403 7645 mblk_t *
7404 7646 sadb_whack_label_v6(mblk_t *mp, ipsa_t *assoc, kstat_named_t *counter,
7405 7647 ipdropper_t *dropper)
7406 7648 {
7407 7649 int delta;
7408 7650 int plen;
7409 7651 dblk_t *db;
7410 7652 int hlen;
7411 7653 uint8_t *opt_storage = assoc->ipsa_opt_storage;
7412 7654 uint_t sec_opt_len; /* label option length not including type, len */
7413 7655 ip6_t *ip6h = (ip6_t *)mp->b_rptr;
7414 7656
7415 7657 plen = ntohs(ip6h->ip6_plen);
7416 7658
7417 7659 delta = tsol_remove_secopt_v6(ip6h, MBLKL(mp));
7418 7660 mp->b_wptr += delta;
7419 7661 plen += delta;
7420 7662
7421 7663 /* XXX XXX code copied from tsol_check_label_v6 */
7422 7664 /*
7423 7665 * Make sure we have room for the worst-case addition. Add 2 bytes for
7424 7666 * the hop-by-hop ext header's next header and length fields. Add
7425 7667 * another 2 bytes for the label option type, len and then round
7426 7668 * up to the next 8-byte multiple.
7427 7669 */
7428 7670 sec_opt_len = opt_storage[1];
7429 7671
7430 7672 db = mp->b_datap;
7431 7673 hlen = (4 + sec_opt_len + 7) & ~7;
7432 7674
7433 7675 if ((db->db_ref != 1) || (mp->b_wptr + hlen > db->db_lim)) {
7434 7676 int copylen;
7435 7677 mblk_t *new_mp;
7436 7678 uint16_t hdr_len;
7437 7679
7438 7680 hdr_len = ip_hdr_length_v6(mp, ip6h);
7439 7681 /*
7440 7682 * Allocate enough to be meaningful, but not *too* much.
7441 7683 * Also all the IPv6 extension headers must be in the same mblk
7442 7684 */
7443 7685 copylen = MBLKL(mp);
7444 7686 if (copylen > 256)
7445 7687 copylen = 256;
7446 7688 if (copylen < hdr_len)
7447 7689 copylen = hdr_len;
7448 7690 new_mp = allocb_tmpl(hlen + copylen +
7449 7691 (mp->b_rptr - mp->b_datap->db_base), mp);
7450 7692 if (new_mp == NULL) {
7451 7693 ip_drop_packet(mp, B_FALSE, NULL, counter, dropper);
7452 7694 return (NULL);
7453 7695 }
7454 7696
7455 7697 /* keep the bias */
7456 7698 new_mp->b_rptr += mp->b_rptr - mp->b_datap->db_base;
7457 7699 new_mp->b_wptr = new_mp->b_rptr + copylen;
7458 7700 bcopy(mp->b_rptr, new_mp->b_rptr, copylen);
7459 7701 new_mp->b_cont = mp;
7460 7702 if ((mp->b_rptr += copylen) >= mp->b_wptr) {
7461 7703 new_mp->b_cont = mp->b_cont;
7462 7704 freeb(mp);
7463 7705 }
7464 7706 mp = new_mp;
7465 7707 ip6h = (ip6_t *)mp->b_rptr;
7466 7708 }
7467 7709
7468 7710 delta = tsol_prepend_option_v6(assoc->ipsa_opt_storage,
7469 7711 ip6h, MBLKL(mp));
7470 7712
7471 7713 ASSERT(delta != -1);
7472 7714
7473 7715 plen += delta;
7474 7716 mp->b_wptr += delta;
7475 7717
7476 7718 /*
7477 7719 * Paranoia
7478 7720 */
7479 7721 db = mp->b_datap;
7480 7722
7481 7723 ASSERT3P(mp->b_wptr, <=, db->db_lim);
7482 7724 ASSERT3P(mp->b_rptr, <=, db->db_lim);
7483 7725
7484 7726 ASSERT3P(mp->b_wptr, >=, db->db_base);
7485 7727 ASSERT3P(mp->b_rptr, >=, db->db_base);
7486 7728 /* End paranoia */
7487 7729
7488 7730 ip6h->ip6_plen = htons(plen);
7489 7731
7490 7732 return (mp);
7491 7733 }
7492 7734
7493 7735 /* Whack the labels and update ip_xmit_attr_t as needed */
7494 7736 mblk_t *
7495 7737 sadb_whack_label(mblk_t *mp, ipsa_t *assoc, ip_xmit_attr_t *ixa,
7496 7738 kstat_named_t *counter, ipdropper_t *dropper)
7497 7739 {
7498 7740 int adjust;
7499 7741 int iplen;
7500 7742
7501 7743 if (ixa->ixa_flags & IXAF_IS_IPV4) {
7502 7744 ipha_t *ipha = (ipha_t *)mp->b_rptr;
7503 7745
7504 7746 ASSERT(IPH_HDR_VERSION(ipha) == IPV4_VERSION);
7505 7747 iplen = ntohs(ipha->ipha_length);
7506 7748 mp = sadb_whack_label_v4(mp, assoc, counter, dropper);
7507 7749 if (mp == NULL)
7508 7750 return (NULL);
7509 7751
7510 7752 ipha = (ipha_t *)mp->b_rptr;
7511 7753 ASSERT(IPH_HDR_VERSION(ipha) == IPV4_VERSION);
7512 7754 adjust = (int)ntohs(ipha->ipha_length) - iplen;
7513 7755 } else {
7514 7756 ip6_t *ip6h = (ip6_t *)mp->b_rptr;
7515 7757
7516 7758 ASSERT(IPH_HDR_VERSION(ip6h) == IPV6_VERSION);
7517 7759 iplen = ntohs(ip6h->ip6_plen);
7518 7760 mp = sadb_whack_label_v6(mp, assoc, counter, dropper);
7519 7761 if (mp == NULL)
7520 7762 return (NULL);
7521 7763
7522 7764 ip6h = (ip6_t *)mp->b_rptr;
7523 7765 ASSERT(IPH_HDR_VERSION(ip6h) == IPV6_VERSION);
7524 7766 adjust = (int)ntohs(ip6h->ip6_plen) - iplen;
7525 7767 }
7526 7768 ixa->ixa_pktlen += adjust;
7527 7769 ixa->ixa_ip_hdr_length += adjust;
7528 7770 return (mp);
7529 7771 }
7530 7772
7531 7773 /*
7532 7774 * If this is an outgoing SA then add some fuzz to the
7533 7775 * SOFT EXPIRE time. The reason for this is to stop
7534 7776 * peers trying to renegotiate SOFT expiring SA's at
7535 7777 * the same time. The amount of fuzz needs to be at
7536 7778 * least 8 seconds which is the typical interval
7537 7779 * sadb_ager(), although this is only a guide as it
7538 7780 * selftunes.
7539 7781 */
7540 7782 static void
7541 7783 lifetime_fuzz(ipsa_t *assoc)
7542 7784 {
7543 7785 uint8_t rnd;
7544 7786
7545 7787 if (assoc->ipsa_softaddlt == 0)
7546 7788 return;
7547 7789
7548 7790 (void) random_get_pseudo_bytes(&rnd, sizeof (rnd));
7549 7791 rnd = (rnd & 0xF) + 8;
7550 7792 assoc->ipsa_softexpiretime -= rnd;
7551 7793 assoc->ipsa_softaddlt -= rnd;
7552 7794 }
7553 7795
7554 7796 static void
7555 7797 destroy_ipsa_pair(ipsap_t *ipsapp)
7556 7798 {
7557 7799 /*
7558 7800 * Because of the multi-line macro nature of IPSA_REFRELE, keep
7559 7801 * them in { }.
7560 7802 */
7561 7803 if (ipsapp->ipsap_sa_ptr != NULL) {
7562 7804 IPSA_REFRELE(ipsapp->ipsap_sa_ptr);
7563 7805 }
7564 7806 if (ipsapp->ipsap_psa_ptr != NULL) {
7565 7807 IPSA_REFRELE(ipsapp->ipsap_psa_ptr);
7566 7808 }
7567 7809 init_ipsa_pair(ipsapp);
7568 7810 }
7569 7811
7570 7812 static void
7571 7813 init_ipsa_pair(ipsap_t *ipsapp)
7572 7814 {
7573 7815 ipsapp->ipsap_bucket = NULL;
7574 7816 ipsapp->ipsap_sa_ptr = NULL;
7575 7817 ipsapp->ipsap_pbucket = NULL;
7576 7818 ipsapp->ipsap_psa_ptr = NULL;
7577 7819 }
7578 7820
7579 7821 /*
7580 7822 * The sadb_ager() function walks through the hash tables of SA's and ages
7581 7823 * them, if the SA expires as a result, its marked as DEAD and will be reaped
7582 7824 * the next time sadb_ager() runs. SA's which are paired or have a peer (same
7583 7825 * SA appears in both the inbound and outbound tables because its not possible
7584 7826 * to determine its direction) are placed on a list when they expire. This is
7585 7827 * to ensure that pair/peer SA's are reaped at the same time, even if they
7586 7828 * expire at different times.
7587 7829 *
7588 7830 * This function is called twice by sadb_ager(), one after processing the
7589 7831 * inbound table, then again after processing the outbound table.
7590 7832 */
7591 7833 void
7592 7834 age_pair_peer_list(templist_t *haspeerlist, sadb_t *sp, boolean_t outbound)
7593 7835 {
7594 7836 templist_t *listptr;
7595 7837 int outhash;
7596 7838 isaf_t *bucket;
7597 7839 boolean_t haspeer;
7598 7840 ipsa_t *peer_assoc, *dying;
7599 7841 /*
7600 7842 * Haspeer cases will contain both IPv4 and IPv6. This code
7601 7843 * is address independent.
7602 7844 */
7603 7845 while (haspeerlist != NULL) {
7604 7846 /* "dying" contains the SA that has a peer. */
7605 7847 dying = haspeerlist->ipsa;
7606 7848 haspeer = (dying->ipsa_haspeer);
7607 7849 listptr = haspeerlist;
7608 7850 haspeerlist = listptr->next;
7609 7851 kmem_free(listptr, sizeof (*listptr));
7610 7852 /*
7611 7853 * Pick peer bucket based on addrfam.
7612 7854 */
7613 7855 if (outbound) {
7614 7856 if (haspeer)
7615 7857 bucket = INBOUND_BUCKET(sp, dying->ipsa_spi);
7616 7858 else
7617 7859 bucket = INBOUND_BUCKET(sp,
7618 7860 dying->ipsa_otherspi);
7619 7861 } else { /* inbound */
7620 7862 if (haspeer) {
7621 7863 if (dying->ipsa_addrfam == AF_INET6) {
7622 7864 outhash = OUTBOUND_HASH_V6(sp,
7623 7865 *((in6_addr_t *)&dying->
7624 7866 ipsa_dstaddr));
7625 7867 } else {
7626 7868 outhash = OUTBOUND_HASH_V4(sp,
7627 7869 *((ipaddr_t *)&dying->
7628 7870 ipsa_dstaddr));
7629 7871 }
7630 7872 } else if (dying->ipsa_addrfam == AF_INET6) {
7631 7873 outhash = OUTBOUND_HASH_V6(sp,
7632 7874 *((in6_addr_t *)&dying->
7633 7875 ipsa_srcaddr));
7634 7876 } else {
7635 7877 outhash = OUTBOUND_HASH_V4(sp,
7636 7878 *((ipaddr_t *)&dying->
7637 7879 ipsa_srcaddr));
7638 7880 }
7639 7881 bucket = &(sp->sdb_of[outhash]);
7640 7882 }
7641 7883
7642 7884 mutex_enter(&bucket->isaf_lock);
7643 7885 /*
7644 7886 * "haspeer" SA's have the same src/dst address ordering,
7645 7887 * "paired" SA's have the src/dst addresses reversed.
7646 7888 */
7647 7889 if (haspeer) {
7648 7890 peer_assoc = ipsec_getassocbyspi(bucket,
7649 7891 dying->ipsa_spi, dying->ipsa_srcaddr,
7650 7892 dying->ipsa_dstaddr, dying->ipsa_addrfam);
7651 7893 } else {
7652 7894 peer_assoc = ipsec_getassocbyspi(bucket,
7653 7895 dying->ipsa_otherspi, dying->ipsa_dstaddr,
7654 7896 dying->ipsa_srcaddr, dying->ipsa_addrfam);
7655 7897 }
7656 7898
7657 7899 mutex_exit(&bucket->isaf_lock);
7658 7900 if (peer_assoc != NULL) {
7659 7901 mutex_enter(&peer_assoc->ipsa_lock);
7660 7902 mutex_enter(&dying->ipsa_lock);
7661 7903 if (!haspeer) {
7662 7904 /*
7663 7905 * Only SA's which have a "peer" or are
7664 7906 * "paired" end up on this list, so this
7665 7907 * must be a "paired" SA, update the flags
7666 7908 * to break the pair.
7667 7909 */
7668 7910 peer_assoc->ipsa_otherspi = 0;
7669 7911 peer_assoc->ipsa_flags &= ~IPSA_F_PAIRED;
7670 7912 dying->ipsa_otherspi = 0;
7671 7913 dying->ipsa_flags &= ~IPSA_F_PAIRED;
7672 7914 }
7673 7915 if (haspeer || outbound) {
7674 7916 /*
7675 7917 * Update the state of the "inbound" SA when
7676 7918 * the "outbound" SA has expired. Don't update
7677 7919 * the "outbound" SA when the "inbound" SA
7678 7920 * SA expires because setting the hard_addtime
7679 7921 * below will cause this to happen.
7680 7922 */
7681 7923 peer_assoc->ipsa_state = dying->ipsa_state;
7682 7924 }
7683 7925 if (dying->ipsa_state == IPSA_STATE_DEAD)
7684 7926 peer_assoc->ipsa_hardexpiretime = 1;
7685 7927
7686 7928 mutex_exit(&dying->ipsa_lock);
7687 7929 mutex_exit(&peer_assoc->ipsa_lock);
7688 7930 IPSA_REFRELE(peer_assoc);
7689 7931 }
7690 7932 IPSA_REFRELE(dying);
7691 7933 }
7692 7934 }
7693 7935
7694 7936 /*
7695 7937 * Ensure that the IV used for CCM mode never repeats. The IV should
7696 7938 * only be updated by this function. Also check to see if the IV
7697 7939 * is about to wrap and generate a SOFT Expire. This function is only
7698 7940 * called for outgoing packets, the IV for incomming packets is taken
7699 7941 * from the wire. If the outgoing SA needs to be expired, update
7700 7942 * the matching incomming SA.
7701 7943 */
7702 7944 boolean_t
7703 7945 update_iv(uint8_t *iv_ptr, queue_t *pfkey_q, ipsa_t *assoc,
7704 7946 ipsecesp_stack_t *espstack)
7705 7947 {
7706 7948 boolean_t rc = B_TRUE;
7707 7949 isaf_t *inbound_bucket;
7708 7950 sadb_t *sp;
7709 7951 ipsa_t *pair_sa = NULL;
7710 7952 int sa_new_state = 0;
7711 7953
7712 7954 /* For non counter modes, the IV is random data. */
7713 7955 if (!(assoc->ipsa_flags & IPSA_F_COUNTERMODE)) {
7714 7956 (void) random_get_pseudo_bytes(iv_ptr, assoc->ipsa_iv_len);
7715 7957 return (rc);
7716 7958 }
7717 7959
7718 7960 mutex_enter(&assoc->ipsa_lock);
7719 7961
7720 7962 (*assoc->ipsa_iv)++;
7721 7963
7722 7964 if (*assoc->ipsa_iv == assoc->ipsa_iv_hardexpire) {
7723 7965 sa_new_state = IPSA_STATE_DEAD;
7724 7966 rc = B_FALSE;
7725 7967 } else if (*assoc->ipsa_iv == assoc->ipsa_iv_softexpire) {
7726 7968 if (assoc->ipsa_state != IPSA_STATE_DYING) {
7727 7969 /*
7728 7970 * This SA may have already been expired when its
7729 7971 * PAIR_SA expired.
7730 7972 */
7731 7973 sa_new_state = IPSA_STATE_DYING;
7732 7974 }
7733 7975 }
7734 7976 if (sa_new_state) {
7735 7977 /*
7736 7978 * If there is a state change, we need to update this SA
7737 7979 * and its "pair", we can find the bucket for the "pair" SA
7738 7980 * while holding the ipsa_t mutex, but we won't actually
7739 7981 * update anything untill the ipsa_t mutex has been released
7740 7982 * for _this_ SA.
7741 7983 */
7742 7984 assoc->ipsa_state = sa_new_state;
7743 7985 if (assoc->ipsa_addrfam == AF_INET6) {
7744 7986 sp = &espstack->esp_sadb.s_v6;
7745 7987 } else {
7746 7988 sp = &espstack->esp_sadb.s_v4;
7747 7989 }
7748 7990 inbound_bucket = INBOUND_BUCKET(sp, assoc->ipsa_otherspi);
7749 7991 sadb_expire_assoc(pfkey_q, assoc);
7750 7992 }
7751 7993 if (rc == B_TRUE)
7752 7994 bcopy(assoc->ipsa_iv, iv_ptr, assoc->ipsa_iv_len);
7753 7995
7754 7996 mutex_exit(&assoc->ipsa_lock);
7755 7997
7756 7998 if (sa_new_state) {
7757 7999 /* Find the inbound SA, need to lock hash bucket. */
7758 8000 mutex_enter(&inbound_bucket->isaf_lock);
7759 8001 pair_sa = ipsec_getassocbyspi(inbound_bucket,
7760 8002 assoc->ipsa_otherspi, assoc->ipsa_dstaddr,
7761 8003 assoc->ipsa_srcaddr, assoc->ipsa_addrfam);
7762 8004 mutex_exit(&inbound_bucket->isaf_lock);
7763 8005 if (pair_sa != NULL) {
7764 8006 mutex_enter(&pair_sa->ipsa_lock);
7765 8007 pair_sa->ipsa_state = sa_new_state;
7766 8008 mutex_exit(&pair_sa->ipsa_lock);
7767 8009 IPSA_REFRELE(pair_sa);
7768 8010 }
7769 8011 }
7770 8012
7771 8013 return (rc);
7772 8014 }
7773 8015
7774 8016 void
7775 8017 ccm_params_init(ipsa_t *assoc, uchar_t *esph, uint_t data_len, uchar_t *iv_ptr,
7776 8018 ipsa_cm_mech_t *cm_mech, crypto_data_t *crypto_data)
7777 8019 {
7778 8020 uchar_t *nonce;
7779 8021 crypto_mechanism_t *combined_mech;
7780 8022 CK_AES_CCM_PARAMS *params;
7781 8023
7782 8024 combined_mech = (crypto_mechanism_t *)cm_mech;
7783 8025 params = (CK_AES_CCM_PARAMS *)(combined_mech + 1);
7784 8026 nonce = (uchar_t *)(params + 1);
7785 8027 params->ulMACSize = assoc->ipsa_mac_len;
7786 8028 params->ulNonceSize = assoc->ipsa_nonce_len;
7787 8029 params->ulAuthDataSize = sizeof (esph_t);
7788 8030 params->ulDataSize = data_len;
7789 8031 params->nonce = nonce;
7790 8032 params->authData = esph;
7791 8033
7792 8034 cm_mech->combined_mech.cm_type = assoc->ipsa_emech.cm_type;
7793 8035 cm_mech->combined_mech.cm_param_len = sizeof (CK_AES_CCM_PARAMS);
7794 8036 cm_mech->combined_mech.cm_param = (caddr_t)params;
7795 8037 /* See gcm_params_init() for comments. */
7796 8038 bcopy(assoc->ipsa_nonce, nonce, assoc->ipsa_saltlen);
7797 8039 nonce += assoc->ipsa_saltlen;
7798 8040 bcopy(iv_ptr, nonce, assoc->ipsa_iv_len);
7799 8041 crypto_data->cd_miscdata = NULL;
7800 8042 }
7801 8043
7802 8044 /* ARGSUSED */
7803 8045 void
7804 8046 cbc_params_init(ipsa_t *assoc, uchar_t *esph, uint_t data_len, uchar_t *iv_ptr,
7805 8047 ipsa_cm_mech_t *cm_mech, crypto_data_t *crypto_data)
7806 8048 {
7807 8049 cm_mech->combined_mech.cm_type = assoc->ipsa_emech.cm_type;
7808 8050 cm_mech->combined_mech.cm_param_len = 0;
7809 8051 cm_mech->combined_mech.cm_param = NULL;
7810 8052 crypto_data->cd_miscdata = (char *)iv_ptr;
7811 8053 }
7812 8054
7813 8055 /* ARGSUSED */
7814 8056 void
7815 8057 gcm_params_init(ipsa_t *assoc, uchar_t *esph, uint_t data_len, uchar_t *iv_ptr,
7816 8058 ipsa_cm_mech_t *cm_mech, crypto_data_t *crypto_data)
7817 8059 {
7818 8060 uchar_t *nonce;
7819 8061 crypto_mechanism_t *combined_mech;
7820 8062 CK_AES_GCM_PARAMS *params;
7821 8063
7822 8064 combined_mech = (crypto_mechanism_t *)cm_mech;
7823 8065 params = (CK_AES_GCM_PARAMS *)(combined_mech + 1);
7824 8066 nonce = (uchar_t *)(params + 1);
7825 8067
7826 8068 params->pIv = nonce;
7827 8069 params->ulIvLen = assoc->ipsa_nonce_len;
7828 8070 params->ulIvBits = SADB_8TO1(assoc->ipsa_nonce_len);
7829 8071 params->pAAD = esph;
7830 8072 params->ulAADLen = sizeof (esph_t);
7831 8073 params->ulTagBits = SADB_8TO1(assoc->ipsa_mac_len);
7832 8074
7833 8075 cm_mech->combined_mech.cm_type = assoc->ipsa_emech.cm_type;
7834 8076 cm_mech->combined_mech.cm_param_len = sizeof (CK_AES_GCM_PARAMS);
7835 8077 cm_mech->combined_mech.cm_param = (caddr_t)params;
7836 8078 /*
7837 8079 * Create the nonce, which is made up of the salt and the IV.
7838 8080 * Copy the salt from the SA and the IV from the packet.
7839 8081 * For inbound packets we copy the IV from the packet because it
7840 8082 * was set by the sending system, for outbound packets we copy the IV
7841 8083 * from the packet because the IV in the SA may be changed by another
7842 8084 * thread, the IV in the packet was created while holding a mutex.
7843 8085 */
7844 8086 bcopy(assoc->ipsa_nonce, nonce, assoc->ipsa_saltlen);
7845 8087 nonce += assoc->ipsa_saltlen;
7846 8088 bcopy(iv_ptr, nonce, assoc->ipsa_iv_len);
7847 8089 crypto_data->cd_miscdata = NULL;
7848 8090 }
|
↓ open down ↓ |
972 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX