Print this page
Bayard's initial drop, needs finishing, or at least testing.

*** 19,28 **** --- 19,29 ---- * CDDL HEADER END */ /* * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * Copyright (c) 2012 Nexenta Systems, Inc. All rights reserved. */ #include <sys/types.h> #include <sys/stream.h> #include <sys/stropts.h>
*** 93,116 **** { 0, 0xffffffffU, 28800, "ipsecah_default_hard_addtime"}, { 0, 0xffffffffU, 0, "ipsecah_default_soft_usetime"}, { 0, 0xffffffffU, 0, "ipsecah_default_hard_usetime"}, { 0, 1, 0, "ipsecah_log_unknown_spi"}, }; - #define ipsecah_debug ipsecah_params[0].ipsecah_param_value - #define ipsecah_age_interval ipsecah_params[1].ipsecah_param_value - #define ipsecah_age_int_max ipsecah_params[1].ipsecah_param_max - #define ipsecah_reap_delay ipsecah_params[2].ipsecah_param_value - #define ipsecah_replay_size ipsecah_params[3].ipsecah_param_value - #define ipsecah_acquire_timeout ipsecah_params[4].ipsecah_param_value - #define ipsecah_larval_timeout ipsecah_params[5].ipsecah_param_value - #define ipsecah_default_soft_bytes ipsecah_params[6].ipsecah_param_value - #define ipsecah_default_hard_bytes ipsecah_params[7].ipsecah_param_value - #define ipsecah_default_soft_addtime ipsecah_params[8].ipsecah_param_value - #define ipsecah_default_hard_addtime ipsecah_params[9].ipsecah_param_value - #define ipsecah_default_soft_usetime ipsecah_params[10].ipsecah_param_value - #define ipsecah_default_hard_usetime ipsecah_params[11].ipsecah_param_value - #define ipsecah_log_unknown_spi ipsecah_params[12].ipsecah_param_value #define ah0dbg(a) printf a /* NOTE: != 0 instead of > 0 so lint doesn't complain. */ #define ah1dbg(ahstack, a) if (ahstack->ipsecah_debug != 0) printf a #define ah2dbg(ahstack, a) if (ahstack->ipsecah_debug > 1) printf a --- 94,103 ----
*** 146,156 **** static void ah_outbound_finish(mblk_t *, ip_xmit_attr_t *); static int ipsecah_open(queue_t *, dev_t *, int, int, cred_t *); static int ipsecah_close(queue_t *); static void ipsecah_wput(queue_t *, mblk_t *); - static void ah_send_acquire(ipsacq_t *, mblk_t *, netstack_t *); static boolean_t ah_register_out(uint32_t, uint32_t, uint_t, ipsecah_stack_t *, cred_t *); static void *ipsecah_stack_init(netstackid_t stackid, netstack_t *ns); static void ipsecah_stack_fini(netstackid_t stackid, void *arg); --- 133,142 ----
*** 245,257 **** netstack_rele(ns); return (-1); } ekp = (ah_kstats_t *)kp->ks_data; ! mutex_enter(&ipss->ipsec_alg_lock); ekp->ah_stat_num_aalgs.value.ui64 = ipss->ipsec_nalgs[IPSEC_ALG_AUTH]; ! mutex_exit(&ipss->ipsec_alg_lock); netstack_rele(ns); return (0); } --- 231,243 ---- netstack_rele(ns); return (-1); } ekp = (ah_kstats_t *)kp->ks_data; ! rw_enter(&ipss->ipsec_alg_lock, RW_READER); ekp->ah_stat_num_aalgs.value.ui64 = ipss->ipsec_nalgs[IPSEC_ALG_AUTH]; ! rw_exit(&ipss->ipsec_alg_lock); netstack_rele(ns); return (0); }
*** 417,427 **** A_CNT(lcl_param_arr)); (void) ah_kstat_init(ahstack, stackid); ahstack->ah_sadb.s_acquire_timeout = &ahstack->ipsecah_acquire_timeout; - ahstack->ah_sadb.s_acqfn = ah_send_acquire; sadbp_init("AH", &ahstack->ah_sadb, SADB_SATYPE_AH, ah_hash_size, ahstack->ipsecah_netstack); mutex_init(&ahstack->ipsecah_param_lock, NULL, MUTEX_DEFAULT, 0); --- 403,412 ----
*** 448,458 **** ipsecah_stack_t *ahstack = (ipsecah_stack_t *)arg; if (ahstack->ah_pfkey_q != NULL) { (void) quntimeout(ahstack->ah_pfkey_q, ahstack->ah_event); } - ahstack->ah_sadb.s_acqfn = NULL; ahstack->ah_sadb.s_acquire_timeout = NULL; sadbp_destroy(&ahstack->ah_sadb, ahstack->ipsecah_netstack); ip_drop_unregister(&ahstack->ah_dropper); mutex_destroy(&ahstack->ipsecah_param_lock); nd_free(&ahstack->ipsecah_g_nd); --- 433,442 ----
*** 571,581 **** * Allocate the PF_KEY message that follows KEYSOCK_OUT. * The alg reader lock needs to be held while allocating * the variable part (i.e. the algorithms) of the message. */ ! mutex_enter(&ipss->ipsec_alg_lock); /* * Return only valid algorithms, so the number of algorithms * to send up may be less than the number of algorithm entries * in the table. --- 555,565 ---- * Allocate the PF_KEY message that follows KEYSOCK_OUT. * The alg reader lock needs to be held while allocating * the variable part (i.e. the algorithms) of the message. */ ! rw_enter(&ipss->ipsec_alg_lock, RW_READER); /* * Return only valid algorithms, so the number of algorithms * to send up may be less than the number of algorithm entries * in the table.
*** 593,603 **** allocsize += (num_aalgs * sizeof (*saalg)); allocsize += sizeof (*sasupp); } mp->b_cont = allocb(allocsize, BPRI_HI); if (mp->b_cont == NULL) { ! mutex_exit(&ipss->ipsec_alg_lock); freemsg(mp); return (B_FALSE); } mp->b_cont->b_wptr += allocsize; --- 577,587 ---- allocsize += (num_aalgs * sizeof (*saalg)); allocsize += sizeof (*sasupp); } mp->b_cont = allocb(allocsize, BPRI_HI); if (mp->b_cont == NULL) { ! rw_exit(&ipss->ipsec_alg_lock); freemsg(mp); return (B_FALSE); } mp->b_cont->b_wptr += allocsize;
*** 640,650 **** "ah_register_out()! Missed #%d.\n", i); #endif /* DEBUG */ nextext = (sadb_ext_t *)saalg; } ! mutex_exit(&ipss->ipsec_alg_lock); if (sens_tsl != NULL) { sens = (sadb_sens_t *)nextext; sadb_sens_from_label(sens, SADB_EXT_SENSITIVITY, sens_tsl, sens_len); --- 624,634 ---- "ah_register_out()! Missed #%d.\n", i); #endif /* DEBUG */ nextext = (sadb_ext_t *)saalg; } ! rw_exit(&ipss->ipsec_alg_lock); if (sens_tsl != NULL) { sens = (sadb_sens_t *)nextext; sadb_sens_from_label(sens, SADB_EXT_SENSITIVITY, sens_tsl, sens_len);
*** 1121,1156 **** * if I did, I'd do them here, before I sent the weak key * check up to the algorithm. */ /* verify that there is a mapping for the specified algorithm */ ! mutex_enter(&ipss->ipsec_alg_lock); aalg = ipss->ipsec_alglists[IPSEC_ALG_AUTH][assoc->sadb_sa_auth]; if (aalg == NULL || !ALG_VALID(aalg)) { ! mutex_exit(&ipss->ipsec_alg_lock); ah1dbg(ahstack, ("Couldn't find auth alg #%d.\n", assoc->sadb_sa_auth)); *diagnostic = SADB_X_DIAGNOSTIC_BAD_AALG; return (EINVAL); } ASSERT(aalg->alg_mech_type != CRYPTO_MECHANISM_INVALID); /* sanity check key sizes */ if (!ipsec_valid_key_size(key->sadb_key_bits, aalg)) { ! mutex_exit(&ipss->ipsec_alg_lock); *diagnostic = SADB_X_DIAGNOSTIC_BAD_AKEYBITS; return (EINVAL); } /* check key and fix parity if needed */ if (ipsec_check_key(aalg->alg_mech_type, key, B_TRUE, diagnostic) != 0) { ! mutex_exit(&ipss->ipsec_alg_lock); return (EINVAL); } ! mutex_exit(&ipss->ipsec_alg_lock); return (ah_add_sa_finish(mp, (sadb_msg_t *)mp->b_cont->b_rptr, ksi, diagnostic, ahstack)); } --- 1105,1140 ---- * if I did, I'd do them here, before I sent the weak key * check up to the algorithm. */ /* verify that there is a mapping for the specified algorithm */ ! rw_enter(&ipss->ipsec_alg_lock, RW_READER); aalg = ipss->ipsec_alglists[IPSEC_ALG_AUTH][assoc->sadb_sa_auth]; if (aalg == NULL || !ALG_VALID(aalg)) { ! rw_exit(&ipss->ipsec_alg_lock); ah1dbg(ahstack, ("Couldn't find auth alg #%d.\n", assoc->sadb_sa_auth)); *diagnostic = SADB_X_DIAGNOSTIC_BAD_AALG; return (EINVAL); } ASSERT(aalg->alg_mech_type != CRYPTO_MECHANISM_INVALID); /* sanity check key sizes */ if (!ipsec_valid_key_size(key->sadb_key_bits, aalg)) { ! rw_exit(&ipss->ipsec_alg_lock); *diagnostic = SADB_X_DIAGNOSTIC_BAD_AKEYBITS; return (EINVAL); } /* check key and fix parity if needed */ if (ipsec_check_key(aalg->alg_mech_type, key, B_TRUE, diagnostic) != 0) { ! rw_exit(&ipss->ipsec_alg_lock); return (EINVAL); } ! rw_exit(&ipss->ipsec_alg_lock); return (ah_add_sa_finish(mp, (sadb_msg_t *)mp->b_cont->b_rptr, ksi, diagnostic, ahstack)); }
*** 1733,1896 **** } return (inrc && outrc); } - /* - * Perform the really difficult work of inserting the proposed situation. - * Called while holding the algorithm lock. - */ - static void - ah_insert_prop(sadb_prop_t *prop, ipsacq_t *acqrec, uint_t combs, - netstack_t *ns) - { - sadb_comb_t *comb = (sadb_comb_t *)(prop + 1); - ipsec_action_t *ap; - ipsec_prot_t *prot; - ipsecah_stack_t *ahstack = ns->netstack_ipsecah; - ipsec_stack_t *ipss = ns->netstack_ipsec; - - ASSERT(MUTEX_HELD(&ipss->ipsec_alg_lock)); - - prop->sadb_prop_exttype = SADB_EXT_PROPOSAL; - prop->sadb_prop_len = SADB_8TO64(sizeof (sadb_prop_t)); - *(uint32_t *)(&prop->sadb_prop_replay) = 0; /* Quick zero-out! */ - - prop->sadb_prop_replay = ahstack->ipsecah_replay_size; - - /* - * Based upon algorithm properties, and what-not, prioritize a - * proposal, based on the ordering of the AH algorithms in the - * alternatives in the policy rule or socket that was placed - * in the acquire record. - */ - - for (ap = acqrec->ipsacq_act; ap != NULL; - ap = ap->ipa_next) { - ipsec_alginfo_t *aalg; - - if ((ap->ipa_act.ipa_type != IPSEC_POLICY_APPLY) || - (!ap->ipa_act.ipa_apply.ipp_use_ah)) - continue; - - prot = &ap->ipa_act.ipa_apply; - - ASSERT(prot->ipp_auth_alg > 0); - - aalg = ipss->ipsec_alglists[IPSEC_ALG_AUTH] - [prot->ipp_auth_alg]; - if (aalg == NULL || !ALG_VALID(aalg)) - continue; - - /* XXX check aalg for duplicates??.. */ - - comb->sadb_comb_flags = 0; - comb->sadb_comb_reserved = 0; - comb->sadb_comb_encrypt = 0; - comb->sadb_comb_encrypt_minbits = 0; - comb->sadb_comb_encrypt_maxbits = 0; - - comb->sadb_comb_auth = aalg->alg_id; - comb->sadb_comb_auth_minbits = - MAX(prot->ipp_ah_minbits, aalg->alg_ef_minbits); - comb->sadb_comb_auth_maxbits = - MIN(prot->ipp_ah_maxbits, aalg->alg_ef_maxbits); - - /* - * The following may be based on algorithm - * properties, but in the meantime, we just pick - * some good, sensible numbers. Key mgmt. can - * (and perhaps should) be the place to finalize - * such decisions. - */ - - /* - * No limits on allocations, since we really don't - * support that concept currently. - */ - comb->sadb_comb_soft_allocations = 0; - comb->sadb_comb_hard_allocations = 0; - - /* - * These may want to come from policy rule.. - */ - comb->sadb_comb_soft_bytes = - ahstack->ipsecah_default_soft_bytes; - comb->sadb_comb_hard_bytes = - ahstack->ipsecah_default_hard_bytes; - comb->sadb_comb_soft_addtime = - ahstack->ipsecah_default_soft_addtime; - comb->sadb_comb_hard_addtime = - ahstack->ipsecah_default_hard_addtime; - comb->sadb_comb_soft_usetime = - ahstack->ipsecah_default_soft_usetime; - comb->sadb_comb_hard_usetime = - ahstack->ipsecah_default_hard_usetime; - - prop->sadb_prop_len += SADB_8TO64(sizeof (*comb)); - if (--combs == 0) - return; /* out of space.. */ - comb++; - } - } - - /* - * Prepare and actually send the SADB_ACQUIRE message to PF_KEY. - */ - static void - ah_send_acquire(ipsacq_t *acqrec, mblk_t *extended, netstack_t *ns) - { - uint_t combs; - sadb_msg_t *samsg; - sadb_prop_t *prop; - mblk_t *pfkeymp, *msgmp; - ipsecah_stack_t *ahstack = ns->netstack_ipsecah; - ipsec_stack_t *ipss = ns->netstack_ipsec; - - AH_BUMP_STAT(ahstack, acquire_requests); - - if (ahstack->ah_pfkey_q == NULL) { - mutex_exit(&acqrec->ipsacq_lock); - return; - } - - /* Set up ACQUIRE. */ - pfkeymp = sadb_setup_acquire(acqrec, SADB_SATYPE_AH, - ns->netstack_ipsec); - if (pfkeymp == NULL) { - ah0dbg(("sadb_setup_acquire failed.\n")); - mutex_exit(&acqrec->ipsacq_lock); - return; - } - ASSERT(MUTEX_HELD(&ipss->ipsec_alg_lock)); - combs = ipss->ipsec_nalgs[IPSEC_ALG_AUTH]; - msgmp = pfkeymp->b_cont; - samsg = (sadb_msg_t *)(msgmp->b_rptr); - - /* Insert proposal here. */ - - prop = (sadb_prop_t *)(((uint64_t *)samsg) + samsg->sadb_msg_len); - ah_insert_prop(prop, acqrec, combs, ns); - samsg->sadb_msg_len += prop->sadb_prop_len; - msgmp->b_wptr += SADB_64TO8(samsg->sadb_msg_len); - - mutex_exit(&ipss->ipsec_alg_lock); - - /* - * Must mutex_exit() before sending PF_KEY message up, in - * order to avoid recursive mutex_enter() if there are no registered - * listeners. - * - * Once I've sent the message, I'm cool anyway. - */ - mutex_exit(&acqrec->ipsacq_lock); - if (extended != NULL) { - putnext(ahstack->ah_pfkey_q, extended); - } - putnext(ahstack->ah_pfkey_q, pfkeymp); - } - /* Refactor me */ /* * Handle the SADB_GETSPI message. Create a larval SA. */ static void --- 1717,1726 ----