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 /*
22*4558d122SViswanathan Kannappan * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
23a6d42e7dSPeter Dunlap */
24a6d42e7dSPeter Dunlap
25a6d42e7dSPeter Dunlap #include <sys/cpuvar.h>
26a6d42e7dSPeter Dunlap #include <sys/types.h>
27a6d42e7dSPeter Dunlap #include <sys/conf.h>
28a6d42e7dSPeter Dunlap #include <sys/file.h>
29a6d42e7dSPeter Dunlap #include <sys/ddi.h>
30a6d42e7dSPeter Dunlap #include <sys/sunddi.h>
31a6d42e7dSPeter Dunlap #include <sys/modctl.h>
32a6d42e7dSPeter Dunlap
33a6d42e7dSPeter Dunlap #include <sys/socket.h>
34a6d42e7dSPeter Dunlap #include <sys/strsubr.h>
35a6d42e7dSPeter Dunlap #include <sys/sysmacros.h>
36a6d42e7dSPeter Dunlap
37a6d42e7dSPeter Dunlap #include <sys/stmf.h>
38a6d42e7dSPeter Dunlap #include <sys/stmf_ioctl.h>
39a6d42e7dSPeter Dunlap #include <sys/portif.h>
40a6d42e7dSPeter Dunlap #include <sys/idm/idm.h>
41a6d42e7dSPeter Dunlap #include <sys/idm/idm_text.h>
42*4558d122SViswanathan Kannappan
43*4558d122SViswanathan Kannappan #include "iscsit.h"
44*4558d122SViswanathan Kannappan #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 *
am_id_to_name(int id)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
iscsit_auth_get_handler(iscsit_auth_client_t * client,iscsikey_id_t kv_id)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
iscsit_select_auth(iscsit_conn_t * ict,nvpair_t * nvp,const idm_kv_xlate_t * ikvx)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
auth_propose_chap(iscsit_conn_t * ict,nvpair_t * nvp,const idm_kv_xlate_t * ikvx)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
auth_chap_select_alg(iscsit_conn_t * ict,nvpair_t * nvp,const idm_kv_xlate_t * ikvx)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
auth_chap_recv_n(iscsit_conn_t * ict,nvpair_t * nvp,const idm_kv_xlate_t * ikvx)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
auth_chap_recv_r(iscsit_conn_t * ict,nvpair_t * nvp,const idm_kv_xlate_t * ikvx)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
auth_chap_recv_i(iscsit_conn_t * ict,nvpair_t * nvp,const idm_kv_xlate_t * ikvx)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
auth_chap_recv_c(iscsit_conn_t * ict,nvpair_t * nvp,const idm_kv_xlate_t * ikvx)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
auth_chap_expect_r(iscsit_conn_t * ict,nvpair_t * nvp,const idm_kv_xlate_t * ikvx)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
iscsit_auth_propose(iscsit_conn_t * ict,nvpair_t * nvp,const idm_kv_xlate_t * ikvx)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
iscsit_auth_expect_key(iscsit_conn_t * ict,nvpair_t * nvp,const idm_kv_xlate_t * ikvx)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
auth_chap_done(iscsit_conn_t * ict,nvpair_t * nvp,const idm_kv_xlate_t * ikvx)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
iscsit_auth_gen_challenge(iscsit_conn_t * ict)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]);
67930e7468fSPeter 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
iscsit_auth_gen_response(iscsit_conn_t * ict)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;
71030e7468fSPeter 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