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