1a6d42e7dSPeter Dunlap /* 2a6d42e7dSPeter Dunlap * CDDL HEADER START 3a6d42e7dSPeter Dunlap * 4a6d42e7dSPeter Dunlap * The contents of this file are subject to the terms of the 5a6d42e7dSPeter Dunlap * Common Development and Distribution License (the "License"). 6a6d42e7dSPeter Dunlap * You may not use this file except in compliance with the License. 7a6d42e7dSPeter Dunlap * 8a6d42e7dSPeter Dunlap * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9a6d42e7dSPeter Dunlap * or http://www.opensolaris.org/os/licensing. 10a6d42e7dSPeter Dunlap * See the License for the specific language governing permissions 11a6d42e7dSPeter Dunlap * and limitations under the License. 12a6d42e7dSPeter Dunlap * 13a6d42e7dSPeter Dunlap * When distributing Covered Code, include this CDDL HEADER in each 14a6d42e7dSPeter Dunlap * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15a6d42e7dSPeter Dunlap * If applicable, add the following below this CDDL HEADER, with the 16a6d42e7dSPeter Dunlap * fields enclosed by brackets "[]" replaced with your own identifying 17a6d42e7dSPeter Dunlap * information: Portions Copyright [yyyy] [name of copyright owner] 18a6d42e7dSPeter Dunlap * 19a6d42e7dSPeter Dunlap * CDDL HEADER END 20a6d42e7dSPeter Dunlap */ 21a6d42e7dSPeter Dunlap /* 222ef9abdcSjv * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23a6d42e7dSPeter Dunlap * Use is subject to license terms. 24a6d42e7dSPeter Dunlap */ 25a6d42e7dSPeter Dunlap 26a6d42e7dSPeter Dunlap #include <sys/cpuvar.h> 27a6d42e7dSPeter Dunlap #include <sys/types.h> 28a6d42e7dSPeter Dunlap #include <sys/conf.h> 29a6d42e7dSPeter Dunlap #include <sys/file.h> 30a6d42e7dSPeter Dunlap #include <sys/ddi.h> 31a6d42e7dSPeter Dunlap #include <sys/sunddi.h> 32a6d42e7dSPeter Dunlap #include <sys/modctl.h> 33a6d42e7dSPeter Dunlap 34a6d42e7dSPeter Dunlap #include <sys/socket.h> 35a6d42e7dSPeter Dunlap #include <sys/strsubr.h> 36a6d42e7dSPeter Dunlap #include <sys/sysmacros.h> 37a6d42e7dSPeter Dunlap 38a6d42e7dSPeter Dunlap #include <sys/stmf.h> 39a6d42e7dSPeter Dunlap #include <sys/stmf_ioctl.h> 40a6d42e7dSPeter Dunlap #include <sys/portif.h> 41a6d42e7dSPeter Dunlap #include <sys/idm/idm.h> 42a6d42e7dSPeter Dunlap #include <sys/idm/idm_text.h> 43a6d42e7dSPeter Dunlap #include <iscsit.h> 44a6d42e7dSPeter Dunlap #include <iscsit_auth.h> 45a6d42e7dSPeter Dunlap 46a6d42e7dSPeter Dunlap static kv_status_t 47a6d42e7dSPeter Dunlap iscsit_select_auth(iscsit_conn_t *ict, nvpair_t *nvp, 48a6d42e7dSPeter Dunlap const idm_kv_xlate_t *ikvx); 49a6d42e7dSPeter Dunlap 50a6d42e7dSPeter Dunlap static kv_status_t 51a6d42e7dSPeter Dunlap auth_propose_chap(iscsit_conn_t *ict, nvpair_t *nvp, 52a6d42e7dSPeter Dunlap const idm_kv_xlate_t *ikvx); 53a6d42e7dSPeter Dunlap 54a6d42e7dSPeter Dunlap static kv_status_t 55a6d42e7dSPeter Dunlap auth_chap_select_alg(iscsit_conn_t *ict, nvpair_t *nvp, 56a6d42e7dSPeter Dunlap const idm_kv_xlate_t *ikvx); 57a6d42e7dSPeter Dunlap 58a6d42e7dSPeter Dunlap static kv_status_t 59a6d42e7dSPeter Dunlap auth_chap_recv_n(iscsit_conn_t *ict, nvpair_t *nvp, 60a6d42e7dSPeter Dunlap const idm_kv_xlate_t *ikvx); 61a6d42e7dSPeter Dunlap 62a6d42e7dSPeter Dunlap static kv_status_t 63a6d42e7dSPeter Dunlap auth_chap_recv_r(iscsit_conn_t *ict, nvpair_t *nvp, 64a6d42e7dSPeter Dunlap const idm_kv_xlate_t *ikvx); 65a6d42e7dSPeter Dunlap 66a6d42e7dSPeter Dunlap static kv_status_t 67a6d42e7dSPeter Dunlap auth_chap_recv_i(iscsit_conn_t *ict, nvpair_t *nvp, 68a6d42e7dSPeter Dunlap const idm_kv_xlate_t *ikvx); 69a6d42e7dSPeter Dunlap 70a6d42e7dSPeter Dunlap static kv_status_t 71a6d42e7dSPeter Dunlap auth_chap_recv_c(iscsit_conn_t *ict, nvpair_t *nvp, 72a6d42e7dSPeter Dunlap const idm_kv_xlate_t *ikvx); 73a6d42e7dSPeter Dunlap 74a6d42e7dSPeter Dunlap static kv_status_t 75a6d42e7dSPeter Dunlap iscsit_auth_propose(iscsit_conn_t *ict, nvpair_t *nvp, 76a6d42e7dSPeter Dunlap const idm_kv_xlate_t *ikvx); 77a6d42e7dSPeter Dunlap 78a6d42e7dSPeter Dunlap static kv_status_t 79a6d42e7dSPeter Dunlap iscsit_auth_expect_key(iscsit_conn_t *ict, nvpair_t *nvp, 80a6d42e7dSPeter Dunlap const idm_kv_xlate_t *ikvx); 81a6d42e7dSPeter Dunlap 82a6d42e7dSPeter Dunlap static kv_status_t 83a6d42e7dSPeter Dunlap auth_chap_expect_r(iscsit_conn_t *ict, nvpair_t *nvp, 84a6d42e7dSPeter Dunlap const idm_kv_xlate_t *ikvx); 85a6d42e7dSPeter Dunlap 86a6d42e7dSPeter Dunlap static kv_status_t 87a6d42e7dSPeter Dunlap auth_chap_done(iscsit_conn_t *ict, nvpair_t *nvp, 88a6d42e7dSPeter Dunlap const idm_kv_xlate_t *ikvx); 89a6d42e7dSPeter Dunlap 90a6d42e7dSPeter Dunlap static kv_status_t 91a6d42e7dSPeter Dunlap iscsit_auth_gen_challenge(iscsit_conn_t *ict); 92a6d42e7dSPeter Dunlap 93a6d42e7dSPeter Dunlap static kv_status_t 94a6d42e7dSPeter Dunlap iscsit_auth_gen_response(iscsit_conn_t *ict); 95a6d42e7dSPeter Dunlap 96a6d42e7dSPeter Dunlap typedef struct { 97a6d42e7dSPeter Dunlap iscsit_auth_phase_t phase; 98a6d42e7dSPeter Dunlap iscsikey_id_t kv_id; 99a6d42e7dSPeter Dunlap iscsit_auth_handler_t handler; 100a6d42e7dSPeter Dunlap } auth_phase_entry_t; 101a6d42e7dSPeter Dunlap 102a6d42e7dSPeter Dunlap /* 103a6d42e7dSPeter Dunlap * This table defines all authentication phases which have valid 104a6d42e7dSPeter Dunlap * handler. The entries which have a non-zero key index are for 105a6d42e7dSPeter Dunlap * a key/value pair handling when a key/value is being received, 106a6d42e7dSPeter Dunlap * the rest of entries are for target checking the authentication 107a6d42e7dSPeter Dunlap * phase after all key/value pair(s) are handled. 108a6d42e7dSPeter Dunlap */ 109a6d42e7dSPeter Dunlap static const auth_phase_entry_t apet[] = { 110a6d42e7dSPeter Dunlap /* by key */ 111a6d42e7dSPeter Dunlap { AP_AM_UNDECIDED, KI_AUTH_METHOD, iscsit_select_auth }, 112a6d42e7dSPeter Dunlap { AP_AM_PROPOSED, KI_CHAP_A, auth_propose_chap }, 113a6d42e7dSPeter Dunlap 114a6d42e7dSPeter Dunlap { AP_CHAP_A_WAITING, KI_CHAP_A, auth_chap_select_alg }, 115a6d42e7dSPeter Dunlap { AP_CHAP_R_WAITING, KI_CHAP_N, auth_chap_recv_n }, 116a6d42e7dSPeter Dunlap { AP_CHAP_R_WAITING, KI_CHAP_R, auth_chap_recv_r }, 117a6d42e7dSPeter Dunlap { AP_CHAP_R_WAITING, KI_CHAP_I, auth_chap_recv_i }, 118a6d42e7dSPeter Dunlap { AP_CHAP_R_WAITING, KI_CHAP_C, auth_chap_recv_c }, 119a6d42e7dSPeter Dunlap { AP_CHAP_R_RCVD, KI_CHAP_N, auth_chap_recv_n }, 120a6d42e7dSPeter Dunlap { AP_CHAP_R_RCVD, KI_CHAP_R, auth_chap_recv_r }, 121a6d42e7dSPeter Dunlap { AP_CHAP_R_RCVD, KI_CHAP_I, auth_chap_recv_i }, 122a6d42e7dSPeter Dunlap { AP_CHAP_R_RCVD, KI_CHAP_C, auth_chap_recv_c }, 123a6d42e7dSPeter Dunlap 124a6d42e7dSPeter Dunlap /* by target */ 125a6d42e7dSPeter Dunlap { AP_AM_UNDECIDED, 0, iscsit_auth_propose }, 126a6d42e7dSPeter Dunlap { AP_AM_DECIDED, 0, iscsit_auth_expect_key }, 127a6d42e7dSPeter Dunlap 128a6d42e7dSPeter Dunlap { AP_CHAP_A_RCVD, 0, auth_chap_expect_r }, 129a6d42e7dSPeter Dunlap { AP_CHAP_R_RCVD, 0, auth_chap_done } 130a6d42e7dSPeter Dunlap }; 131a6d42e7dSPeter Dunlap 132a6d42e7dSPeter Dunlap typedef struct { 133a6d42e7dSPeter Dunlap iscsit_auth_method_t am_id; 134a6d42e7dSPeter Dunlap char *am_name; 135a6d42e7dSPeter Dunlap } auth_id_name_t; 136a6d42e7dSPeter Dunlap 137a6d42e7dSPeter Dunlap /* 138a6d42e7dSPeter Dunlap * a table of mapping from the authentication index to name. 139a6d42e7dSPeter Dunlap */ 140a6d42e7dSPeter Dunlap static const auth_id_name_t aint[] = { 141a6d42e7dSPeter Dunlap { AM_CHAP, "CHAP" }, 142a6d42e7dSPeter Dunlap { AM_NONE, "None" }, 143a6d42e7dSPeter Dunlap /* { AM_KRB5, "KRB5" }, */ /* Not supported */ 144a6d42e7dSPeter Dunlap /* { AM_SPKM1, "SPKM1" }, */ /* Not supported */ 145a6d42e7dSPeter Dunlap /* { AM_SPKM2, "SPKM2" }, */ /* Not supported */ 146a6d42e7dSPeter Dunlap /* { AM_SRP, "SRP" }, */ /* Not supported */ 147a6d42e7dSPeter Dunlap }; 148a6d42e7dSPeter Dunlap 149a6d42e7dSPeter Dunlap #define ARRAY_LENGTH(ARRAY) (sizeof (ARRAY) / sizeof (ARRAY[0])) 150a6d42e7dSPeter Dunlap 151a6d42e7dSPeter Dunlap /* 152a6d42e7dSPeter Dunlap * get the authentication method name for the method id. 153a6d42e7dSPeter Dunlap */ 154a6d42e7dSPeter Dunlap static const char * 155a6d42e7dSPeter Dunlap am_id_to_name(int id) 156a6d42e7dSPeter Dunlap { 157a6d42e7dSPeter Dunlap int i; 158a6d42e7dSPeter Dunlap const auth_id_name_t *p; 159a6d42e7dSPeter Dunlap i = 0; 160a6d42e7dSPeter Dunlap while (i < ARRAY_LENGTH(aint)) { 161a6d42e7dSPeter Dunlap p = &(aint[i]); 162a6d42e7dSPeter Dunlap if (id == p->am_id) { 163a6d42e7dSPeter Dunlap return (p->am_name); 164a6d42e7dSPeter Dunlap } 165a6d42e7dSPeter Dunlap i ++; 166a6d42e7dSPeter Dunlap } 167a6d42e7dSPeter Dunlap 168a6d42e7dSPeter Dunlap return (NULL); 169a6d42e7dSPeter Dunlap } 170a6d42e7dSPeter Dunlap 171a6d42e7dSPeter Dunlap /* 172a6d42e7dSPeter Dunlap * Look for an apporiate function handler which is defined for 173a6d42e7dSPeter Dunlap * current authentication phase and matches the key which is 174a6d42e7dSPeter Dunlap * being handled. The key index is passed in as zero when it 175a6d42e7dSPeter Dunlap * is looking for an handler for checking the authentication phase 176a6d42e7dSPeter Dunlap * after all security keys are handled. 177a6d42e7dSPeter Dunlap */ 178a6d42e7dSPeter Dunlap iscsit_auth_handler_t 179a6d42e7dSPeter Dunlap iscsit_auth_get_handler(iscsit_auth_client_t *client, iscsikey_id_t kv_id) 180a6d42e7dSPeter Dunlap { 181a6d42e7dSPeter Dunlap iscsit_auth_phase_t phase = client->phase; 182a6d42e7dSPeter Dunlap int i; 183a6d42e7dSPeter Dunlap const auth_phase_entry_t *p; 184a6d42e7dSPeter Dunlap 185a6d42e7dSPeter Dunlap i = 0; 186a6d42e7dSPeter Dunlap p = NULL; 187a6d42e7dSPeter Dunlap while (i < ARRAY_LENGTH(apet)) { 188a6d42e7dSPeter Dunlap p = &(apet[i]); 189a6d42e7dSPeter Dunlap if (phase == p->phase && 190a6d42e7dSPeter Dunlap kv_id == p->kv_id) { 191a6d42e7dSPeter Dunlap return (p->handler); 192a6d42e7dSPeter Dunlap } 193a6d42e7dSPeter Dunlap i ++; 194a6d42e7dSPeter Dunlap } 195a6d42e7dSPeter Dunlap 196a6d42e7dSPeter Dunlap /* No handler can be found, it must be an invalid requst. */ 197a6d42e7dSPeter Dunlap return (NULL); 198a6d42e7dSPeter Dunlap } 199a6d42e7dSPeter Dunlap 200a6d42e7dSPeter Dunlap /* 201a6d42e7dSPeter Dunlap * Select an authentication method from a list of values proposed 202a6d42e7dSPeter Dunlap * by initiator. After a valid method is selected, shift the 203a6d42e7dSPeter Dunlap * authentication phase to AP_AM_DECIDED. 204a6d42e7dSPeter Dunlap */ 205a6d42e7dSPeter Dunlap static kv_status_t 206a6d42e7dSPeter Dunlap iscsit_select_auth(iscsit_conn_t *ict, nvpair_t *nvp, 207a6d42e7dSPeter Dunlap const idm_kv_xlate_t *ikvx) 208a6d42e7dSPeter Dunlap { 209a6d42e7dSPeter Dunlap iscsit_conn_login_t *lsm = &ict->ict_login_sm; 210a6d42e7dSPeter Dunlap conn_auth_t *auth = &lsm->icl_auth; 211a6d42e7dSPeter Dunlap iscsit_auth_method_t *am_list = &auth->ca_method_valid_list[0]; 212a6d42e7dSPeter Dunlap iscsit_auth_client_t *client = &lsm->icl_auth_client; 213a6d42e7dSPeter Dunlap int nvrc; 214a6d42e7dSPeter Dunlap kv_status_t kvrc; 215a6d42e7dSPeter Dunlap nvpair_t *am_choice; 216a6d42e7dSPeter Dunlap char *am; 217a6d42e7dSPeter Dunlap const char *am_name; 218a6d42e7dSPeter Dunlap const char *text; 219a6d42e7dSPeter Dunlap iscsit_auth_method_t am_id; 220a6d42e7dSPeter Dunlap int i; 221a6d42e7dSPeter Dunlap 222a6d42e7dSPeter Dunlap client->phase = AP_AM_DECIDED; 223a6d42e7dSPeter Dunlap 224a6d42e7dSPeter Dunlap /* select a valid authentication method */ 225a6d42e7dSPeter Dunlap am_choice = idm_get_next_listvalue(nvp, NULL); 226a6d42e7dSPeter Dunlap while (am_choice != NULL) { 227a6d42e7dSPeter Dunlap nvrc = nvpair_value_string(am_choice, &am); 228a6d42e7dSPeter Dunlap ASSERT(nvrc == 0); 229a6d42e7dSPeter Dunlap 230a6d42e7dSPeter Dunlap i = 0; 231a6d42e7dSPeter Dunlap am_id = am_list[i]; 232a6d42e7dSPeter Dunlap while (am_id != 0) { 233a6d42e7dSPeter Dunlap am_name = am_id_to_name(am_id); 234a6d42e7dSPeter Dunlap if (strcasecmp(am, am_name) == 0) { 235a6d42e7dSPeter Dunlap text = am; 236a6d42e7dSPeter Dunlap goto am_decided; 237a6d42e7dSPeter Dunlap } 238a6d42e7dSPeter Dunlap i++; 239a6d42e7dSPeter Dunlap am_id = am_list[i]; 240a6d42e7dSPeter Dunlap } 241a6d42e7dSPeter Dunlap am_choice = idm_get_next_listvalue(nvp, am_choice); 242a6d42e7dSPeter Dunlap } 243a6d42e7dSPeter Dunlap 244a6d42e7dSPeter Dunlap /* none of authentication method is valid */ 245a6d42e7dSPeter Dunlap am_id = 0; 246a6d42e7dSPeter Dunlap text = ISCSI_TEXT_REJECT; 247a6d42e7dSPeter Dunlap 248a6d42e7dSPeter Dunlap am_decided: 249a6d42e7dSPeter Dunlap client->negotiatedMethod = am_id; 250a6d42e7dSPeter Dunlap /* add the selected method to the response nvlist */ 251a6d42e7dSPeter Dunlap nvrc = nvlist_add_string(lsm->icl_response_nvlist, 252a6d42e7dSPeter Dunlap ikvx->ik_key_name, text); 253a6d42e7dSPeter Dunlap kvrc = idm_nvstat_to_kvstat(nvrc); 254a6d42e7dSPeter Dunlap 255a6d42e7dSPeter Dunlap return (kvrc); 256a6d42e7dSPeter Dunlap } 257a6d42e7dSPeter Dunlap 258a6d42e7dSPeter Dunlap /* 259a6d42e7dSPeter Dunlap * Initiator chooses to use CHAP after target proposed a list of 260a6d42e7dSPeter Dunlap * authentication method. Set the authentication method to CHAP and 261a6d42e7dSPeter Dunlap * continue on chap authentication phase. 262a6d42e7dSPeter Dunlap */ 263a6d42e7dSPeter Dunlap static kv_status_t 264a6d42e7dSPeter Dunlap auth_propose_chap(iscsit_conn_t *ict, nvpair_t *nvp, 265a6d42e7dSPeter Dunlap const idm_kv_xlate_t *ikvx) 266a6d42e7dSPeter Dunlap { 267a6d42e7dSPeter Dunlap iscsit_conn_login_t *lsm = &ict->ict_login_sm; 268a6d42e7dSPeter Dunlap iscsit_auth_client_t *client = &lsm->icl_auth_client; 269a6d42e7dSPeter Dunlap 270a6d42e7dSPeter Dunlap client->negotiatedMethod = AM_CHAP; 271a6d42e7dSPeter Dunlap client->phase = AP_AM_DECIDED; 272a6d42e7dSPeter Dunlap 273a6d42e7dSPeter Dunlap return (auth_chap_select_alg(ict, nvp, ikvx)); 274a6d42e7dSPeter Dunlap } 275a6d42e7dSPeter Dunlap 276a6d42e7dSPeter Dunlap /* 277a6d42e7dSPeter Dunlap * Select a CHAP algorithm from a list of values proposed by 278a6d42e7dSPeter Dunlap * initiator and shift the authentication phase to AP_CHAP_A_RCVD. 279a6d42e7dSPeter Dunlap */ 280a6d42e7dSPeter Dunlap static kv_status_t 281a6d42e7dSPeter Dunlap auth_chap_select_alg(iscsit_conn_t *ict, nvpair_t *nvp, 282a6d42e7dSPeter Dunlap const idm_kv_xlate_t *ikvx) 283a6d42e7dSPeter Dunlap { 284a6d42e7dSPeter Dunlap iscsit_conn_login_t *lsm = &ict->ict_login_sm; 285a6d42e7dSPeter Dunlap iscsit_auth_client_t *client = &lsm->icl_auth_client; 286a6d42e7dSPeter Dunlap int nvrc, rc; 287a6d42e7dSPeter Dunlap kv_status_t kvrc; 288a6d42e7dSPeter Dunlap nvpair_t *alg_choice; 289a6d42e7dSPeter Dunlap char *alg_string; 290a6d42e7dSPeter Dunlap uint64_t alg; 291a6d42e7dSPeter Dunlap const char *text; 292a6d42e7dSPeter Dunlap 293a6d42e7dSPeter Dunlap client->phase = AP_CHAP_A_RCVD; 294a6d42e7dSPeter Dunlap 295a6d42e7dSPeter Dunlap alg_choice = idm_get_next_listvalue(nvp, NULL); 296a6d42e7dSPeter Dunlap while (alg_choice != NULL) { 297a6d42e7dSPeter Dunlap nvrc = nvpair_value_string(alg_choice, &alg_string); 298a6d42e7dSPeter Dunlap ASSERT(nvrc == 0); 2992ef9abdcSjv rc = ddi_strtoull(alg_string, NULL, 0, (u_longlong_t *)&alg); 300a6d42e7dSPeter Dunlap if (rc == 0 && alg == 5) { 301a6d42e7dSPeter Dunlap /* only MD5 is supported */ 302a6d42e7dSPeter Dunlap text = alg_string; 303a6d42e7dSPeter Dunlap goto alg_selected; 304a6d42e7dSPeter Dunlap } 305a6d42e7dSPeter Dunlap 306a6d42e7dSPeter Dunlap alg_choice = idm_get_next_listvalue(nvp, alg_choice); 307a6d42e7dSPeter Dunlap } 308a6d42e7dSPeter Dunlap 309a6d42e7dSPeter Dunlap /* none of algorithm is selected */ 310a6d42e7dSPeter Dunlap alg = 0; 311a6d42e7dSPeter Dunlap text = ISCSI_TEXT_REJECT; 312a6d42e7dSPeter Dunlap 313a6d42e7dSPeter Dunlap alg_selected: 314a6d42e7dSPeter Dunlap /* save the selected algorithm or zero for none is selected */ 315a6d42e7dSPeter Dunlap client_set_numeric_data( 316a6d42e7dSPeter Dunlap &client->recvKeyBlock, 317a6d42e7dSPeter Dunlap AKT_CHAP_A, 318a6d42e7dSPeter Dunlap (uint32_t)alg); 319a6d42e7dSPeter Dunlap 320a6d42e7dSPeter Dunlap /* add the selected algorithm to the response nvlist */ 321a6d42e7dSPeter Dunlap nvrc = nvlist_add_string(lsm->icl_response_nvlist, 322a6d42e7dSPeter Dunlap ikvx->ik_key_name, text); 323a6d42e7dSPeter Dunlap if (alg == 0) { 324a6d42e7dSPeter Dunlap kvrc = KV_AUTH_FAILED; /* No algorithm selected */ 325a6d42e7dSPeter Dunlap } else { 326a6d42e7dSPeter Dunlap kvrc = idm_nvstat_to_kvstat(nvrc); 327a6d42e7dSPeter Dunlap if (kvrc == 0) { 328a6d42e7dSPeter Dunlap kvrc = iscsit_auth_gen_challenge(ict); 329a6d42e7dSPeter Dunlap } 330a6d42e7dSPeter Dunlap } 331a6d42e7dSPeter Dunlap 332a6d42e7dSPeter Dunlap return (kvrc); 333a6d42e7dSPeter Dunlap } 334a6d42e7dSPeter Dunlap 335a6d42e7dSPeter Dunlap /* 336a6d42e7dSPeter Dunlap * Validate and save the the chap name which is sent by initiator 337a6d42e7dSPeter Dunlap * and shift the authentication phase to AP_CHAP_R_RCVD. 338a6d42e7dSPeter Dunlap * 339a6d42e7dSPeter Dunlap * Note: the CHAP_N, CHAP_R, optionally CHAP_I and CHAP_C key/value 340a6d42e7dSPeter Dunlap * pairs need to be received in one packet, we handle each of them 341a6d42e7dSPeter Dunlap * separately, in order to track the authentication phase, we set 342a6d42e7dSPeter Dunlap * the authentication phase to AP_CHAP_R_RCVD once one of them is 343a6d42e7dSPeter Dunlap * handled. So both of AP_CHAP_R_WAITING and AP_CHAP_R_RCVD phases 344a6d42e7dSPeter Dunlap * are valid for these keys. The function auth_chap_done is going 345a6d42e7dSPeter Dunlap * to detect if any of these keys is missing. 346a6d42e7dSPeter Dunlap */ 347a6d42e7dSPeter Dunlap 348a6d42e7dSPeter Dunlap /*ARGSUSED*/ 349a6d42e7dSPeter Dunlap static kv_status_t 350a6d42e7dSPeter Dunlap auth_chap_recv_n(iscsit_conn_t *ict, nvpair_t *nvp, 351a6d42e7dSPeter Dunlap const idm_kv_xlate_t *ikvx) 352a6d42e7dSPeter Dunlap { 353a6d42e7dSPeter Dunlap iscsit_conn_login_t *lsm = &ict->ict_login_sm; 354a6d42e7dSPeter Dunlap iscsit_auth_client_t *client = &lsm->icl_auth_client; 355a6d42e7dSPeter Dunlap int nvrc; 356a6d42e7dSPeter Dunlap char *chap_name; 357a6d42e7dSPeter Dunlap 358a6d42e7dSPeter Dunlap nvrc = nvpair_value_string(nvp, &chap_name); 359a6d42e7dSPeter Dunlap ASSERT(nvrc == 0); 360a6d42e7dSPeter Dunlap 361a6d42e7dSPeter Dunlap client_set_string_data(&client->recvKeyBlock, 362a6d42e7dSPeter Dunlap AKT_CHAP_N, 363a6d42e7dSPeter Dunlap chap_name); 364a6d42e7dSPeter Dunlap 365a6d42e7dSPeter Dunlap client->phase = AP_CHAP_R_RCVD; 366a6d42e7dSPeter Dunlap 367a6d42e7dSPeter Dunlap return (KV_HANDLED); 368a6d42e7dSPeter Dunlap } 369a6d42e7dSPeter Dunlap 370a6d42e7dSPeter Dunlap /* 371a6d42e7dSPeter Dunlap * Validate and save the the chap response which is sent by initiator 372a6d42e7dSPeter Dunlap * and shift the authentication phase to AP_CHAP_R_RCVD. 373a6d42e7dSPeter Dunlap * 374a6d42e7dSPeter Dunlap * Note: see function auth_chap_recv_n. 375a6d42e7dSPeter Dunlap */ 376a6d42e7dSPeter Dunlap 377a6d42e7dSPeter Dunlap /*ARGSUSED*/ 378a6d42e7dSPeter Dunlap static kv_status_t 379a6d42e7dSPeter Dunlap auth_chap_recv_r(iscsit_conn_t *ict, nvpair_t *nvp, 380a6d42e7dSPeter Dunlap const idm_kv_xlate_t *ikvx) 381a6d42e7dSPeter Dunlap { 382a6d42e7dSPeter Dunlap iscsit_conn_login_t *lsm = &ict->ict_login_sm; 383a6d42e7dSPeter Dunlap iscsit_auth_client_t *client = &lsm->icl_auth_client; 384a6d42e7dSPeter Dunlap int nvrc; 385a6d42e7dSPeter Dunlap unsigned char *chap_resp; 386a6d42e7dSPeter Dunlap uint_t len; 387a6d42e7dSPeter Dunlap 388a6d42e7dSPeter Dunlap nvrc = nvpair_value_byte_array(nvp, &chap_resp, &len); 389a6d42e7dSPeter Dunlap ASSERT(nvrc == 0); 390a6d42e7dSPeter Dunlap 391a6d42e7dSPeter Dunlap client_set_binary_data(&client->recvKeyBlock, 392a6d42e7dSPeter Dunlap AKT_CHAP_R, 393a6d42e7dSPeter Dunlap chap_resp, len); 394a6d42e7dSPeter Dunlap 395a6d42e7dSPeter Dunlap client->phase = AP_CHAP_R_RCVD; 396a6d42e7dSPeter Dunlap 397a6d42e7dSPeter Dunlap return (KV_HANDLED); 398a6d42e7dSPeter Dunlap } 399a6d42e7dSPeter Dunlap 400a6d42e7dSPeter Dunlap /* 401a6d42e7dSPeter Dunlap * Validate and save the the chap identifier which is sent by initiator 402a6d42e7dSPeter Dunlap * and shift the authentication phase to AP_CHAP_R_RCVD. 403a6d42e7dSPeter Dunlap * 404a6d42e7dSPeter Dunlap * Note: see function auth_chap_recv_n. 405a6d42e7dSPeter Dunlap */ 406a6d42e7dSPeter Dunlap 407a6d42e7dSPeter Dunlap /*ARGSUSED*/ 408a6d42e7dSPeter Dunlap static kv_status_t 409a6d42e7dSPeter Dunlap auth_chap_recv_i(iscsit_conn_t *ict, nvpair_t *nvp, 410a6d42e7dSPeter Dunlap const idm_kv_xlate_t *ikvx) 411a6d42e7dSPeter Dunlap { 412a6d42e7dSPeter Dunlap iscsit_conn_login_t *lsm = &ict->ict_login_sm; 413a6d42e7dSPeter Dunlap iscsit_auth_client_t *client = &lsm->icl_auth_client; 414a6d42e7dSPeter Dunlap int nvrc; 415a6d42e7dSPeter Dunlap uint64_t chap_id; 416a6d42e7dSPeter Dunlap 417a6d42e7dSPeter Dunlap nvrc = nvpair_value_uint64(nvp, &chap_id); 418a6d42e7dSPeter Dunlap ASSERT(nvrc == 0); 419a6d42e7dSPeter Dunlap 420a6d42e7dSPeter Dunlap client_set_numeric_data(&client->recvKeyBlock, 421a6d42e7dSPeter Dunlap AKT_CHAP_I, 422a6d42e7dSPeter Dunlap chap_id); 423a6d42e7dSPeter Dunlap 424a6d42e7dSPeter Dunlap client->phase = AP_CHAP_R_RCVD; 425a6d42e7dSPeter Dunlap 426a6d42e7dSPeter Dunlap return (KV_HANDLED); 427a6d42e7dSPeter Dunlap } 428a6d42e7dSPeter Dunlap 429a6d42e7dSPeter Dunlap /* 430a6d42e7dSPeter Dunlap * Validate and save the the chap challenge which is sent by initiator 431a6d42e7dSPeter Dunlap * and shift the authentication phase to AP_CHAP_R_RCVD. 432a6d42e7dSPeter Dunlap * 433a6d42e7dSPeter Dunlap * Note: see function auth_chap_recv_n. 434a6d42e7dSPeter Dunlap */ 435a6d42e7dSPeter Dunlap 436a6d42e7dSPeter Dunlap /*ARGSUSED*/ 437a6d42e7dSPeter Dunlap static kv_status_t 438a6d42e7dSPeter Dunlap auth_chap_recv_c(iscsit_conn_t *ict, nvpair_t *nvp, 439a6d42e7dSPeter Dunlap const idm_kv_xlate_t *ikvx) 440a6d42e7dSPeter Dunlap { 441a6d42e7dSPeter Dunlap iscsit_conn_login_t *lsm = &ict->ict_login_sm; 442a6d42e7dSPeter Dunlap iscsit_auth_client_t *client = &lsm->icl_auth_client; 443a6d42e7dSPeter Dunlap int nvrc; 444a6d42e7dSPeter Dunlap unsigned char *chap_challenge; 445a6d42e7dSPeter Dunlap uint_t len; 446a6d42e7dSPeter Dunlap 447a6d42e7dSPeter Dunlap nvrc = nvpair_value_byte_array(nvp, &chap_challenge, &len); 448a6d42e7dSPeter Dunlap ASSERT(nvrc == 0); 449a6d42e7dSPeter Dunlap 450a6d42e7dSPeter Dunlap client_set_binary_data( 451a6d42e7dSPeter Dunlap &client->recvKeyBlock, 452a6d42e7dSPeter Dunlap AKT_CHAP_C, 453a6d42e7dSPeter Dunlap chap_challenge, len); 454a6d42e7dSPeter Dunlap 455a6d42e7dSPeter Dunlap client->phase = AP_CHAP_R_RCVD; 456a6d42e7dSPeter Dunlap 457a6d42e7dSPeter Dunlap return (KV_HANDLED); 458a6d42e7dSPeter Dunlap } 459a6d42e7dSPeter Dunlap 460a6d42e7dSPeter Dunlap /* 461a6d42e7dSPeter Dunlap * Shift the authentication phase to AP_CHAP_R_WAITING after target 462a6d42e7dSPeter Dunlap * has successfully selected a chap algorithm. 463a6d42e7dSPeter Dunlap */ 464a6d42e7dSPeter Dunlap 465a6d42e7dSPeter Dunlap /*ARGSUSED*/ 466a6d42e7dSPeter Dunlap static kv_status_t 467a6d42e7dSPeter Dunlap auth_chap_expect_r(iscsit_conn_t *ict, nvpair_t *nvp, 468a6d42e7dSPeter Dunlap const idm_kv_xlate_t *ikvx) 469a6d42e7dSPeter Dunlap { 470a6d42e7dSPeter Dunlap iscsit_conn_login_t *lsm = &ict->ict_login_sm; 471a6d42e7dSPeter Dunlap iscsit_auth_client_t *client = &lsm->icl_auth_client; 472a6d42e7dSPeter Dunlap 473a6d42e7dSPeter Dunlap uint32_t alg; 474a6d42e7dSPeter Dunlap 475a6d42e7dSPeter Dunlap client_get_numeric_data(&client->recvKeyBlock, 476a6d42e7dSPeter Dunlap AKT_CHAP_A, 477a6d42e7dSPeter Dunlap &alg); 478a6d42e7dSPeter Dunlap 479a6d42e7dSPeter Dunlap if (alg != 0) { 480a6d42e7dSPeter Dunlap client->phase = AP_CHAP_R_WAITING; 481a6d42e7dSPeter Dunlap } else { 482a6d42e7dSPeter Dunlap /* none of proposed algorithm is supported or understood. */ 483a6d42e7dSPeter Dunlap client->phase = AP_CHAP_A_WAITING; 484a6d42e7dSPeter Dunlap } 485a6d42e7dSPeter Dunlap 486a6d42e7dSPeter Dunlap return (KV_HANDLED); 487a6d42e7dSPeter Dunlap } 488a6d42e7dSPeter Dunlap 489a6d42e7dSPeter Dunlap /* 490a6d42e7dSPeter Dunlap * Initiator does not propose security negotiation, target needs to 491a6d42e7dSPeter Dunlap * verify if we can bypass the security negotiation phase or propose 492a6d42e7dSPeter Dunlap * a security negotiation for the initiator. 493a6d42e7dSPeter Dunlap */ 494a6d42e7dSPeter Dunlap 495a6d42e7dSPeter Dunlap /*ARGSUSED*/ 496a6d42e7dSPeter Dunlap static kv_status_t 497a6d42e7dSPeter Dunlap iscsit_auth_propose(iscsit_conn_t *ict, nvpair_t *nvp, 498a6d42e7dSPeter Dunlap const idm_kv_xlate_t *ikvx) 499a6d42e7dSPeter Dunlap { 500a6d42e7dSPeter Dunlap iscsit_conn_login_t *lsm = &ict->ict_login_sm; 501a6d42e7dSPeter Dunlap conn_auth_t *auth = &lsm->icl_auth; 502a6d42e7dSPeter Dunlap iscsit_auth_method_t *am_list = &auth->ca_method_valid_list[0]; 503a6d42e7dSPeter Dunlap iscsit_auth_client_t *client = &lsm->icl_auth_client; 504a6d42e7dSPeter Dunlap 505a6d42e7dSPeter Dunlap int nvrc; 506a6d42e7dSPeter Dunlap kv_status_t kvrc; 507a6d42e7dSPeter Dunlap const char *am_name; 508a6d42e7dSPeter Dunlap 509a6d42e7dSPeter Dunlap if (am_list[0] == AM_NONE || am_list[0] == 0) { 510a6d42e7dSPeter Dunlap lsm->icl_auth_pass = 1; 511a6d42e7dSPeter Dunlap } 512a6d42e7dSPeter Dunlap 513a6d42e7dSPeter Dunlap if (lsm->icl_auth_pass == 0) { 514a6d42e7dSPeter Dunlap /* 515a6d42e7dSPeter Dunlap * It should be noted that the negotiation might also 516a6d42e7dSPeter Dunlap * be directed by the target if the initiator does 517a6d42e7dSPeter Dunlap * support security, but is not ready to direct the 518a6d42e7dSPeter Dunlap * negotiation (propose options). 519a6d42e7dSPeter Dunlap * - RFC3720 section 5.3.2. 520a6d42e7dSPeter Dunlap */ 521a6d42e7dSPeter Dunlap am_name = am_id_to_name(am_list[0]); 522a6d42e7dSPeter Dunlap nvrc = nvlist_add_string( 523a6d42e7dSPeter Dunlap lsm->icl_response_nvlist, 524a6d42e7dSPeter Dunlap "AuthMethod", am_name); 525a6d42e7dSPeter Dunlap kvrc = idm_nvstat_to_kvstat(nvrc); 526a6d42e7dSPeter Dunlap 527a6d42e7dSPeter Dunlap client->phase = AP_AM_PROPOSED; 528a6d42e7dSPeter Dunlap } else { 529a6d42e7dSPeter Dunlap kvrc = KV_HANDLED; 530a6d42e7dSPeter Dunlap 531a6d42e7dSPeter Dunlap client->phase = AP_DONE; 532a6d42e7dSPeter Dunlap } 533a6d42e7dSPeter Dunlap 534a6d42e7dSPeter Dunlap return (kvrc); 535a6d42e7dSPeter Dunlap } 536a6d42e7dSPeter Dunlap 537a6d42e7dSPeter Dunlap /* 538a6d42e7dSPeter Dunlap * Shift the authentication phase according to the authentication 539a6d42e7dSPeter Dunlap * method once it is selected. 540a6d42e7dSPeter Dunlap */ 541a6d42e7dSPeter Dunlap 542a6d42e7dSPeter Dunlap /*ARGSUSED*/ 543a6d42e7dSPeter Dunlap static kv_status_t 544a6d42e7dSPeter Dunlap iscsit_auth_expect_key(iscsit_conn_t *ict, nvpair_t *nvp, 545a6d42e7dSPeter Dunlap const idm_kv_xlate_t *ikvx) 546a6d42e7dSPeter Dunlap { 547a6d42e7dSPeter Dunlap iscsit_conn_login_t *lsm = &ict->ict_login_sm; 548a6d42e7dSPeter Dunlap iscsit_auth_client_t *client = &lsm->icl_auth_client; 549a6d42e7dSPeter Dunlap 550a6d42e7dSPeter Dunlap if (client->negotiatedMethod != 0) { 551a6d42e7dSPeter Dunlap /* Shift security negotiation phase. */ 552a6d42e7dSPeter Dunlap switch (client->negotiatedMethod) { 553a6d42e7dSPeter Dunlap case AM_CHAP: 554a6d42e7dSPeter Dunlap client->phase = AP_CHAP_A_WAITING; 555a6d42e7dSPeter Dunlap break; 556a6d42e7dSPeter Dunlap case AM_NONE: 557a6d42e7dSPeter Dunlap client->phase = AP_DONE; 558a6d42e7dSPeter Dunlap lsm->icl_auth_pass = 1; 559a6d42e7dSPeter Dunlap break; 560a6d42e7dSPeter Dunlap default: 561a6d42e7dSPeter Dunlap ASSERT(0); 562a6d42e7dSPeter Dunlap break; 563a6d42e7dSPeter Dunlap } 564a6d42e7dSPeter Dunlap } else { 565a6d42e7dSPeter Dunlap /* None of proposed method is supported or understood. */ 566a6d42e7dSPeter Dunlap client->phase = AP_AM_UNDECIDED; 567a6d42e7dSPeter Dunlap } 568a6d42e7dSPeter Dunlap 569a6d42e7dSPeter Dunlap return (KV_HANDLED); 570a6d42e7dSPeter Dunlap } 571a6d42e7dSPeter Dunlap 572a6d42e7dSPeter Dunlap /* 573a6d42e7dSPeter Dunlap * The last step of the chap authentication. We will validate the 574a6d42e7dSPeter Dunlap * chap parameters we received and authenticate the client here. 575a6d42e7dSPeter Dunlap */ 576a6d42e7dSPeter Dunlap 577a6d42e7dSPeter Dunlap /*ARGSUSED*/ 578a6d42e7dSPeter Dunlap static kv_status_t 579a6d42e7dSPeter Dunlap auth_chap_done(iscsit_conn_t *ict, nvpair_t *nvp, 580a6d42e7dSPeter Dunlap const idm_kv_xlate_t *ikvx) 581a6d42e7dSPeter Dunlap { 582a6d42e7dSPeter Dunlap iscsit_conn_login_t *lsm = &ict->ict_login_sm; 583a6d42e7dSPeter Dunlap iscsit_auth_client_t *client = &lsm->icl_auth_client; 584a6d42e7dSPeter Dunlap kv_status_t kvrc = KV_HANDLED; 585a6d42e7dSPeter Dunlap 586a6d42e7dSPeter Dunlap conn_auth_t *auth = &lsm->icl_auth; 587a6d42e7dSPeter Dunlap char *username_in; 588a6d42e7dSPeter Dunlap 589a6d42e7dSPeter Dunlap uint32_t chap_id; 590a6d42e7dSPeter Dunlap unsigned char *chap_challenge; 591a6d42e7dSPeter Dunlap unsigned int challenge_len; 592a6d42e7dSPeter Dunlap char *chap_name; 593a6d42e7dSPeter Dunlap unsigned char *chap_resp; 594a6d42e7dSPeter Dunlap unsigned int resp_len; 595a6d42e7dSPeter Dunlap 596a6d42e7dSPeter Dunlap int bi_auth; 597a6d42e7dSPeter Dunlap 598a6d42e7dSPeter Dunlap username_in = auth->ca_ini_chapuser; 599a6d42e7dSPeter Dunlap if (username_in[0] == '\0') 600a6d42e7dSPeter Dunlap return (KV_AUTH_FAILED); 601a6d42e7dSPeter Dunlap 602a6d42e7dSPeter Dunlap /* 603a6d42e7dSPeter Dunlap * Check if we have received a valid list of response keys. 604a6d42e7dSPeter Dunlap */ 605a6d42e7dSPeter Dunlap if (!client_auth_key_present(&client->recvKeyBlock, AKT_CHAP_N) || 606a6d42e7dSPeter Dunlap !client_auth_key_present(&client->recvKeyBlock, AKT_CHAP_R) || 607a6d42e7dSPeter Dunlap ((bi_auth = 608a6d42e7dSPeter Dunlap client_auth_key_present(&client->recvKeyBlock, AKT_CHAP_I)) ^ 609a6d42e7dSPeter Dunlap client_auth_key_present(&client->recvKeyBlock, AKT_CHAP_C))) { 610a6d42e7dSPeter Dunlap return (KV_MISSING_FIELDS); 611a6d42e7dSPeter Dunlap } 612a6d42e7dSPeter Dunlap 613a6d42e7dSPeter Dunlap client->phase = AP_DONE; 614a6d42e7dSPeter Dunlap 615a6d42e7dSPeter Dunlap client_get_string_data(&client->recvKeyBlock, 616a6d42e7dSPeter Dunlap AKT_CHAP_N, 617a6d42e7dSPeter Dunlap &chap_name); 618a6d42e7dSPeter Dunlap 619a6d42e7dSPeter Dunlap /* check username */ 620a6d42e7dSPeter Dunlap if (strcmp(username_in, chap_name) != 0) { 621a6d42e7dSPeter Dunlap return (KV_AUTH_FAILED); 622a6d42e7dSPeter Dunlap } 623a6d42e7dSPeter Dunlap 624a6d42e7dSPeter Dunlap client_get_numeric_data(&client->sendKeyBlock, 625a6d42e7dSPeter Dunlap AKT_CHAP_I, 626a6d42e7dSPeter Dunlap &chap_id); 627a6d42e7dSPeter Dunlap 628a6d42e7dSPeter Dunlap client_get_binary_data(&client->sendKeyBlock, 629a6d42e7dSPeter Dunlap AKT_CHAP_C, 630a6d42e7dSPeter Dunlap &chap_challenge, &challenge_len); 631a6d42e7dSPeter Dunlap 632a6d42e7dSPeter Dunlap client_get_binary_data(&client->recvKeyBlock, 633a6d42e7dSPeter Dunlap AKT_CHAP_R, 634a6d42e7dSPeter Dunlap &chap_resp, &resp_len); 635a6d42e7dSPeter Dunlap 636a6d42e7dSPeter Dunlap if (iscsit_verify_chap_resp(lsm, 637a6d42e7dSPeter Dunlap chap_id, chap_challenge, challenge_len, 638a6d42e7dSPeter Dunlap chap_resp, resp_len) != ISCSI_AUTH_PASSED) { 639a6d42e7dSPeter Dunlap return (KV_AUTH_FAILED); 640a6d42e7dSPeter Dunlap } 641a6d42e7dSPeter Dunlap 642a6d42e7dSPeter Dunlap /* bi-direction authentication is required */ 643a6d42e7dSPeter Dunlap if (bi_auth != 0) { 644a6d42e7dSPeter Dunlap kvrc = iscsit_auth_gen_response(ict); 645a6d42e7dSPeter Dunlap } 646a6d42e7dSPeter Dunlap 647a6d42e7dSPeter Dunlap lsm->icl_auth_pass = 1; 648a6d42e7dSPeter Dunlap 649a6d42e7dSPeter Dunlap return (kvrc); 650a6d42e7dSPeter Dunlap } 651a6d42e7dSPeter Dunlap 652a6d42e7dSPeter Dunlap static kv_status_t 653a6d42e7dSPeter Dunlap iscsit_auth_gen_challenge(iscsit_conn_t *ict) 654a6d42e7dSPeter Dunlap { 655a6d42e7dSPeter Dunlap iscsit_conn_login_t *lsm = &ict->ict_login_sm; 656a6d42e7dSPeter Dunlap iscsit_auth_client_t *client = &lsm->icl_auth_client; 657a6d42e7dSPeter Dunlap int nvrc; 658a6d42e7dSPeter Dunlap kv_status_t kvrc; 659a6d42e7dSPeter Dunlap 660a6d42e7dSPeter Dunlap unsigned char idData[1]; 661a6d42e7dSPeter Dunlap unsigned char *bin; 662a6d42e7dSPeter Dunlap int len; 663a6d42e7dSPeter Dunlap 664a6d42e7dSPeter Dunlap auth_random_set_data(idData, 1); 665a6d42e7dSPeter Dunlap client_set_numeric_data(&client->sendKeyBlock, 666a6d42e7dSPeter Dunlap AKT_CHAP_I, 667a6d42e7dSPeter Dunlap idData[0]); 668a6d42e7dSPeter Dunlap 669a6d42e7dSPeter Dunlap /* send chap identifier */ 670a6d42e7dSPeter Dunlap nvrc = nvlist_add_uint64( 671a6d42e7dSPeter Dunlap lsm->icl_response_nvlist, 672a6d42e7dSPeter Dunlap "CHAP_I", idData[0]); 673a6d42e7dSPeter Dunlap kvrc = idm_nvstat_to_kvstat(nvrc); 674a6d42e7dSPeter Dunlap if (kvrc != 0) { 675a6d42e7dSPeter Dunlap return (kvrc); 676a6d42e7dSPeter Dunlap } 677a6d42e7dSPeter Dunlap 678a6d42e7dSPeter Dunlap bin = &(client->auth_send_binary_block.largeBinary[0]); 679*30e7468fSPeter Dunlap len = iscsitAuthChapResponseLength; 680a6d42e7dSPeter Dunlap auth_random_set_data(bin, len); 681a6d42e7dSPeter Dunlap client_set_binary_data(&client->sendKeyBlock, 682a6d42e7dSPeter Dunlap AKT_CHAP_C, 683a6d42e7dSPeter Dunlap bin, len); 684a6d42e7dSPeter Dunlap 685a6d42e7dSPeter Dunlap /* send chap challenge */ 686a6d42e7dSPeter Dunlap nvrc = nvlist_add_byte_array( 687a6d42e7dSPeter Dunlap lsm->icl_response_nvlist, 688a6d42e7dSPeter Dunlap "CHAP_C", bin, len); 689a6d42e7dSPeter Dunlap kvrc = idm_nvstat_to_kvstat(nvrc); 690a6d42e7dSPeter Dunlap 691a6d42e7dSPeter Dunlap return (kvrc); 692a6d42e7dSPeter Dunlap } 693a6d42e7dSPeter Dunlap 694a6d42e7dSPeter Dunlap static kv_status_t 695a6d42e7dSPeter Dunlap iscsit_auth_gen_response(iscsit_conn_t *ict) 696a6d42e7dSPeter Dunlap { 697a6d42e7dSPeter Dunlap iscsit_conn_login_t *lsm = &ict->ict_login_sm; 698a6d42e7dSPeter Dunlap iscsit_auth_client_t *client = &lsm->icl_auth_client; 699a6d42e7dSPeter Dunlap int nvrc; 700a6d42e7dSPeter Dunlap kv_status_t kvrc; 701a6d42e7dSPeter Dunlap 702a6d42e7dSPeter Dunlap conn_auth_t *auth = &lsm->icl_auth; 703a6d42e7dSPeter Dunlap char *tgt_username; 704a6d42e7dSPeter Dunlap uint8_t *tgt_password; 705a6d42e7dSPeter Dunlap int tgt_password_length; 706a6d42e7dSPeter Dunlap 707a6d42e7dSPeter Dunlap uint32_t chap_id; 708a6d42e7dSPeter Dunlap unsigned char *chap_challenge; 709a6d42e7dSPeter Dunlap unsigned int challenge_len; 710*30e7468fSPeter Dunlap uchar_t resp[iscsitAuthChapResponseLength]; 711a6d42e7dSPeter Dunlap 712a6d42e7dSPeter Dunlap tgt_username = auth->ca_tgt_chapuser; 713a6d42e7dSPeter Dunlap tgt_password = auth->ca_tgt_chapsecret; 714a6d42e7dSPeter Dunlap tgt_password_length = auth->ca_tgt_chapsecretlen; 715a6d42e7dSPeter Dunlap 716a6d42e7dSPeter Dunlap /* 717a6d42e7dSPeter Dunlap * We can't know in advance whether the initiator will attempt 718a6d42e7dSPeter Dunlap * mutual authentication, so now we need to check whether we 719a6d42e7dSPeter Dunlap * have a target CHAP secret configured. 720a6d42e7dSPeter Dunlap */ 721a6d42e7dSPeter Dunlap if (tgt_password_length == 0) { 722a6d42e7dSPeter Dunlap return (KV_AUTH_FAILED); 723a6d42e7dSPeter Dunlap } 724a6d42e7dSPeter Dunlap 725a6d42e7dSPeter Dunlap client_get_numeric_data(&client->recvKeyBlock, 726a6d42e7dSPeter Dunlap AKT_CHAP_I, 727a6d42e7dSPeter Dunlap &chap_id); 728a6d42e7dSPeter Dunlap 729a6d42e7dSPeter Dunlap client_get_binary_data(&client->recvKeyBlock, 730a6d42e7dSPeter Dunlap AKT_CHAP_C, 731a6d42e7dSPeter Dunlap &chap_challenge, &challenge_len); 732a6d42e7dSPeter Dunlap 733a6d42e7dSPeter Dunlap client_compute_chap_resp( 734a6d42e7dSPeter Dunlap &resp[0], 735a6d42e7dSPeter Dunlap chap_id, 736a6d42e7dSPeter Dunlap tgt_password, tgt_password_length, 737a6d42e7dSPeter Dunlap chap_challenge, challenge_len); 738a6d42e7dSPeter Dunlap 739a6d42e7dSPeter Dunlap nvrc = nvlist_add_string( 740a6d42e7dSPeter Dunlap lsm->icl_response_nvlist, 741a6d42e7dSPeter Dunlap "CHAP_N", tgt_username); 742a6d42e7dSPeter Dunlap 743a6d42e7dSPeter Dunlap if (nvrc == 0) { 744a6d42e7dSPeter Dunlap nvrc = nvlist_add_byte_array( 745a6d42e7dSPeter Dunlap lsm->icl_response_nvlist, 746a6d42e7dSPeter Dunlap "CHAP_R", resp, sizeof (resp)); 747a6d42e7dSPeter Dunlap } 748a6d42e7dSPeter Dunlap kvrc = idm_nvstat_to_kvstat(nvrc); 749a6d42e7dSPeter Dunlap 750a6d42e7dSPeter Dunlap return (kvrc); 751a6d42e7dSPeter Dunlap } 752