1fcf3ce44SJohn Forte /*
2fcf3ce44SJohn Forte  * CDDL HEADER START
3fcf3ce44SJohn Forte  *
4fcf3ce44SJohn Forte  * The contents of this file are subject to the terms of the
5fcf3ce44SJohn Forte  * Common Development and Distribution License (the "License").
6fcf3ce44SJohn Forte  * You may not use this file except in compliance with the License.
7fcf3ce44SJohn Forte  *
8fcf3ce44SJohn Forte  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9fcf3ce44SJohn Forte  * or http://www.opensolaris.org/os/licensing.
10fcf3ce44SJohn Forte  * See the License for the specific language governing permissions
11fcf3ce44SJohn Forte  * and limitations under the License.
12fcf3ce44SJohn Forte  *
13fcf3ce44SJohn Forte  * When distributing Covered Code, include this CDDL HEADER in each
14fcf3ce44SJohn Forte  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15fcf3ce44SJohn Forte  * If applicable, add the following below this CDDL HEADER, with the
16fcf3ce44SJohn Forte  * fields enclosed by brackets "[]" replaced with your own identifying
17fcf3ce44SJohn Forte  * information: Portions Copyright [yyyy] [name of copyright owner]
18fcf3ce44SJohn Forte  *
19fcf3ce44SJohn Forte  * CDDL HEADER END
20fcf3ce44SJohn Forte  */
21fcf3ce44SJohn Forte /*
22fcf3ce44SJohn Forte  * Copyright 2000 by Cisco Systems, Inc.  All rights reserved.
23*1a1a84a3SPeter Dunlap  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24fcf3ce44SJohn Forte  * Use is subject to license terms.
25fcf3ce44SJohn Forte  *
26fcf3ce44SJohn Forte  * This file implements the iSCSI CHAP authentication method based.
27fcf3ce44SJohn Forte  * The code in this file is meant to be platform independent, and
28fcf3ce44SJohn Forte  * makes use of only limited library functions, presently only string.h.
29fcf3ce44SJohn Forte  * Platform dependent routines are  defined in iscsiAuthClient.h, but
30fcf3ce44SJohn Forte  * implemented in another file.
31fcf3ce44SJohn Forte  *
32fcf3ce44SJohn Forte  * This code in this files assumes a single thread of execution
33fcf3ce44SJohn Forte  * for each IscsiAuthClient structure, and does no locking.
34fcf3ce44SJohn Forte  */
35fcf3ce44SJohn Forte 
36fcf3ce44SJohn Forte #include "iscsi.h"
37fcf3ce44SJohn Forte #include "iscsiAuthClient.h"
38fcf3ce44SJohn Forte 
39fcf3ce44SJohn Forte 
40fcf3ce44SJohn Forte struct iscsiAuthKeyInfo_t {
41fcf3ce44SJohn Forte 	const char *name;
42fcf3ce44SJohn Forte };
43fcf3ce44SJohn Forte typedef struct iscsiAuthKeyInfo_t IscsiAuthKeyInfo;
44fcf3ce44SJohn Forte 
45fcf3ce44SJohn Forte 
46fcf3ce44SJohn Forte IscsiAuthClientGlobalStats iscsiAuthClientGlobalStats;
47fcf3ce44SJohn Forte 
48fcf3ce44SJohn Forte /*
49fcf3ce44SJohn Forte  * Note: The ordering of this table must match the order
50fcf3ce44SJohn Forte  *       defined by IscsiAuthKeyType in iscsiAuthClient.h.
51fcf3ce44SJohn Forte  */
52fcf3ce44SJohn Forte static IscsiAuthKeyInfo iscsiAuthClientKeyInfo[iscsiAuthKeyTypeMaxCount] = {
53fcf3ce44SJohn Forte 	{"AuthMethod"},
54fcf3ce44SJohn Forte 	{"CHAP_A"},
55fcf3ce44SJohn Forte 	{"CHAP_N"},
56fcf3ce44SJohn Forte 	{"CHAP_R"},
57fcf3ce44SJohn Forte 	{"CHAP_I"},
58fcf3ce44SJohn Forte 	{"CHAP_C"}
59fcf3ce44SJohn Forte };
60fcf3ce44SJohn Forte 
61fcf3ce44SJohn Forte static const char iscsiAuthClientHexString[] = "0123456789abcdefABCDEF";
62fcf3ce44SJohn Forte static const char iscsiAuthClientBase64String[] =
63fcf3ce44SJohn Forte 	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
64fcf3ce44SJohn Forte static const char iscsiAuthClientAuthMethodChapOptionName[] = "CHAP";
65fcf3ce44SJohn Forte 
66fcf3ce44SJohn Forte 
67fcf3ce44SJohn Forte static int
iscsiAuthClientCheckString(const char * s,unsigned int maxLength,unsigned int * pOutLength)68fcf3ce44SJohn Forte iscsiAuthClientCheckString(const char *s,
69fcf3ce44SJohn Forte     unsigned int maxLength, unsigned int *pOutLength)
70fcf3ce44SJohn Forte {
71fcf3ce44SJohn Forte 	unsigned int length;
72fcf3ce44SJohn Forte 
73fcf3ce44SJohn Forte 	if (!s) {
74fcf3ce44SJohn Forte 		return (TRUE);
75fcf3ce44SJohn Forte 	}
76fcf3ce44SJohn Forte 
77fcf3ce44SJohn Forte 	for (length = 0; length < maxLength; length++) {
78fcf3ce44SJohn Forte 		if (*s++ == '\0') {
79fcf3ce44SJohn Forte 			if (pOutLength) {
80fcf3ce44SJohn Forte 				*pOutLength = length;
81fcf3ce44SJohn Forte 			}
82fcf3ce44SJohn Forte 			return (FALSE);
83fcf3ce44SJohn Forte 		}
84fcf3ce44SJohn Forte 	}
85fcf3ce44SJohn Forte 
86fcf3ce44SJohn Forte 	return (TRUE);
87fcf3ce44SJohn Forte }
88fcf3ce44SJohn Forte 
89fcf3ce44SJohn Forte 
90fcf3ce44SJohn Forte static int
iscsiAuthClientStringCopy(char * stringOut,const char * stringIn,unsigned int length)91fcf3ce44SJohn Forte iscsiAuthClientStringCopy(char *stringOut, const char *stringIn,
92fcf3ce44SJohn Forte     unsigned int length)
93fcf3ce44SJohn Forte {
94fcf3ce44SJohn Forte 	if (!stringOut || !stringIn || length == 0) {
95fcf3ce44SJohn Forte 		return (TRUE);
96fcf3ce44SJohn Forte 	}
97fcf3ce44SJohn Forte 
98fcf3ce44SJohn Forte 	while ((*stringOut++ = *stringIn++) != '\0') {
99fcf3ce44SJohn Forte 		if (--length == 0) {
100fcf3ce44SJohn Forte 			stringOut--;
101fcf3ce44SJohn Forte 			*stringOut = '\0';
102fcf3ce44SJohn Forte 			return (TRUE);
103fcf3ce44SJohn Forte 		}
104fcf3ce44SJohn Forte 	}
105fcf3ce44SJohn Forte 
106fcf3ce44SJohn Forte 	return (FALSE);
107fcf3ce44SJohn Forte }
108fcf3ce44SJohn Forte 
109fcf3ce44SJohn Forte 
110fcf3ce44SJohn Forte static int
iscsiAuthClientStringAppend(char * stringOut,const char * stringIn,unsigned int length)111fcf3ce44SJohn Forte iscsiAuthClientStringAppend(char *stringOut, const char *stringIn,
112fcf3ce44SJohn Forte     unsigned int length)
113fcf3ce44SJohn Forte {
114fcf3ce44SJohn Forte 	if (!stringOut || !stringIn || length == 0) {
115fcf3ce44SJohn Forte 		return (TRUE);
116fcf3ce44SJohn Forte 	}
117fcf3ce44SJohn Forte 
118fcf3ce44SJohn Forte 	while (*stringOut++ != '\0') {
119fcf3ce44SJohn Forte 		if (--length == 0) {
120fcf3ce44SJohn Forte 			stringOut--;
121fcf3ce44SJohn Forte 			*stringOut = '\0';
122fcf3ce44SJohn Forte 			return (TRUE);
123fcf3ce44SJohn Forte 		}
124fcf3ce44SJohn Forte 	}
125fcf3ce44SJohn Forte 
126fcf3ce44SJohn Forte 	stringOut--;
127fcf3ce44SJohn Forte 
128fcf3ce44SJohn Forte 	while ((*stringOut++ = *stringIn++) != '\0') {
129fcf3ce44SJohn Forte 		if (--length == 0) {
130fcf3ce44SJohn Forte 			stringOut--;
131fcf3ce44SJohn Forte 			*stringOut = '\0';
132fcf3ce44SJohn Forte 			return (TRUE);
133fcf3ce44SJohn Forte 		}
134fcf3ce44SJohn Forte 	}
135fcf3ce44SJohn Forte 
136fcf3ce44SJohn Forte 	return (FALSE);
137fcf3ce44SJohn Forte }
138fcf3ce44SJohn Forte 
139fcf3ce44SJohn Forte 
140fcf3ce44SJohn Forte static int
iscsiAuthClientStringIndex(const char * s,int c)141fcf3ce44SJohn Forte iscsiAuthClientStringIndex(const char *s, int c)
142fcf3ce44SJohn Forte {
143fcf3ce44SJohn Forte 	int n = 0;
144fcf3ce44SJohn Forte 
145fcf3ce44SJohn Forte 	while (*s != '\0') {
146fcf3ce44SJohn Forte 		if (*s++ == c) {
147fcf3ce44SJohn Forte 			return (n);
148fcf3ce44SJohn Forte 		}
149fcf3ce44SJohn Forte 		n++;
150fcf3ce44SJohn Forte 	}
151fcf3ce44SJohn Forte 
152fcf3ce44SJohn Forte 	return (-1);
153fcf3ce44SJohn Forte }
154fcf3ce44SJohn Forte 
155fcf3ce44SJohn Forte 
156fcf3ce44SJohn Forte static int
iscsiAuthClientCheckNodeType(int nodeType)157fcf3ce44SJohn Forte iscsiAuthClientCheckNodeType(int nodeType)
158fcf3ce44SJohn Forte {
159fcf3ce44SJohn Forte 	if (nodeType == iscsiAuthNodeTypeInitiator ||
160fcf3ce44SJohn Forte 	    nodeType == iscsiAuthNodeTypeTarget) {
161fcf3ce44SJohn Forte 		return (FALSE);
162fcf3ce44SJohn Forte 	}
163fcf3ce44SJohn Forte 
164fcf3ce44SJohn Forte 	return (TRUE);
165fcf3ce44SJohn Forte }
166fcf3ce44SJohn Forte 
167fcf3ce44SJohn Forte 
168fcf3ce44SJohn Forte static int
iscsiAuthClientCheckVersion(int value)169fcf3ce44SJohn Forte iscsiAuthClientCheckVersion(int value)
170fcf3ce44SJohn Forte {
171fcf3ce44SJohn Forte 	if (value == iscsiAuthVersionDraft8 || value == iscsiAuthVersionRfc) {
172fcf3ce44SJohn Forte 
173fcf3ce44SJohn Forte 		return (FALSE);
174fcf3ce44SJohn Forte 	}
175fcf3ce44SJohn Forte 
176fcf3ce44SJohn Forte 	return (TRUE);
177fcf3ce44SJohn Forte }
178fcf3ce44SJohn Forte 
179fcf3ce44SJohn Forte 
180fcf3ce44SJohn Forte static int
iscsiAuthClientCheckNegRole(int value)181fcf3ce44SJohn Forte iscsiAuthClientCheckNegRole(int value)
182fcf3ce44SJohn Forte {
183fcf3ce44SJohn Forte 	if (value == iscsiAuthNegRoleOriginator ||
184fcf3ce44SJohn Forte 	    value == iscsiAuthNegRoleResponder) {
185fcf3ce44SJohn Forte 		return (FALSE);
186fcf3ce44SJohn Forte 	}
187fcf3ce44SJohn Forte 
188fcf3ce44SJohn Forte 	return (TRUE);
189fcf3ce44SJohn Forte }
190fcf3ce44SJohn Forte 
191fcf3ce44SJohn Forte 
192fcf3ce44SJohn Forte static int
iscsiAuthClientCheckAuthMethodOption(int value)193fcf3ce44SJohn Forte iscsiAuthClientCheckAuthMethodOption(int value)
194fcf3ce44SJohn Forte {
195fcf3ce44SJohn Forte 	if (value == iscsiAuthOptionNone || value == iscsiAuthMethodChap) {
196fcf3ce44SJohn Forte 
197fcf3ce44SJohn Forte 		return (FALSE);
198fcf3ce44SJohn Forte 	}
199fcf3ce44SJohn Forte 
200fcf3ce44SJohn Forte 	return (TRUE);
201fcf3ce44SJohn Forte }
202fcf3ce44SJohn Forte 
203fcf3ce44SJohn Forte 
204fcf3ce44SJohn Forte static const char *
iscsiAuthClientAuthMethodOptionToText(IscsiAuthClient * client,int value)205fcf3ce44SJohn Forte iscsiAuthClientAuthMethodOptionToText(IscsiAuthClient * client, int value)
206fcf3ce44SJohn Forte {
207fcf3ce44SJohn Forte 	const char *s;
208fcf3ce44SJohn Forte 
209fcf3ce44SJohn Forte 	switch (value) {
210fcf3ce44SJohn Forte 	case iscsiAuthOptionReject:
211fcf3ce44SJohn Forte 		s = client->rejectOptionName;
212fcf3ce44SJohn Forte 		break;
213fcf3ce44SJohn Forte 
214fcf3ce44SJohn Forte 	case iscsiAuthOptionNone:
215fcf3ce44SJohn Forte 		s = client->noneOptionName;
216fcf3ce44SJohn Forte 		break;
217fcf3ce44SJohn Forte 
218fcf3ce44SJohn Forte 	case iscsiAuthMethodChap:
219fcf3ce44SJohn Forte 		s = iscsiAuthClientAuthMethodChapOptionName;
220fcf3ce44SJohn Forte 		break;
221fcf3ce44SJohn Forte 
222fcf3ce44SJohn Forte 	default:
223fcf3ce44SJohn Forte 		s = 0;
224fcf3ce44SJohn Forte 	}
225fcf3ce44SJohn Forte 
226fcf3ce44SJohn Forte 	return (s);
227fcf3ce44SJohn Forte }
228fcf3ce44SJohn Forte 
229fcf3ce44SJohn Forte 
230fcf3ce44SJohn Forte static int
iscsiAuthClientCheckChapAlgorithmOption(int chapAlgorithm)231fcf3ce44SJohn Forte iscsiAuthClientCheckChapAlgorithmOption(int chapAlgorithm)
232fcf3ce44SJohn Forte {
233fcf3ce44SJohn Forte 	if (chapAlgorithm == iscsiAuthOptionNone ||
234fcf3ce44SJohn Forte 	    chapAlgorithm == iscsiAuthChapAlgorithmMd5) {
235fcf3ce44SJohn Forte 		return (FALSE);
236fcf3ce44SJohn Forte 	}
237fcf3ce44SJohn Forte 
238fcf3ce44SJohn Forte 	return (TRUE);
239fcf3ce44SJohn Forte }
240fcf3ce44SJohn Forte 
241fcf3ce44SJohn Forte 
242fcf3ce44SJohn Forte static int
iscsiAuthClientDataToHex(unsigned char * data,unsigned int dataLength,char * text,unsigned int textLength)243fcf3ce44SJohn Forte iscsiAuthClientDataToHex(unsigned char *data, unsigned int dataLength,
244fcf3ce44SJohn Forte     char *text, unsigned int textLength)
245fcf3ce44SJohn Forte {
246fcf3ce44SJohn Forte 	unsigned long n;
247fcf3ce44SJohn Forte 
248fcf3ce44SJohn Forte 	if (!text || textLength == 0) {
249fcf3ce44SJohn Forte 		return (TRUE);
250fcf3ce44SJohn Forte 	}
251fcf3ce44SJohn Forte 
252fcf3ce44SJohn Forte 	if (!data || dataLength == 0) {
253fcf3ce44SJohn Forte 		*text = '\0';
254fcf3ce44SJohn Forte 		return (TRUE);
255fcf3ce44SJohn Forte 	}
256fcf3ce44SJohn Forte 
257fcf3ce44SJohn Forte 	if (textLength < 3) {
258fcf3ce44SJohn Forte 		*text = '\0';
259fcf3ce44SJohn Forte 		return (TRUE);
260fcf3ce44SJohn Forte 	}
261fcf3ce44SJohn Forte 
262fcf3ce44SJohn Forte 	*text++ = '0';
263fcf3ce44SJohn Forte 	*text++ = 'x';
264fcf3ce44SJohn Forte 
265fcf3ce44SJohn Forte 	textLength -= 2;
266fcf3ce44SJohn Forte 
267fcf3ce44SJohn Forte 	while (dataLength > 0) {
268fcf3ce44SJohn Forte 
269fcf3ce44SJohn Forte 		if (textLength < 3) {
270fcf3ce44SJohn Forte 			*text = '\0';
271fcf3ce44SJohn Forte 			return (TRUE);
272fcf3ce44SJohn Forte 		}
273fcf3ce44SJohn Forte 
274fcf3ce44SJohn Forte 		n = *data++;
275fcf3ce44SJohn Forte 		dataLength--;
276fcf3ce44SJohn Forte 
277fcf3ce44SJohn Forte 		*text++ = iscsiAuthClientHexString[(n >> 4) & 0xf];
278fcf3ce44SJohn Forte 		*text++ = iscsiAuthClientHexString[n & 0xf];
279fcf3ce44SJohn Forte 
280fcf3ce44SJohn Forte 		textLength -= 2;
281fcf3ce44SJohn Forte 	}
282fcf3ce44SJohn Forte 
283fcf3ce44SJohn Forte 	*text = '\0';
284fcf3ce44SJohn Forte 
285fcf3ce44SJohn Forte 	return (FALSE);
286fcf3ce44SJohn Forte }
287fcf3ce44SJohn Forte 
288fcf3ce44SJohn Forte 
289fcf3ce44SJohn Forte static int
iscsiAuthClientDataToBase64(unsigned char * data,unsigned int dataLength,char * text,unsigned int textLength)290fcf3ce44SJohn Forte iscsiAuthClientDataToBase64(unsigned char *data, unsigned int dataLength,
291fcf3ce44SJohn Forte     char *text, unsigned int textLength)
292fcf3ce44SJohn Forte {
293fcf3ce44SJohn Forte 	unsigned long n;
294fcf3ce44SJohn Forte 
295fcf3ce44SJohn Forte 	if (!text || textLength == 0) {
296fcf3ce44SJohn Forte 		return (TRUE);
297fcf3ce44SJohn Forte 	}
298fcf3ce44SJohn Forte 
299fcf3ce44SJohn Forte 	if (!data || dataLength == 0) {
300fcf3ce44SJohn Forte 		*text = '\0';
301fcf3ce44SJohn Forte 		return (TRUE);
302fcf3ce44SJohn Forte 	}
303fcf3ce44SJohn Forte 
304fcf3ce44SJohn Forte 	if (textLength < 3) {
305fcf3ce44SJohn Forte 		*text = '\0';
306fcf3ce44SJohn Forte 		return (TRUE);
307fcf3ce44SJohn Forte 	}
308fcf3ce44SJohn Forte 
309fcf3ce44SJohn Forte 	*text++ = '0';
310fcf3ce44SJohn Forte 	*text++ = 'b';
311fcf3ce44SJohn Forte 
312fcf3ce44SJohn Forte 	textLength -= 2;
313fcf3ce44SJohn Forte 
314fcf3ce44SJohn Forte 	while (dataLength >= 3) {
315fcf3ce44SJohn Forte 
316fcf3ce44SJohn Forte 		if (textLength < 5) {
317fcf3ce44SJohn Forte 			*text = '\0';
318fcf3ce44SJohn Forte 			return (TRUE);
319fcf3ce44SJohn Forte 		}
320fcf3ce44SJohn Forte 
321fcf3ce44SJohn Forte 		n = *data++;
322fcf3ce44SJohn Forte 		n = (n << 8) | *data++;
323fcf3ce44SJohn Forte 		n = (n << 8) | *data++;
324fcf3ce44SJohn Forte 		dataLength -= 3;
325fcf3ce44SJohn Forte 
326fcf3ce44SJohn Forte 		*text++ = iscsiAuthClientBase64String[(n >> 18) & 0x3f];
327fcf3ce44SJohn Forte 		*text++ = iscsiAuthClientBase64String[(n >> 12) & 0x3f];
328fcf3ce44SJohn Forte 		*text++ = iscsiAuthClientBase64String[(n >> 6) & 0x3f];
329fcf3ce44SJohn Forte 		*text++ = iscsiAuthClientBase64String[n & 0x3f];
330fcf3ce44SJohn Forte 
331fcf3ce44SJohn Forte 		textLength -= 4;
332fcf3ce44SJohn Forte 	}
333fcf3ce44SJohn Forte 
334fcf3ce44SJohn Forte 	if (dataLength == 1) {
335fcf3ce44SJohn Forte 
336fcf3ce44SJohn Forte 		if (textLength < 5) {
337fcf3ce44SJohn Forte 			*text = '\0';
338fcf3ce44SJohn Forte 			return (TRUE);
339fcf3ce44SJohn Forte 		}
340fcf3ce44SJohn Forte 
341fcf3ce44SJohn Forte 		n = *data++;
342fcf3ce44SJohn Forte 		n = n << 4;
343fcf3ce44SJohn Forte 
344fcf3ce44SJohn Forte 		*text++ = iscsiAuthClientBase64String[(n >> 6) & 0x3f];
345fcf3ce44SJohn Forte 		*text++ = iscsiAuthClientBase64String[n & 0x3f];
346fcf3ce44SJohn Forte 		*text++ = '=';
347fcf3ce44SJohn Forte 		*text++ = '=';
348fcf3ce44SJohn Forte 
349fcf3ce44SJohn Forte 	} else if (dataLength == 2) {
350fcf3ce44SJohn Forte 
351fcf3ce44SJohn Forte 		if (textLength < 5) {
352fcf3ce44SJohn Forte 			return (TRUE);
353fcf3ce44SJohn Forte 		}
354fcf3ce44SJohn Forte 
355fcf3ce44SJohn Forte 		n = *data++;
356fcf3ce44SJohn Forte 		n = (n << 8) | *data++;
357fcf3ce44SJohn Forte 		n = n << 2;
358fcf3ce44SJohn Forte 
359fcf3ce44SJohn Forte 		*text++ = iscsiAuthClientBase64String[(n >> 12) & 0x3f];
360fcf3ce44SJohn Forte 		*text++ = iscsiAuthClientBase64String[(n >> 6) & 0x3f];
361fcf3ce44SJohn Forte 		*text++ = iscsiAuthClientBase64String[n & 0x3f];
362fcf3ce44SJohn Forte 		*text++ = '=';
363fcf3ce44SJohn Forte 	}
364fcf3ce44SJohn Forte 
365fcf3ce44SJohn Forte 	*text = '\0';
366fcf3ce44SJohn Forte 
367fcf3ce44SJohn Forte 	return (FALSE);
368fcf3ce44SJohn Forte }
369fcf3ce44SJohn Forte 
370fcf3ce44SJohn Forte 
371fcf3ce44SJohn Forte static int
iscsiAuthClientDataToText(int base64,unsigned char * data,unsigned int dataLength,char * text,unsigned int textLength)372fcf3ce44SJohn Forte iscsiAuthClientDataToText(int base64, unsigned char *data,
373fcf3ce44SJohn Forte     unsigned int dataLength, char *text, unsigned int textLength)
374fcf3ce44SJohn Forte {
375fcf3ce44SJohn Forte 	int status;
376fcf3ce44SJohn Forte 
377fcf3ce44SJohn Forte 	if (base64) {
378fcf3ce44SJohn Forte 		status = iscsiAuthClientDataToBase64(
379fcf3ce44SJohn Forte 		    data, dataLength, text, textLength);
380fcf3ce44SJohn Forte 	} else {
381fcf3ce44SJohn Forte 		status = iscsiAuthClientDataToHex(
382fcf3ce44SJohn Forte 		    data, dataLength, text, textLength);
383fcf3ce44SJohn Forte 	}
384fcf3ce44SJohn Forte 
385fcf3ce44SJohn Forte 	return (status);
386fcf3ce44SJohn Forte }
387fcf3ce44SJohn Forte 
388fcf3ce44SJohn Forte 
389fcf3ce44SJohn Forte static int
iscsiAuthClientHexToData(const char * text,unsigned int textLength,unsigned char * data,unsigned int * pDataLength)390fcf3ce44SJohn Forte iscsiAuthClientHexToData(const char *text, unsigned int textLength,
391fcf3ce44SJohn Forte     unsigned char *data, unsigned int *pDataLength)
392fcf3ce44SJohn Forte {
393fcf3ce44SJohn Forte 	int i;
394fcf3ce44SJohn Forte 	unsigned int n1;
395fcf3ce44SJohn Forte 	unsigned int n2;
396fcf3ce44SJohn Forte 	unsigned int dataLength = *pDataLength;
397fcf3ce44SJohn Forte 
398fcf3ce44SJohn Forte 	if ((textLength % 2) == 1) {
399fcf3ce44SJohn Forte 		i = iscsiAuthClientStringIndex(iscsiAuthClientHexString,
400fcf3ce44SJohn Forte 		    *text++);
401fcf3ce44SJohn Forte 		if (i < 0) {
402fcf3ce44SJohn Forte 			return (TRUE);	/* error, bad character */
403fcf3ce44SJohn Forte 		}
404fcf3ce44SJohn Forte 
405fcf3ce44SJohn Forte 		if (i > 15)
406fcf3ce44SJohn Forte 			i -= 6;
407fcf3ce44SJohn Forte 		n2 = i;
408fcf3ce44SJohn Forte 
409fcf3ce44SJohn Forte 		if (dataLength < 1) {
410fcf3ce44SJohn Forte 			return (TRUE);	/* error, too much data */
411fcf3ce44SJohn Forte 		}
412fcf3ce44SJohn Forte 
413fcf3ce44SJohn Forte 		*data++ = n2;
414fcf3ce44SJohn Forte 		dataLength--;
415fcf3ce44SJohn Forte 	}
416fcf3ce44SJohn Forte 
417fcf3ce44SJohn Forte 	while (*text != '\0') {
418fcf3ce44SJohn Forte 
419fcf3ce44SJohn Forte 		i = iscsiAuthClientStringIndex(
420fcf3ce44SJohn Forte 		    iscsiAuthClientHexString, *text++);
421fcf3ce44SJohn Forte 		if (i < 0) {
422fcf3ce44SJohn Forte 			return (TRUE);	/* error, bad character */
423fcf3ce44SJohn Forte 		}
424fcf3ce44SJohn Forte 
425fcf3ce44SJohn Forte 		if (i > 15)
426fcf3ce44SJohn Forte 			i -= 6;
427fcf3ce44SJohn Forte 		n1 = i;
428fcf3ce44SJohn Forte 
429fcf3ce44SJohn Forte 		if (*text == '\0') {
430fcf3ce44SJohn Forte 			return (TRUE);	/* error, odd string length */
431fcf3ce44SJohn Forte 		}
432fcf3ce44SJohn Forte 
433fcf3ce44SJohn Forte 		i = iscsiAuthClientStringIndex(
434fcf3ce44SJohn Forte 		    iscsiAuthClientHexString, *text++);
435fcf3ce44SJohn Forte 		if (i < 0) {
436fcf3ce44SJohn Forte 			return (TRUE);	/* error, bad character */
437fcf3ce44SJohn Forte 		}
438fcf3ce44SJohn Forte 
439fcf3ce44SJohn Forte 		if (i > 15)
440fcf3ce44SJohn Forte 			i -= 6;
441fcf3ce44SJohn Forte 		n2 = i;
442fcf3ce44SJohn Forte 
443fcf3ce44SJohn Forte 		if (dataLength < 1) {
444fcf3ce44SJohn Forte 			return (TRUE);	/* error, too much data */
445fcf3ce44SJohn Forte 		}
446fcf3ce44SJohn Forte 
447fcf3ce44SJohn Forte 		*data++ = (n1 << 4) | n2;
448fcf3ce44SJohn Forte 		dataLength--;
449fcf3ce44SJohn Forte 	}
450fcf3ce44SJohn Forte 
451fcf3ce44SJohn Forte 	if (dataLength >= *pDataLength) {
452fcf3ce44SJohn Forte 		return (TRUE);	/* error, no data */
453fcf3ce44SJohn Forte 	}
454fcf3ce44SJohn Forte 
455fcf3ce44SJohn Forte 	*pDataLength = *pDataLength - dataLength;
456fcf3ce44SJohn Forte 
457fcf3ce44SJohn Forte 	return (FALSE);		/* no error */
458fcf3ce44SJohn Forte }
459fcf3ce44SJohn Forte 
460fcf3ce44SJohn Forte 
461fcf3ce44SJohn Forte static int
iscsiAuthClientBase64ToData(const char * text,unsigned int textLength,unsigned char * data,unsigned int * pDataLength)462fcf3ce44SJohn Forte iscsiAuthClientBase64ToData(const char *text, unsigned int textLength,
463fcf3ce44SJohn Forte     unsigned char *data, unsigned int *pDataLength)
464fcf3ce44SJohn Forte {
465fcf3ce44SJohn Forte 	int i;
466fcf3ce44SJohn Forte 	unsigned int n;
467fcf3ce44SJohn Forte 	unsigned int count;
468fcf3ce44SJohn Forte 	unsigned int dataLength = *pDataLength;
469fcf3ce44SJohn Forte 
470fcf3ce44SJohn Forte 	textLength = textLength;	/* not used */
471fcf3ce44SJohn Forte 
472fcf3ce44SJohn Forte 	n = 0;
473fcf3ce44SJohn Forte 	count = 0;
474fcf3ce44SJohn Forte 
475fcf3ce44SJohn Forte 	while (*text != '\0' && *text != '=') {
476fcf3ce44SJohn Forte 
477fcf3ce44SJohn Forte 		i = iscsiAuthClientStringIndex(
478fcf3ce44SJohn Forte 		    iscsiAuthClientBase64String, *text++);
479fcf3ce44SJohn Forte 		if (i < 0) {
480fcf3ce44SJohn Forte 			return (TRUE);	/* error, bad character */
481fcf3ce44SJohn Forte 		}
482fcf3ce44SJohn Forte 
483fcf3ce44SJohn Forte 		n = (n << 6 | (unsigned int)i);
484fcf3ce44SJohn Forte 		count++;
485fcf3ce44SJohn Forte 
486fcf3ce44SJohn Forte 		if (count >= 4) {
487fcf3ce44SJohn Forte 			if (dataLength < 3) {
488fcf3ce44SJohn Forte 				return (TRUE);	/* error, too much data */
489fcf3ce44SJohn Forte 			}
490fcf3ce44SJohn Forte 			*data++ = n >> 16;
491fcf3ce44SJohn Forte 			*data++ = n >> 8;
492fcf3ce44SJohn Forte 			*data++ = n;
493fcf3ce44SJohn Forte 			dataLength -= 3;
494fcf3ce44SJohn Forte 			n = 0;
495fcf3ce44SJohn Forte 			count = 0;
496fcf3ce44SJohn Forte 		}
497fcf3ce44SJohn Forte 	}
498fcf3ce44SJohn Forte 
499fcf3ce44SJohn Forte 	while (*text != '\0') {
500fcf3ce44SJohn Forte 		if (*text++ != '=') {
501fcf3ce44SJohn Forte 			return (TRUE);	/* error, bad pad */
502fcf3ce44SJohn Forte 		}
503fcf3ce44SJohn Forte 	}
504fcf3ce44SJohn Forte 
505fcf3ce44SJohn Forte 	if (count == 0) {
506fcf3ce44SJohn Forte 		/*
507fcf3ce44SJohn Forte 		 * do nothing
508fcf3ce44SJohn Forte 		 */
509fcf3ce44SJohn Forte 		/* EMPTY */
510fcf3ce44SJohn Forte 	} else if (count == 2) {
511fcf3ce44SJohn Forte 		if (dataLength < 1) {
512fcf3ce44SJohn Forte 			return (TRUE);	/* error, too much data */
513fcf3ce44SJohn Forte 		}
514fcf3ce44SJohn Forte 		n = n >> 4;
515fcf3ce44SJohn Forte 		*data++ = n;
516fcf3ce44SJohn Forte 		dataLength--;
517fcf3ce44SJohn Forte 	} else if (count == 3) {
518fcf3ce44SJohn Forte 		if (dataLength < 2) {
519fcf3ce44SJohn Forte 			return (TRUE);	/* error, too much data */
520fcf3ce44SJohn Forte 		}
521fcf3ce44SJohn Forte 		n = n >> 2;
522fcf3ce44SJohn Forte 		*data++ = n >> 8;
523fcf3ce44SJohn Forte 		*data++ = n;
524fcf3ce44SJohn Forte 		dataLength -= 2;
525fcf3ce44SJohn Forte 	} else {
526fcf3ce44SJohn Forte 		return (TRUE);	/* bad encoding */
527fcf3ce44SJohn Forte 	}
528fcf3ce44SJohn Forte 
529fcf3ce44SJohn Forte 	if (dataLength >= *pDataLength) {
530fcf3ce44SJohn Forte 		return (TRUE);	/* error, no data */
531fcf3ce44SJohn Forte 	}
532fcf3ce44SJohn Forte 
533fcf3ce44SJohn Forte 	*pDataLength = *pDataLength - dataLength;
534fcf3ce44SJohn Forte 
535fcf3ce44SJohn Forte 	return (FALSE);		/* no error */
536fcf3ce44SJohn Forte }
537fcf3ce44SJohn Forte 
538fcf3ce44SJohn Forte 
539fcf3ce44SJohn Forte static int
iscsiAuthClientTextToData(const char * text,unsigned char * data,unsigned int * dataLength)540fcf3ce44SJohn Forte iscsiAuthClientTextToData(const char *text, unsigned char *data,
541fcf3ce44SJohn Forte     unsigned int *dataLength)
542fcf3ce44SJohn Forte {
543fcf3ce44SJohn Forte 	int status;
544fcf3ce44SJohn Forte 	unsigned int textLength;
545fcf3ce44SJohn Forte 
546fcf3ce44SJohn Forte 	status = iscsiAuthClientCheckString(text,
547fcf3ce44SJohn Forte 	    2 + 2 * iscsiAuthLargeBinaryMaxLength + 1, &textLength);
548fcf3ce44SJohn Forte 
549fcf3ce44SJohn Forte 	if (status) {
550fcf3ce44SJohn Forte 		return (status);
551fcf3ce44SJohn Forte 	}
552fcf3ce44SJohn Forte 
553fcf3ce44SJohn Forte 	if (text[0] == '0' && (text[1] == 'x' || text[1] == 'X')) {
554fcf3ce44SJohn Forte 		/*
555fcf3ce44SJohn Forte 		 * skip prefix
556fcf3ce44SJohn Forte 		 */
557fcf3ce44SJohn Forte 		text += 2;
558fcf3ce44SJohn Forte 		textLength -= 2;
559fcf3ce44SJohn Forte 		status = iscsiAuthClientHexToData(text,
560fcf3ce44SJohn Forte 		    textLength, data, dataLength);
561fcf3ce44SJohn Forte 	} else if (text[0] == '0' && (text[1] == 'b' || text[1] == 'B')) {
562fcf3ce44SJohn Forte 		/*
563fcf3ce44SJohn Forte 		 * skip prefix
564fcf3ce44SJohn Forte 		 */
565fcf3ce44SJohn Forte 		text += 2;
566fcf3ce44SJohn Forte 		textLength -= 2;
567fcf3ce44SJohn Forte 		status = iscsiAuthClientBase64ToData(text,
568fcf3ce44SJohn Forte 		    textLength, data, dataLength);
569fcf3ce44SJohn Forte 	} else {
570fcf3ce44SJohn Forte 		status = TRUE;	/* prefix not recognized. */
571fcf3ce44SJohn Forte 	}
572fcf3ce44SJohn Forte 
573fcf3ce44SJohn Forte 	return (status);
574fcf3ce44SJohn Forte }
575fcf3ce44SJohn Forte 
576fcf3ce44SJohn Forte 
577fcf3ce44SJohn Forte static IscsiAuthDebugStatus
iscsiAuthClientChapComputeResponse(IscsiAuthClient * client,int remoteAuthentication,unsigned int id,unsigned char * challengeData,unsigned int challengeLength,unsigned char * responseData)578fcf3ce44SJohn Forte iscsiAuthClientChapComputeResponse(IscsiAuthClient * client,
579fcf3ce44SJohn Forte     int remoteAuthentication, unsigned int id,
580fcf3ce44SJohn Forte     unsigned char *challengeData, unsigned int challengeLength,
581fcf3ce44SJohn Forte     unsigned char *responseData)
582fcf3ce44SJohn Forte {
583fcf3ce44SJohn Forte 	unsigned char idData[1];
584fcf3ce44SJohn Forte 	IscsiAuthMd5Context context;
585fcf3ce44SJohn Forte 	unsigned char outData[iscsiAuthStringMaxLength];
586fcf3ce44SJohn Forte 	unsigned int outLength = iscsiAuthStringMaxLength;
587fcf3ce44SJohn Forte 
588fcf3ce44SJohn Forte 	if (!client->passwordPresent) {
589fcf3ce44SJohn Forte 		return (iscsiAuthDebugStatusLocalPasswordNotSet);
590fcf3ce44SJohn Forte 	}
591fcf3ce44SJohn Forte 
592fcf3ce44SJohn Forte 	iscsiAuthMd5Init(&context);
593fcf3ce44SJohn Forte 
594fcf3ce44SJohn Forte 	/*
595fcf3ce44SJohn Forte 	 * id byte
596fcf3ce44SJohn Forte 	 */
597fcf3ce44SJohn Forte 	idData[0] = id;
598fcf3ce44SJohn Forte 	iscsiAuthMd5Update(&context, idData, 1);
599fcf3ce44SJohn Forte 
600fcf3ce44SJohn Forte 	/*
601fcf3ce44SJohn Forte 	 * decrypt password
602fcf3ce44SJohn Forte 	 */
603fcf3ce44SJohn Forte 	if (iscsiAuthClientData(outData, &outLength,
604fcf3ce44SJohn Forte 	    client->passwordData, client->passwordLength)) {
605fcf3ce44SJohn Forte 
606fcf3ce44SJohn Forte 		return (iscsiAuthDebugStatusPasswordDecryptFailed);
607fcf3ce44SJohn Forte 	}
608fcf3ce44SJohn Forte 
609fcf3ce44SJohn Forte 	if (!remoteAuthentication && !client->ipSec && outLength < 12) {
610fcf3ce44SJohn Forte 		return (iscsiAuthDebugStatusPasswordTooShortWithNoIpSec);
611fcf3ce44SJohn Forte 	}
612fcf3ce44SJohn Forte 
613fcf3ce44SJohn Forte 	/*
614fcf3ce44SJohn Forte 	 * shared secret
615fcf3ce44SJohn Forte 	 */
616fcf3ce44SJohn Forte 	iscsiAuthMd5Update(&context, outData, outLength);
617fcf3ce44SJohn Forte 
618fcf3ce44SJohn Forte 	/*
619fcf3ce44SJohn Forte 	 * clear decrypted password
620fcf3ce44SJohn Forte 	 */
621fcf3ce44SJohn Forte 	bzero(outData, iscsiAuthStringMaxLength);
622fcf3ce44SJohn Forte 
623fcf3ce44SJohn Forte 	/*
624fcf3ce44SJohn Forte 	 * challenge value
625fcf3ce44SJohn Forte 	 */
626fcf3ce44SJohn Forte 	iscsiAuthMd5Update(&context, challengeData, challengeLength);
627fcf3ce44SJohn Forte 
628fcf3ce44SJohn Forte 	iscsiAuthMd5Final(responseData, &context);
629fcf3ce44SJohn Forte 
630fcf3ce44SJohn Forte 	return (iscsiAuthDebugStatusNotSet);	/* no error */
631fcf3ce44SJohn Forte }
632fcf3ce44SJohn Forte 
633fcf3ce44SJohn Forte 
634fcf3ce44SJohn Forte static void
iscsiAuthClientInitKeyBlock(IscsiAuthKeyBlock * keyBlock)635fcf3ce44SJohn Forte iscsiAuthClientInitKeyBlock(IscsiAuthKeyBlock * keyBlock)
636fcf3ce44SJohn Forte {
637fcf3ce44SJohn Forte 	char *stringBlock = keyBlock->stringBlock;
638fcf3ce44SJohn Forte 
639fcf3ce44SJohn Forte 	bzero(keyBlock, sizeof (*keyBlock));
640fcf3ce44SJohn Forte 	keyBlock->stringBlock = stringBlock;
641fcf3ce44SJohn Forte }
642fcf3ce44SJohn Forte 
643fcf3ce44SJohn Forte 
644fcf3ce44SJohn Forte static void
iscsiAuthClientSetKeyValue(IscsiAuthKeyBlock * keyBlock,int keyType,const char * keyValue)645fcf3ce44SJohn Forte iscsiAuthClientSetKeyValue(IscsiAuthKeyBlock * keyBlock,
646fcf3ce44SJohn Forte     int keyType, const char *keyValue)
647fcf3ce44SJohn Forte {
648fcf3ce44SJohn Forte 	unsigned int length;
649fcf3ce44SJohn Forte 	char *string;
650fcf3ce44SJohn Forte 
651fcf3ce44SJohn Forte 	if (keyBlock->key[keyType].valueSet) {
652fcf3ce44SJohn Forte 		keyBlock->duplicateSet = TRUE;
653fcf3ce44SJohn Forte 		return;
654fcf3ce44SJohn Forte 	}
655fcf3ce44SJohn Forte 
656fcf3ce44SJohn Forte 	keyBlock->key[keyType].valueSet = TRUE;
657fcf3ce44SJohn Forte 
658fcf3ce44SJohn Forte 	if (!keyValue) {
659fcf3ce44SJohn Forte 		return;
660fcf3ce44SJohn Forte 	}
661fcf3ce44SJohn Forte 
662fcf3ce44SJohn Forte 	if (iscsiAuthClientCheckString(keyValue,
663fcf3ce44SJohn Forte 	    iscsiAuthStringMaxLength, &length)) {
664fcf3ce44SJohn Forte 		keyBlock->stringTooLong = TRUE;
665fcf3ce44SJohn Forte 		return;
666fcf3ce44SJohn Forte 	}
667fcf3ce44SJohn Forte 
668fcf3ce44SJohn Forte 	length += 1;
669fcf3ce44SJohn Forte 
670fcf3ce44SJohn Forte 	if ((keyBlock->blockLength + length) > iscsiAuthStringBlockMaxLength) {
671fcf3ce44SJohn Forte 		keyBlock->tooMuchData = TRUE;
672fcf3ce44SJohn Forte 		return;
673fcf3ce44SJohn Forte 	}
674fcf3ce44SJohn Forte 
675fcf3ce44SJohn Forte 	string = &keyBlock->stringBlock[keyBlock->blockLength];
676fcf3ce44SJohn Forte 
677fcf3ce44SJohn Forte 	if (iscsiAuthClientStringCopy(string, keyValue, length)) {
678fcf3ce44SJohn Forte 		keyBlock->tooMuchData = TRUE;
679fcf3ce44SJohn Forte 		return;
680fcf3ce44SJohn Forte 	}
681fcf3ce44SJohn Forte 	keyBlock->blockLength += length;
682fcf3ce44SJohn Forte 
683fcf3ce44SJohn Forte 	keyBlock->key[keyType].string = string;
684fcf3ce44SJohn Forte 	keyBlock->key[keyType].present = TRUE;
685fcf3ce44SJohn Forte }
686fcf3ce44SJohn Forte 
687fcf3ce44SJohn Forte 
688fcf3ce44SJohn Forte static const char *
iscsiAuthClientGetKeyValue(IscsiAuthKeyBlock * keyBlock,int keyType)689fcf3ce44SJohn Forte iscsiAuthClientGetKeyValue(IscsiAuthKeyBlock * keyBlock, int keyType)
690fcf3ce44SJohn Forte {
691fcf3ce44SJohn Forte 	keyBlock->key[keyType].processed = TRUE;
692fcf3ce44SJohn Forte 
693fcf3ce44SJohn Forte 	if (!keyBlock->key[keyType].present) {
694fcf3ce44SJohn Forte 		return (0);
695fcf3ce44SJohn Forte 	}
696fcf3ce44SJohn Forte 
697fcf3ce44SJohn Forte 	return (keyBlock->key[keyType].string);
698fcf3ce44SJohn Forte }
699fcf3ce44SJohn Forte 
700fcf3ce44SJohn Forte 
701fcf3ce44SJohn Forte static void
iscsiAuthClientCheckKey(IscsiAuthClient * client,int keyType,int * negotiatedOption,unsigned int optionCount,int * optionList,const char * (* valueToText)(IscsiAuthClient *,int))702fcf3ce44SJohn Forte iscsiAuthClientCheckKey(IscsiAuthClient * client,
703fcf3ce44SJohn Forte     int keyType,
704fcf3ce44SJohn Forte     int *negotiatedOption,
705fcf3ce44SJohn Forte     unsigned int optionCount,
706fcf3ce44SJohn Forte     int *optionList, const char *(*valueToText) (IscsiAuthClient *, int))
707fcf3ce44SJohn Forte {
708fcf3ce44SJohn Forte 	const char *keyValue;
709fcf3ce44SJohn Forte 	int length;
710fcf3ce44SJohn Forte 	unsigned int i;
711fcf3ce44SJohn Forte 
712fcf3ce44SJohn Forte 	keyValue = iscsiAuthClientGetKeyValue(&client->recvKeyBlock, keyType);
713fcf3ce44SJohn Forte 	if (!keyValue) {
714fcf3ce44SJohn Forte 		*negotiatedOption = iscsiAuthOptionNotPresent;
715fcf3ce44SJohn Forte 		return;
716fcf3ce44SJohn Forte 	}
717fcf3ce44SJohn Forte 
718fcf3ce44SJohn Forte 	while (*keyValue != '\0') {
719fcf3ce44SJohn Forte 
720fcf3ce44SJohn Forte 		length = 0;
721fcf3ce44SJohn Forte 
722fcf3ce44SJohn Forte 		while (*keyValue != '\0' && *keyValue != ',') {
723fcf3ce44SJohn Forte 			client->scratchKeyValue[length++] = *keyValue++;
724fcf3ce44SJohn Forte 		}
725fcf3ce44SJohn Forte 
726fcf3ce44SJohn Forte 		if (*keyValue == ',')
727fcf3ce44SJohn Forte 			keyValue++;
728fcf3ce44SJohn Forte 		client->scratchKeyValue[length++] = '\0';
729fcf3ce44SJohn Forte 
730fcf3ce44SJohn Forte 		for (i = 0; i < optionCount; i++) {
731fcf3ce44SJohn Forte 			const char *s = (*valueToText) (client, optionList[i]);
732fcf3ce44SJohn Forte 
733fcf3ce44SJohn Forte 			if (!s)
734fcf3ce44SJohn Forte 				continue;
735fcf3ce44SJohn Forte 
736fcf3ce44SJohn Forte 			if (strcmp(client->scratchKeyValue, s) == 0) {
737fcf3ce44SJohn Forte 				*negotiatedOption = optionList[i];
738fcf3ce44SJohn Forte 				return;
739fcf3ce44SJohn Forte 			}
740fcf3ce44SJohn Forte 		}
741fcf3ce44SJohn Forte 	}
742fcf3ce44SJohn Forte 
743fcf3ce44SJohn Forte 	*negotiatedOption = iscsiAuthOptionReject;
744fcf3ce44SJohn Forte }
745fcf3ce44SJohn Forte 
746fcf3ce44SJohn Forte 
747fcf3ce44SJohn Forte static void
iscsiAuthClientSetKey(IscsiAuthClient * client,int keyType,unsigned int optionCount,int * optionList,const char * (* valueToText)(IscsiAuthClient *,int))748fcf3ce44SJohn Forte iscsiAuthClientSetKey(IscsiAuthClient * client,
749fcf3ce44SJohn Forte     int keyType,
750fcf3ce44SJohn Forte     unsigned int optionCount,
751fcf3ce44SJohn Forte     int *optionList, const char *(*valueToText) (IscsiAuthClient *, int))
752fcf3ce44SJohn Forte {
753fcf3ce44SJohn Forte 	unsigned int i;
754fcf3ce44SJohn Forte 
755fcf3ce44SJohn Forte 	if (optionCount == 0) {
756fcf3ce44SJohn Forte 		/*
757fcf3ce44SJohn Forte 		 * No valid options to send, but we always want to
758fcf3ce44SJohn Forte 		 * send something.
759fcf3ce44SJohn Forte 		 */
760fcf3ce44SJohn Forte 		iscsiAuthClientSetKeyValue(&client->sendKeyBlock, keyType,
761fcf3ce44SJohn Forte 		    client->noneOptionName);
762fcf3ce44SJohn Forte 		return;
763fcf3ce44SJohn Forte 	}
764fcf3ce44SJohn Forte 
765fcf3ce44SJohn Forte 	if (optionCount == 1 && optionList[0] == iscsiAuthOptionNotPresent) {
766fcf3ce44SJohn Forte 		iscsiAuthClientSetKeyValue(&client->sendKeyBlock, keyType, 0);
767fcf3ce44SJohn Forte 		return;
768fcf3ce44SJohn Forte 	}
769fcf3ce44SJohn Forte 
770fcf3ce44SJohn Forte 	for (i = 0; i < optionCount; i++) {
771fcf3ce44SJohn Forte 		const char *s = (*valueToText) (client, optionList[i]);
772fcf3ce44SJohn Forte 
773fcf3ce44SJohn Forte 		if (!s)
774fcf3ce44SJohn Forte 			continue;
775fcf3ce44SJohn Forte 
776fcf3ce44SJohn Forte 		if (i == 0) {
777fcf3ce44SJohn Forte 			(void) iscsiAuthClientStringCopy(
778fcf3ce44SJohn Forte 			    client->scratchKeyValue,
779fcf3ce44SJohn Forte 			    s, iscsiAuthStringMaxLength);
780fcf3ce44SJohn Forte 		} else {
781fcf3ce44SJohn Forte 			(void) iscsiAuthClientStringAppend(
782fcf3ce44SJohn Forte 			    client->scratchKeyValue,
783fcf3ce44SJohn Forte 			    ",", iscsiAuthStringMaxLength);
784fcf3ce44SJohn Forte 			(void) iscsiAuthClientStringAppend(
785fcf3ce44SJohn Forte 			    client->scratchKeyValue,
786fcf3ce44SJohn Forte 			    s, iscsiAuthStringMaxLength);
787fcf3ce44SJohn Forte 		}
788fcf3ce44SJohn Forte 	}
789fcf3ce44SJohn Forte 
790fcf3ce44SJohn Forte 	iscsiAuthClientSetKeyValue(&client->sendKeyBlock,
791fcf3ce44SJohn Forte 	    keyType, client->scratchKeyValue);
792fcf3ce44SJohn Forte }
793fcf3ce44SJohn Forte 
794fcf3ce44SJohn Forte 
795fcf3ce44SJohn Forte static void
iscsiAuthClientCheckAuthMethodKey(IscsiAuthClient * client)796fcf3ce44SJohn Forte iscsiAuthClientCheckAuthMethodKey(IscsiAuthClient * client)
797fcf3ce44SJohn Forte {
798fcf3ce44SJohn Forte 	iscsiAuthClientCheckKey(client,
799fcf3ce44SJohn Forte 	    iscsiAuthKeyTypeAuthMethod,
800fcf3ce44SJohn Forte 	    &client->negotiatedAuthMethod,
801fcf3ce44SJohn Forte 	    client->authMethodValidCount,
802fcf3ce44SJohn Forte 	    client->authMethodValidList, iscsiAuthClientAuthMethodOptionToText);
803fcf3ce44SJohn Forte }
804fcf3ce44SJohn Forte 
805fcf3ce44SJohn Forte 
806fcf3ce44SJohn Forte static void
iscsiAuthClientSetAuthMethodKey(IscsiAuthClient * client,unsigned int authMethodCount,int * authMethodList)807fcf3ce44SJohn Forte iscsiAuthClientSetAuthMethodKey(IscsiAuthClient * client,
808fcf3ce44SJohn Forte     unsigned int authMethodCount, int *authMethodList)
809fcf3ce44SJohn Forte {
810fcf3ce44SJohn Forte 	iscsiAuthClientSetKey(client, iscsiAuthKeyTypeAuthMethod,
811fcf3ce44SJohn Forte 	    authMethodCount, authMethodList,
812fcf3ce44SJohn Forte 	    iscsiAuthClientAuthMethodOptionToText);
813fcf3ce44SJohn Forte }
814fcf3ce44SJohn Forte 
815fcf3ce44SJohn Forte 
816fcf3ce44SJohn Forte static void
iscsiAuthClientCheckChapAlgorithmKey(IscsiAuthClient * client)817fcf3ce44SJohn Forte iscsiAuthClientCheckChapAlgorithmKey(IscsiAuthClient * client)
818fcf3ce44SJohn Forte {
819fcf3ce44SJohn Forte 	const char *keyValue;
820fcf3ce44SJohn Forte 	int length;
821fcf3ce44SJohn Forte 	unsigned long number;
822fcf3ce44SJohn Forte 	unsigned int i;
823fcf3ce44SJohn Forte 
824fcf3ce44SJohn Forte 	keyValue = iscsiAuthClientGetKeyValue(&client->recvKeyBlock,
825fcf3ce44SJohn Forte 	    iscsiAuthKeyTypeChapAlgorithm);
826fcf3ce44SJohn Forte 	if (!keyValue) {
827fcf3ce44SJohn Forte 		client->negotiatedChapAlgorithm = iscsiAuthOptionNotPresent;
828fcf3ce44SJohn Forte 		return;
829fcf3ce44SJohn Forte 	}
830fcf3ce44SJohn Forte 
831fcf3ce44SJohn Forte 	while (*keyValue != '\0') {
832fcf3ce44SJohn Forte 		length = 0;
833fcf3ce44SJohn Forte 
834fcf3ce44SJohn Forte 		while (*keyValue != '\0' && *keyValue != ',') {
835fcf3ce44SJohn Forte 			client->scratchKeyValue[length++] = *keyValue++;
836fcf3ce44SJohn Forte 		}
837fcf3ce44SJohn Forte 
838fcf3ce44SJohn Forte 		if (*keyValue == ',')
839fcf3ce44SJohn Forte 			keyValue++;
840fcf3ce44SJohn Forte 		client->scratchKeyValue[length++] = '\0';
841fcf3ce44SJohn Forte 
842fcf3ce44SJohn Forte 		if (iscsiAuthClientTextToNumber(client->scratchKeyValue,
843fcf3ce44SJohn Forte 		    &number)) {
844fcf3ce44SJohn Forte 			continue;
845fcf3ce44SJohn Forte 		}
846fcf3ce44SJohn Forte 
847fcf3ce44SJohn Forte 		for (i = 0; i < client->chapAlgorithmCount; i++) {
848fcf3ce44SJohn Forte 
849fcf3ce44SJohn Forte 			if (number == (unsigned long)client->
850fcf3ce44SJohn Forte 			    chapAlgorithmList[i]) {
851fcf3ce44SJohn Forte 				client->negotiatedChapAlgorithm = number;
852fcf3ce44SJohn Forte 				return;
853fcf3ce44SJohn Forte 			}
854fcf3ce44SJohn Forte 		}
855fcf3ce44SJohn Forte 	}
856fcf3ce44SJohn Forte 
857fcf3ce44SJohn Forte 	client->negotiatedChapAlgorithm = iscsiAuthOptionReject;
858fcf3ce44SJohn Forte }
859fcf3ce44SJohn Forte 
860fcf3ce44SJohn Forte 
861fcf3ce44SJohn Forte static void
iscsiAuthClientSetChapAlgorithmKey(IscsiAuthClient * client,unsigned int chapAlgorithmCount,int * chapAlgorithmList)862fcf3ce44SJohn Forte iscsiAuthClientSetChapAlgorithmKey(IscsiAuthClient * client,
863fcf3ce44SJohn Forte     unsigned int chapAlgorithmCount, int *chapAlgorithmList)
864fcf3ce44SJohn Forte {
865fcf3ce44SJohn Forte 	unsigned int i;
866fcf3ce44SJohn Forte 
867fcf3ce44SJohn Forte 	if (chapAlgorithmCount == 0) {
868fcf3ce44SJohn Forte 		iscsiAuthClientSetKeyValue(&client->sendKeyBlock,
869fcf3ce44SJohn Forte 		    iscsiAuthKeyTypeChapAlgorithm, 0);
870fcf3ce44SJohn Forte 		return;
871fcf3ce44SJohn Forte 	}
872fcf3ce44SJohn Forte 
873fcf3ce44SJohn Forte 	if (chapAlgorithmCount == 1 &&
874fcf3ce44SJohn Forte 	    chapAlgorithmList[0] == iscsiAuthOptionNotPresent) {
875fcf3ce44SJohn Forte 		iscsiAuthClientSetKeyValue(&client->sendKeyBlock,
876fcf3ce44SJohn Forte 		    iscsiAuthKeyTypeChapAlgorithm, 0);
877fcf3ce44SJohn Forte 		return;
878fcf3ce44SJohn Forte 	}
879fcf3ce44SJohn Forte 
880fcf3ce44SJohn Forte 	if (chapAlgorithmCount == 1 &&
881fcf3ce44SJohn Forte 	    chapAlgorithmList[0] == iscsiAuthOptionReject) {
882fcf3ce44SJohn Forte 		iscsiAuthClientSetKeyValue(&client->sendKeyBlock,
883fcf3ce44SJohn Forte 		    iscsiAuthKeyTypeChapAlgorithm, client->rejectOptionName);
884fcf3ce44SJohn Forte 		return;
885fcf3ce44SJohn Forte 	}
886fcf3ce44SJohn Forte 
887fcf3ce44SJohn Forte 	for (i = 0; i < chapAlgorithmCount; i++) {
888fcf3ce44SJohn Forte 		char s[20];
889fcf3ce44SJohn Forte 
890fcf3ce44SJohn Forte 		iscsiAuthClientNumberToText(chapAlgorithmList[i],
891fcf3ce44SJohn Forte 		    s, sizeof (s));
892fcf3ce44SJohn Forte 
893fcf3ce44SJohn Forte 		if (i == 0) {
894fcf3ce44SJohn Forte 			(void) iscsiAuthClientStringCopy(
895fcf3ce44SJohn Forte 			    client->scratchKeyValue, s,
896fcf3ce44SJohn Forte 			    iscsiAuthStringMaxLength);
897fcf3ce44SJohn Forte 		} else {
898fcf3ce44SJohn Forte 			(void) iscsiAuthClientStringAppend(
899fcf3ce44SJohn Forte 			    client->scratchKeyValue,
900fcf3ce44SJohn Forte 			    ",", iscsiAuthStringMaxLength);
901fcf3ce44SJohn Forte 			(void) iscsiAuthClientStringAppend(
902fcf3ce44SJohn Forte 			    client->scratchKeyValue,
903fcf3ce44SJohn Forte 			    s, iscsiAuthStringMaxLength);
904fcf3ce44SJohn Forte 		}
905fcf3ce44SJohn Forte 	}
906fcf3ce44SJohn Forte 
907fcf3ce44SJohn Forte 	iscsiAuthClientSetKeyValue(&client->sendKeyBlock,
908fcf3ce44SJohn Forte 	    iscsiAuthKeyTypeChapAlgorithm, client->scratchKeyValue);
909fcf3ce44SJohn Forte }
910fcf3ce44SJohn Forte 
911fcf3ce44SJohn Forte 
912fcf3ce44SJohn Forte static void
iscsiAuthClientNextPhase(IscsiAuthClient * client)913fcf3ce44SJohn Forte iscsiAuthClientNextPhase(IscsiAuthClient * client)
914fcf3ce44SJohn Forte {
915fcf3ce44SJohn Forte 	switch (client->phase) {
916fcf3ce44SJohn Forte 	case iscsiAuthPhaseConfigure:
917fcf3ce44SJohn Forte 		client->phase = iscsiAuthPhaseNegotiate;
918fcf3ce44SJohn Forte 		break;
919fcf3ce44SJohn Forte 
920fcf3ce44SJohn Forte 	case iscsiAuthPhaseNegotiate:
921fcf3ce44SJohn Forte 		client->phase = iscsiAuthPhaseAuthenticate;
922fcf3ce44SJohn Forte 
923fcf3ce44SJohn Forte 		if (client->negotiatedAuthMethod ==
924fcf3ce44SJohn Forte 		    iscsiAuthOptionReject ||
925fcf3ce44SJohn Forte 		    client->negotiatedAuthMethod ==
926fcf3ce44SJohn Forte 		    iscsiAuthOptionNotPresent ||
927fcf3ce44SJohn Forte 		    client->negotiatedAuthMethod == iscsiAuthOptionNone) {
928fcf3ce44SJohn Forte 
929fcf3ce44SJohn Forte 			client->localState = iscsiAuthLocalStateDone;
930fcf3ce44SJohn Forte 			client->remoteState = iscsiAuthRemoteStateDone;
931fcf3ce44SJohn Forte 
932fcf3ce44SJohn Forte 			if (client->authRemote) {
933fcf3ce44SJohn Forte 				client->remoteAuthStatus = iscsiAuthStatusFail;
934fcf3ce44SJohn Forte 				client->phase = iscsiAuthPhaseDone;
935fcf3ce44SJohn Forte 			} else {
936fcf3ce44SJohn Forte 				client->remoteAuthStatus = iscsiAuthStatusPass;
937fcf3ce44SJohn Forte 			}
938fcf3ce44SJohn Forte 
939fcf3ce44SJohn Forte 			switch (client->negotiatedAuthMethod) {
940fcf3ce44SJohn Forte 			case iscsiAuthOptionReject:
941fcf3ce44SJohn Forte 				client->debugStatus =
942fcf3ce44SJohn Forte 				    iscsiAuthDebugStatusAuthMethodReject;
943fcf3ce44SJohn Forte 				break;
944fcf3ce44SJohn Forte 
945fcf3ce44SJohn Forte 			case iscsiAuthOptionNotPresent:
946fcf3ce44SJohn Forte 				client->debugStatus =
947fcf3ce44SJohn Forte 				    iscsiAuthDebugStatusAuthMethodNotPresent;
948fcf3ce44SJohn Forte 				break;
949fcf3ce44SJohn Forte 
950fcf3ce44SJohn Forte 			case iscsiAuthOptionNone:
951fcf3ce44SJohn Forte 				client->debugStatus =
952fcf3ce44SJohn Forte 				    iscsiAuthDebugStatusAuthMethodNone;
953fcf3ce44SJohn Forte 			}
954fcf3ce44SJohn Forte 
955fcf3ce44SJohn Forte 		} else if (client->negotiatedAuthMethod ==
956fcf3ce44SJohn Forte 		    iscsiAuthMethodChap) {
957fcf3ce44SJohn Forte 			client->localState = iscsiAuthLocalStateSendAlgorithm;
958fcf3ce44SJohn Forte 			client->remoteState = iscsiAuthRemoteStateSendAlgorithm;
959fcf3ce44SJohn Forte 		} else {
960fcf3ce44SJohn Forte 			client->localState = iscsiAuthLocalStateDone;
961fcf3ce44SJohn Forte 			client->remoteState = iscsiAuthRemoteStateDone;
962fcf3ce44SJohn Forte 			client->remoteAuthStatus = iscsiAuthStatusFail;
963fcf3ce44SJohn Forte 			client->debugStatus = iscsiAuthDebugStatusAuthMethodBad;
964fcf3ce44SJohn Forte 		}
965fcf3ce44SJohn Forte 
966fcf3ce44SJohn Forte 		break;
967fcf3ce44SJohn Forte 
968fcf3ce44SJohn Forte 	case iscsiAuthPhaseAuthenticate:
969fcf3ce44SJohn Forte 		client->phase = iscsiAuthPhaseDone;
970fcf3ce44SJohn Forte 		break;
971fcf3ce44SJohn Forte 
972fcf3ce44SJohn Forte 	case iscsiAuthPhaseDone:
973fcf3ce44SJohn Forte 	case iscsiAuthPhaseError:
974fcf3ce44SJohn Forte 	default:
975fcf3ce44SJohn Forte 		client->phase = iscsiAuthPhaseError;
976fcf3ce44SJohn Forte 	}
977fcf3ce44SJohn Forte }
978fcf3ce44SJohn Forte 
979fcf3ce44SJohn Forte 
980fcf3ce44SJohn Forte static void
iscsiAuthClientLocalAuthentication(IscsiAuthClient * client)981fcf3ce44SJohn Forte iscsiAuthClientLocalAuthentication(IscsiAuthClient * client)
982fcf3ce44SJohn Forte {
983fcf3ce44SJohn Forte 	unsigned int chapIdentifier;
984fcf3ce44SJohn Forte 	unsigned char responseData[iscsiAuthChapResponseLength];
985fcf3ce44SJohn Forte 	unsigned long number;
986fcf3ce44SJohn Forte 	int status;
987fcf3ce44SJohn Forte 	IscsiAuthDebugStatus debugStatus;
988fcf3ce44SJohn Forte 	const char *chapIdentifierKeyValue;
989fcf3ce44SJohn Forte 	const char *chapChallengeKeyValue;
990fcf3ce44SJohn Forte 
991fcf3ce44SJohn Forte 	switch (client->localState) {
992fcf3ce44SJohn Forte 	case iscsiAuthLocalStateSendAlgorithm:
993fcf3ce44SJohn Forte 		if (client->nodeType == iscsiAuthNodeTypeInitiator) {
994fcf3ce44SJohn Forte 			iscsiAuthClientSetChapAlgorithmKey(
995fcf3ce44SJohn Forte 			    client, client->chapAlgorithmCount,
996fcf3ce44SJohn Forte 			    client->chapAlgorithmList);
997fcf3ce44SJohn Forte 			client->localState = iscsiAuthLocalStateRecvAlgorithm;
998fcf3ce44SJohn Forte 			break;
999fcf3ce44SJohn Forte 		}
1000fcf3ce44SJohn Forte 
1001fcf3ce44SJohn Forte 		/* FALLTHRU */
1002fcf3ce44SJohn Forte 
1003fcf3ce44SJohn Forte 	case iscsiAuthLocalStateRecvAlgorithm:
1004fcf3ce44SJohn Forte 		iscsiAuthClientCheckChapAlgorithmKey(client);
1005fcf3ce44SJohn Forte 
1006fcf3ce44SJohn Forte 		if (client->nodeType == iscsiAuthNodeTypeTarget) {
1007fcf3ce44SJohn Forte 
1008fcf3ce44SJohn Forte 			iscsiAuthClientSetChapAlgorithmKey(client, 1,
1009fcf3ce44SJohn Forte 			    &client->negotiatedChapAlgorithm);
1010fcf3ce44SJohn Forte 		}
1011fcf3ce44SJohn Forte 
1012fcf3ce44SJohn Forte 		/*
1013fcf3ce44SJohn Forte 		 * Make sure only supported CHAP algorithm is used.
1014fcf3ce44SJohn Forte 		 */
1015fcf3ce44SJohn Forte 		if (client->negotiatedChapAlgorithm ==
1016fcf3ce44SJohn Forte 		    iscsiAuthOptionNotPresent) {
1017fcf3ce44SJohn Forte 			client->localState = iscsiAuthLocalStateError;
1018fcf3ce44SJohn Forte 			client->debugStatus =
1019fcf3ce44SJohn Forte 			    iscsiAuthDebugStatusChapAlgorithmExpected;
1020fcf3ce44SJohn Forte 			break;
1021fcf3ce44SJohn Forte 
1022fcf3ce44SJohn Forte 		} else if (client->negotiatedChapAlgorithm ==
1023fcf3ce44SJohn Forte 		    iscsiAuthOptionReject) {
1024fcf3ce44SJohn Forte 			client->localState = iscsiAuthLocalStateError;
1025fcf3ce44SJohn Forte 			client->debugStatus =
1026fcf3ce44SJohn Forte 			    iscsiAuthDebugStatusChapAlgorithmReject;
1027fcf3ce44SJohn Forte 			break;
1028fcf3ce44SJohn Forte 
1029fcf3ce44SJohn Forte 		} else if (client->negotiatedChapAlgorithm !=
1030fcf3ce44SJohn Forte 		    iscsiAuthChapAlgorithmMd5) {
1031fcf3ce44SJohn Forte 			client->localState = iscsiAuthLocalStateError;
1032fcf3ce44SJohn Forte 			client->debugStatus =
1033fcf3ce44SJohn Forte 			    iscsiAuthDebugStatusChapAlgorithmBad;
1034fcf3ce44SJohn Forte 			break;
1035fcf3ce44SJohn Forte 		}
1036fcf3ce44SJohn Forte 
1037fcf3ce44SJohn Forte 		if (client->nodeType == iscsiAuthNodeTypeTarget) {
1038fcf3ce44SJohn Forte 
1039fcf3ce44SJohn Forte 			client->localState = iscsiAuthLocalStateRecvChallenge;
1040fcf3ce44SJohn Forte 			break;
1041fcf3ce44SJohn Forte 		}
1042fcf3ce44SJohn Forte 
1043fcf3ce44SJohn Forte 		/* FALLTHRU */
1044fcf3ce44SJohn Forte 
1045fcf3ce44SJohn Forte 	case iscsiAuthLocalStateRecvChallenge:
1046fcf3ce44SJohn Forte 		chapIdentifierKeyValue = iscsiAuthClientGetKeyValue(
1047fcf3ce44SJohn Forte 		    &client->recvKeyBlock, iscsiAuthKeyTypeChapIdentifier);
1048fcf3ce44SJohn Forte 		chapChallengeKeyValue = iscsiAuthClientGetKeyValue(
1049fcf3ce44SJohn Forte 		    &client->recvKeyBlock, iscsiAuthKeyTypeChapChallenge);
1050fcf3ce44SJohn Forte 
1051fcf3ce44SJohn Forte 		if (client->nodeType == iscsiAuthNodeTypeTarget) {
1052fcf3ce44SJohn Forte 			if (!chapIdentifierKeyValue && !chapChallengeKeyValue) {
1053fcf3ce44SJohn Forte 				client->localState = iscsiAuthLocalStateDone;
1054fcf3ce44SJohn Forte 				break;
1055fcf3ce44SJohn Forte 			}
1056fcf3ce44SJohn Forte 		}
1057fcf3ce44SJohn Forte 
1058fcf3ce44SJohn Forte 		if (!chapIdentifierKeyValue) {
1059fcf3ce44SJohn Forte 			client->localState = iscsiAuthLocalStateError;
1060fcf3ce44SJohn Forte 			client->debugStatus =
1061fcf3ce44SJohn Forte 			    iscsiAuthDebugStatusChapIdentifierExpected;
1062fcf3ce44SJohn Forte 			break;
1063fcf3ce44SJohn Forte 		}
1064fcf3ce44SJohn Forte 
1065fcf3ce44SJohn Forte 		if (!chapChallengeKeyValue) {
1066fcf3ce44SJohn Forte 			client->localState = iscsiAuthLocalStateError;
1067fcf3ce44SJohn Forte 			client->debugStatus =
1068fcf3ce44SJohn Forte 			    iscsiAuthDebugStatusChapChallengeExpected;
1069fcf3ce44SJohn Forte 			break;
1070fcf3ce44SJohn Forte 		}
1071fcf3ce44SJohn Forte 
1072fcf3ce44SJohn Forte 		status = iscsiAuthClientTextToNumber(
1073fcf3ce44SJohn Forte 		    chapIdentifierKeyValue, &number);
1074fcf3ce44SJohn Forte 
1075fcf3ce44SJohn Forte 		if (status || (255 < number)) {
1076fcf3ce44SJohn Forte 			client->localState = iscsiAuthLocalStateError;
1077fcf3ce44SJohn Forte 			client->debugStatus =
1078fcf3ce44SJohn Forte 			    iscsiAuthDebugStatusChapIdentifierBad;
1079fcf3ce44SJohn Forte 			break;
1080fcf3ce44SJohn Forte 		}
1081fcf3ce44SJohn Forte 		chapIdentifier = number;
1082fcf3ce44SJohn Forte 
1083fcf3ce44SJohn Forte 		if (client->recvChapChallengeStatus) {
1084fcf3ce44SJohn Forte 			client->localState = iscsiAuthLocalStateError;
1085fcf3ce44SJohn Forte 			client->debugStatus =
1086fcf3ce44SJohn Forte 			    iscsiAuthDebugStatusChapChallengeBad;
1087fcf3ce44SJohn Forte 			break;
1088fcf3ce44SJohn Forte 		}
1089fcf3ce44SJohn Forte 
1090fcf3ce44SJohn Forte 		if (client->nodeType == iscsiAuthNodeTypeTarget &&
1091fcf3ce44SJohn Forte 		    client->recvChapChallenge.length ==
1092fcf3ce44SJohn Forte 		    client->sendChapChallenge.length &&
1093fcf3ce44SJohn Forte 		    bcmp(client->recvChapChallenge.largeBinary,
1094fcf3ce44SJohn Forte 		    client->sendChapChallenge.largeBinary,
1095fcf3ce44SJohn Forte 		    client->sendChapChallenge.length) == 0) {
1096fcf3ce44SJohn Forte 
1097fcf3ce44SJohn Forte 			client->localState = iscsiAuthLocalStateError;
1098fcf3ce44SJohn Forte 			client->debugStatus =
1099fcf3ce44SJohn Forte 			    iscsiAuthDebugStatusChapChallengeReflected;
1100fcf3ce44SJohn Forte 			break;
1101fcf3ce44SJohn Forte 		}
1102fcf3ce44SJohn Forte 
1103fcf3ce44SJohn Forte 		debugStatus = iscsiAuthClientChapComputeResponse(client,
1104fcf3ce44SJohn Forte 		    FALSE,
1105fcf3ce44SJohn Forte 		    chapIdentifier,
1106fcf3ce44SJohn Forte 		    client->recvChapChallenge.largeBinary,
1107fcf3ce44SJohn Forte 		    client->recvChapChallenge.length, responseData);
1108fcf3ce44SJohn Forte 
1109fcf3ce44SJohn Forte 		if (debugStatus != iscsiAuthDebugStatusNotSet) {
1110fcf3ce44SJohn Forte 			client->localState = iscsiAuthLocalStateError;
1111fcf3ce44SJohn Forte 			client->debugStatus = debugStatus;
1112fcf3ce44SJohn Forte 			break;
1113fcf3ce44SJohn Forte 		}
1114fcf3ce44SJohn Forte 
1115fcf3ce44SJohn Forte 		(void) iscsiAuthClientDataToText(client->base64,
1116fcf3ce44SJohn Forte 		    responseData, iscsiAuthChapResponseLength,
1117fcf3ce44SJohn Forte 		    client->scratchKeyValue, iscsiAuthStringMaxLength);
1118fcf3ce44SJohn Forte 		iscsiAuthClientSetKeyValue(&client->sendKeyBlock,
1119fcf3ce44SJohn Forte 		    iscsiAuthKeyTypeChapResponse, client->scratchKeyValue);
1120fcf3ce44SJohn Forte 
1121fcf3ce44SJohn Forte 		iscsiAuthClientSetKeyValue(&client->sendKeyBlock,
1122fcf3ce44SJohn Forte 		    iscsiAuthKeyTypeChapUsername, client->username);
1123fcf3ce44SJohn Forte 
1124fcf3ce44SJohn Forte 		client->localState = iscsiAuthLocalStateDone;
1125fcf3ce44SJohn Forte 		break;
1126fcf3ce44SJohn Forte 
1127fcf3ce44SJohn Forte 	case iscsiAuthLocalStateDone:
1128fcf3ce44SJohn Forte 		break;
1129fcf3ce44SJohn Forte 
1130fcf3ce44SJohn Forte 	case iscsiAuthLocalStateError:
1131fcf3ce44SJohn Forte 	default:
1132fcf3ce44SJohn Forte 		client->phase = iscsiAuthPhaseError;
1133fcf3ce44SJohn Forte 	}
1134fcf3ce44SJohn Forte }
1135fcf3ce44SJohn Forte 
1136fcf3ce44SJohn Forte 
1137fcf3ce44SJohn Forte static void
iscsiAuthClientRemoteAuthentication(IscsiAuthClient * client)1138fcf3ce44SJohn Forte iscsiAuthClientRemoteAuthentication(IscsiAuthClient * client)
1139fcf3ce44SJohn Forte {
1140fcf3ce44SJohn Forte 	unsigned char idData[1];
1141fcf3ce44SJohn Forte 	unsigned char responseData[iscsiAuthStringMaxLength];
1142fcf3ce44SJohn Forte 	unsigned int responseLength = iscsiAuthStringMaxLength;
1143fcf3ce44SJohn Forte 	unsigned char myResponseData[iscsiAuthChapResponseLength];
1144fcf3ce44SJohn Forte 	int status;
1145fcf3ce44SJohn Forte 	IscsiAuthDebugStatus debugStatus;
1146fcf3ce44SJohn Forte 	const char *chapResponseKeyValue;
1147fcf3ce44SJohn Forte 	const char *chapUsernameKeyValue;
1148fcf3ce44SJohn Forte 
1149fcf3ce44SJohn Forte 	switch (client->remoteState) {
1150fcf3ce44SJohn Forte 	case iscsiAuthRemoteStateSendAlgorithm:
1151fcf3ce44SJohn Forte 		if (client->nodeType == iscsiAuthNodeTypeInitiator) {
1152fcf3ce44SJohn Forte 			client->remoteState = iscsiAuthRemoteStateSendChallenge;
1153fcf3ce44SJohn Forte 			break;
1154fcf3ce44SJohn Forte 		}
1155fcf3ce44SJohn Forte 
1156fcf3ce44SJohn Forte 		/* FALLTHRU */
1157fcf3ce44SJohn Forte 
1158fcf3ce44SJohn Forte 	case iscsiAuthRemoteStateSendChallenge:
1159fcf3ce44SJohn Forte 		if (!client->authRemote) {
1160fcf3ce44SJohn Forte 			client->remoteAuthStatus = iscsiAuthStatusPass;
1161fcf3ce44SJohn Forte 			client->debugStatus =
1162fcf3ce44SJohn Forte 			    iscsiAuthDebugStatusAuthRemoteFalse;
1163fcf3ce44SJohn Forte 			client->remoteState = iscsiAuthRemoteStateDone;
1164fcf3ce44SJohn Forte 			break;
1165fcf3ce44SJohn Forte 		}
1166fcf3ce44SJohn Forte 
1167fcf3ce44SJohn Forte 		iscsiAuthRandomSetData(idData, 1);
1168fcf3ce44SJohn Forte 		client->sendChapIdentifier = idData[0];
1169fcf3ce44SJohn Forte 
1170fcf3ce44SJohn Forte 		iscsiAuthClientNumberToText(client->sendChapIdentifier,
1171fcf3ce44SJohn Forte 		    client->scratchKeyValue, iscsiAuthStringMaxLength);
1172fcf3ce44SJohn Forte 		iscsiAuthClientSetKeyValue(&client->sendKeyBlock,
1173fcf3ce44SJohn Forte 		    iscsiAuthKeyTypeChapIdentifier, client->scratchKeyValue);
1174fcf3ce44SJohn Forte 
1175fcf3ce44SJohn Forte 		client->sendChapChallenge.length = client->chapChallengeLength;
1176fcf3ce44SJohn Forte 		iscsiAuthRandomSetData(client->sendChapChallenge.largeBinary,
1177fcf3ce44SJohn Forte 		    client->sendChapChallenge.length);
1178fcf3ce44SJohn Forte 
1179fcf3ce44SJohn Forte 		iscsiAuthClientSetKeyValue(&client->sendKeyBlock,
1180fcf3ce44SJohn Forte 		    iscsiAuthKeyTypeChapChallenge, "");
1181fcf3ce44SJohn Forte 
1182fcf3ce44SJohn Forte 		client->remoteState = iscsiAuthRemoteStateRecvResponse;
1183fcf3ce44SJohn Forte 		break;
1184fcf3ce44SJohn Forte 
1185fcf3ce44SJohn Forte 	case iscsiAuthRemoteStateRecvResponse:
1186fcf3ce44SJohn Forte 		chapResponseKeyValue = iscsiAuthClientGetKeyValue(
1187fcf3ce44SJohn Forte 		    &client->recvKeyBlock, iscsiAuthKeyTypeChapResponse);
1188fcf3ce44SJohn Forte 
1189fcf3ce44SJohn Forte 		chapUsernameKeyValue = iscsiAuthClientGetKeyValue(
1190fcf3ce44SJohn Forte 		    &client->recvKeyBlock, iscsiAuthKeyTypeChapUsername);
1191fcf3ce44SJohn Forte 
1192fcf3ce44SJohn Forte 		if (!chapResponseKeyValue) {
1193fcf3ce44SJohn Forte 			client->remoteState = iscsiAuthRemoteStateError;
1194fcf3ce44SJohn Forte 			client->debugStatus =
1195fcf3ce44SJohn Forte 			    iscsiAuthDebugStatusChapResponseExpected;
1196fcf3ce44SJohn Forte 			break;
1197fcf3ce44SJohn Forte 		}
1198fcf3ce44SJohn Forte 
1199fcf3ce44SJohn Forte 		if (!chapUsernameKeyValue) {
1200fcf3ce44SJohn Forte 			client->remoteState = iscsiAuthRemoteStateError;
1201fcf3ce44SJohn Forte 			client->debugStatus =
1202fcf3ce44SJohn Forte 			    iscsiAuthDebugStatusChapUsernameExpected;
1203fcf3ce44SJohn Forte 			break;
1204fcf3ce44SJohn Forte 		}
1205fcf3ce44SJohn Forte 
1206fcf3ce44SJohn Forte 		status = iscsiAuthClientTextToData(chapResponseKeyValue,
1207fcf3ce44SJohn Forte 		    responseData, &responseLength);
1208fcf3ce44SJohn Forte 
1209fcf3ce44SJohn Forte 		if (status) {
1210fcf3ce44SJohn Forte 			client->remoteState = iscsiAuthRemoteStateError;
1211fcf3ce44SJohn Forte 			client->debugStatus =
1212fcf3ce44SJohn Forte 			    iscsiAuthDebugStatusChapResponseBad;
1213fcf3ce44SJohn Forte 			break;
1214fcf3ce44SJohn Forte 		}
1215fcf3ce44SJohn Forte 
1216fcf3ce44SJohn Forte 		if (responseLength == iscsiAuthChapResponseLength) {
1217fcf3ce44SJohn Forte 			debugStatus = iscsiAuthClientChapComputeResponse(
1218fcf3ce44SJohn Forte 			    client, TRUE, client->sendChapIdentifier,
1219fcf3ce44SJohn Forte 			    client->sendChapChallenge.largeBinary,
1220fcf3ce44SJohn Forte 			    client->sendChapChallenge.length, myResponseData);
1221fcf3ce44SJohn Forte 
1222fcf3ce44SJohn Forte 			/*
1223fcf3ce44SJohn Forte 			 * Check if the same CHAP secret is being used for
1224fcf3ce44SJohn Forte 			 * authentication in both directions.
1225fcf3ce44SJohn Forte 			 */
1226fcf3ce44SJohn Forte 			if (debugStatus == iscsiAuthDebugStatusNotSet &&
1227fcf3ce44SJohn Forte 			    bcmp(myResponseData, responseData,
1228fcf3ce44SJohn Forte 			    iscsiAuthChapResponseLength) == 0) {
1229fcf3ce44SJohn Forte 
1230fcf3ce44SJohn Forte 				client->remoteState =
1231fcf3ce44SJohn Forte 				    iscsiAuthRemoteStateError;
1232fcf3ce44SJohn Forte 				client->debugStatus =
1233fcf3ce44SJohn Forte 				    iscsiAuthDebugStatusPasswordIdentical;
1234fcf3ce44SJohn Forte 				break;
1235fcf3ce44SJohn Forte 			}
1236fcf3ce44SJohn Forte 		}
1237fcf3ce44SJohn Forte 
1238fcf3ce44SJohn Forte 		(void) iscsiAuthClientStringCopy(client->chapUsername,
1239fcf3ce44SJohn Forte 		    chapUsernameKeyValue, iscsiAuthStringMaxLength);
1240fcf3ce44SJohn Forte 
1241fcf3ce44SJohn Forte 		/* To verify the target's response. */
1242fcf3ce44SJohn Forte 		status = iscsiAuthClientChapAuthRequest(
1243fcf3ce44SJohn Forte 		    client, client->chapUsername, client->sendChapIdentifier,
1244fcf3ce44SJohn Forte 		    client->sendChapChallenge.largeBinary,
1245fcf3ce44SJohn Forte 		    client->sendChapChallenge.length, responseData,
1246fcf3ce44SJohn Forte 		    responseLength);
1247fcf3ce44SJohn Forte 
1248fcf3ce44SJohn Forte 		if (status == iscsiAuthStatusInProgress) {
1249fcf3ce44SJohn Forte 			iscsiAuthClientGlobalStats.requestSent++;
1250fcf3ce44SJohn Forte 			client->remoteState = iscsiAuthRemoteStateAuthRequest;
1251fcf3ce44SJohn Forte 			break;
1252fcf3ce44SJohn Forte 		}
1253fcf3ce44SJohn Forte 
1254fcf3ce44SJohn Forte 		client->remoteAuthStatus = (IscsiAuthStatus) status;
1255fcf3ce44SJohn Forte 		client->authResponseFlag = TRUE;
1256fcf3ce44SJohn Forte 
1257fcf3ce44SJohn Forte 		/* FALLTHRU */
1258fcf3ce44SJohn Forte 
1259fcf3ce44SJohn Forte 	case iscsiAuthRemoteStateAuthRequest:
1260fcf3ce44SJohn Forte 		/*
1261fcf3ce44SJohn Forte 		 * client->remoteAuthStatus already set
1262fcf3ce44SJohn Forte 		 */
1263fcf3ce44SJohn Forte 		if (client->authServerErrorFlag) {
1264fcf3ce44SJohn Forte 			client->remoteAuthStatus = iscsiAuthStatusFail;
1265fcf3ce44SJohn Forte 			client->debugStatus =
1266fcf3ce44SJohn Forte 			    iscsiAuthDebugStatusAuthServerError;
1267fcf3ce44SJohn Forte 		} else if (client->remoteAuthStatus == iscsiAuthStatusPass) {
1268fcf3ce44SJohn Forte 			client->debugStatus = iscsiAuthDebugStatusAuthPass;
1269fcf3ce44SJohn Forte 		} else if (client->remoteAuthStatus == iscsiAuthStatusFail) {
1270fcf3ce44SJohn Forte 			client->debugStatus = iscsiAuthDebugStatusAuthFail;
1271fcf3ce44SJohn Forte 		} else {
1272fcf3ce44SJohn Forte 			client->remoteAuthStatus = iscsiAuthStatusFail;
1273fcf3ce44SJohn Forte 			client->debugStatus = iscsiAuthDebugStatusAuthStatusBad;
1274fcf3ce44SJohn Forte 		}
1275fcf3ce44SJohn Forte 		client->remoteState = iscsiAuthRemoteStateDone;
1276fcf3ce44SJohn Forte 
1277fcf3ce44SJohn Forte 		/* FALLTHRU */
1278fcf3ce44SJohn Forte 
1279fcf3ce44SJohn Forte 	case iscsiAuthRemoteStateDone:
1280fcf3ce44SJohn Forte 		break;
1281fcf3ce44SJohn Forte 
1282fcf3ce44SJohn Forte 	case iscsiAuthRemoteStateError:
1283fcf3ce44SJohn Forte 	default:
1284fcf3ce44SJohn Forte 		client->phase = iscsiAuthPhaseError;
1285fcf3ce44SJohn Forte 	}
1286fcf3ce44SJohn Forte }
1287fcf3ce44SJohn Forte 
1288fcf3ce44SJohn Forte 
1289fcf3ce44SJohn Forte static void
iscsiAuthClientHandshake(IscsiAuthClient * client)1290fcf3ce44SJohn Forte iscsiAuthClientHandshake(IscsiAuthClient * client)
1291fcf3ce44SJohn Forte {
1292fcf3ce44SJohn Forte 	if (client->phase == iscsiAuthPhaseDone) {
1293fcf3ce44SJohn Forte 		/*
1294fcf3ce44SJohn Forte 		 * Should only happen if authentication
1295fcf3ce44SJohn Forte 		 * protocol error occured.
1296fcf3ce44SJohn Forte 		 */
1297fcf3ce44SJohn Forte 		return;
1298fcf3ce44SJohn Forte 	}
1299fcf3ce44SJohn Forte 
1300fcf3ce44SJohn Forte 	if (client->remoteState == iscsiAuthRemoteStateAuthRequest) {
1301fcf3ce44SJohn Forte 		/*
1302fcf3ce44SJohn Forte 		 * Defer until authentication response received
1303fcf3ce44SJohn Forte 		 * from internal authentication service.
1304fcf3ce44SJohn Forte 		 */
1305fcf3ce44SJohn Forte 		return;
1306fcf3ce44SJohn Forte 	}
1307fcf3ce44SJohn Forte 
1308fcf3ce44SJohn Forte 	if (client->nodeType == iscsiAuthNodeTypeInitiator) {
1309fcf3ce44SJohn Forte 
1310fcf3ce44SJohn Forte 		/*
1311fcf3ce44SJohn Forte 		 * Target should only have set T bit on response if
1312fcf3ce44SJohn Forte 		 * initiator set it on previous message.
1313fcf3ce44SJohn Forte 		 */
1314fcf3ce44SJohn Forte 		if (client->recvKeyBlock.transitBit &&
1315fcf3ce44SJohn Forte 		    client->transitBitSentFlag == 0) {
1316fcf3ce44SJohn Forte 			client->remoteAuthStatus = iscsiAuthStatusFail;
1317fcf3ce44SJohn Forte 			client->phase = iscsiAuthPhaseDone;
1318fcf3ce44SJohn Forte 			client->debugStatus =
1319fcf3ce44SJohn Forte 			    iscsiAuthDebugStatusTbitSetIllegal;
1320fcf3ce44SJohn Forte 			return;
1321fcf3ce44SJohn Forte 		}
1322fcf3ce44SJohn Forte 	}
1323fcf3ce44SJohn Forte 
1324fcf3ce44SJohn Forte 	if (client->phase == iscsiAuthPhaseNegotiate) {
1325fcf3ce44SJohn Forte 		/*
1326fcf3ce44SJohn Forte 		 * Should only happen if waiting for peer
1327fcf3ce44SJohn Forte 		 * to send AuthMethod key or set Transit Bit.
1328fcf3ce44SJohn Forte 		 */
1329fcf3ce44SJohn Forte 		if (client->nodeType == iscsiAuthNodeTypeInitiator) {
1330fcf3ce44SJohn Forte 			client->sendKeyBlock.transitBit = TRUE;
1331fcf3ce44SJohn Forte 		}
1332fcf3ce44SJohn Forte 		return;
1333fcf3ce44SJohn Forte 	}
1334fcf3ce44SJohn Forte 
1335fcf3ce44SJohn Forte 	if (client->remoteState == iscsiAuthRemoteStateRecvResponse ||
1336fcf3ce44SJohn Forte 	    client->remoteState == iscsiAuthRemoteStateDone) {
1337fcf3ce44SJohn Forte 
1338fcf3ce44SJohn Forte 		if (client->nodeType == iscsiAuthNodeTypeInitiator) {
1339fcf3ce44SJohn Forte 			if (client->recvKeyBlock.transitBit) {
1340fcf3ce44SJohn Forte 				if (client->remoteState !=
1341fcf3ce44SJohn Forte 				    iscsiAuthRemoteStateDone) {
1342fcf3ce44SJohn Forte 					goto recvTransitBitError;
1343fcf3ce44SJohn Forte 				}
1344fcf3ce44SJohn Forte 				iscsiAuthClientNextPhase(client);
1345fcf3ce44SJohn Forte 			} else {
1346fcf3ce44SJohn Forte 				client->sendKeyBlock.transitBit = TRUE;
1347fcf3ce44SJohn Forte 			}
1348fcf3ce44SJohn Forte 		} else {
1349fcf3ce44SJohn Forte 			if (client->remoteState == iscsiAuthRemoteStateDone &&
1350fcf3ce44SJohn Forte 			    client->remoteAuthStatus != iscsiAuthStatusPass) {
1351fcf3ce44SJohn Forte 
1352fcf3ce44SJohn Forte 				/*
1353fcf3ce44SJohn Forte 				 * Authentication failed, don't
1354fcf3ce44SJohn Forte 				 * do T bit handshake.
1355fcf3ce44SJohn Forte 				 */
1356fcf3ce44SJohn Forte 				iscsiAuthClientNextPhase(client);
1357fcf3ce44SJohn Forte 			} else {
1358fcf3ce44SJohn Forte 
1359fcf3ce44SJohn Forte 				/*
1360fcf3ce44SJohn Forte 				 * Target can only set T bit on response if
1361fcf3ce44SJohn Forte 				 * initiator set it on current message.
1362fcf3ce44SJohn Forte 				 */
1363fcf3ce44SJohn Forte 				if (client->recvKeyBlock.transitBit) {
1364fcf3ce44SJohn Forte 					client->sendKeyBlock.transitBit = TRUE;
1365fcf3ce44SJohn Forte 					iscsiAuthClientNextPhase(client);
1366fcf3ce44SJohn Forte 				}
1367fcf3ce44SJohn Forte 			}
1368fcf3ce44SJohn Forte 		}
1369fcf3ce44SJohn Forte 	} else {
1370fcf3ce44SJohn Forte 		if (client->nodeType == iscsiAuthNodeTypeInitiator) {
1371fcf3ce44SJohn Forte 			if (client->recvKeyBlock.transitBit) {
1372fcf3ce44SJohn Forte 				goto recvTransitBitError;
1373fcf3ce44SJohn Forte 			}
1374fcf3ce44SJohn Forte 		}
1375fcf3ce44SJohn Forte 	}
1376fcf3ce44SJohn Forte 
1377fcf3ce44SJohn Forte 	return;
1378fcf3ce44SJohn Forte 
1379fcf3ce44SJohn Forte recvTransitBitError:
1380fcf3ce44SJohn Forte 	/*
1381fcf3ce44SJohn Forte 	 * Target set T bit on response but
1382fcf3ce44SJohn Forte 	 * initiator was not done with authentication.
1383fcf3ce44SJohn Forte 	 */
1384fcf3ce44SJohn Forte 	client->remoteAuthStatus = iscsiAuthStatusFail;
1385fcf3ce44SJohn Forte 	client->phase = iscsiAuthPhaseDone;
1386fcf3ce44SJohn Forte 	client->debugStatus = iscsiAuthDebugStatusTbitSetPremature;
1387fcf3ce44SJohn Forte }
1388fcf3ce44SJohn Forte 
1389fcf3ce44SJohn Forte 
1390fcf3ce44SJohn Forte static int
iscsiAuthClientRecvEndStatus(IscsiAuthClient * client)1391fcf3ce44SJohn Forte iscsiAuthClientRecvEndStatus(IscsiAuthClient * client)
1392fcf3ce44SJohn Forte {
1393fcf3ce44SJohn Forte 	int authStatus;
1394fcf3ce44SJohn Forte 	int keyType;
1395fcf3ce44SJohn Forte 
1396fcf3ce44SJohn Forte 	if (client->phase == iscsiAuthPhaseError) {
1397fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
1398fcf3ce44SJohn Forte 	}
1399fcf3ce44SJohn Forte 
1400fcf3ce44SJohn Forte 	if (client->phase == iscsiAuthPhaseDone) {
1401fcf3ce44SJohn Forte 
1402fcf3ce44SJohn Forte 		/*
1403fcf3ce44SJohn Forte 		 * Perform sanity check against configured parameters.
1404fcf3ce44SJohn Forte 		 */
1405fcf3ce44SJohn Forte 
1406fcf3ce44SJohn Forte 		if (client->authRemote && !client->authResponseFlag &&
1407fcf3ce44SJohn Forte 		    client->remoteAuthStatus == iscsiAuthStatusPass) {
1408fcf3ce44SJohn Forte 
1409fcf3ce44SJohn Forte 			client->remoteAuthStatus = iscsiAuthStatusFail;
1410fcf3ce44SJohn Forte 			client->debugStatus =
1411fcf3ce44SJohn Forte 			    iscsiAuthDebugStatusAuthPassNotValid;
1412fcf3ce44SJohn Forte 		}
1413fcf3ce44SJohn Forte 
1414fcf3ce44SJohn Forte 		authStatus = client->remoteAuthStatus;
1415fcf3ce44SJohn Forte 	} else if (client->remoteState == iscsiAuthRemoteStateAuthRequest) {
1416fcf3ce44SJohn Forte 		authStatus = iscsiAuthStatusInProgress;
1417fcf3ce44SJohn Forte 	} else {
1418fcf3ce44SJohn Forte 		authStatus = iscsiAuthStatusContinue;
1419fcf3ce44SJohn Forte 	}
1420fcf3ce44SJohn Forte 
1421fcf3ce44SJohn Forte 	if (authStatus != iscsiAuthStatusInProgress) {
1422fcf3ce44SJohn Forte 		client->recvInProgressFlag = FALSE;
1423fcf3ce44SJohn Forte 	}
1424fcf3ce44SJohn Forte 
1425fcf3ce44SJohn Forte 	if (authStatus == iscsiAuthStatusContinue ||
1426fcf3ce44SJohn Forte 	    authStatus == iscsiAuthStatusPass) {
1427fcf3ce44SJohn Forte 		if (client->sendKeyBlock.duplicateSet) {
1428fcf3ce44SJohn Forte 			client->remoteAuthStatus = iscsiAuthStatusFail;
1429fcf3ce44SJohn Forte 			client->phase = iscsiAuthPhaseDone;
1430fcf3ce44SJohn Forte 			client->debugStatus =
1431fcf3ce44SJohn Forte 			    iscsiAuthDebugStatusSendDuplicateSetKeyValue;
1432fcf3ce44SJohn Forte 			authStatus = iscsiAuthStatusFail;
1433fcf3ce44SJohn Forte 		} else if (client->sendKeyBlock.stringTooLong) {
1434fcf3ce44SJohn Forte 			client->remoteAuthStatus = iscsiAuthStatusFail;
1435fcf3ce44SJohn Forte 			client->phase = iscsiAuthPhaseDone;
1436fcf3ce44SJohn Forte 			client->debugStatus =
1437fcf3ce44SJohn Forte 			    iscsiAuthDebugStatusSendStringTooLong;
1438fcf3ce44SJohn Forte 			authStatus = iscsiAuthStatusFail;
1439fcf3ce44SJohn Forte 		} else if (client->sendKeyBlock.tooMuchData) {
1440fcf3ce44SJohn Forte 			client->remoteAuthStatus = iscsiAuthStatusFail;
1441fcf3ce44SJohn Forte 			client->phase = iscsiAuthPhaseDone;
1442fcf3ce44SJohn Forte 			client->debugStatus =
1443fcf3ce44SJohn Forte 			    iscsiAuthDebugStatusSendTooMuchData;
1444fcf3ce44SJohn Forte 			authStatus = iscsiAuthStatusFail;
1445fcf3ce44SJohn Forte 		} else {
1446fcf3ce44SJohn Forte 			/*
1447fcf3ce44SJohn Forte 			 * Check that all incoming keys have been processed.
1448fcf3ce44SJohn Forte 			 */
1449fcf3ce44SJohn Forte 			for (keyType = iscsiAuthKeyTypeFirst;
1450fcf3ce44SJohn Forte 			    keyType < iscsiAuthKeyTypeMaxCount; keyType++) {
1451fcf3ce44SJohn Forte 				if (client->recvKeyBlock.key[keyType].present &&
1452fcf3ce44SJohn Forte 				    client->recvKeyBlock.key[keyType].
1453fcf3ce44SJohn Forte 				    processed == 0) {
1454fcf3ce44SJohn Forte 					break;
1455fcf3ce44SJohn Forte 				}
1456fcf3ce44SJohn Forte 			}
1457fcf3ce44SJohn Forte 
1458fcf3ce44SJohn Forte 			if (keyType < iscsiAuthKeyTypeMaxCount) {
1459fcf3ce44SJohn Forte 				client->remoteAuthStatus = iscsiAuthStatusFail;
1460fcf3ce44SJohn Forte 				client->phase = iscsiAuthPhaseDone;
1461fcf3ce44SJohn Forte 				client->debugStatus =
1462fcf3ce44SJohn Forte 				    iscsiAuthDebugStatusUnexpectedKeyPresent;
1463fcf3ce44SJohn Forte 				authStatus = iscsiAuthStatusFail;
1464fcf3ce44SJohn Forte 			}
1465fcf3ce44SJohn Forte 		}
1466fcf3ce44SJohn Forte 	}
1467fcf3ce44SJohn Forte 
1468fcf3ce44SJohn Forte 	if (authStatus != iscsiAuthStatusPass &&
1469fcf3ce44SJohn Forte 	    authStatus != iscsiAuthStatusContinue &&
1470fcf3ce44SJohn Forte 	    authStatus != iscsiAuthStatusInProgress) {
1471fcf3ce44SJohn Forte 		int authMethodKeyPresent = FALSE;
1472fcf3ce44SJohn Forte 		int chapAlgorithmKeyPresent = FALSE;
1473fcf3ce44SJohn Forte 
1474fcf3ce44SJohn Forte 		/*
1475fcf3ce44SJohn Forte 		 * Suppress send keys on error, except
1476fcf3ce44SJohn Forte 		 * for AuthMethod and CHAP_A.
1477fcf3ce44SJohn Forte 		 */
1478fcf3ce44SJohn Forte 		if (client->nodeType == iscsiAuthNodeTypeTarget) {
1479fcf3ce44SJohn Forte 			if (iscsiAuthClientGetKeyValue(&client->sendKeyBlock,
1480fcf3ce44SJohn Forte 			    iscsiAuthKeyTypeAuthMethod)) {
1481fcf3ce44SJohn Forte 				authMethodKeyPresent = TRUE;
1482fcf3ce44SJohn Forte 			} else if (iscsiAuthClientGetKeyValue(
1483fcf3ce44SJohn Forte 			    &client->sendKeyBlock,
1484fcf3ce44SJohn Forte 			    iscsiAuthKeyTypeChapAlgorithm)) {
1485fcf3ce44SJohn Forte 				chapAlgorithmKeyPresent = TRUE;
1486fcf3ce44SJohn Forte 			}
1487fcf3ce44SJohn Forte 		}
1488fcf3ce44SJohn Forte 
1489fcf3ce44SJohn Forte 		iscsiAuthClientInitKeyBlock(&client->sendKeyBlock);
1490fcf3ce44SJohn Forte 
1491fcf3ce44SJohn Forte 		if (client->nodeType == iscsiAuthNodeTypeTarget) {
1492fcf3ce44SJohn Forte 			if (authMethodKeyPresent &&
1493fcf3ce44SJohn Forte 			    client->negotiatedAuthMethod ==
1494fcf3ce44SJohn Forte 			    iscsiAuthOptionReject) {
1495fcf3ce44SJohn Forte 				iscsiAuthClientSetKeyValue(
1496fcf3ce44SJohn Forte 				    &client->sendKeyBlock,
1497fcf3ce44SJohn Forte 				    iscsiAuthKeyTypeAuthMethod,
1498fcf3ce44SJohn Forte 				    client->rejectOptionName);
1499fcf3ce44SJohn Forte 			} else if (chapAlgorithmKeyPresent &&
1500fcf3ce44SJohn Forte 			    client->negotiatedChapAlgorithm ==
1501fcf3ce44SJohn Forte 			    iscsiAuthOptionReject) {
1502fcf3ce44SJohn Forte 				iscsiAuthClientSetKeyValue(
1503fcf3ce44SJohn Forte 				    &client->sendKeyBlock,
1504fcf3ce44SJohn Forte 				    iscsiAuthKeyTypeChapAlgorithm,
1505fcf3ce44SJohn Forte 				    client->rejectOptionName);
1506fcf3ce44SJohn Forte 			}
1507fcf3ce44SJohn Forte 		}
1508fcf3ce44SJohn Forte 	}
1509fcf3ce44SJohn Forte 
1510fcf3ce44SJohn Forte 	return (authStatus);
1511fcf3ce44SJohn Forte }
1512fcf3ce44SJohn Forte 
1513fcf3ce44SJohn Forte 
1514fcf3ce44SJohn Forte int
iscsiAuthClientRecvBegin(IscsiAuthClient * client)1515fcf3ce44SJohn Forte iscsiAuthClientRecvBegin(IscsiAuthClient * client)
1516fcf3ce44SJohn Forte {
1517fcf3ce44SJohn Forte 	if (!client || client->signature != iscsiAuthClientSignature) {
1518fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
1519fcf3ce44SJohn Forte 	}
1520fcf3ce44SJohn Forte 
1521fcf3ce44SJohn Forte 	if (client->phase == iscsiAuthPhaseError) {
1522fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
1523fcf3ce44SJohn Forte 	}
1524fcf3ce44SJohn Forte 
1525fcf3ce44SJohn Forte 	if (client->phase == iscsiAuthPhaseDone) {
1526fcf3ce44SJohn Forte 		client->phase = iscsiAuthPhaseError;
1527fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
1528fcf3ce44SJohn Forte 	}
1529fcf3ce44SJohn Forte 
1530fcf3ce44SJohn Forte 	if (client->recvInProgressFlag) {
1531fcf3ce44SJohn Forte 		client->phase = iscsiAuthPhaseError;
1532fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
1533fcf3ce44SJohn Forte 	}
1534fcf3ce44SJohn Forte 
1535fcf3ce44SJohn Forte 	client->recvInProgressFlag = TRUE;
1536fcf3ce44SJohn Forte 
1537fcf3ce44SJohn Forte 	if (client->phase == iscsiAuthPhaseConfigure) {
1538fcf3ce44SJohn Forte 		iscsiAuthClientNextPhase(client);
1539fcf3ce44SJohn Forte 	}
1540fcf3ce44SJohn Forte 
1541fcf3ce44SJohn Forte 	client->transitBitSentFlag = client->sendKeyBlock.transitBit;
1542fcf3ce44SJohn Forte 
1543fcf3ce44SJohn Forte 	iscsiAuthClientInitKeyBlock(&client->recvKeyBlock);
1544fcf3ce44SJohn Forte 	iscsiAuthClientInitKeyBlock(&client->sendKeyBlock);
1545fcf3ce44SJohn Forte 
1546fcf3ce44SJohn Forte 	return (iscsiAuthStatusNoError);
1547fcf3ce44SJohn Forte }
1548fcf3ce44SJohn Forte 
1549fcf3ce44SJohn Forte 
1550fcf3ce44SJohn Forte int
iscsiAuthClientRecvEnd(IscsiAuthClient * client,IscsiAuthClientCallback * callback,void * userHandle,void * messageHandle)1551fcf3ce44SJohn Forte iscsiAuthClientRecvEnd(IscsiAuthClient * client,
1552fcf3ce44SJohn Forte     IscsiAuthClientCallback * callback, void *userHandle, void *messageHandle)
1553fcf3ce44SJohn Forte {
1554fcf3ce44SJohn Forte 	int nextPhaseFlag = FALSE;
1555fcf3ce44SJohn Forte 
1556fcf3ce44SJohn Forte 	if (!client || client->signature != iscsiAuthClientSignature) {
1557fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
1558fcf3ce44SJohn Forte 	}
1559fcf3ce44SJohn Forte 
1560fcf3ce44SJohn Forte 	if (client->phase == iscsiAuthPhaseError) {
1561fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
1562fcf3ce44SJohn Forte 	}
1563fcf3ce44SJohn Forte 
1564fcf3ce44SJohn Forte 	if (!callback || !client->recvInProgressFlag) {
1565fcf3ce44SJohn Forte 		client->phase = iscsiAuthPhaseError;
1566fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
1567fcf3ce44SJohn Forte 	}
1568fcf3ce44SJohn Forte 
1569fcf3ce44SJohn Forte 	if (client->recvEndCount > iscsiAuthRecvEndMaxCount) {
1570fcf3ce44SJohn Forte 		client->remoteAuthStatus = iscsiAuthStatusFail;
1571fcf3ce44SJohn Forte 		client->phase = iscsiAuthPhaseDone;
1572fcf3ce44SJohn Forte 		client->debugStatus =
1573fcf3ce44SJohn Forte 		    iscsiAuthDebugStatusRecvMessageCountLimit;
1574fcf3ce44SJohn Forte 	} else if (client->recvKeyBlock.duplicateSet) {
1575fcf3ce44SJohn Forte 		client->remoteAuthStatus = iscsiAuthStatusFail;
1576fcf3ce44SJohn Forte 		client->phase = iscsiAuthPhaseDone;
1577fcf3ce44SJohn Forte 		client->debugStatus =
1578fcf3ce44SJohn Forte 		    iscsiAuthDebugStatusRecvDuplicateSetKeyValue;
1579fcf3ce44SJohn Forte 	} else if (client->recvKeyBlock.stringTooLong) {
1580fcf3ce44SJohn Forte 		client->remoteAuthStatus = iscsiAuthStatusFail;
1581fcf3ce44SJohn Forte 		client->phase = iscsiAuthPhaseDone;
1582fcf3ce44SJohn Forte 		client->debugStatus = iscsiAuthDebugStatusRecvStringTooLong;
1583fcf3ce44SJohn Forte 	} else if (client->recvKeyBlock.tooMuchData) {
1584fcf3ce44SJohn Forte 		client->remoteAuthStatus = iscsiAuthStatusFail;
1585fcf3ce44SJohn Forte 		client->phase = iscsiAuthPhaseDone;
1586fcf3ce44SJohn Forte 		client->debugStatus = iscsiAuthDebugStatusRecvTooMuchData;
1587fcf3ce44SJohn Forte 	}
1588fcf3ce44SJohn Forte 
1589fcf3ce44SJohn Forte 	client->recvEndCount++;
1590fcf3ce44SJohn Forte 
1591fcf3ce44SJohn Forte 	client->callback = callback;
1592fcf3ce44SJohn Forte 	client->userHandle = userHandle;
1593fcf3ce44SJohn Forte 	client->messageHandle = messageHandle;
1594fcf3ce44SJohn Forte 
1595fcf3ce44SJohn Forte 	switch (client->phase) {
1596fcf3ce44SJohn Forte 	case iscsiAuthPhaseNegotiate:
1597fcf3ce44SJohn Forte 		iscsiAuthClientCheckAuthMethodKey(client);
1598fcf3ce44SJohn Forte 
1599fcf3ce44SJohn Forte 		if (client->authMethodValidNegRole ==
1600fcf3ce44SJohn Forte 		    iscsiAuthNegRoleResponder) {
1601fcf3ce44SJohn Forte 			if (client->negotiatedAuthMethod ==
1602fcf3ce44SJohn Forte 			    iscsiAuthOptionNotPresent) {
1603fcf3ce44SJohn Forte 				if (client->authRemote ||
1604fcf3ce44SJohn Forte 				    client->recvKeyBlock.transitBit == 0) {
1605fcf3ce44SJohn Forte 					/*
1606fcf3ce44SJohn Forte 					 * No AuthMethod key from peer
1607fcf3ce44SJohn Forte 					 * on first message, try moving
1608fcf3ce44SJohn Forte 					 * the process along by sending
1609fcf3ce44SJohn Forte 					 * the AuthMethod key.
1610fcf3ce44SJohn Forte 					 */
1611fcf3ce44SJohn Forte 
1612fcf3ce44SJohn Forte 					client->authMethodValidNegRole =
1613fcf3ce44SJohn Forte 					    iscsiAuthNegRoleOriginator;
1614fcf3ce44SJohn Forte 
1615fcf3ce44SJohn Forte 					iscsiAuthClientSetAuthMethodKey(client,
1616fcf3ce44SJohn Forte 					    client->authMethodValidCount,
1617fcf3ce44SJohn Forte 					    client->authMethodValidList);
1618fcf3ce44SJohn Forte 					break;
1619fcf3ce44SJohn Forte 				}
1620fcf3ce44SJohn Forte 
1621fcf3ce44SJohn Forte 				/*
1622fcf3ce44SJohn Forte 				 * Special case if peer sent no
1623fcf3ce44SJohn Forte 				 * AuthMethod key, but did set Transit
1624fcf3ce44SJohn Forte 				 * Bit, allowing this side to do a
1625fcf3ce44SJohn Forte 				 * null authentication, and compelete
1626fcf3ce44SJohn Forte 				 * the iSCSI security phase without
1627fcf3ce44SJohn Forte 				 * either side sending the AuthMethod
1628fcf3ce44SJohn Forte 				 * key.
1629fcf3ce44SJohn Forte 				 */
1630fcf3ce44SJohn Forte 			} else {
1631fcf3ce44SJohn Forte 				/*
1632fcf3ce44SJohn Forte 				 * Send response to AuthMethod key.
1633fcf3ce44SJohn Forte 				 */
1634fcf3ce44SJohn Forte 
1635fcf3ce44SJohn Forte 				iscsiAuthClientSetAuthMethodKey(client, 1,
1636fcf3ce44SJohn Forte 				    &client->negotiatedAuthMethod);
1637fcf3ce44SJohn Forte 			}
1638fcf3ce44SJohn Forte 
1639fcf3ce44SJohn Forte 			if (client->nodeType == iscsiAuthNodeTypeInitiator) {
1640fcf3ce44SJohn Forte 				iscsiAuthClientNextPhase(client);
1641fcf3ce44SJohn Forte 			} else {
1642fcf3ce44SJohn Forte 				nextPhaseFlag = TRUE;
1643fcf3ce44SJohn Forte 			}
1644fcf3ce44SJohn Forte 
1645fcf3ce44SJohn Forte 		} else {
1646fcf3ce44SJohn Forte 			if (client->negotiatedAuthMethod ==
1647fcf3ce44SJohn Forte 			    iscsiAuthOptionNotPresent) {
1648fcf3ce44SJohn Forte 				client->remoteAuthStatus = iscsiAuthStatusFail;
1649fcf3ce44SJohn Forte 				client->phase = iscsiAuthPhaseDone;
1650fcf3ce44SJohn Forte 				client->debugStatus =
1651fcf3ce44SJohn Forte 				    iscsiAuthDebugStatusAuthMethodExpected;
1652fcf3ce44SJohn Forte 				break;
1653fcf3ce44SJohn Forte 			}
1654fcf3ce44SJohn Forte 
1655fcf3ce44SJohn Forte 			iscsiAuthClientNextPhase(client);
1656fcf3ce44SJohn Forte 		}
1657fcf3ce44SJohn Forte 		break;
1658fcf3ce44SJohn Forte 
1659fcf3ce44SJohn Forte 	case iscsiAuthPhaseAuthenticate:
1660fcf3ce44SJohn Forte 	case iscsiAuthPhaseDone:
1661fcf3ce44SJohn Forte 		break;
1662fcf3ce44SJohn Forte 
1663fcf3ce44SJohn Forte 	default:
1664fcf3ce44SJohn Forte 		client->phase = iscsiAuthPhaseError;
1665fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
1666fcf3ce44SJohn Forte 	}
1667fcf3ce44SJohn Forte 
1668fcf3ce44SJohn Forte 	switch (client->phase) {
1669fcf3ce44SJohn Forte 	case iscsiAuthPhaseNegotiate:
1670fcf3ce44SJohn Forte 		if (nextPhaseFlag) {
1671fcf3ce44SJohn Forte 			iscsiAuthClientNextPhase(client);
1672fcf3ce44SJohn Forte 		}
1673fcf3ce44SJohn Forte 		break;
1674fcf3ce44SJohn Forte 
1675fcf3ce44SJohn Forte 	case iscsiAuthPhaseAuthenticate:
1676fcf3ce44SJohn Forte 		/*
1677fcf3ce44SJohn Forte 		 * Must call iscsiAuthClientLocalAuthentication()
1678fcf3ce44SJohn Forte 		 * before iscsiAuthClientRemoteAuthentication()
1679fcf3ce44SJohn Forte 		 * to insure processing of the CHAP algorithm key,
1680fcf3ce44SJohn Forte 		 * and to avoid leaving an in progress request to the
1681fcf3ce44SJohn Forte 		 * authentication service.
1682fcf3ce44SJohn Forte 		 */
1683fcf3ce44SJohn Forte 		iscsiAuthClientLocalAuthentication(client);
1684fcf3ce44SJohn Forte 
1685fcf3ce44SJohn Forte 		if (client->localState != iscsiAuthLocalStateError) {
1686fcf3ce44SJohn Forte 			iscsiAuthClientRemoteAuthentication(client);
1687fcf3ce44SJohn Forte 		}
1688fcf3ce44SJohn Forte 
1689fcf3ce44SJohn Forte 		if (client->localState == iscsiAuthLocalStateError ||
1690fcf3ce44SJohn Forte 		    client->remoteState == iscsiAuthRemoteStateError) {
1691fcf3ce44SJohn Forte 
1692fcf3ce44SJohn Forte 			client->remoteAuthStatus = iscsiAuthStatusFail;
1693fcf3ce44SJohn Forte 			client->phase = iscsiAuthPhaseDone;
1694fcf3ce44SJohn Forte 			/*
1695fcf3ce44SJohn Forte 			 * client->debugStatus should already be set.
1696fcf3ce44SJohn Forte 			 */
1697fcf3ce44SJohn Forte 		}
1698fcf3ce44SJohn Forte 		break;
1699fcf3ce44SJohn Forte 
1700fcf3ce44SJohn Forte 	case iscsiAuthPhaseDone:
1701fcf3ce44SJohn Forte 		break;
1702fcf3ce44SJohn Forte 
1703fcf3ce44SJohn Forte 	default:
1704fcf3ce44SJohn Forte 		client->phase = iscsiAuthPhaseError;
1705fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
1706fcf3ce44SJohn Forte 	}
1707fcf3ce44SJohn Forte 
1708fcf3ce44SJohn Forte 	iscsiAuthClientHandshake(client);
1709fcf3ce44SJohn Forte 
1710fcf3ce44SJohn Forte 	return (iscsiAuthClientRecvEndStatus(client));
1711fcf3ce44SJohn Forte }
1712fcf3ce44SJohn Forte 
1713fcf3ce44SJohn Forte 
1714fcf3ce44SJohn Forte void
iscsiAuthClientAuthResponse(IscsiAuthClient * client,int authStatus)1715fcf3ce44SJohn Forte iscsiAuthClientAuthResponse(IscsiAuthClient * client, int authStatus)
1716fcf3ce44SJohn Forte {
1717fcf3ce44SJohn Forte 	iscsiAuthClientGlobalStats.responseReceived++;
1718fcf3ce44SJohn Forte 
1719fcf3ce44SJohn Forte 	if (!client || client->signature != iscsiAuthClientSignature) {
1720fcf3ce44SJohn Forte 		return;
1721fcf3ce44SJohn Forte 	}
1722fcf3ce44SJohn Forte 
1723fcf3ce44SJohn Forte 	if (!client->recvInProgressFlag ||
1724fcf3ce44SJohn Forte 	    client->phase != iscsiAuthPhaseAuthenticate ||
1725fcf3ce44SJohn Forte 	    client->remoteState != iscsiAuthRemoteStateAuthRequest) {
1726fcf3ce44SJohn Forte 
1727fcf3ce44SJohn Forte 		client->phase = iscsiAuthPhaseError;
1728fcf3ce44SJohn Forte 		return;
1729fcf3ce44SJohn Forte 	}
1730fcf3ce44SJohn Forte 
1731fcf3ce44SJohn Forte 	client->remoteAuthStatus = (IscsiAuthStatus) authStatus;
1732fcf3ce44SJohn Forte 	client->authResponseFlag = TRUE;
1733fcf3ce44SJohn Forte 
1734fcf3ce44SJohn Forte 	iscsiAuthClientRemoteAuthentication(client);
1735fcf3ce44SJohn Forte 
1736fcf3ce44SJohn Forte 	iscsiAuthClientHandshake(client);
1737fcf3ce44SJohn Forte 
1738fcf3ce44SJohn Forte 	authStatus = iscsiAuthClientRecvEndStatus(client);
1739fcf3ce44SJohn Forte 
1740fcf3ce44SJohn Forte 	client->callback(client->userHandle, client->messageHandle, authStatus);
1741fcf3ce44SJohn Forte }
1742fcf3ce44SJohn Forte 
1743fcf3ce44SJohn Forte 
1744fcf3ce44SJohn Forte const char *
iscsiAuthClientGetKeyName(int keyType)1745fcf3ce44SJohn Forte iscsiAuthClientGetKeyName(int keyType)
1746fcf3ce44SJohn Forte {
1747fcf3ce44SJohn Forte 	if (keyType < iscsiAuthKeyTypeFirst || keyType > iscsiAuthKeyTypeLast) {
1748fcf3ce44SJohn Forte 		return (0);
1749fcf3ce44SJohn Forte 	}
1750fcf3ce44SJohn Forte 	return (iscsiAuthClientKeyInfo[keyType].name);
1751fcf3ce44SJohn Forte }
1752fcf3ce44SJohn Forte 
1753fcf3ce44SJohn Forte 
1754fcf3ce44SJohn Forte int
iscsiAuthClientGetNextKeyType(int * pKeyType)1755fcf3ce44SJohn Forte iscsiAuthClientGetNextKeyType(int *pKeyType)
1756fcf3ce44SJohn Forte {
1757fcf3ce44SJohn Forte 	int keyType = *pKeyType;
1758fcf3ce44SJohn Forte 
1759fcf3ce44SJohn Forte 	if (keyType >= iscsiAuthKeyTypeLast) {
1760fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
1761fcf3ce44SJohn Forte 	}
1762fcf3ce44SJohn Forte 
1763fcf3ce44SJohn Forte 	if (keyType < iscsiAuthKeyTypeFirst) {
1764fcf3ce44SJohn Forte 		keyType = iscsiAuthKeyTypeFirst;
1765fcf3ce44SJohn Forte 	} else {
1766fcf3ce44SJohn Forte 		keyType++;
1767fcf3ce44SJohn Forte 	}
1768fcf3ce44SJohn Forte 
1769fcf3ce44SJohn Forte 	*pKeyType = keyType;
1770fcf3ce44SJohn Forte 
1771fcf3ce44SJohn Forte 	return (iscsiAuthStatusNoError);
1772fcf3ce44SJohn Forte }
1773fcf3ce44SJohn Forte 
1774fcf3ce44SJohn Forte 
1775fcf3ce44SJohn Forte int
iscsiAuthClientKeyNameToKeyType(const char * keyName)1776fcf3ce44SJohn Forte iscsiAuthClientKeyNameToKeyType(const char *keyName)
1777fcf3ce44SJohn Forte {
1778fcf3ce44SJohn Forte 	int keyType = iscsiAuthKeyTypeNone;
1779fcf3ce44SJohn Forte 
1780fcf3ce44SJohn Forte 	while (iscsiAuthClientGetNextKeyType(&keyType) ==
1781fcf3ce44SJohn Forte 	    iscsiAuthStatusNoError) {
1782fcf3ce44SJohn Forte 		const char *keyName2 = iscsiAuthClientGetKeyName(keyType);
1783fcf3ce44SJohn Forte 
1784fcf3ce44SJohn Forte 		if (!keyName2) {
1785fcf3ce44SJohn Forte 			return (iscsiAuthKeyTypeNone);
1786fcf3ce44SJohn Forte 		}
1787fcf3ce44SJohn Forte 
1788fcf3ce44SJohn Forte 		if (strcmp(keyName, keyName2) == 0) {
1789fcf3ce44SJohn Forte 			return (keyType);
1790fcf3ce44SJohn Forte 		}
1791fcf3ce44SJohn Forte 	}
1792fcf3ce44SJohn Forte 
1793fcf3ce44SJohn Forte 	return (iscsiAuthKeyTypeNone);
1794fcf3ce44SJohn Forte }
1795fcf3ce44SJohn Forte 
1796fcf3ce44SJohn Forte 
1797fcf3ce44SJohn Forte int
iscsiAuthClientRecvKeyValue(IscsiAuthClient * client,int keyType,const char * userKeyValue)1798fcf3ce44SJohn Forte iscsiAuthClientRecvKeyValue(IscsiAuthClient * client, int keyType,
1799fcf3ce44SJohn Forte     const char *userKeyValue)
1800fcf3ce44SJohn Forte {
1801fcf3ce44SJohn Forte 	if (!client || client->signature != iscsiAuthClientSignature) {
1802fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
1803fcf3ce44SJohn Forte 	}
1804fcf3ce44SJohn Forte 
1805fcf3ce44SJohn Forte 	if (client->phase != iscsiAuthPhaseNegotiate &&
1806fcf3ce44SJohn Forte 	    client->phase != iscsiAuthPhaseAuthenticate) {
1807fcf3ce44SJohn Forte 
1808fcf3ce44SJohn Forte 		client->phase = iscsiAuthPhaseError;
1809fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
1810fcf3ce44SJohn Forte 	}
1811fcf3ce44SJohn Forte 
1812fcf3ce44SJohn Forte 	if (keyType < iscsiAuthKeyTypeFirst || keyType > iscsiAuthKeyTypeLast) {
1813fcf3ce44SJohn Forte 
1814fcf3ce44SJohn Forte 		client->phase = iscsiAuthPhaseError;
1815fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
1816fcf3ce44SJohn Forte 	}
1817fcf3ce44SJohn Forte 
1818fcf3ce44SJohn Forte 	if (keyType == iscsiAuthKeyTypeChapChallenge) {
1819fcf3ce44SJohn Forte 		client->recvChapChallenge.length =
1820fcf3ce44SJohn Forte 		    iscsiAuthLargeBinaryMaxLength;
1821fcf3ce44SJohn Forte 		client->recvChapChallengeStatus =
1822fcf3ce44SJohn Forte 		    iscsiAuthClientTextToData(userKeyValue,
1823fcf3ce44SJohn Forte 		    client->recvChapChallenge.largeBinary,
1824fcf3ce44SJohn Forte 		    &client->recvChapChallenge.length);
1825fcf3ce44SJohn Forte 		userKeyValue = "";
1826fcf3ce44SJohn Forte 	}
1827fcf3ce44SJohn Forte 
1828fcf3ce44SJohn Forte 	iscsiAuthClientSetKeyValue(&client->recvKeyBlock,
1829fcf3ce44SJohn Forte 	    keyType, userKeyValue);
1830fcf3ce44SJohn Forte 
1831fcf3ce44SJohn Forte 	return (iscsiAuthStatusNoError);
1832fcf3ce44SJohn Forte }
1833fcf3ce44SJohn Forte 
1834fcf3ce44SJohn Forte 
1835fcf3ce44SJohn Forte int
iscsiAuthClientSendKeyValue(IscsiAuthClient * client,int keyType,int * keyPresent,char * userKeyValue,unsigned int maxLength)1836fcf3ce44SJohn Forte iscsiAuthClientSendKeyValue(IscsiAuthClient * client, int keyType,
1837fcf3ce44SJohn Forte     int *keyPresent, char *userKeyValue, unsigned int maxLength)
1838fcf3ce44SJohn Forte {
1839fcf3ce44SJohn Forte 	const char *keyValue;
1840fcf3ce44SJohn Forte 
1841fcf3ce44SJohn Forte 	if (!client || client->signature != iscsiAuthClientSignature) {
1842fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
1843fcf3ce44SJohn Forte 	}
1844fcf3ce44SJohn Forte 
1845fcf3ce44SJohn Forte 	if (client->phase != iscsiAuthPhaseConfigure &&
1846fcf3ce44SJohn Forte 	    client->phase != iscsiAuthPhaseNegotiate &&
1847fcf3ce44SJohn Forte 	    client->phase != iscsiAuthPhaseAuthenticate &&
1848fcf3ce44SJohn Forte 	    client->phase != iscsiAuthPhaseDone) {
1849fcf3ce44SJohn Forte 
1850fcf3ce44SJohn Forte 		client->phase = iscsiAuthPhaseError;
1851fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
1852fcf3ce44SJohn Forte 	}
1853fcf3ce44SJohn Forte 
1854fcf3ce44SJohn Forte 	if (keyType < iscsiAuthKeyTypeFirst || keyType > iscsiAuthKeyTypeLast) {
1855fcf3ce44SJohn Forte 
1856fcf3ce44SJohn Forte 		client->phase = iscsiAuthPhaseError;
1857fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
1858fcf3ce44SJohn Forte 	}
1859fcf3ce44SJohn Forte 
1860fcf3ce44SJohn Forte 	keyValue = iscsiAuthClientGetKeyValue(&client->sendKeyBlock, keyType);
1861fcf3ce44SJohn Forte 	if (keyValue) {
1862fcf3ce44SJohn Forte 		if (keyType == iscsiAuthKeyTypeChapChallenge) {
1863fcf3ce44SJohn Forte 			if (iscsiAuthClientDataToText(client->base64,
1864fcf3ce44SJohn Forte 			    client->sendChapChallenge.largeBinary,
1865fcf3ce44SJohn Forte 			    client->sendChapChallenge.length,
1866fcf3ce44SJohn Forte 			    userKeyValue, maxLength)) {
1867fcf3ce44SJohn Forte 				client->phase = iscsiAuthPhaseError;
1868fcf3ce44SJohn Forte 				return (iscsiAuthStatusError);
1869fcf3ce44SJohn Forte 			}
1870fcf3ce44SJohn Forte 		} else {
1871fcf3ce44SJohn Forte 			if (iscsiAuthClientStringCopy(userKeyValue,
1872fcf3ce44SJohn Forte 			    keyValue, maxLength)) {
1873fcf3ce44SJohn Forte 				client->phase = iscsiAuthPhaseError;
1874fcf3ce44SJohn Forte 				return (iscsiAuthStatusError);
1875fcf3ce44SJohn Forte 			}
1876fcf3ce44SJohn Forte 		}
1877fcf3ce44SJohn Forte 		*keyPresent = TRUE;
1878fcf3ce44SJohn Forte 	} else {
1879fcf3ce44SJohn Forte 		*keyPresent = FALSE;
1880fcf3ce44SJohn Forte 	}
1881fcf3ce44SJohn Forte 
1882fcf3ce44SJohn Forte 	return (iscsiAuthStatusNoError);
1883fcf3ce44SJohn Forte }
1884fcf3ce44SJohn Forte 
1885fcf3ce44SJohn Forte 
1886fcf3ce44SJohn Forte int
iscsiAuthClientRecvTransitBit(IscsiAuthClient * client,int value)1887fcf3ce44SJohn Forte iscsiAuthClientRecvTransitBit(IscsiAuthClient * client, int value)
1888fcf3ce44SJohn Forte {
1889fcf3ce44SJohn Forte 	if (!client || client->signature != iscsiAuthClientSignature) {
1890fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
1891fcf3ce44SJohn Forte 	}
1892fcf3ce44SJohn Forte 
1893fcf3ce44SJohn Forte 	if (client->phase != iscsiAuthPhaseNegotiate &&
1894fcf3ce44SJohn Forte 	    client->phase != iscsiAuthPhaseAuthenticate) {
1895fcf3ce44SJohn Forte 
1896fcf3ce44SJohn Forte 		client->phase = iscsiAuthPhaseError;
1897fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
1898fcf3ce44SJohn Forte 	}
1899fcf3ce44SJohn Forte 
1900fcf3ce44SJohn Forte 	if (value) {
1901fcf3ce44SJohn Forte 		client->recvKeyBlock.transitBit = TRUE;
1902fcf3ce44SJohn Forte 	} else {
1903fcf3ce44SJohn Forte 		client->recvKeyBlock.transitBit = FALSE;
1904fcf3ce44SJohn Forte 	}
1905fcf3ce44SJohn Forte 
1906fcf3ce44SJohn Forte 	return (iscsiAuthStatusNoError);
1907fcf3ce44SJohn Forte }
1908fcf3ce44SJohn Forte 
1909fcf3ce44SJohn Forte 
1910fcf3ce44SJohn Forte int
iscsiAuthClientSendTransitBit(IscsiAuthClient * client,int * value)1911fcf3ce44SJohn Forte iscsiAuthClientSendTransitBit(IscsiAuthClient * client, int *value)
1912fcf3ce44SJohn Forte {
1913fcf3ce44SJohn Forte 	if (!client || client->signature != iscsiAuthClientSignature) {
1914fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
1915fcf3ce44SJohn Forte 	}
1916fcf3ce44SJohn Forte 
1917fcf3ce44SJohn Forte 	if (client->phase != iscsiAuthPhaseConfigure &&
1918fcf3ce44SJohn Forte 	    client->phase != iscsiAuthPhaseNegotiate &&
1919fcf3ce44SJohn Forte 	    client->phase != iscsiAuthPhaseAuthenticate &&
1920fcf3ce44SJohn Forte 	    client->phase != iscsiAuthPhaseDone) {
1921fcf3ce44SJohn Forte 
1922fcf3ce44SJohn Forte 		client->phase = iscsiAuthPhaseError;
1923fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
1924fcf3ce44SJohn Forte 	}
1925fcf3ce44SJohn Forte 
1926fcf3ce44SJohn Forte 	*value = client->sendKeyBlock.transitBit;
1927fcf3ce44SJohn Forte 
1928fcf3ce44SJohn Forte 	return (iscsiAuthStatusNoError);
1929fcf3ce44SJohn Forte }
1930fcf3ce44SJohn Forte 
1931fcf3ce44SJohn Forte 
1932fcf3ce44SJohn Forte int
iscsiAuthClientInit(int nodeType,int bufferDescCount,IscsiAuthBufferDesc * bufferDesc)1933fcf3ce44SJohn Forte iscsiAuthClientInit(int nodeType, int bufferDescCount,
1934fcf3ce44SJohn Forte     IscsiAuthBufferDesc * bufferDesc)
1935fcf3ce44SJohn Forte {
1936fcf3ce44SJohn Forte 	IscsiAuthClient *client;
1937fcf3ce44SJohn Forte 	IscsiAuthStringBlock *recvStringBlock;
1938fcf3ce44SJohn Forte 	IscsiAuthStringBlock *sendStringBlock;
1939fcf3ce44SJohn Forte 	IscsiAuthLargeBinary *recvChapChallenge;
1940fcf3ce44SJohn Forte 	IscsiAuthLargeBinary *sendChapChallenge;
1941fcf3ce44SJohn Forte 	int valueList[2];
1942fcf3ce44SJohn Forte 
1943fcf3ce44SJohn Forte 	if (bufferDescCount != 5 ||
1944fcf3ce44SJohn Forte 	    bufferDesc == 0) {
1945fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
1946fcf3ce44SJohn Forte 	}
1947fcf3ce44SJohn Forte 
1948fcf3ce44SJohn Forte 	if (!bufferDesc[0].address ||
1949fcf3ce44SJohn Forte 	    bufferDesc[0].length != sizeof (*client)) {
1950fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
1951fcf3ce44SJohn Forte 	}
1952fcf3ce44SJohn Forte 	client = (IscsiAuthClient *) bufferDesc[0].address;
1953fcf3ce44SJohn Forte 
1954fcf3ce44SJohn Forte 	if (bufferDesc[1].address == 0 ||
1955fcf3ce44SJohn Forte 	    bufferDesc[1].length != sizeof (*recvStringBlock)) {
1956fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
1957fcf3ce44SJohn Forte 	}
1958fcf3ce44SJohn Forte 	recvStringBlock = (IscsiAuthStringBlock *) bufferDesc[1].address;
1959fcf3ce44SJohn Forte 
1960fcf3ce44SJohn Forte 	if (bufferDesc[2].address == 0 ||
1961fcf3ce44SJohn Forte 	    bufferDesc[2].length != sizeof (*sendStringBlock)) {
1962fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
1963fcf3ce44SJohn Forte 	}
1964fcf3ce44SJohn Forte 	sendStringBlock = (IscsiAuthStringBlock *) bufferDesc[2].address;
1965fcf3ce44SJohn Forte 
1966fcf3ce44SJohn Forte 	if (bufferDesc[3].address == 0 ||
1967fcf3ce44SJohn Forte 	    bufferDesc[3].length != sizeof (*recvChapChallenge)) {
1968fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
1969fcf3ce44SJohn Forte 	}
1970fcf3ce44SJohn Forte 	recvChapChallenge = (IscsiAuthLargeBinary *) bufferDesc[3].address;
1971fcf3ce44SJohn Forte 
1972fcf3ce44SJohn Forte 	if (bufferDesc[4].address == 0 ||
1973fcf3ce44SJohn Forte 	    bufferDesc[4].length != sizeof (*sendChapChallenge)) {
1974fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
1975fcf3ce44SJohn Forte 	}
1976fcf3ce44SJohn Forte 	sendChapChallenge = (IscsiAuthLargeBinary *) bufferDesc[4].address;
1977fcf3ce44SJohn Forte 
1978fcf3ce44SJohn Forte 	bzero(client, sizeof (*client));
1979fcf3ce44SJohn Forte 	bzero(recvStringBlock, sizeof (*recvStringBlock));
1980fcf3ce44SJohn Forte 	bzero(sendStringBlock, sizeof (*sendStringBlock));
1981fcf3ce44SJohn Forte 	bzero(recvChapChallenge, sizeof (*recvChapChallenge));
1982fcf3ce44SJohn Forte 	bzero(sendChapChallenge, sizeof (*sendChapChallenge));
1983fcf3ce44SJohn Forte 
1984fcf3ce44SJohn Forte 	client->recvKeyBlock.stringBlock = recvStringBlock->stringBlock;
1985fcf3ce44SJohn Forte 	client->sendKeyBlock.stringBlock = sendStringBlock->stringBlock;
1986fcf3ce44SJohn Forte 	client->recvChapChallenge.largeBinary = recvChapChallenge->largeBinary;
1987fcf3ce44SJohn Forte 	client->sendChapChallenge.largeBinary = sendChapChallenge->largeBinary;
1988fcf3ce44SJohn Forte 
1989fcf3ce44SJohn Forte 	if (iscsiAuthClientCheckNodeType(nodeType)) {
1990fcf3ce44SJohn Forte 		client->phase = iscsiAuthPhaseError;
1991fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
1992fcf3ce44SJohn Forte 	}
1993fcf3ce44SJohn Forte 
1994fcf3ce44SJohn Forte 	client->signature = iscsiAuthClientSignature;
1995fcf3ce44SJohn Forte 	client->nodeType = (IscsiAuthNodeType) nodeType;
1996fcf3ce44SJohn Forte 	/* Assume bi-directional authentication enabled. */
1997fcf3ce44SJohn Forte 	client->authRemote = TRUE;
1998fcf3ce44SJohn Forte 	client->passwordPresent = FALSE;
1999fcf3ce44SJohn Forte 	client->version = iscsiAuthVersionRfc;
2000fcf3ce44SJohn Forte 	client->chapChallengeLength = iscsiAuthChapResponseLength;
2001fcf3ce44SJohn Forte 	client->ipSec = TRUE;
2002fcf3ce44SJohn Forte 	client->base64 = FALSE;
2003fcf3ce44SJohn Forte 
2004fcf3ce44SJohn Forte 	client->phase = iscsiAuthPhaseConfigure;
2005fcf3ce44SJohn Forte 	client->negotiatedAuthMethod = iscsiAuthOptionNotPresent;
2006fcf3ce44SJohn Forte 	client->negotiatedChapAlgorithm = iscsiAuthOptionNotPresent;
2007fcf3ce44SJohn Forte 
2008fcf3ce44SJohn Forte 	if (client->nodeType == iscsiAuthNodeTypeInitiator) {
2009fcf3ce44SJohn Forte 		client->authMethodNegRole = iscsiAuthNegRoleOriginator;
2010fcf3ce44SJohn Forte 	} else {
2011fcf3ce44SJohn Forte 		/*
2012fcf3ce44SJohn Forte 		 * Initial value ignored for Target.
2013fcf3ce44SJohn Forte 		 */
2014fcf3ce44SJohn Forte 		client->authMethodNegRole = iscsiAuthNegRoleResponder;
2015fcf3ce44SJohn Forte 	}
2016fcf3ce44SJohn Forte 
2017fcf3ce44SJohn Forte 	/* All supported authentication methods */
2018fcf3ce44SJohn Forte 	valueList[0] = iscsiAuthMethodChap;
2019fcf3ce44SJohn Forte 	valueList[1] = iscsiAuthOptionNone;
2020fcf3ce44SJohn Forte 
2021fcf3ce44SJohn Forte 	/*
2022fcf3ce44SJohn Forte 	 * Must call after setting authRemote, password,
2023fcf3ce44SJohn Forte 	 * version and authMethodNegRole
2024fcf3ce44SJohn Forte 	 */
2025fcf3ce44SJohn Forte 	if (iscsiAuthClientSetAuthMethodList(client, 2, valueList) !=
2026fcf3ce44SJohn Forte 	    iscsiAuthStatusNoError) {
2027fcf3ce44SJohn Forte 		client->phase = iscsiAuthPhaseError;
2028fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
2029fcf3ce44SJohn Forte 	}
2030fcf3ce44SJohn Forte 
2031fcf3ce44SJohn Forte 	valueList[0] = iscsiAuthChapAlgorithmMd5;
2032fcf3ce44SJohn Forte 
2033fcf3ce44SJohn Forte 	if (iscsiAuthClientSetChapAlgorithmList(client, 1, valueList) !=
2034fcf3ce44SJohn Forte 	    iscsiAuthStatusNoError) {
2035fcf3ce44SJohn Forte 		client->phase = iscsiAuthPhaseError;
2036fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
2037fcf3ce44SJohn Forte 	}
2038fcf3ce44SJohn Forte 
2039fcf3ce44SJohn Forte 	return (iscsiAuthStatusNoError);
2040fcf3ce44SJohn Forte }
2041fcf3ce44SJohn Forte 
2042fcf3ce44SJohn Forte 
2043fcf3ce44SJohn Forte int
iscsiAuthClientFinish(IscsiAuthClient * client)2044fcf3ce44SJohn Forte iscsiAuthClientFinish(IscsiAuthClient * client)
2045fcf3ce44SJohn Forte {
2046fcf3ce44SJohn Forte 	if (!client || client->signature != iscsiAuthClientSignature) {
2047fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
2048fcf3ce44SJohn Forte 	}
2049fcf3ce44SJohn Forte 
2050fcf3ce44SJohn Forte 	iscsiAuthClientChapAuthCancel(client);
2051fcf3ce44SJohn Forte 
2052fcf3ce44SJohn Forte 	bzero(client, sizeof (*client));
2053fcf3ce44SJohn Forte 
2054fcf3ce44SJohn Forte 	return (iscsiAuthStatusNoError);
2055fcf3ce44SJohn Forte }
2056fcf3ce44SJohn Forte 
2057fcf3ce44SJohn Forte 
2058fcf3ce44SJohn Forte static int
iscsiAuthClientSetOptionList(IscsiAuthClient * client,unsigned int optionCount,const int * optionList,unsigned int * clientOptionCount,int * clientOptionList,unsigned int optionMaxCount,int (* checkOption)(int),int (* checkList)(unsigned int optionCount,const int * optionList))2059fcf3ce44SJohn Forte iscsiAuthClientSetOptionList(IscsiAuthClient * client,
2060fcf3ce44SJohn Forte     unsigned int optionCount,
2061fcf3ce44SJohn Forte     const int *optionList,
2062fcf3ce44SJohn Forte     unsigned int *clientOptionCount,
2063fcf3ce44SJohn Forte     int *clientOptionList,
2064fcf3ce44SJohn Forte     unsigned int optionMaxCount,
2065fcf3ce44SJohn Forte     int (*checkOption) (int),
2066fcf3ce44SJohn Forte     int (*checkList) (unsigned int optionCount, const int *optionList))
2067fcf3ce44SJohn Forte {
2068fcf3ce44SJohn Forte 	unsigned int i;
2069fcf3ce44SJohn Forte 	unsigned int j;
2070fcf3ce44SJohn Forte 
2071fcf3ce44SJohn Forte 	if (!client || client->signature != iscsiAuthClientSignature) {
2072fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
2073fcf3ce44SJohn Forte 	}
2074fcf3ce44SJohn Forte 
2075fcf3ce44SJohn Forte 	if (client->phase != iscsiAuthPhaseConfigure ||
2076fcf3ce44SJohn Forte 	    optionCount > optionMaxCount) {
2077fcf3ce44SJohn Forte 		client->phase = iscsiAuthPhaseError;
2078fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
2079fcf3ce44SJohn Forte 	}
2080fcf3ce44SJohn Forte 
2081fcf3ce44SJohn Forte 	for (i = 0; i < optionCount; i++) {
2082fcf3ce44SJohn Forte 		if ((*checkOption) (optionList[i])) {
2083fcf3ce44SJohn Forte 			client->phase = iscsiAuthPhaseError;
2084fcf3ce44SJohn Forte 			return (iscsiAuthStatusError);
2085fcf3ce44SJohn Forte 		}
2086fcf3ce44SJohn Forte 	}
2087fcf3ce44SJohn Forte 
2088fcf3ce44SJohn Forte 	/*
2089fcf3ce44SJohn Forte 	 * Check for duplicate entries.
2090fcf3ce44SJohn Forte 	 */
2091fcf3ce44SJohn Forte 	for (i = 0; i < optionCount; i++) {
2092fcf3ce44SJohn Forte 		for (j = 0; j < optionCount; j++) {
2093fcf3ce44SJohn Forte 			if (j == i)
2094fcf3ce44SJohn Forte 				continue;
2095fcf3ce44SJohn Forte 			if (optionList[i] == optionList[j]) {
2096fcf3ce44SJohn Forte 				client->phase = iscsiAuthPhaseError;
2097fcf3ce44SJohn Forte 				return (iscsiAuthStatusError);
2098fcf3ce44SJohn Forte 			}
2099fcf3ce44SJohn Forte 		}
2100fcf3ce44SJohn Forte 	}
2101fcf3ce44SJohn Forte 
2102fcf3ce44SJohn Forte 	/*
2103fcf3ce44SJohn Forte 	 * Check for key specific constraints.
2104fcf3ce44SJohn Forte 	 */
2105fcf3ce44SJohn Forte 	if (checkList) {
2106fcf3ce44SJohn Forte 		if ((*checkList) (optionCount, optionList)) {
2107fcf3ce44SJohn Forte 			client->phase = iscsiAuthPhaseError;
2108fcf3ce44SJohn Forte 			return (iscsiAuthStatusError);
2109fcf3ce44SJohn Forte 		}
2110fcf3ce44SJohn Forte 	}
2111fcf3ce44SJohn Forte 
2112fcf3ce44SJohn Forte 	for (i = 0; i < optionCount; i++) {
2113fcf3ce44SJohn Forte 		clientOptionList[i] = optionList[i];
2114fcf3ce44SJohn Forte 	}
2115fcf3ce44SJohn Forte 
2116fcf3ce44SJohn Forte 	*clientOptionCount = optionCount;
2117fcf3ce44SJohn Forte 
2118fcf3ce44SJohn Forte 	return (iscsiAuthStatusNoError);
2119fcf3ce44SJohn Forte }
2120fcf3ce44SJohn Forte 
2121fcf3ce44SJohn Forte 
2122fcf3ce44SJohn Forte static void
iscsiAuthClientSetAuthMethodValid(IscsiAuthClient * client)2123fcf3ce44SJohn Forte iscsiAuthClientSetAuthMethodValid(IscsiAuthClient * client)
2124fcf3ce44SJohn Forte {
2125fcf3ce44SJohn Forte 	static const char rejectOptionNameDraft8[] = "reject";
2126fcf3ce44SJohn Forte 	static const char rejectOptionNameRfc[] = "Reject";
2127fcf3ce44SJohn Forte 	static const char noneOptionNameDraft8[] = "none";
2128fcf3ce44SJohn Forte 	static const char noneOptionNameRfc[] = "None";
2129fcf3ce44SJohn Forte 	unsigned int i;
2130fcf3ce44SJohn Forte 	unsigned int j = 0;
2131fcf3ce44SJohn Forte 	int option = 0;
2132fcf3ce44SJohn Forte 
2133fcf3ce44SJohn Forte 	if (client->version == iscsiAuthVersionDraft8) {
2134fcf3ce44SJohn Forte 		client->rejectOptionName = rejectOptionNameDraft8;
2135fcf3ce44SJohn Forte 		client->noneOptionName = noneOptionNameDraft8;
2136fcf3ce44SJohn Forte 	} else {
2137fcf3ce44SJohn Forte 		client->rejectOptionName = rejectOptionNameRfc;
2138fcf3ce44SJohn Forte 		client->noneOptionName = noneOptionNameRfc;
2139fcf3ce44SJohn Forte 	}
2140fcf3ce44SJohn Forte 
2141fcf3ce44SJohn Forte 	/*
2142fcf3ce44SJohn Forte 	 * Following checks may need to be revised if
2143fcf3ce44SJohn Forte 	 * authentication options other than CHAP and none
2144fcf3ce44SJohn Forte 	 * are supported.
2145fcf3ce44SJohn Forte 	 */
2146fcf3ce44SJohn Forte 
2147fcf3ce44SJohn Forte 	if (client->nodeType == iscsiAuthNodeTypeInitiator) {
2148fcf3ce44SJohn Forte 
2149fcf3ce44SJohn Forte 		if (client->authRemote) {
2150fcf3ce44SJohn Forte 			/*
2151fcf3ce44SJohn Forte 			 * If initiator doing authentication,
2152fcf3ce44SJohn Forte 			 * don't offer authentication option none.
2153fcf3ce44SJohn Forte 			 */
2154fcf3ce44SJohn Forte 			option = 1;
2155fcf3ce44SJohn Forte 		} else if (!client->passwordPresent) {
2156fcf3ce44SJohn Forte 			/*
2157fcf3ce44SJohn Forte 			 * If initiator password not set,
2158fcf3ce44SJohn Forte 			 * only offer authentication option none.
2159fcf3ce44SJohn Forte 			 */
2160fcf3ce44SJohn Forte 			option = 2;
2161fcf3ce44SJohn Forte 		}
2162fcf3ce44SJohn Forte 	}
2163fcf3ce44SJohn Forte 
2164fcf3ce44SJohn Forte 	if (client->nodeType == iscsiAuthNodeTypeTarget) {
2165fcf3ce44SJohn Forte 
2166fcf3ce44SJohn Forte 		if (client->authRemote) {
2167fcf3ce44SJohn Forte 			/*
2168fcf3ce44SJohn Forte 			 * If target doing authentication,
2169fcf3ce44SJohn Forte 			 * don't accept authentication option none.
2170fcf3ce44SJohn Forte 			 */
2171fcf3ce44SJohn Forte 			option = 1;
2172fcf3ce44SJohn Forte 		} else {
2173fcf3ce44SJohn Forte 			/*
2174fcf3ce44SJohn Forte 			 * If target not doing authentication,
2175fcf3ce44SJohn Forte 			 * only accept authentication option none.
2176fcf3ce44SJohn Forte 			 */
2177fcf3ce44SJohn Forte 			option = 2;
2178fcf3ce44SJohn Forte 		}
2179fcf3ce44SJohn Forte 	}
2180fcf3ce44SJohn Forte 
2181fcf3ce44SJohn Forte 	for (i = 0; i < client->authMethodCount; i++) {
2182fcf3ce44SJohn Forte 
2183fcf3ce44SJohn Forte 		if (option == 1) {
2184fcf3ce44SJohn Forte 			if (client->authMethodList[i] == iscsiAuthOptionNone) {
2185fcf3ce44SJohn Forte 				continue;
2186fcf3ce44SJohn Forte 			}
2187fcf3ce44SJohn Forte 		} else if (option == 2) {
2188fcf3ce44SJohn Forte 			if (client->authMethodList[i] != iscsiAuthOptionNone) {
2189fcf3ce44SJohn Forte 				continue;
2190fcf3ce44SJohn Forte 			}
2191fcf3ce44SJohn Forte 		}
2192fcf3ce44SJohn Forte 
2193fcf3ce44SJohn Forte 		client->authMethodValidList[j++] = client->authMethodList[i];
2194fcf3ce44SJohn Forte 	}
2195fcf3ce44SJohn Forte 
2196fcf3ce44SJohn Forte 	client->authMethodValidCount = j;
2197fcf3ce44SJohn Forte 
2198fcf3ce44SJohn Forte 	iscsiAuthClientInitKeyBlock(&client->sendKeyBlock);
2199fcf3ce44SJohn Forte 
2200fcf3ce44SJohn Forte 	if (client->nodeType == iscsiAuthNodeTypeInitiator) {
2201fcf3ce44SJohn Forte 		if (client->authRemote) {
2202fcf3ce44SJohn Forte 			/*
2203fcf3ce44SJohn Forte 			 * Initiator wants to authenticate target,
2204fcf3ce44SJohn Forte 			 * always send AuthMethod key.
2205fcf3ce44SJohn Forte 			 */
2206fcf3ce44SJohn Forte 			client->sendKeyBlock.transitBit = FALSE;
2207fcf3ce44SJohn Forte 			client->authMethodValidNegRole =
2208fcf3ce44SJohn Forte 			    iscsiAuthNegRoleOriginator;
2209fcf3ce44SJohn Forte 		} else {
2210fcf3ce44SJohn Forte 			client->sendKeyBlock.transitBit = TRUE;
2211fcf3ce44SJohn Forte 			client->authMethodValidNegRole =
2212fcf3ce44SJohn Forte 			    client->authMethodNegRole;
2213fcf3ce44SJohn Forte 		}
2214fcf3ce44SJohn Forte 	} else {
2215fcf3ce44SJohn Forte 		client->sendKeyBlock.transitBit = FALSE;
2216fcf3ce44SJohn Forte 		client->authMethodValidNegRole = iscsiAuthNegRoleResponder;
2217fcf3ce44SJohn Forte 	}
2218fcf3ce44SJohn Forte 
2219fcf3ce44SJohn Forte 	if (client->authMethodValidNegRole == iscsiAuthNegRoleOriginator) {
2220fcf3ce44SJohn Forte 		iscsiAuthClientSetAuthMethodKey(client,
2221fcf3ce44SJohn Forte 		    client->authMethodValidCount,
2222fcf3ce44SJohn Forte 		    client->authMethodValidList);
2223fcf3ce44SJohn Forte 	} else {
2224fcf3ce44SJohn Forte 		int value = iscsiAuthOptionNotPresent;
2225fcf3ce44SJohn Forte 		iscsiAuthClientSetAuthMethodKey(client, 1, &value);
2226fcf3ce44SJohn Forte 	}
2227fcf3ce44SJohn Forte }
2228fcf3ce44SJohn Forte 
2229fcf3ce44SJohn Forte 
2230fcf3ce44SJohn Forte static int
iscsiAuthClientCheckAuthMethodList(unsigned int optionCount,const int * optionList)2231fcf3ce44SJohn Forte iscsiAuthClientCheckAuthMethodList(unsigned int optionCount,
2232fcf3ce44SJohn Forte     const int *optionList)
2233fcf3ce44SJohn Forte {
2234fcf3ce44SJohn Forte 	unsigned int i;
2235fcf3ce44SJohn Forte 
2236fcf3ce44SJohn Forte 	if (!optionList || optionCount < 2) {
2237fcf3ce44SJohn Forte 		return (TRUE);
2238fcf3ce44SJohn Forte 	}
2239fcf3ce44SJohn Forte 
2240fcf3ce44SJohn Forte 	if (optionList[optionCount - 1] != iscsiAuthOptionNone) {
2241fcf3ce44SJohn Forte 		return (TRUE);
2242fcf3ce44SJohn Forte 	}
2243fcf3ce44SJohn Forte 
2244fcf3ce44SJohn Forte 	for (i = 0; i < (optionCount - 1); i++) {
2245fcf3ce44SJohn Forte 		if (optionList[i] != iscsiAuthOptionNone) {
2246fcf3ce44SJohn Forte 			return (FALSE);
2247fcf3ce44SJohn Forte 		}
2248fcf3ce44SJohn Forte 	}
2249fcf3ce44SJohn Forte 
2250fcf3ce44SJohn Forte 	return (FALSE);
2251fcf3ce44SJohn Forte }
2252fcf3ce44SJohn Forte 
2253fcf3ce44SJohn Forte 
2254fcf3ce44SJohn Forte int
iscsiAuthClientSetAuthMethodList(IscsiAuthClient * client,unsigned int optionCount,const int * optionList)2255fcf3ce44SJohn Forte iscsiAuthClientSetAuthMethodList(IscsiAuthClient * client,
2256fcf3ce44SJohn Forte     unsigned int optionCount, const int *optionList)
2257fcf3ce44SJohn Forte {
2258fcf3ce44SJohn Forte 	int status;
2259fcf3ce44SJohn Forte 
2260fcf3ce44SJohn Forte 	status = iscsiAuthClientSetOptionList(
2261fcf3ce44SJohn Forte 	    client, optionCount, optionList, &client->authMethodCount,
2262fcf3ce44SJohn Forte 	    client->authMethodList, iscsiAuthMethodMaxCount,
2263fcf3ce44SJohn Forte 	    iscsiAuthClientCheckAuthMethodOption,
2264fcf3ce44SJohn Forte 	    iscsiAuthClientCheckAuthMethodList);
2265fcf3ce44SJohn Forte 
2266fcf3ce44SJohn Forte 	if (status != iscsiAuthStatusNoError) {
2267fcf3ce44SJohn Forte 		return (status);
2268fcf3ce44SJohn Forte 	}
2269fcf3ce44SJohn Forte 
2270fcf3ce44SJohn Forte 	/*
2271fcf3ce44SJohn Forte 	 * Setting authMethod affects authMethodValid.
2272fcf3ce44SJohn Forte 	 */
2273fcf3ce44SJohn Forte 	iscsiAuthClientSetAuthMethodValid(client);
2274fcf3ce44SJohn Forte 
2275fcf3ce44SJohn Forte 	return (iscsiAuthStatusNoError);
2276fcf3ce44SJohn Forte }
2277fcf3ce44SJohn Forte 
2278fcf3ce44SJohn Forte 
2279fcf3ce44SJohn Forte int
iscsiAuthClientSetAuthMethodNegRole(IscsiAuthClient * client,int negRole)2280fcf3ce44SJohn Forte iscsiAuthClientSetAuthMethodNegRole(IscsiAuthClient * client, int negRole)
2281fcf3ce44SJohn Forte {
2282fcf3ce44SJohn Forte 	if (!client || client->signature != iscsiAuthClientSignature) {
2283fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
2284fcf3ce44SJohn Forte 	}
2285fcf3ce44SJohn Forte 
2286fcf3ce44SJohn Forte 	if (client->phase != iscsiAuthPhaseConfigure ||
2287fcf3ce44SJohn Forte 	    iscsiAuthClientCheckNegRole(negRole) ||
2288fcf3ce44SJohn Forte 	    client->nodeType != iscsiAuthNodeTypeInitiator) {
2289fcf3ce44SJohn Forte 
2290fcf3ce44SJohn Forte 		client->phase = iscsiAuthPhaseError;
2291fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
2292fcf3ce44SJohn Forte 	}
2293fcf3ce44SJohn Forte 
2294fcf3ce44SJohn Forte 	client->authMethodNegRole = (IscsiAuthNegRole) negRole;
2295fcf3ce44SJohn Forte 
2296fcf3ce44SJohn Forte 	/*
2297fcf3ce44SJohn Forte 	 * Setting negRole affects authMethodValid.
2298fcf3ce44SJohn Forte 	 */
2299fcf3ce44SJohn Forte 	iscsiAuthClientSetAuthMethodValid(client);
2300fcf3ce44SJohn Forte 
2301fcf3ce44SJohn Forte 	return (iscsiAuthStatusNoError);
2302fcf3ce44SJohn Forte }
2303fcf3ce44SJohn Forte 
2304fcf3ce44SJohn Forte 
2305fcf3ce44SJohn Forte static int
iscsiAuthClientCheckChapAlgorithmList(unsigned int optionCount,const int * optionList)2306fcf3ce44SJohn Forte iscsiAuthClientCheckChapAlgorithmList(unsigned int optionCount,
2307fcf3ce44SJohn Forte     const int *optionList)
2308fcf3ce44SJohn Forte {
2309fcf3ce44SJohn Forte 	if (!optionList || optionCount < 1) {
2310fcf3ce44SJohn Forte 		return (TRUE);
2311fcf3ce44SJohn Forte 	}
2312fcf3ce44SJohn Forte 
2313fcf3ce44SJohn Forte 	return (FALSE);
2314fcf3ce44SJohn Forte }
2315fcf3ce44SJohn Forte 
2316fcf3ce44SJohn Forte 
2317fcf3ce44SJohn Forte int
iscsiAuthClientSetChapAlgorithmList(IscsiAuthClient * client,unsigned int optionCount,const int * optionList)2318fcf3ce44SJohn Forte iscsiAuthClientSetChapAlgorithmList(IscsiAuthClient * client,
2319fcf3ce44SJohn Forte     unsigned int optionCount, const int *optionList)
2320fcf3ce44SJohn Forte {
2321fcf3ce44SJohn Forte 	return (iscsiAuthClientSetOptionList(client,
2322fcf3ce44SJohn Forte 	    optionCount,
2323fcf3ce44SJohn Forte 	    optionList,
2324fcf3ce44SJohn Forte 	    &client->chapAlgorithmCount,
2325fcf3ce44SJohn Forte 	    client->chapAlgorithmList,
2326fcf3ce44SJohn Forte 	    iscsiAuthChapAlgorithmMaxCount,
2327fcf3ce44SJohn Forte 	    iscsiAuthClientCheckChapAlgorithmOption,
2328fcf3ce44SJohn Forte 	    iscsiAuthClientCheckChapAlgorithmList));
2329fcf3ce44SJohn Forte }
2330fcf3ce44SJohn Forte 
2331fcf3ce44SJohn Forte 
2332fcf3ce44SJohn Forte int
iscsiAuthClientSetUsername(IscsiAuthClient * client,const char * username)2333fcf3ce44SJohn Forte iscsiAuthClientSetUsername(IscsiAuthClient * client, const char *username)
2334fcf3ce44SJohn Forte {
2335fcf3ce44SJohn Forte 	if (!client || client->signature != iscsiAuthClientSignature) {
2336fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
2337fcf3ce44SJohn Forte 	}
2338fcf3ce44SJohn Forte 
2339fcf3ce44SJohn Forte 	if (client->phase != iscsiAuthPhaseConfigure ||
2340fcf3ce44SJohn Forte 	    iscsiAuthClientCheckString(username, iscsiAuthStringMaxLength, 0)) {
2341fcf3ce44SJohn Forte 		client->phase = iscsiAuthPhaseError;
2342fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
2343fcf3ce44SJohn Forte 	}
2344fcf3ce44SJohn Forte 
2345fcf3ce44SJohn Forte 	if (iscsiAuthClientStringCopy(client->username, username,
2346fcf3ce44SJohn Forte 	    iscsiAuthStringMaxLength)) {
2347fcf3ce44SJohn Forte 		client->phase = iscsiAuthPhaseError;
2348fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
2349fcf3ce44SJohn Forte 	}
2350fcf3ce44SJohn Forte 
2351fcf3ce44SJohn Forte 	return (iscsiAuthStatusNoError);
2352fcf3ce44SJohn Forte }
2353fcf3ce44SJohn Forte 
2354fcf3ce44SJohn Forte 
2355fcf3ce44SJohn Forte int
iscsiAuthClientSetPassword(IscsiAuthClient * client,const unsigned char * passwordData,unsigned int passwordLength)2356fcf3ce44SJohn Forte iscsiAuthClientSetPassword(IscsiAuthClient * client,
2357fcf3ce44SJohn Forte     const unsigned char *passwordData, unsigned int passwordLength)
2358fcf3ce44SJohn Forte {
2359fcf3ce44SJohn Forte 	if (!client || client->signature != iscsiAuthClientSignature) {
2360fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
2361fcf3ce44SJohn Forte 	}
2362fcf3ce44SJohn Forte 
2363fcf3ce44SJohn Forte 	if (client->phase != iscsiAuthPhaseConfigure ||
2364fcf3ce44SJohn Forte 	    passwordLength > iscsiAuthStringMaxLength) {
2365fcf3ce44SJohn Forte 
2366fcf3ce44SJohn Forte 		client->phase = iscsiAuthPhaseError;
2367fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
2368fcf3ce44SJohn Forte 	}
2369fcf3ce44SJohn Forte 
2370fcf3ce44SJohn Forte 	bcopy(passwordData, client->passwordData, passwordLength);
2371fcf3ce44SJohn Forte 	client->passwordLength = passwordLength;
2372fcf3ce44SJohn Forte 	if (client->passwordLength > 0) {
2373fcf3ce44SJohn Forte 		client->passwordPresent = TRUE;
2374fcf3ce44SJohn Forte 	} else {
2375fcf3ce44SJohn Forte 		client->passwordPresent = FALSE;
2376fcf3ce44SJohn Forte 	}
2377fcf3ce44SJohn Forte 
2378fcf3ce44SJohn Forte 	/*
2379fcf3ce44SJohn Forte 	 * Setting password may affect authMethodValid.
2380fcf3ce44SJohn Forte 	 */
2381fcf3ce44SJohn Forte 	iscsiAuthClientSetAuthMethodValid(client);
2382fcf3ce44SJohn Forte 
2383fcf3ce44SJohn Forte 	return (iscsiAuthStatusNoError);
2384fcf3ce44SJohn Forte }
2385fcf3ce44SJohn Forte 
2386fcf3ce44SJohn Forte 
2387fcf3ce44SJohn Forte int
iscsiAuthClientSetAuthRemote(IscsiAuthClient * client,int authRemote)2388fcf3ce44SJohn Forte iscsiAuthClientSetAuthRemote(IscsiAuthClient * client, int authRemote)
2389fcf3ce44SJohn Forte {
2390fcf3ce44SJohn Forte 	if (!client || client->signature != iscsiAuthClientSignature) {
2391fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
2392fcf3ce44SJohn Forte 	}
2393fcf3ce44SJohn Forte 
2394fcf3ce44SJohn Forte 	if (client->phase != iscsiAuthPhaseConfigure) {
2395fcf3ce44SJohn Forte 		client->phase = iscsiAuthPhaseError;
2396fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
2397fcf3ce44SJohn Forte 	}
2398fcf3ce44SJohn Forte 
2399fcf3ce44SJohn Forte 	client->authRemote = authRemote;
2400fcf3ce44SJohn Forte 
2401fcf3ce44SJohn Forte 	/*
2402fcf3ce44SJohn Forte 	 * Setting authRemote may affect authMethodValid.
2403fcf3ce44SJohn Forte 	 */
2404fcf3ce44SJohn Forte 	iscsiAuthClientSetAuthMethodValid(client);
2405fcf3ce44SJohn Forte 
2406fcf3ce44SJohn Forte 	return (iscsiAuthStatusNoError);
2407fcf3ce44SJohn Forte }
2408fcf3ce44SJohn Forte 
2409fcf3ce44SJohn Forte 
2410fcf3ce44SJohn Forte int
iscsiAuthClientSetGlueHandle(IscsiAuthClient * client,void * glueHandle)2411fcf3ce44SJohn Forte iscsiAuthClientSetGlueHandle(IscsiAuthClient * client, void *glueHandle)
2412fcf3ce44SJohn Forte {
2413fcf3ce44SJohn Forte 	if (!client || client->signature != iscsiAuthClientSignature) {
2414fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
2415fcf3ce44SJohn Forte 	}
2416fcf3ce44SJohn Forte 
2417fcf3ce44SJohn Forte 	if (client->phase != iscsiAuthPhaseConfigure &&
2418fcf3ce44SJohn Forte 	    client->phase != iscsiAuthPhaseNegotiate &&
2419fcf3ce44SJohn Forte 	    client->phase != iscsiAuthPhaseAuthenticate) {
2420fcf3ce44SJohn Forte 
2421fcf3ce44SJohn Forte 		client->phase = iscsiAuthPhaseError;
2422fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
2423fcf3ce44SJohn Forte 	}
2424fcf3ce44SJohn Forte 
2425fcf3ce44SJohn Forte 	client->glueHandle = glueHandle;
2426fcf3ce44SJohn Forte 
2427fcf3ce44SJohn Forte 	return (iscsiAuthStatusNoError);
2428fcf3ce44SJohn Forte }
2429fcf3ce44SJohn Forte 
2430fcf3ce44SJohn Forte 
2431fcf3ce44SJohn Forte int
iscsiAuthClientSetMethodListName(IscsiAuthClient * client,const char * methodListName)2432fcf3ce44SJohn Forte iscsiAuthClientSetMethodListName(IscsiAuthClient *client,
2433fcf3ce44SJohn Forte     const char *methodListName)
2434fcf3ce44SJohn Forte {
2435fcf3ce44SJohn Forte 	if (!client || client->signature != iscsiAuthClientSignature) {
2436fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
2437fcf3ce44SJohn Forte 	}
2438fcf3ce44SJohn Forte 
2439fcf3ce44SJohn Forte 	if (client->phase != iscsiAuthPhaseConfigure ||
2440fcf3ce44SJohn Forte 	    iscsiAuthClientCheckString(methodListName,
2441fcf3ce44SJohn Forte 	    iscsiAuthStringMaxLength, 0)) {
2442fcf3ce44SJohn Forte 
2443fcf3ce44SJohn Forte 		client->phase = iscsiAuthPhaseError;
2444fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
2445fcf3ce44SJohn Forte 	}
2446fcf3ce44SJohn Forte 
2447fcf3ce44SJohn Forte 	if (iscsiAuthClientStringCopy(client->methodListName, methodListName,
2448fcf3ce44SJohn Forte 	    iscsiAuthStringMaxLength)) {
2449fcf3ce44SJohn Forte 
2450fcf3ce44SJohn Forte 		client->phase = iscsiAuthPhaseError;
2451fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
2452fcf3ce44SJohn Forte 	}
2453fcf3ce44SJohn Forte 
2454fcf3ce44SJohn Forte 	return (iscsiAuthStatusNoError);
2455fcf3ce44SJohn Forte }
2456fcf3ce44SJohn Forte 
2457fcf3ce44SJohn Forte 
2458fcf3ce44SJohn Forte int
iscsiAuthClientSetVersion(IscsiAuthClient * client,int version)2459fcf3ce44SJohn Forte iscsiAuthClientSetVersion(IscsiAuthClient * client, int version)
2460fcf3ce44SJohn Forte {
2461fcf3ce44SJohn Forte 	if (client == 0 ||
2462fcf3ce44SJohn Forte 	    client->signature != iscsiAuthClientSignature) {
2463fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
2464fcf3ce44SJohn Forte 	}
2465fcf3ce44SJohn Forte 
2466fcf3ce44SJohn Forte 	if (client->phase != iscsiAuthPhaseConfigure ||
2467fcf3ce44SJohn Forte 	    iscsiAuthClientCheckVersion(version)) {
2468fcf3ce44SJohn Forte 
2469fcf3ce44SJohn Forte 		client->phase = iscsiAuthPhaseError;
2470fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
2471fcf3ce44SJohn Forte 	}
2472fcf3ce44SJohn Forte 
2473fcf3ce44SJohn Forte 	client->version = (IscsiAuthVersion) version;
2474fcf3ce44SJohn Forte 
2475fcf3ce44SJohn Forte 	iscsiAuthClientSetAuthMethodValid(client);
2476fcf3ce44SJohn Forte 
2477fcf3ce44SJohn Forte 	return (iscsiAuthStatusNoError);
2478fcf3ce44SJohn Forte }
2479fcf3ce44SJohn Forte 
2480fcf3ce44SJohn Forte 
2481fcf3ce44SJohn Forte int
iscsiAuthClientSetIpSec(IscsiAuthClient * client,int ipSec)2482fcf3ce44SJohn Forte iscsiAuthClientSetIpSec(IscsiAuthClient * client, int ipSec)
2483fcf3ce44SJohn Forte {
2484fcf3ce44SJohn Forte 	if (!client || client->signature != iscsiAuthClientSignature) {
2485fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
2486fcf3ce44SJohn Forte 	}
2487fcf3ce44SJohn Forte 
2488fcf3ce44SJohn Forte 	if (client->phase != iscsiAuthPhaseConfigure) {
2489fcf3ce44SJohn Forte 		client->phase = iscsiAuthPhaseError;
2490fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
2491fcf3ce44SJohn Forte 	}
2492fcf3ce44SJohn Forte 
2493fcf3ce44SJohn Forte 	client->ipSec = ipSec;
2494fcf3ce44SJohn Forte 
2495fcf3ce44SJohn Forte 	return (iscsiAuthStatusNoError);
2496fcf3ce44SJohn Forte }
2497fcf3ce44SJohn Forte 
2498fcf3ce44SJohn Forte 
2499fcf3ce44SJohn Forte int
iscsiAuthClientSetBase64(IscsiAuthClient * client,int base64)2500fcf3ce44SJohn Forte iscsiAuthClientSetBase64(IscsiAuthClient * client, int base64)
2501fcf3ce44SJohn Forte {
2502fcf3ce44SJohn Forte 	if (!client || client->signature != iscsiAuthClientSignature) {
2503fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
2504fcf3ce44SJohn Forte 	}
2505fcf3ce44SJohn Forte 
2506fcf3ce44SJohn Forte 	if (client->phase != iscsiAuthPhaseConfigure) {
2507fcf3ce44SJohn Forte 		client->phase = iscsiAuthPhaseError;
2508fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
2509fcf3ce44SJohn Forte 	}
2510fcf3ce44SJohn Forte 
2511fcf3ce44SJohn Forte 	client->base64 = base64;
2512fcf3ce44SJohn Forte 
2513fcf3ce44SJohn Forte 	return (iscsiAuthStatusNoError);
2514fcf3ce44SJohn Forte }
2515fcf3ce44SJohn Forte 
2516fcf3ce44SJohn Forte 
2517fcf3ce44SJohn Forte int
iscsiAuthClientSetChapChallengeLength(IscsiAuthClient * client,unsigned int chapChallengeLength)2518fcf3ce44SJohn Forte iscsiAuthClientSetChapChallengeLength(IscsiAuthClient * client,
2519fcf3ce44SJohn Forte     unsigned int chapChallengeLength)
2520fcf3ce44SJohn Forte {
2521fcf3ce44SJohn Forte 	if (!client || client->signature != iscsiAuthClientSignature) {
2522fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
2523fcf3ce44SJohn Forte 	}
2524fcf3ce44SJohn Forte 
2525fcf3ce44SJohn Forte 	if (client->phase != iscsiAuthPhaseConfigure ||
2526fcf3ce44SJohn Forte 	    chapChallengeLength < iscsiAuthChapResponseLength ||
2527fcf3ce44SJohn Forte 	    chapChallengeLength > iscsiAuthLargeBinaryMaxLength) {
2528fcf3ce44SJohn Forte 
2529fcf3ce44SJohn Forte 		client->phase = iscsiAuthPhaseError;
2530fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
2531fcf3ce44SJohn Forte 	}
2532fcf3ce44SJohn Forte 
2533fcf3ce44SJohn Forte 	client->chapChallengeLength = chapChallengeLength;
2534fcf3ce44SJohn Forte 
2535fcf3ce44SJohn Forte 	return (iscsiAuthStatusNoError);
2536fcf3ce44SJohn Forte }
2537fcf3ce44SJohn Forte 
2538fcf3ce44SJohn Forte 
2539fcf3ce44SJohn Forte int
iscsiAuthClientCheckPasswordNeeded(IscsiAuthClient * client,int * passwordNeeded)2540fcf3ce44SJohn Forte iscsiAuthClientCheckPasswordNeeded(IscsiAuthClient *client, int *passwordNeeded)
2541fcf3ce44SJohn Forte {
2542fcf3ce44SJohn Forte 	if (!client || client->signature != iscsiAuthClientSignature) {
2543fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
2544fcf3ce44SJohn Forte 	}
2545fcf3ce44SJohn Forte 
2546fcf3ce44SJohn Forte 	if (client->phase != iscsiAuthPhaseConfigure) {
2547fcf3ce44SJohn Forte 		client->phase = iscsiAuthPhaseError;
2548fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
2549fcf3ce44SJohn Forte 	}
2550fcf3ce44SJohn Forte 
2551fcf3ce44SJohn Forte 	if (client->nodeType == iscsiAuthNodeTypeInitiator) {
2552fcf3ce44SJohn Forte 		if (client->authRemote && !client->passwordPresent) {
2553fcf3ce44SJohn Forte 			*passwordNeeded = TRUE;
2554fcf3ce44SJohn Forte 		} else {
2555fcf3ce44SJohn Forte 			*passwordNeeded = FALSE;
2556fcf3ce44SJohn Forte 		}
2557fcf3ce44SJohn Forte 	} else {
2558fcf3ce44SJohn Forte 		*passwordNeeded = FALSE;
2559fcf3ce44SJohn Forte 	}
2560fcf3ce44SJohn Forte 
2561fcf3ce44SJohn Forte 	return (iscsiAuthStatusNoError);
2562fcf3ce44SJohn Forte }
2563fcf3ce44SJohn Forte 
2564fcf3ce44SJohn Forte 
2565fcf3ce44SJohn Forte int
iscsiAuthClientGetAuthPhase(IscsiAuthClient * client,int * value)2566fcf3ce44SJohn Forte iscsiAuthClientGetAuthPhase(IscsiAuthClient * client, int *value)
2567fcf3ce44SJohn Forte {
2568fcf3ce44SJohn Forte 	if (!client || client->signature != iscsiAuthClientSignature) {
2569fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
2570fcf3ce44SJohn Forte 	}
2571fcf3ce44SJohn Forte 
2572fcf3ce44SJohn Forte 	*value = client->phase;
2573fcf3ce44SJohn Forte 
2574fcf3ce44SJohn Forte 	return (iscsiAuthStatusNoError);
2575fcf3ce44SJohn Forte }
2576fcf3ce44SJohn Forte 
2577fcf3ce44SJohn Forte 
2578fcf3ce44SJohn Forte int
iscsiAuthClientGetAuthStatus(IscsiAuthClient * client,int * value)2579fcf3ce44SJohn Forte iscsiAuthClientGetAuthStatus(IscsiAuthClient * client, int *value)
2580fcf3ce44SJohn Forte {
2581fcf3ce44SJohn Forte 	if (!client || client->signature != iscsiAuthClientSignature) {
2582fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
2583fcf3ce44SJohn Forte 	}
2584fcf3ce44SJohn Forte 
2585fcf3ce44SJohn Forte 	if (client->phase != iscsiAuthPhaseDone) {
2586fcf3ce44SJohn Forte 
2587fcf3ce44SJohn Forte 		client->phase = iscsiAuthPhaseError;
2588fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
2589fcf3ce44SJohn Forte 	}
2590fcf3ce44SJohn Forte 
2591fcf3ce44SJohn Forte 	*value = client->remoteAuthStatus;
2592fcf3ce44SJohn Forte 
2593fcf3ce44SJohn Forte 	return (iscsiAuthStatusNoError);
2594fcf3ce44SJohn Forte }
2595fcf3ce44SJohn Forte 
2596fcf3ce44SJohn Forte 
2597fcf3ce44SJohn Forte int
iscsiAuthClientAuthStatusPass(int authStatus)2598fcf3ce44SJohn Forte iscsiAuthClientAuthStatusPass(int authStatus)
2599fcf3ce44SJohn Forte {
2600fcf3ce44SJohn Forte 	if (authStatus == iscsiAuthStatusPass) {
2601fcf3ce44SJohn Forte 		return (TRUE);
2602fcf3ce44SJohn Forte 	}
2603fcf3ce44SJohn Forte 
2604fcf3ce44SJohn Forte 	return (FALSE);
2605fcf3ce44SJohn Forte }
2606fcf3ce44SJohn Forte 
2607fcf3ce44SJohn Forte 
2608fcf3ce44SJohn Forte int
iscsiAuthClientGetAuthMethod(IscsiAuthClient * client,int * value)2609fcf3ce44SJohn Forte iscsiAuthClientGetAuthMethod(IscsiAuthClient * client, int *value)
2610fcf3ce44SJohn Forte {
2611fcf3ce44SJohn Forte 	if (!client || client->signature != iscsiAuthClientSignature) {
2612fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
2613fcf3ce44SJohn Forte 	}
2614fcf3ce44SJohn Forte 
2615fcf3ce44SJohn Forte 	if (client->phase != iscsiAuthPhaseDone &&
2616fcf3ce44SJohn Forte 	    client->phase != iscsiAuthPhaseAuthenticate) {
2617fcf3ce44SJohn Forte 		client->phase = iscsiAuthPhaseError;
2618fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
2619fcf3ce44SJohn Forte 	}
2620fcf3ce44SJohn Forte 
2621fcf3ce44SJohn Forte 	*value = client->negotiatedAuthMethod;
2622fcf3ce44SJohn Forte 
2623fcf3ce44SJohn Forte 	return (iscsiAuthStatusNoError);
2624fcf3ce44SJohn Forte }
2625fcf3ce44SJohn Forte 
2626fcf3ce44SJohn Forte 
2627fcf3ce44SJohn Forte int
iscsiAuthClientGetChapAlgorithm(IscsiAuthClient * client,int * value)2628fcf3ce44SJohn Forte iscsiAuthClientGetChapAlgorithm(IscsiAuthClient * client, int *value)
2629fcf3ce44SJohn Forte {
2630fcf3ce44SJohn Forte 	if (!client || client->signature != iscsiAuthClientSignature) {
2631fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
2632fcf3ce44SJohn Forte 	}
2633fcf3ce44SJohn Forte 
2634fcf3ce44SJohn Forte 	if (client->phase != iscsiAuthPhaseDone) {
2635fcf3ce44SJohn Forte 
2636fcf3ce44SJohn Forte 		client->phase = iscsiAuthPhaseError;
2637fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
2638fcf3ce44SJohn Forte 	}
2639fcf3ce44SJohn Forte 
2640fcf3ce44SJohn Forte 	*value = client->negotiatedChapAlgorithm;
2641fcf3ce44SJohn Forte 
2642fcf3ce44SJohn Forte 	return (iscsiAuthStatusNoError);
2643fcf3ce44SJohn Forte }
2644fcf3ce44SJohn Forte 
2645fcf3ce44SJohn Forte 
2646fcf3ce44SJohn Forte int
iscsiAuthClientGetChapUsername(IscsiAuthClient * client,char * value,unsigned int maxLength)2647fcf3ce44SJohn Forte iscsiAuthClientGetChapUsername(IscsiAuthClient * client,
2648fcf3ce44SJohn Forte     char *value, unsigned int maxLength)
2649fcf3ce44SJohn Forte {
2650fcf3ce44SJohn Forte 	if (!client || client->signature != iscsiAuthClientSignature) {
2651fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
2652fcf3ce44SJohn Forte 	}
2653fcf3ce44SJohn Forte 
2654fcf3ce44SJohn Forte 	if (client->phase != iscsiAuthPhaseDone) {
2655fcf3ce44SJohn Forte 
2656fcf3ce44SJohn Forte 		client->phase = iscsiAuthPhaseError;
2657fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
2658fcf3ce44SJohn Forte 	}
2659fcf3ce44SJohn Forte 
2660fcf3ce44SJohn Forte 	if (iscsiAuthClientStringCopy(value, client->chapUsername, maxLength)) {
2661fcf3ce44SJohn Forte 		client->phase = iscsiAuthPhaseError;
2662fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
2663fcf3ce44SJohn Forte 	}
2664fcf3ce44SJohn Forte 
2665fcf3ce44SJohn Forte 	return (iscsiAuthStatusNoError);
2666fcf3ce44SJohn Forte }
2667fcf3ce44SJohn Forte 
2668fcf3ce44SJohn Forte 
2669fcf3ce44SJohn Forte int
iscsiAuthClientSendStatusCode(IscsiAuthClient * client,int * statusCode)2670fcf3ce44SJohn Forte iscsiAuthClientSendStatusCode(IscsiAuthClient * client, int *statusCode)
2671fcf3ce44SJohn Forte {
2672fcf3ce44SJohn Forte 	if (!client || client->signature != iscsiAuthClientSignature) {
2673fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
2674fcf3ce44SJohn Forte 	}
2675fcf3ce44SJohn Forte 
2676fcf3ce44SJohn Forte 	if (client->phase != iscsiAuthPhaseConfigure &&
2677fcf3ce44SJohn Forte 	    client->phase != iscsiAuthPhaseNegotiate &&
2678fcf3ce44SJohn Forte 	    client->phase != iscsiAuthPhaseAuthenticate &&
2679fcf3ce44SJohn Forte 	    client->phase != iscsiAuthPhaseDone) {
2680fcf3ce44SJohn Forte 
2681fcf3ce44SJohn Forte 		client->phase = iscsiAuthPhaseError;
2682fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
2683fcf3ce44SJohn Forte 	}
2684fcf3ce44SJohn Forte 
2685fcf3ce44SJohn Forte 	if (client->phase != iscsiAuthPhaseDone) {
2686fcf3ce44SJohn Forte 		*statusCode = 0x0000;
2687fcf3ce44SJohn Forte 		return (iscsiAuthStatusNoError);
2688fcf3ce44SJohn Forte 	}
2689fcf3ce44SJohn Forte 
2690fcf3ce44SJohn Forte 	switch (client->remoteAuthStatus) {
2691fcf3ce44SJohn Forte 	case iscsiAuthStatusPass:
2692fcf3ce44SJohn Forte 		*statusCode = 0x0000;	/* no error */
2693fcf3ce44SJohn Forte 		break;
2694fcf3ce44SJohn Forte 
2695fcf3ce44SJohn Forte 	case iscsiAuthStatusFail:
2696fcf3ce44SJohn Forte 		switch (client->debugStatus) {
2697fcf3ce44SJohn Forte 		case iscsiAuthDebugStatusAuthFail:
2698fcf3ce44SJohn Forte 			/*
2699fcf3ce44SJohn Forte 			 * Authentication error with peer.
2700fcf3ce44SJohn Forte 			 */
2701fcf3ce44SJohn Forte 			if (client->nodeType == iscsiAuthNodeTypeInitiator) {
2702fcf3ce44SJohn Forte 				*statusCode = 0x0300;
2703fcf3ce44SJohn Forte 				/*
2704fcf3ce44SJohn Forte 				 * iSCSI Target error
2705fcf3ce44SJohn Forte 				 */
2706fcf3ce44SJohn Forte 			} else {
2707fcf3ce44SJohn Forte 				*statusCode = 0x0201;
2708fcf3ce44SJohn Forte 				/*
2709fcf3ce44SJohn Forte 				 * iSCSI Initiator error
2710fcf3ce44SJohn Forte 				 */
2711fcf3ce44SJohn Forte 			}
2712fcf3ce44SJohn Forte 			break;
2713fcf3ce44SJohn Forte 
2714fcf3ce44SJohn Forte 		case iscsiAuthDebugStatusAuthMethodExpected:
2715fcf3ce44SJohn Forte 		case iscsiAuthDebugStatusChapAlgorithmExpected:
2716fcf3ce44SJohn Forte 		case iscsiAuthDebugStatusChapIdentifierExpected:
2717fcf3ce44SJohn Forte 		case iscsiAuthDebugStatusChapChallengeExpected:
2718fcf3ce44SJohn Forte 		case iscsiAuthDebugStatusChapResponseExpected:
2719fcf3ce44SJohn Forte 		case iscsiAuthDebugStatusChapUsernameExpected:
2720fcf3ce44SJohn Forte 			/*
2721fcf3ce44SJohn Forte 			 * Missing parameter with peer.
2722fcf3ce44SJohn Forte 			 */
2723fcf3ce44SJohn Forte 			if (client->nodeType == iscsiAuthNodeTypeInitiator) {
2724fcf3ce44SJohn Forte 				*statusCode = 0x0300;
2725fcf3ce44SJohn Forte 				/*
2726fcf3ce44SJohn Forte 				 * iSCSI Target error
2727fcf3ce44SJohn Forte 				 */
2728fcf3ce44SJohn Forte 			} else {
2729fcf3ce44SJohn Forte 				*statusCode = 0x0207;
2730fcf3ce44SJohn Forte 				/*
2731fcf3ce44SJohn Forte 				 * iSCSI Initiator error
2732fcf3ce44SJohn Forte 				 */
2733fcf3ce44SJohn Forte 			}
2734fcf3ce44SJohn Forte 			break;
2735fcf3ce44SJohn Forte 
2736fcf3ce44SJohn Forte 		case iscsiAuthDebugStatusAuthMethodNotPresent:
2737fcf3ce44SJohn Forte 		case iscsiAuthDebugStatusAuthMethodReject:
2738fcf3ce44SJohn Forte 		case iscsiAuthDebugStatusAuthMethodNone:
2739fcf3ce44SJohn Forte 		case iscsiAuthDebugStatusChapAlgorithmReject:
2740fcf3ce44SJohn Forte 		case iscsiAuthDebugStatusChapChallengeReflected:
2741fcf3ce44SJohn Forte 		case iscsiAuthDebugStatusPasswordIdentical:
2742fcf3ce44SJohn Forte 			/*
2743fcf3ce44SJohn Forte 			 * Could not authenticate with peer.
2744fcf3ce44SJohn Forte 			 */
2745fcf3ce44SJohn Forte 			if (client->nodeType == iscsiAuthNodeTypeInitiator) {
2746fcf3ce44SJohn Forte 				*statusCode = 0x0300;
2747fcf3ce44SJohn Forte 				/*
2748fcf3ce44SJohn Forte 				 * iSCSI Target error
2749fcf3ce44SJohn Forte 				 */
2750fcf3ce44SJohn Forte 			} else {
2751fcf3ce44SJohn Forte 				*statusCode = 0x0201;
2752fcf3ce44SJohn Forte 				/*
2753fcf3ce44SJohn Forte 				 * iSCSI Initiator error
2754fcf3ce44SJohn Forte 				 */
2755fcf3ce44SJohn Forte 			}
2756fcf3ce44SJohn Forte 			break;
2757fcf3ce44SJohn Forte 
2758fcf3ce44SJohn Forte 		case iscsiAuthDebugStatusLocalPasswordNotSet:
2759fcf3ce44SJohn Forte 			/*
2760fcf3ce44SJohn Forte 			 * Local password not set.
2761fcf3ce44SJohn Forte 			 */
2762fcf3ce44SJohn Forte 			if (client->nodeType == iscsiAuthNodeTypeInitiator) {
2763fcf3ce44SJohn Forte 				*statusCode = 0x0200;
2764fcf3ce44SJohn Forte 				/*
2765fcf3ce44SJohn Forte 				 * iSCSI Initiator error
2766fcf3ce44SJohn Forte 				 */
2767fcf3ce44SJohn Forte 			} else {
2768fcf3ce44SJohn Forte 				*statusCode = 0x0201;
2769fcf3ce44SJohn Forte 				/*
2770fcf3ce44SJohn Forte 				 * iSCSI Target error
2771fcf3ce44SJohn Forte 				 */
2772fcf3ce44SJohn Forte 			}
2773fcf3ce44SJohn Forte 			break;
2774fcf3ce44SJohn Forte 
2775fcf3ce44SJohn Forte 		case iscsiAuthDebugStatusChapIdentifierBad:
2776fcf3ce44SJohn Forte 		case iscsiAuthDebugStatusChapChallengeBad:
2777fcf3ce44SJohn Forte 		case iscsiAuthDebugStatusChapResponseBad:
2778fcf3ce44SJohn Forte 		case iscsiAuthDebugStatusUnexpectedKeyPresent:
2779fcf3ce44SJohn Forte 		case iscsiAuthDebugStatusTbitSetIllegal:
2780fcf3ce44SJohn Forte 		case iscsiAuthDebugStatusTbitSetPremature:
2781fcf3ce44SJohn Forte 		case iscsiAuthDebugStatusRecvMessageCountLimit:
2782fcf3ce44SJohn Forte 		case iscsiAuthDebugStatusRecvDuplicateSetKeyValue:
2783fcf3ce44SJohn Forte 		case iscsiAuthDebugStatusRecvStringTooLong:
2784fcf3ce44SJohn Forte 		case iscsiAuthDebugStatusRecvTooMuchData:
2785fcf3ce44SJohn Forte 			/*
2786fcf3ce44SJohn Forte 			 * Other error with peer.
2787fcf3ce44SJohn Forte 			 */
2788fcf3ce44SJohn Forte 			if (client->nodeType == iscsiAuthNodeTypeInitiator) {
2789fcf3ce44SJohn Forte 				*statusCode = 0x0300;
2790fcf3ce44SJohn Forte 				/*
2791fcf3ce44SJohn Forte 				 * iSCSI Target error
2792fcf3ce44SJohn Forte 				 */
2793fcf3ce44SJohn Forte 			} else {
2794fcf3ce44SJohn Forte 				*statusCode = 0x0200;
2795fcf3ce44SJohn Forte 				/*
2796fcf3ce44SJohn Forte 				 * iSCSI Initiator error
2797fcf3ce44SJohn Forte 				 */
2798fcf3ce44SJohn Forte 			}
2799fcf3ce44SJohn Forte 			break;
2800fcf3ce44SJohn Forte 
2801fcf3ce44SJohn Forte 		case iscsiAuthDebugStatusNotSet:
2802fcf3ce44SJohn Forte 		case iscsiAuthDebugStatusAuthPass:
2803fcf3ce44SJohn Forte 		case iscsiAuthDebugStatusAuthRemoteFalse:
2804fcf3ce44SJohn Forte 		case iscsiAuthDebugStatusAuthMethodBad:
2805fcf3ce44SJohn Forte 		case iscsiAuthDebugStatusChapAlgorithmBad:
2806fcf3ce44SJohn Forte 		case iscsiAuthDebugStatusPasswordDecryptFailed:
2807fcf3ce44SJohn Forte 		case iscsiAuthDebugStatusPasswordTooShortWithNoIpSec:
2808fcf3ce44SJohn Forte 		case iscsiAuthDebugStatusAuthServerError:
2809fcf3ce44SJohn Forte 		case iscsiAuthDebugStatusAuthStatusBad:
2810fcf3ce44SJohn Forte 		case iscsiAuthDebugStatusAuthPassNotValid:
2811fcf3ce44SJohn Forte 		case iscsiAuthDebugStatusSendDuplicateSetKeyValue:
2812fcf3ce44SJohn Forte 		case iscsiAuthDebugStatusSendStringTooLong:
2813fcf3ce44SJohn Forte 		case iscsiAuthDebugStatusSendTooMuchData:
2814fcf3ce44SJohn Forte 		default:
2815fcf3ce44SJohn Forte 			/*
2816fcf3ce44SJohn Forte 			 * Error on this side.
2817fcf3ce44SJohn Forte 			 */
2818fcf3ce44SJohn Forte 			if (client->nodeType == iscsiAuthNodeTypeInitiator) {
2819fcf3ce44SJohn Forte 				*statusCode = 0x0200;
2820fcf3ce44SJohn Forte 				/*
2821fcf3ce44SJohn Forte 				 * iSCSI Initiator error
2822fcf3ce44SJohn Forte 				 */
2823fcf3ce44SJohn Forte 			} else {
2824fcf3ce44SJohn Forte 				*statusCode = 0x0300;
2825fcf3ce44SJohn Forte 				/*
2826fcf3ce44SJohn Forte 				 * iSCSI Target error
2827fcf3ce44SJohn Forte 				 */
2828fcf3ce44SJohn Forte 			}
2829fcf3ce44SJohn Forte 
2830fcf3ce44SJohn Forte 		}
2831fcf3ce44SJohn Forte 		break;
2832fcf3ce44SJohn Forte 
2833fcf3ce44SJohn Forte 	case iscsiAuthStatusNoError:
2834fcf3ce44SJohn Forte 	case iscsiAuthStatusError:
2835fcf3ce44SJohn Forte 	case iscsiAuthStatusContinue:
2836fcf3ce44SJohn Forte 	case iscsiAuthStatusInProgress:
2837fcf3ce44SJohn Forte 	default:
2838fcf3ce44SJohn Forte 		/*
2839fcf3ce44SJohn Forte 		 * Bad authStatus
2840fcf3ce44SJohn Forte 		 */
2841fcf3ce44SJohn Forte 		if (client->nodeType == iscsiAuthNodeTypeInitiator) {
2842fcf3ce44SJohn Forte 			*statusCode = 0x0200;
2843fcf3ce44SJohn Forte 			/*
2844fcf3ce44SJohn Forte 			 * iSCSI Initiator error
2845fcf3ce44SJohn Forte 			 */
2846fcf3ce44SJohn Forte 		} else {
2847fcf3ce44SJohn Forte 			*statusCode = 0x0300;
2848fcf3ce44SJohn Forte 			/*
2849fcf3ce44SJohn Forte 			 * iSCSI Target error
2850fcf3ce44SJohn Forte 			 */
2851fcf3ce44SJohn Forte 		}
2852fcf3ce44SJohn Forte 	}
2853fcf3ce44SJohn Forte 
2854fcf3ce44SJohn Forte 	return (iscsiAuthStatusNoError);
2855fcf3ce44SJohn Forte }
2856fcf3ce44SJohn Forte 
2857fcf3ce44SJohn Forte 
2858fcf3ce44SJohn Forte int
iscsiAuthClientGetDebugStatus(IscsiAuthClient * client,int * value)2859fcf3ce44SJohn Forte iscsiAuthClientGetDebugStatus(IscsiAuthClient * client, int *value)
2860fcf3ce44SJohn Forte {
2861fcf3ce44SJohn Forte 	if (!client || client->signature != iscsiAuthClientSignature) {
2862fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
2863fcf3ce44SJohn Forte 	}
2864fcf3ce44SJohn Forte 
2865fcf3ce44SJohn Forte 	if (client->phase != iscsiAuthPhaseDone) {
2866fcf3ce44SJohn Forte 
2867fcf3ce44SJohn Forte 		client->phase = iscsiAuthPhaseError;
2868fcf3ce44SJohn Forte 		return (iscsiAuthStatusError);
2869fcf3ce44SJohn Forte 	}
2870fcf3ce44SJohn Forte 
2871fcf3ce44SJohn Forte 	*value = client->debugStatus;
2872fcf3ce44SJohn Forte 
2873fcf3ce44SJohn Forte 	return (iscsiAuthStatusNoError);
2874fcf3ce44SJohn Forte }
2875fcf3ce44SJohn Forte 
2876fcf3ce44SJohn Forte 
2877fcf3ce44SJohn Forte const char *
iscsiAuthClientDebugStatusToText(int debugStatus)2878fcf3ce44SJohn Forte iscsiAuthClientDebugStatusToText(int debugStatus)
2879fcf3ce44SJohn Forte {
2880fcf3ce44SJohn Forte 	const char *s;
2881fcf3ce44SJohn Forte 
2882fcf3ce44SJohn Forte 	switch (debugStatus) {
2883fcf3ce44SJohn Forte 	case iscsiAuthDebugStatusNotSet:
2884fcf3ce44SJohn Forte 		s = "Debug status not set";
2885fcf3ce44SJohn Forte 		break;
2886fcf3ce44SJohn Forte 
2887fcf3ce44SJohn Forte 	case iscsiAuthDebugStatusAuthPass:
2888fcf3ce44SJohn Forte 		s = "Authentication request passed";
2889fcf3ce44SJohn Forte 		break;
2890fcf3ce44SJohn Forte 
2891fcf3ce44SJohn Forte 	case iscsiAuthDebugStatusAuthRemoteFalse:
2892fcf3ce44SJohn Forte 		s = "Authentication not enabled";
2893fcf3ce44SJohn Forte 		break;
2894fcf3ce44SJohn Forte 
2895fcf3ce44SJohn Forte 	case iscsiAuthDebugStatusAuthFail:
2896fcf3ce44SJohn Forte 		s = "Authentication request failed";
2897fcf3ce44SJohn Forte 		break;
2898fcf3ce44SJohn Forte 
2899fcf3ce44SJohn Forte 	case iscsiAuthDebugStatusAuthMethodBad:
2900fcf3ce44SJohn Forte 		s = "AuthMethod bad";
2901fcf3ce44SJohn Forte 		break;
2902fcf3ce44SJohn Forte 
2903fcf3ce44SJohn Forte 	case iscsiAuthDebugStatusChapAlgorithmBad:
2904fcf3ce44SJohn Forte 		s = "CHAP algorithm bad";
2905fcf3ce44SJohn Forte 		break;
2906fcf3ce44SJohn Forte 
2907fcf3ce44SJohn Forte 	case iscsiAuthDebugStatusPasswordDecryptFailed:
2908fcf3ce44SJohn Forte 		s = "Decrypt password failed";
2909fcf3ce44SJohn Forte 		break;
2910fcf3ce44SJohn Forte 
2911fcf3ce44SJohn Forte 	case iscsiAuthDebugStatusPasswordTooShortWithNoIpSec:
2912fcf3ce44SJohn Forte 		s = "Local password too short with no IPSec";
2913fcf3ce44SJohn Forte 		break;
2914fcf3ce44SJohn Forte 
2915fcf3ce44SJohn Forte 	case iscsiAuthDebugStatusAuthServerError:
2916fcf3ce44SJohn Forte 		s = "Unexpected error from authentication server";
2917fcf3ce44SJohn Forte 		break;
2918fcf3ce44SJohn Forte 
2919fcf3ce44SJohn Forte 	case iscsiAuthDebugStatusAuthStatusBad:
2920fcf3ce44SJohn Forte 		s = "Authentication request status bad";
2921fcf3ce44SJohn Forte 		break;
2922fcf3ce44SJohn Forte 
2923fcf3ce44SJohn Forte 	case iscsiAuthDebugStatusAuthPassNotValid:
2924fcf3ce44SJohn Forte 		s = "Authentication pass status not valid";
2925fcf3ce44SJohn Forte 		break;
2926fcf3ce44SJohn Forte 
2927fcf3ce44SJohn Forte 	case iscsiAuthDebugStatusSendDuplicateSetKeyValue:
2928fcf3ce44SJohn Forte 		s = "Same key set more than once on send";
2929fcf3ce44SJohn Forte 		break;
2930fcf3ce44SJohn Forte 
2931fcf3ce44SJohn Forte 	case iscsiAuthDebugStatusSendStringTooLong:
2932fcf3ce44SJohn Forte 		s = "Key value too long on send";
2933fcf3ce44SJohn Forte 		break;
2934fcf3ce44SJohn Forte 
2935fcf3ce44SJohn Forte 	case iscsiAuthDebugStatusSendTooMuchData:
2936fcf3ce44SJohn Forte 		s = "Too much data on send";
2937fcf3ce44SJohn Forte 		break;
2938fcf3ce44SJohn Forte 
2939fcf3ce44SJohn Forte 	case iscsiAuthDebugStatusAuthMethodExpected:
2940fcf3ce44SJohn Forte 		s = "AuthMethod key expected";
2941fcf3ce44SJohn Forte 		break;
2942fcf3ce44SJohn Forte 
2943fcf3ce44SJohn Forte 	case iscsiAuthDebugStatusChapAlgorithmExpected:
2944fcf3ce44SJohn Forte 		s = "CHAP algorithm key expected";
2945fcf3ce44SJohn Forte 		break;
2946fcf3ce44SJohn Forte 
2947fcf3ce44SJohn Forte 	case iscsiAuthDebugStatusChapIdentifierExpected:
2948fcf3ce44SJohn Forte 		s = "CHAP identifier expected";
2949fcf3ce44SJohn Forte 		break;
2950fcf3ce44SJohn Forte 
2951fcf3ce44SJohn Forte 	case iscsiAuthDebugStatusChapChallengeExpected:
2952fcf3ce44SJohn Forte 		s = "CHAP challenge expected";
2953fcf3ce44SJohn Forte 		break;
2954fcf3ce44SJohn Forte 
2955fcf3ce44SJohn Forte 	case iscsiAuthDebugStatusChapResponseExpected:
2956fcf3ce44SJohn Forte 		s = "CHAP response expected";
2957fcf3ce44SJohn Forte 		break;
2958fcf3ce44SJohn Forte 
2959fcf3ce44SJohn Forte 	case iscsiAuthDebugStatusChapUsernameExpected:
2960fcf3ce44SJohn Forte 		s = "CHAP username expected";
2961fcf3ce44SJohn Forte 		break;
2962fcf3ce44SJohn Forte 
2963fcf3ce44SJohn Forte 	case iscsiAuthDebugStatusAuthMethodNotPresent:
2964fcf3ce44SJohn Forte 		s = "AuthMethod key not present";
2965fcf3ce44SJohn Forte 		break;
2966fcf3ce44SJohn Forte 
2967fcf3ce44SJohn Forte 	case iscsiAuthDebugStatusAuthMethodReject:
2968fcf3ce44SJohn Forte 		s = "AuthMethod negotiation failed";
2969fcf3ce44SJohn Forte 		break;
2970fcf3ce44SJohn Forte 
2971fcf3ce44SJohn Forte 	case iscsiAuthDebugStatusAuthMethodNone:
2972fcf3ce44SJohn Forte 		s = "AuthMethod negotiated to none";
2973fcf3ce44SJohn Forte 		break;
2974fcf3ce44SJohn Forte 
2975fcf3ce44SJohn Forte 	case iscsiAuthDebugStatusChapAlgorithmReject:
2976fcf3ce44SJohn Forte 		s = "CHAP algorithm negotiation failed";
2977fcf3ce44SJohn Forte 		break;
2978fcf3ce44SJohn Forte 
2979fcf3ce44SJohn Forte 	case iscsiAuthDebugStatusChapChallengeReflected:
2980fcf3ce44SJohn Forte 		s = "CHAP challange reflected";
2981fcf3ce44SJohn Forte 		break;
2982fcf3ce44SJohn Forte 
2983fcf3ce44SJohn Forte 	case iscsiAuthDebugStatusPasswordIdentical:
2984fcf3ce44SJohn Forte 		s = "Local password same as remote";
2985fcf3ce44SJohn Forte 		break;
2986fcf3ce44SJohn Forte 
2987fcf3ce44SJohn Forte 	case iscsiAuthDebugStatusLocalPasswordNotSet:
2988fcf3ce44SJohn Forte 		s = "Local password not set";
2989fcf3ce44SJohn Forte 		break;
2990fcf3ce44SJohn Forte 
2991fcf3ce44SJohn Forte 	case iscsiAuthDebugStatusChapIdentifierBad:
2992fcf3ce44SJohn Forte 		s = "CHAP identifier bad";
2993fcf3ce44SJohn Forte 		break;
2994fcf3ce44SJohn Forte 
2995fcf3ce44SJohn Forte 	case iscsiAuthDebugStatusChapChallengeBad:
2996fcf3ce44SJohn Forte 		s = "CHAP challenge bad";
2997fcf3ce44SJohn Forte 		break;
2998fcf3ce44SJohn Forte 
2999fcf3ce44SJohn Forte 	case iscsiAuthDebugStatusChapResponseBad:
3000fcf3ce44SJohn Forte 		s = "CHAP response bad";
3001fcf3ce44SJohn Forte 		break;
3002fcf3ce44SJohn Forte 
3003fcf3ce44SJohn Forte 	case iscsiAuthDebugStatusUnexpectedKeyPresent:
3004fcf3ce44SJohn Forte 		s = "Unexpected key present";
3005fcf3ce44SJohn Forte 		break;
3006fcf3ce44SJohn Forte 
3007fcf3ce44SJohn Forte 	case iscsiAuthDebugStatusTbitSetIllegal:
3008fcf3ce44SJohn Forte 		s = "T bit set on response, but not on previous message";
3009fcf3ce44SJohn Forte 		break;
3010fcf3ce44SJohn Forte 
3011fcf3ce44SJohn Forte 	case iscsiAuthDebugStatusTbitSetPremature:
3012fcf3ce44SJohn Forte 		s = "T bit set on response, but authenticaton not complete";
3013fcf3ce44SJohn Forte 		break;
3014fcf3ce44SJohn Forte 
3015fcf3ce44SJohn Forte 	case iscsiAuthDebugStatusRecvMessageCountLimit:
3016fcf3ce44SJohn Forte 		s = "Message count limit reached on receive";
3017fcf3ce44SJohn Forte 		break;
3018fcf3ce44SJohn Forte 
3019fcf3ce44SJohn Forte 	case iscsiAuthDebugStatusRecvDuplicateSetKeyValue:
3020fcf3ce44SJohn Forte 		s = "Same key set more than once on receive";
3021fcf3ce44SJohn Forte 		break;
3022fcf3ce44SJohn Forte 
3023fcf3ce44SJohn Forte 	case iscsiAuthDebugStatusRecvStringTooLong:
3024fcf3ce44SJohn Forte 		s = "Key value too long on receive";
3025fcf3ce44SJohn Forte 		break;
3026fcf3ce44SJohn Forte 
3027fcf3ce44SJohn Forte 	case iscsiAuthDebugStatusRecvTooMuchData:
3028fcf3ce44SJohn Forte 		s = "Too much data on receive";
3029fcf3ce44SJohn Forte 		break;
3030fcf3ce44SJohn Forte 
3031fcf3ce44SJohn Forte 	default:
3032fcf3ce44SJohn Forte 		s = "Unknown error";
3033fcf3ce44SJohn Forte 	}
3034fcf3ce44SJohn Forte 
3035fcf3ce44SJohn Forte 	return (s);
3036fcf3ce44SJohn Forte }
3037