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,127 **** { 0, 0xffffffffU, 0, "ipsecesp_default_hard_usetime"}, { 0, 1, 0, "ipsecesp_log_unknown_spi"}, { 0, 2, 1, "ipsecesp_padding_check"}, { 0, 600, 20, "ipsecesp_nat_keepalive_interval"}, }; - #define ipsecesp_debug ipsecesp_params[0].ipsecesp_param_value - #define ipsecesp_age_interval ipsecesp_params[1].ipsecesp_param_value - #define ipsecesp_age_int_max ipsecesp_params[1].ipsecesp_param_max - #define ipsecesp_reap_delay ipsecesp_params[2].ipsecesp_param_value - #define ipsecesp_replay_size ipsecesp_params[3].ipsecesp_param_value - #define ipsecesp_acquire_timeout \ - ipsecesp_params[4].ipsecesp_param_value - #define ipsecesp_larval_timeout \ - ipsecesp_params[5].ipsecesp_param_value - #define ipsecesp_default_soft_bytes \ - ipsecesp_params[6].ipsecesp_param_value - #define ipsecesp_default_hard_bytes \ - ipsecesp_params[7].ipsecesp_param_value - #define ipsecesp_default_soft_addtime \ - ipsecesp_params[8].ipsecesp_param_value - #define ipsecesp_default_hard_addtime \ - ipsecesp_params[9].ipsecesp_param_value - #define ipsecesp_default_soft_usetime \ - ipsecesp_params[10].ipsecesp_param_value - #define ipsecesp_default_hard_usetime \ - ipsecesp_params[11].ipsecesp_param_value - #define ipsecesp_log_unknown_spi \ - ipsecesp_params[12].ipsecesp_param_value - #define ipsecesp_padding_check \ - ipsecesp_params[13].ipsecesp_param_value /* For ipsecesp_nat_keepalive_interval, see ipsecesp.h. */ #define esp0dbg(a) printf a /* NOTE: != 0 instead of > 0 so lint doesn't complain. */ #define esp1dbg(espstack, a) if (espstack->ipsecesp_debug != 0) printf a --- 94,103 ----
*** 131,141 **** static int ipsecesp_open(queue_t *, dev_t *, int, int, cred_t *); static int ipsecesp_close(queue_t *); static void ipsecesp_wput(queue_t *, mblk_t *); static void *ipsecesp_stack_init(netstackid_t stackid, netstack_t *ns); static void ipsecesp_stack_fini(netstackid_t stackid, void *arg); - static void esp_send_acquire(ipsacq_t *, mblk_t *, netstack_t *); static void esp_prepare_udp(netstack_t *, mblk_t *, ipha_t *); static void esp_outbound_finish(mblk_t *, ip_xmit_attr_t *); static void esp_inbound_restart(mblk_t *, ip_recv_attr_t *); --- 107,116 ----
*** 179,234 **** * * Answer: Yes, because I need to know which queue is BOUND to * IPPROTO_ESP */ - /* - * Stats. This may eventually become a full-blown SNMP MIB once that spec - * stabilizes. - */ - - typedef struct esp_kstats_s { - kstat_named_t esp_stat_num_aalgs; - kstat_named_t esp_stat_good_auth; - kstat_named_t esp_stat_bad_auth; - kstat_named_t esp_stat_bad_padding; - kstat_named_t esp_stat_replay_failures; - kstat_named_t esp_stat_replay_early_failures; - kstat_named_t esp_stat_keysock_in; - kstat_named_t esp_stat_out_requests; - kstat_named_t esp_stat_acquire_requests; - kstat_named_t esp_stat_bytes_expired; - kstat_named_t esp_stat_out_discards; - kstat_named_t esp_stat_crypto_sync; - kstat_named_t esp_stat_crypto_async; - kstat_named_t esp_stat_crypto_failures; - kstat_named_t esp_stat_num_ealgs; - kstat_named_t esp_stat_bad_decrypt; - kstat_named_t esp_stat_sa_port_renumbers; - } esp_kstats_t; - - /* - * espstack->esp_kstats is equal to espstack->esp_ksp->ks_data if - * kstat_create_netstack for espstack->esp_ksp succeeds, but when it - * fails, it will be NULL. Note this is done for all stack instances, - * so it *could* fail. hence a non-NULL checking is done for - * ESP_BUMP_STAT and ESP_DEBUMP_STAT - */ - #define ESP_BUMP_STAT(espstack, x) \ - do { \ - if (espstack->esp_kstats != NULL) \ - (espstack->esp_kstats->esp_stat_ ## x).value.ui64++; \ - _NOTE(CONSTCOND) \ - } while (0) - - #define ESP_DEBUMP_STAT(espstack, x) \ - do { \ - if (espstack->esp_kstats != NULL) \ - (espstack->esp_kstats->esp_stat_ ## x).value.ui64--; \ - _NOTE(CONSTCOND) \ - } while (0) - static int esp_kstat_update(kstat_t *, int); static boolean_t esp_kstat_init(ipsecesp_stack_t *espstack, netstackid_t stackid) { --- 154,163 ----
*** 296,311 **** netstack_rele(ns); return (-1); } ekp = (esp_kstats_t *)kp->ks_data; ! mutex_enter(&ipss->ipsec_alg_lock); ekp->esp_stat_num_aalgs.value.ui64 = ipss->ipsec_nalgs[IPSEC_ALG_AUTH]; ekp->esp_stat_num_ealgs.value.ui64 = ipss->ipsec_nalgs[IPSEC_ALG_ENCR]; ! mutex_exit(&ipss->ipsec_alg_lock); netstack_rele(ns); return (0); } --- 225,240 ---- netstack_rele(ns); return (-1); } ekp = (esp_kstats_t *)kp->ks_data; ! rw_enter(&ipss->ipsec_alg_lock, RW_READER); ekp->esp_stat_num_aalgs.value.ui64 = ipss->ipsec_nalgs[IPSEC_ALG_AUTH]; ekp->esp_stat_num_ealgs.value.ui64 = ipss->ipsec_nalgs[IPSEC_ALG_ENCR]; ! rw_exit(&ipss->ipsec_alg_lock); netstack_rele(ns); return (0); }
*** 501,510 **** --- 430,440 ---- } } } return (B_TRUE); } + /* * Initialize things for ESP for each stack instance */ static void * ipsecesp_stack_init(netstackid_t stackid, netstack_t *ns)
*** 525,535 **** (void) esp_kstat_init(espstack, stackid); espstack->esp_sadb.s_acquire_timeout = &espstack->ipsecesp_acquire_timeout; - espstack->esp_sadb.s_acqfn = esp_send_acquire; sadbp_init("ESP", &espstack->esp_sadb, SADB_SATYPE_ESP, esp_hash_size, espstack->ipsecesp_netstack); mutex_init(&espstack->ipsecesp_param_lock, NULL, MUTEX_DEFAULT, 0); --- 455,464 ----
*** 556,566 **** ipsecesp_stack_t *espstack = (ipsecesp_stack_t *)arg; if (espstack->esp_pfkey_q != NULL) { (void) quntimeout(espstack->esp_pfkey_q, espstack->esp_event); } - espstack->esp_sadb.s_acqfn = NULL; espstack->esp_sadb.s_acquire_timeout = NULL; sadbp_destroy(&espstack->esp_sadb, espstack->ipsecesp_netstack); ip_drop_unregister(&espstack->esp_dropper); mutex_destroy(&espstack->ipsecesp_param_lock); nd_free(&espstack->ipsecesp_g_nd); --- 485,494 ----
*** 1179,1361 **** /* submit the request to the crypto framework */ return (esp_submit_req_inbound(data_mp, ira, ipsa, (uint8_t *)esph - data_mp->b_rptr)); } - /* - * Perform the really difficult work of inserting the proposed situation. - * Called while holding the algorithm lock. - */ - static void - esp_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; - ipsecesp_stack_t *espstack = ns->netstack_ipsecesp; - 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 = espstack->ipsecesp_replay_size; - - /* - * Based upon algorithm properties, and what-not, prioritize a - * proposal, based on the ordering of the ESP algorithms in the - * alternatives in the policy rule or socket that was placed - * in the acquire record. - * - * For each action in policy list - * Add combination. If I've hit limit, return. - */ - - for (ap = acqrec->ipsacq_act; ap != NULL; - ap = ap->ipa_next) { - ipsec_alginfo_t *ealg = NULL; - ipsec_alginfo_t *aalg = NULL; - - if (ap->ipa_act.ipa_type != IPSEC_POLICY_APPLY) - continue; - - prot = &ap->ipa_act.ipa_apply; - - if (!(prot->ipp_use_esp)) - continue; - - if (prot->ipp_esp_auth_alg != 0) { - aalg = ipss->ipsec_alglists[IPSEC_ALG_AUTH] - [prot->ipp_esp_auth_alg]; - if (aalg == NULL || !ALG_VALID(aalg)) - continue; - } - - ASSERT(prot->ipp_encr_alg > 0); - ealg = ipss->ipsec_alglists[IPSEC_ALG_ENCR] - [prot->ipp_encr_alg]; - if (ealg == NULL || !ALG_VALID(ealg)) - continue; - - comb->sadb_comb_flags = 0; - comb->sadb_comb_reserved = 0; - comb->sadb_comb_encrypt = ealg->alg_id; - comb->sadb_comb_encrypt_minbits = - MAX(prot->ipp_espe_minbits, ealg->alg_ef_minbits); - comb->sadb_comb_encrypt_maxbits = - MIN(prot->ipp_espe_maxbits, ealg->alg_ef_maxbits); - - if (aalg == NULL) { - comb->sadb_comb_auth = 0; - comb->sadb_comb_auth_minbits = 0; - comb->sadb_comb_auth_maxbits = 0; - } else { - comb->sadb_comb_auth = aalg->alg_id; - comb->sadb_comb_auth_minbits = - MAX(prot->ipp_espa_minbits, aalg->alg_ef_minbits); - comb->sadb_comb_auth_maxbits = - MIN(prot->ipp_espa_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 = - espstack->ipsecesp_default_soft_bytes; - comb->sadb_comb_hard_bytes = - espstack->ipsecesp_default_hard_bytes; - comb->sadb_comb_soft_addtime = - espstack->ipsecesp_default_soft_addtime; - comb->sadb_comb_hard_addtime = - espstack->ipsecesp_default_hard_addtime; - comb->sadb_comb_soft_usetime = - espstack->ipsecesp_default_soft_usetime; - comb->sadb_comb_hard_usetime = - espstack->ipsecesp_default_hard_usetime; - - prop->sadb_prop_len += SADB_8TO64(sizeof (*comb)); - if (--combs == 0) - break; /* out of space.. */ - comb++; - } - } - - /* - * Prepare and actually send the SADB_ACQUIRE message to PF_KEY. - */ - static void - esp_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; - ipsecesp_stack_t *espstack = ns->netstack_ipsecesp; - ipsec_stack_t *ipss = ns->netstack_ipsec; - - ESP_BUMP_STAT(espstack, acquire_requests); - - if (espstack->esp_pfkey_q == NULL) { - mutex_exit(&acqrec->ipsacq_lock); - return; - } - - /* Set up ACQUIRE. */ - pfkeymp = sadb_setup_acquire(acqrec, SADB_SATYPE_ESP, - ns->netstack_ipsec); - if (pfkeymp == NULL) { - esp0dbg(("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] * - ipss->ipsec_nalgs[IPSEC_ALG_ENCR]; - 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); - esp_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(espstack->esp_pfkey_q, extended); - } - putnext(espstack->esp_pfkey_q, pfkeymp); - } - /* XXX refactor me */ /* * Handle the SADB_GETSPI message. Create a larval SA. */ static void --- 1107,1116 ----
*** 3041,3051 **** /* * Allocate the PF_KEY message that follows KEYSOCK_OUT. */ ! mutex_enter(&ipss->ipsec_alg_lock); /* * Fill SADB_REGISTER message's algorithm descriptors. Hold * down the lock while filling it. * * Return only valid algorithms, so the number of algorithms --- 2796,2806 ---- /* * Allocate the PF_KEY message that follows KEYSOCK_OUT. */ ! rw_enter(&ipss->ipsec_alg_lock, RW_READER); /* * Fill SADB_REGISTER message's algorithm descriptors. Hold * down the lock while filling it. * * Return only valid algorithms, so the number of algorithms
*** 3070,3080 **** allocsize += (num_ealgs * sizeof (*saalg)); allocsize += sizeof (*sasupp_encr); } keysock_out_mp->b_cont = allocb(allocsize, BPRI_HI); if (keysock_out_mp->b_cont == NULL) { ! mutex_exit(&ipss->ipsec_alg_lock); freemsg(keysock_out_mp); return (B_FALSE); } pfkey_msg_mp = keysock_out_mp->b_cont; pfkey_msg_mp->b_wptr += allocsize; --- 2825,2835 ---- allocsize += (num_ealgs * sizeof (*saalg)); allocsize += sizeof (*sasupp_encr); } keysock_out_mp->b_cont = allocb(allocsize, BPRI_HI); if (keysock_out_mp->b_cont == NULL) { ! rw_exit(&ipss->ipsec_alg_lock); freemsg(keysock_out_mp); return (B_FALSE); } pfkey_msg_mp = keysock_out_mp->b_cont; pfkey_msg_mp->b_wptr += allocsize;
*** 3164,3174 **** } current_aalgs = num_aalgs; current_ealgs = num_ealgs; ! 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); --- 2919,2929 ---- } current_aalgs = num_aalgs; current_ealgs = num_ealgs; ! 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);
*** 3689,3699 **** * XXX Policy : I'm not checking identities at this time, * but if I did, I'd do them here, before I sent * the weak key check up to the algorithm. */ ! mutex_enter(&ipss->ipsec_alg_lock); /* * First locate the authentication algorithm. */ #ifdef IPSEC_LATENCY_TEST --- 3444,3454 ---- * XXX Policy : I'm not checking identities at this time, * but if I did, I'd do them here, before I sent * the weak key check up to the algorithm. */ ! rw_enter(&ipss->ipsec_alg_lock, RW_READER); /* * First locate the authentication algorithm. */ #ifdef IPSEC_LATENCY_TEST
*** 3704,3714 **** ipsec_alginfo_t *aalg; aalg = ipss->ipsec_alglists[IPSEC_ALG_AUTH] [assoc->sadb_sa_auth]; if (aalg == NULL || !ALG_VALID(aalg)) { ! mutex_exit(&ipss->ipsec_alg_lock); esp1dbg(espstack, ("Couldn't find auth alg #%d.\n", assoc->sadb_sa_auth)); *diagnostic = SADB_X_DIAGNOSTIC_BAD_AALG; return (EINVAL); } --- 3459,3469 ---- ipsec_alginfo_t *aalg; aalg = ipss->ipsec_alglists[IPSEC_ALG_AUTH] [assoc->sadb_sa_auth]; if (aalg == NULL || !ALG_VALID(aalg)) { ! rw_exit(&ipss->ipsec_alg_lock); esp1dbg(espstack, ("Couldn't find auth alg #%d.\n", assoc->sadb_sa_auth)); *diagnostic = SADB_X_DIAGNOSTIC_BAD_AALG; return (EINVAL); }
*** 3719,3738 **** * this auth_alg is not defined with ALG_FLAG_VALID. If this * ever changes, the same check for SADB_AALG_NONE and * a auth_key != NULL should be made here ( see below). */ if (!ipsec_valid_key_size(akey->sadb_key_bits, aalg)) { ! mutex_exit(&ipss->ipsec_alg_lock); *diagnostic = SADB_X_DIAGNOSTIC_BAD_AKEYBITS; return (EINVAL); } ASSERT(aalg->alg_mech_type != CRYPTO_MECHANISM_INVALID); /* check key and fix parity if needed */ if (ipsec_check_key(aalg->alg_mech_type, akey, B_TRUE, diagnostic) != 0) { ! mutex_exit(&ipss->ipsec_alg_lock); return (EINVAL); } } /* --- 3474,3493 ---- * this auth_alg is not defined with ALG_FLAG_VALID. If this * ever changes, the same check for SADB_AALG_NONE and * a auth_key != NULL should be made here ( see below). */ if (!ipsec_valid_key_size(akey->sadb_key_bits, aalg)) { ! rw_exit(&ipss->ipsec_alg_lock); *diagnostic = SADB_X_DIAGNOSTIC_BAD_AKEYBITS; return (EINVAL); } ASSERT(aalg->alg_mech_type != CRYPTO_MECHANISM_INVALID); /* check key and fix parity if needed */ if (ipsec_check_key(aalg->alg_mech_type, akey, B_TRUE, diagnostic) != 0) { ! rw_exit(&ipss->ipsec_alg_lock); return (EINVAL); } } /*
*** 3743,3753 **** ipsec_alginfo_t *ealg; ealg = ipss->ipsec_alglists[IPSEC_ALG_ENCR] [assoc->sadb_sa_encrypt]; if (ealg == NULL || !ALG_VALID(ealg)) { ! mutex_exit(&ipss->ipsec_alg_lock); esp1dbg(espstack, ("Couldn't find encr alg #%d.\n", assoc->sadb_sa_encrypt)); *diagnostic = SADB_X_DIAGNOSTIC_BAD_EALG; return (EINVAL); } --- 3498,3508 ---- ipsec_alginfo_t *ealg; ealg = ipss->ipsec_alglists[IPSEC_ALG_ENCR] [assoc->sadb_sa_encrypt]; if (ealg == NULL || !ALG_VALID(ealg)) { ! rw_exit(&ipss->ipsec_alg_lock); esp1dbg(espstack, ("Couldn't find encr alg #%d.\n", assoc->sadb_sa_encrypt)); *diagnostic = SADB_X_DIAGNOSTIC_BAD_EALG; return (EINVAL); }
*** 3764,3787 **** keybits = ekey->sadb_key_bits; keybits -= ekey->sadb_key_reserved; keybits -= SADB_8TO1(ealg->alg_saltlen); if ((assoc->sadb_sa_encrypt == SADB_EALG_NULL) || (!ipsec_valid_key_size(keybits, ealg))) { ! mutex_exit(&ipss->ipsec_alg_lock); *diagnostic = SADB_X_DIAGNOSTIC_BAD_EKEYBITS; return (EINVAL); } ASSERT(ealg->alg_mech_type != CRYPTO_MECHANISM_INVALID); /* check key */ if (ipsec_check_key(ealg->alg_mech_type, ekey, B_FALSE, diagnostic) != 0) { ! mutex_exit(&ipss->ipsec_alg_lock); return (EINVAL); } } ! mutex_exit(&ipss->ipsec_alg_lock); return (esp_add_sa_finish(mp, (sadb_msg_t *)mp->b_cont->b_rptr, ksi, diagnostic, espstack)); } --- 3519,3542 ---- keybits = ekey->sadb_key_bits; keybits -= ekey->sadb_key_reserved; keybits -= SADB_8TO1(ealg->alg_saltlen); if ((assoc->sadb_sa_encrypt == SADB_EALG_NULL) || (!ipsec_valid_key_size(keybits, ealg))) { ! rw_exit(&ipss->ipsec_alg_lock); *diagnostic = SADB_X_DIAGNOSTIC_BAD_EKEYBITS; return (EINVAL); } ASSERT(ealg->alg_mech_type != CRYPTO_MECHANISM_INVALID); /* check key */ if (ipsec_check_key(ealg->alg_mech_type, ekey, B_FALSE, diagnostic) != 0) { ! rw_exit(&ipss->ipsec_alg_lock); return (EINVAL); } } ! rw_exit(&ipss->ipsec_alg_lock); return (esp_add_sa_finish(mp, (sadb_msg_t *)mp->b_cont->b_rptr, ksi, diagnostic, espstack)); }