open-isns: Fix warnings reported by gcc-4.5.2
[open-iscsi.git] / usr / auth.c
blobc924545b0914e50ca6422c37c8a0f9e276fa3376
1 /*
2 * iSCSI Authorization Library
4 * maintained by open-iscsi@@googlegroups.com
6 * Originally based on:
7 * Copyright (C) 2001 Cisco Systems, Inc.
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published
11 * by the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
19 * This file implements the iSCSI CHAP authentication method based on
20 * RFC 3720. The code in this file is meant to be common for both kernel and
21 * user level and makes use of only limited library functions, presently only
22 * string.h. Routines specific to kernel, user level are implemented in
23 * seperate files under the appropriate directories.
24 * This code in this files assumes a single thread of execution
25 * for each iscsi_acl structure, and does no locking.
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <unistd.h>
32 #include <fcntl.h>
34 #include "sysdeps.h"
35 #include "auth.h"
36 #include "initiator.h"
37 #include "md5.h"
38 #include "log.h"
40 static const char acl_hexstring[] = "0123456789abcdefABCDEF";
41 static const char acl_base64_string[] =
42 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
43 static const char acl_authmethod_set_chap_alg_list[] = "CHAP";
44 static const char acl_reject_option_name[] = "Reject";
46 void auth_md5_init(struct MD5Context *);
47 void auth_md5_update(struct MD5Context *, unsigned char *, unsigned int);
48 void auth_md5_final(unsigned char *, struct MD5Context *);
49 void get_random_bytes(unsigned char *data, unsigned int length);
50 size_t strlcpy(char *, const char *, size_t);
51 size_t strlcat(char *, const char *, size_t);
53 enum auth_dbg_status
54 acl_chap_compute_rsp(struct iscsi_acl *client, int rmt_auth, unsigned int id,
55 unsigned char *challenge_data,
56 unsigned int challenge_length,
57 unsigned char *response_data)
59 unsigned char id_data[1];
60 struct MD5Context context;
61 unsigned char out_data[AUTH_STR_MAX_LEN];
62 unsigned int out_length = AUTH_STR_MAX_LEN;
64 if (!client->passwd_present)
65 return AUTH_DBG_STATUS_LOCAL_PASSWD_NOT_SET;
67 auth_md5_init(&context);
69 /* id byte */
70 id_data[0] = id;
71 auth_md5_update(&context, id_data, 1);
73 /* decrypt password */
74 if (acl_data(out_data, &out_length, client->passwd_data,
75 client->passwd_length))
76 return AUTH_DBG_STATUS_PASSWD_DECRYPT_FAILED;
78 if (!rmt_auth && !client->ip_sec && out_length < 12)
79 return AUTH_DBG_STATUS_PASSWD_TOO_SHORT_WITH_NO_IPSEC;
81 /* shared secret */
82 auth_md5_update(&context, out_data, out_length);
84 /* clear decrypted password */
85 memset(out_data, 0, AUTH_STR_MAX_LEN);
87 /* challenge value */
88 auth_md5_update(&context, challenge_data, challenge_length);
90 auth_md5_final(response_data, &context);
92 return AUTH_DBG_STATUS_NOT_SET; /* no error */
96 * Authenticate a target's CHAP response.
98 int
99 acl_chap_auth_request(struct iscsi_acl *client, char *username, unsigned int id,
100 unsigned char *challenge_data,
101 unsigned int challenge_length,
102 unsigned char *response_data,
103 unsigned int rsp_length)
105 iscsi_session_t *session = client->session_handle;
106 struct MD5Context context;
107 unsigned char verify_data[16];
109 /* the expected credentials are in the session */
110 if (session->username_in == NULL) {
111 log_error("failing authentication, no incoming username "
112 "configured to authenticate target %s\n",
113 session->target_name);
114 return AUTH_STATUS_FAIL;
116 if (strcmp(username, session->username_in) != 0) {
117 log_error("failing authentication, received incorrect "
118 "username from target %s\n", session->target_name);
119 return AUTH_STATUS_FAIL;
122 if ((session->password_in_length < 1) ||
123 (session->password_in == NULL) ||
124 (session->password_in[0] == '\0')) {
125 log_error("failing authentication, no incoming password "
126 "configured to authenticate target %s\n",
127 session->target_name);
128 return AUTH_STATUS_FAIL;
131 /* challenge length is I->T, and shouldn't need to be checked */
133 if (rsp_length != sizeof(verify_data)) {
134 log_error("failing authentication, received incorrect "
135 "CHAP response length %u from target %s\n",
136 rsp_length, session->target_name);
137 return AUTH_STATUS_FAIL;
140 auth_md5_init(&context);
142 /* id byte */
143 verify_data[0] = id;
144 auth_md5_update(&context, verify_data, 1);
146 /* shared secret */
147 auth_md5_update(&context, (unsigned char *)session->password_in,
148 session->password_in_length);
150 /* challenge value */
151 auth_md5_update(&context, (unsigned char *)challenge_data,
152 challenge_length);
154 auth_md5_final(verify_data, &context);
156 if (memcmp(response_data, verify_data, sizeof(verify_data)) == 0) {
157 log_debug(1, "initiator authenticated target %s\n",
158 session->target_name);
159 return AUTH_STATUS_PASS;
162 log_error("failing authentication, received incorrect CHAP "
163 "response from target %s\n", session->target_name);
164 return AUTH_STATUS_FAIL;
167 void
168 auth_md5_init(struct MD5Context *context)
170 MD5Init(context);
173 void
174 auth_md5_update(struct MD5Context *context, unsigned char *data,
175 unsigned int length)
177 MD5Update(context, data, length);
180 void
181 auth_md5_final(unsigned char *hash, struct MD5Context *context)
183 MD5Final(hash, context);
186 void
187 get_random_bytes(unsigned char *data, unsigned int length)
190 long r;
191 unsigned n;
192 int fd;
194 fd = open("/dev/urandom", O_RDONLY);
195 while (length > 0) {
197 if (!fd || read(fd, &r, sizeof(long)) != -1)
198 r = rand();
199 r = r ^ (r >> 8);
200 r = r ^ (r >> 4);
201 n = r & 0x7;
203 if (!fd || read(fd, &r, sizeof(long)) != -1)
204 r = rand();
205 r = r ^ (r >> 8);
206 r = r ^ (r >> 5);
207 n = (n << 3) | (r & 0x7);
209 if (!fd || read(fd, &r, sizeof(long)) != -1)
210 r = rand();
211 r = r ^ (r >> 8);
212 r = r ^ (r >> 5);
213 n = (n << 2) | (r & 0x3);
215 *data++ = n;
216 length--;
218 if (fd)
219 close(fd);
222 static const char acl_none_option_name[] = "None";
224 static int
225 acl_text_to_number(const char *text, unsigned long *num)
227 char *end;
228 unsigned long number = *num;
230 if (text[0] == '0' && (text[1] == 'x' || text[1] == 'X'))
231 number = strtoul(text + 2, &end, 16);
232 else
233 number = strtoul(text, &end, 10);
235 if (*text != '\0' && *end == '\0') {
236 *num = number;
237 return 0; /* No error */
238 } else
239 return 1; /* Error */
242 static int
243 acl_chk_string(const char *s, unsigned int max_len, unsigned int *out_len)
245 unsigned int len;
247 if (!s)
248 return 1;
250 for (len = 0; len < max_len; len++)
251 if (*s++ == '\0') {
252 if (out_len)
253 *out_len = len;
254 return 0;
257 return 1;
260 static int
261 acl_str_index(const char *s, int c)
263 char *str = strchr(s, c);
265 if (str)
266 return (str - s);
267 else
268 return -1;
271 static int
272 acl_chk_auth_mthd_optn(int val)
274 if (val == AUTH_OPTION_NONE || val == AUTH_METHOD_CHAP)
275 return 0;
277 return 1;
280 static const char *
281 acl_authmethod_optn_to_text(int value)
283 const char *s;
284 switch (value) {
285 case AUTH_OPTION_REJECT:
286 s = acl_reject_option_name;
287 break;
288 case AUTH_OPTION_NONE:
289 s = acl_none_option_name;
290 break;
291 case AUTH_METHOD_CHAP:
292 s = acl_authmethod_set_chap_alg_list;
293 break;
294 default:
295 s = NULL;
297 return s;
300 static int
301 acl_chk_chap_alg_optn(int chap_algorithm)
303 if (chap_algorithm == AUTH_OPTION_NONE ||
304 chap_algorithm == AUTH_CHAP_ALG_MD5)
305 return 0;
307 return 1;
310 static int
311 acl_data_to_text(unsigned char *data, unsigned int data_length, char *text,
312 unsigned int text_length)
314 unsigned long n;
316 if (!text || text_length == 0)
317 return 1;
319 if (!data || data_length == 0) {
320 *text = '\0';
321 return 1;
324 if (text_length < 3) {
325 *text = '\0';
326 return 1;
329 *text++ = '0';
330 *text++ = 'x';
332 text_length -= 2;
334 while (data_length > 0) {
336 if (text_length < 3) {
337 *text = '\0';
338 return 1;
341 n = *data++;
342 data_length--;
344 *text++ = acl_hexstring[(n >> 4) & 0xf];
345 *text++ = acl_hexstring[n & 0xf];
347 text_length -= 2;
350 *text = '\0';
352 return 0;
355 static int
356 acl_hex_to_data(const char *text, unsigned int text_length, unsigned char *data,
357 unsigned int *data_lenp)
359 int i;
360 unsigned int n1;
361 unsigned int n2;
362 unsigned int data_length = *data_lenp;
364 if ((text_length % 2) == 1) {
366 i = acl_str_index(acl_hexstring, *text++);
367 if (i < 0)
368 return 1; /* error, bad character */
370 if (i > 15)
371 i -= 6;
372 n2 = i;
374 if (data_length < 1)
375 return 1; /* error, too much data */
377 *data++ = n2;
378 data_length--;
381 while (*text != '\0') {
382 i = acl_str_index(acl_hexstring, *text++);
383 if (i < 0)
384 return 1; /* error, bad character */
386 if (i > 15)
387 i -= 6;
388 n1 = i;
390 if (*text == '\0')
391 return 1; /* error, odd string length */
393 i = acl_str_index(acl_hexstring, *text++);
394 if (i < 0)
395 return 1; /* error, bad character */
397 if (i > 15)
398 i -= 6;
399 n2 = i;
401 if (data_length < 1)
402 return 1; /* error, too much data */
404 *data++ = (n1 << 4) | n2;
405 data_length--;
408 if (data_length >= *data_lenp)
409 return 1; /* error, no data */
411 *data_lenp = *data_lenp - data_length;
413 return 0; /* no error */
416 static int
417 acl_base64_to_data(const char *text, unsigned char *data,
418 unsigned int *data_lenp)
420 int i;
421 unsigned int n;
422 unsigned int count;
423 unsigned int data_length = *data_lenp;
425 n = 0;
426 count = 0;
428 while (*text != '\0' && *text != '=') {
430 i = acl_str_index(acl_base64_string, *text++);
431 if (i < 0)
432 return 1; /* error, bad character */
434 n = (n << 6 | (unsigned int)i);
435 count++;
437 if (count >= 4) {
438 if (data_length < 3)
439 return 1; /* error, too much data */
440 *data++ = n >> 16;
441 *data++ = n >> 8;
442 *data++ = n;
443 data_length -= 3;
444 n = 0;
445 count = 0;
449 while (*text != '\0')
450 if (*text++ != '=')
451 return 1; /* error, bad pad */
453 if (count == 0) {
454 /* do nothing */
455 } else if (count == 2) {
456 if (data_length < 1)
457 return 1; /* error, too much data */
458 n = n >> 4;
459 *data++ = n;
460 data_length--;
461 } else if (count == 3) {
462 if (data_length < 2)
463 return 1; /* error, too much data */
464 n = n >> 2;
465 *data++ = n >> 8;
466 *data++ = n;
467 data_length -= 2;
468 } else
469 return 1; /* bad encoding */
471 if (data_length >= *data_lenp)
472 return 1; /* error, no data */
474 *data_lenp = *data_lenp - data_length;
476 return 0; /* no error */
479 static int
480 acl_text_to_data(const char *text, unsigned char *data,
481 unsigned int *data_length)
483 int status;
484 unsigned int text_length;
486 status = acl_chk_string(text, 2 + 2 * AUTH_LARGE_BINARY_MAX_LEN + 1,
487 &text_length);
488 if (status)
489 return status;
491 if (text[0] == '0' && (text[1] == 'x' || text[1] == 'X')) {
492 /* skip prefix */
493 text += 2;
494 text_length -= 2;
495 status = acl_hex_to_data(text, text_length, data, data_length);
496 } else if (text[0] == '0' && (text[1] == 'b' || text[1] == 'B')) {
497 /* skip prefix */
498 text += 2;
499 text_length -= 2;
500 status = acl_base64_to_data(text, data, data_length);
501 } else
502 status = 1; /* prefix not recognized. */
504 return status;
507 static void
508 acl_init_key_blk(struct auth_key_block *key_blk)
510 char *str_block = key_blk->str_block;
512 memset(key_blk, 0, sizeof(*key_blk));
513 key_blk->str_block = str_block;
516 static void
517 acl_set_key_value(struct auth_key_block *key_blk, int key_type,
518 const char *key_val)
520 unsigned int length;
521 char *string;
523 if (key_blk->key[key_type].value_set) {
524 key_blk->dup_set = 1;
525 return;
528 key_blk->key[key_type].value_set = 1;
530 if (!key_val)
531 return;
533 if (acl_chk_string(key_val, AUTH_STR_MAX_LEN, &length)) {
534 key_blk->str_too_long = 1;
535 return;
538 length += 1;
540 if ((key_blk->blk_length + length) > AUTH_STR_BLOCK_MAX_LEN) {
541 key_blk->too_much_data = 1;
542 return;
545 string = &key_blk->str_block[key_blk->blk_length];
547 if (strlcpy(string, key_val, length) >= length) {
548 key_blk->too_much_data = 1;
549 return;
551 key_blk->blk_length += length;
553 key_blk->key[key_type].string = string;
554 key_blk->key[key_type].present = 1;
557 static const char *
558 acl_get_key_val(struct auth_key_block *key_blk, int key_type)
560 key_blk->key[key_type].processed = 1;
562 if (!key_blk->key[key_type].present)
563 return NULL;
565 return key_blk->key[key_type].string;
568 static void
569 acl_chk_key(struct iscsi_acl *client, int key_type, int *negotiated_option,
570 unsigned int option_count, int *option_list,
571 const char *(*value_to_text) (int))
573 const char *key_val;
574 int length;
575 unsigned int i;
577 key_val = acl_get_key_val(&client->recv_key_block, key_type);
578 if (!key_val) {
579 *negotiated_option = AUTH_OPTION_NOT_PRESENT;
580 return;
583 while (*key_val != '\0') {
585 length = 0;
587 while (*key_val != '\0' && *key_val != ',')
588 client->scratch_key_value[length++] = *key_val++;
590 if (*key_val == ',')
591 key_val++;
592 client->scratch_key_value[length++] = '\0';
594 for (i = 0; i < option_count; i++) {
595 const char *s = (*value_to_text)(option_list[i]);
597 if (!s)
598 continue;
600 if (strcmp(client->scratch_key_value, s) == 0) {
601 *negotiated_option = option_list[i];
602 return;
607 *negotiated_option = AUTH_OPTION_REJECT;
610 static void
611 acl_set_key(struct iscsi_acl *client, int key_type, unsigned int option_count,
612 int *option_list, const char *(*value_to_text)(int))
614 unsigned int i;
616 if (option_count == 0) {
618 * No valid options to send, but we always want to
619 * send something.
621 acl_set_key_value(&client->send_key_block, key_type,
622 acl_none_option_name);
623 return;
626 if (option_count == 1 && option_list[0] == AUTH_OPTION_NOT_PRESENT) {
627 acl_set_key_value(&client->send_key_block, key_type, NULL);
628 return;
631 for (i = 0; i < option_count; i++) {
632 const char *s = (*value_to_text)(option_list[i]);
634 if (!s)
635 continue;
637 if (i == 0)
638 strlcpy(client->scratch_key_value, s,
639 AUTH_STR_MAX_LEN);
640 else {
641 strlcat(client->scratch_key_value, ",",
642 AUTH_STR_MAX_LEN);
643 strlcat(client->scratch_key_value, s,
644 AUTH_STR_MAX_LEN);
648 acl_set_key_value(&client->send_key_block, key_type,
649 client->scratch_key_value);
652 static void
653 acl_chk_auth_method_key(struct iscsi_acl *client)
655 acl_chk_key(client, AUTH_KEY_TYPE_AUTH_METHOD,
656 &client->negotiated_auth_method,
657 client->auth_method_valid_count,
658 client->auth_method_valid_list,
659 acl_authmethod_optn_to_text);
662 static void
663 acl_set_auth_method_key(struct iscsi_acl *client,
664 unsigned int auth_method_count, int *auth_method_list)
666 acl_set_key(client, AUTH_KEY_TYPE_AUTH_METHOD, auth_method_count,
667 auth_method_list, acl_authmethod_optn_to_text);
670 static void
671 acl_chk_chap_alg_key(struct iscsi_acl *client)
673 const char *key_val;
674 int length;
675 unsigned long number;
676 unsigned int i;
678 key_val = acl_get_key_val(&client->recv_key_block,
679 AUTH_KEY_TYPE_CHAP_ALG);
680 if (!key_val) {
681 client->negotiated_chap_alg = AUTH_OPTION_NOT_PRESENT;
682 return;
685 while (*key_val != '\0') {
687 length = 0;
689 while (*key_val != '\0' && *key_val != ',')
690 client->scratch_key_value[length++] = *key_val++;
692 if (*key_val == ',')
693 key_val++;
694 client->scratch_key_value[length++] = '\0';
696 if (acl_text_to_number(client->scratch_key_value, &number))
697 continue;
700 for (i = 0; i < client->chap_alg_count; i++)
701 if (number == (unsigned long)client->chap_alg_list[i])
703 client->negotiated_chap_alg = number;
704 return;
708 client->negotiated_chap_alg = AUTH_OPTION_REJECT;
711 static void
712 acl_set_chap_alg_key(struct iscsi_acl *client, unsigned int chap_alg_count,
713 int *chap_alg_list)
715 unsigned int i;
717 if (chap_alg_count == 0) {
718 acl_set_key_value(&client->send_key_block,
719 AUTH_KEY_TYPE_CHAP_ALG, NULL);
720 return;
723 if (chap_alg_count == 1 &&
724 chap_alg_list[0] == AUTH_OPTION_NOT_PRESENT) {
725 acl_set_key_value(&client->send_key_block,
726 AUTH_KEY_TYPE_CHAP_ALG, NULL);
727 return;
730 if (chap_alg_count == 1 && chap_alg_list[0] == AUTH_OPTION_REJECT) {
731 acl_set_key_value(&client->send_key_block,
732 AUTH_KEY_TYPE_CHAP_ALG,
733 acl_reject_option_name);
734 return;
737 for (i = 0; i < chap_alg_count; i++) {
738 char s[20];
740 snprintf(s, sizeof(s), "%lu",(unsigned long)chap_alg_list[i]);
742 if (i == 0)
743 strlcpy(client->scratch_key_value, s,
744 AUTH_STR_MAX_LEN);
745 else {
746 strlcat(client->scratch_key_value, ",",
747 AUTH_STR_MAX_LEN);
748 strlcat(client->scratch_key_value, s,
749 AUTH_STR_MAX_LEN);
753 acl_set_key_value(&client->send_key_block, AUTH_KEY_TYPE_CHAP_ALG,
754 client->scratch_key_value);
757 static void
758 acl_next_phase(struct iscsi_acl *client)
760 switch (client->phase) {
761 case AUTH_PHASE_CONFIGURE:
762 client->phase = AUTH_PHASE_NEGOTIATE;
763 break;
764 case AUTH_PHASE_NEGOTIATE:
765 client->phase = AUTH_PHASE_AUTHENTICATE;
767 if (client->negotiated_auth_method == AUTH_OPTION_REJECT ||
768 client->negotiated_auth_method == AUTH_OPTION_NOT_PRESENT ||
769 client->negotiated_auth_method == AUTH_OPTION_NONE) {
771 client->local_state = AUTH_LOCAL_STATE_DONE;
772 client->rmt_state = AUTH_RMT_STATE_DONE;
774 if (client->auth_rmt) {
775 client->rmt_auth_status = AUTH_STATUS_FAIL;
776 client->phase = AUTH_PHASE_DONE;
777 } else
778 client->rmt_auth_status = AUTH_STATUS_PASS;
780 switch (client->negotiated_auth_method) {
781 case AUTH_OPTION_REJECT:
782 client->dbg_status =
783 AUTH_DBG_STATUS_AUTH_METHOD_REJECT;
784 break;
785 case AUTH_OPTION_NOT_PRESENT:
786 client->dbg_status =
787 AUTH_DBG_STATUS_AUTH_METHOD_NOT_PRESENT;
788 break;
789 case AUTH_OPTION_NONE:
790 client->dbg_status =
791 AUTH_DBG_STATUS_AUTH_METHOD_NONE;
794 } else if (client->negotiated_auth_method == AUTH_METHOD_CHAP) {
795 client->local_state = AUTH_LOCAL_STATE_SEND_ALG;
796 client->rmt_state = AUTH_RMT_STATE_SEND_ALG;
797 } else {
799 client->local_state = AUTH_LOCAL_STATE_DONE;
800 client->rmt_state = AUTH_RMT_STATE_DONE;
801 client->rmt_auth_status = AUTH_STATUS_FAIL;
802 client->dbg_status = AUTH_DBG_STATUS_AUTH_METHOD_BAD;
804 break;
805 case AUTH_PHASE_AUTHENTICATE:
806 client->phase = AUTH_PHASE_DONE;
807 break;
808 case AUTH_PHASE_DONE:
809 case AUTH_PHASE_ERROR:
810 default:
811 client->phase = AUTH_PHASE_ERROR;
815 static void
816 acl_local_auth(struct iscsi_acl *client)
818 unsigned int chap_identifier;
819 unsigned char response_data[AUTH_CHAP_RSP_LEN];
820 unsigned long number;
821 int status;
822 enum auth_dbg_status dbg_status;
823 const char *chap_identifier_key_val;
824 const char *chap_challenge_key_val;
826 switch (client->local_state) {
827 case AUTH_LOCAL_STATE_SEND_ALG:
828 if (client->node_type == TYPE_INITIATOR) {
829 acl_set_chap_alg_key(client, client->chap_alg_count,
830 client->chap_alg_list);
831 client->local_state = AUTH_LOCAL_STATE_RECV_ALG;
832 break;
834 /* Fall through */
835 case AUTH_LOCAL_STATE_RECV_ALG:
836 acl_chk_chap_alg_key(client);
838 if (client->node_type == TYPE_TARGET)
839 acl_set_chap_alg_key(client, 1,
840 &client->negotiated_chap_alg);
842 /* Make sure only supported CHAP algorithm is used. */
843 if (client->negotiated_chap_alg == AUTH_OPTION_NOT_PRESENT) {
844 client->local_state = AUTH_LOCAL_STATE_ERROR;
845 client->dbg_status = AUTH_DBG_STATUS_CHAP_ALG_EXPECTED;
846 break;
847 } else if (client->negotiated_chap_alg == AUTH_OPTION_REJECT) {
848 client->local_state = AUTH_LOCAL_STATE_ERROR;
849 client->dbg_status = AUTH_DBG_STATUS_CHAP_ALG_REJECT;
850 break;
851 } else if (client->negotiated_chap_alg != AUTH_CHAP_ALG_MD5) {
852 client->local_state = AUTH_LOCAL_STATE_ERROR;
853 client->dbg_status = AUTH_DBG_STATUS_CHAP_ALG_BAD;
854 break;
856 if (client->node_type == TYPE_TARGET) {
857 client->local_state = AUTH_LOCAL_STATE_RECV_CHALLENGE;
858 break;
860 /* Fall through */
861 case AUTH_LOCAL_STATE_RECV_CHALLENGE:
862 chap_identifier_key_val = acl_get_key_val(&client->recv_key_block,
863 AUTH_KEY_TYPE_CHAP_IDENTIFIER);
864 chap_challenge_key_val = acl_get_key_val(&client->recv_key_block,
865 AUTH_KEY_TYPE_CHAP_CHALLENGE);
866 if (client->node_type == TYPE_TARGET) {
867 if (!chap_identifier_key_val &&
868 !chap_challenge_key_val) {
869 client->local_state = AUTH_LOCAL_STATE_DONE;
870 break;
874 if (!chap_identifier_key_val) {
875 client->local_state = AUTH_LOCAL_STATE_ERROR;
876 client->dbg_status =
877 AUTH_DBG_STATUS_CHAP_IDENTIFIER_EXPECTED;
878 break;
881 if (!chap_challenge_key_val) {
882 client->local_state = AUTH_LOCAL_STATE_ERROR;
883 client->dbg_status =
884 AUTH_DBG_STATUS_CHAP_CHALLENGE_EXPECTED;
885 break;
888 status = acl_text_to_number(chap_identifier_key_val, &number);
889 if (status || (255 < number)) {
890 client->local_state = AUTH_LOCAL_STATE_ERROR;
891 client->dbg_status = AUTH_DBG_STATUS_CHAP_IDENTIFIER_BAD;
892 break;
894 chap_identifier = number;
896 if (client->recv_chap_challenge_status) {
897 client->local_state = AUTH_LOCAL_STATE_ERROR;
898 client->dbg_status = AUTH_DBG_STATUS_CHALLENGE_BAD;
899 break;
902 if (client->node_type == TYPE_TARGET &&
903 client->recv_chap_challenge.length ==
904 client->send_chap_challenge.length &&
905 memcmp(client->recv_chap_challenge.large_binary,
906 client->send_chap_challenge.large_binary,
907 client->send_chap_challenge.length) == 0) {
908 client->local_state = AUTH_LOCAL_STATE_ERROR;
909 client->dbg_status =
910 AUTH_DBG_STATUS_CHAP_CHALLENGE_REFLECTED;
911 break;
914 dbg_status = acl_chap_compute_rsp(client, 0,
915 chap_identifier,
916 client->recv_chap_challenge.large_binary,
917 client->recv_chap_challenge.length,
918 response_data);
920 if (dbg_status != AUTH_DBG_STATUS_NOT_SET) {
921 client->local_state = AUTH_LOCAL_STATE_ERROR;
922 client->dbg_status = dbg_status;
923 break;
926 acl_data_to_text(response_data,
927 AUTH_CHAP_RSP_LEN, client->scratch_key_value,
928 AUTH_STR_MAX_LEN);
929 acl_set_key_value(&client->send_key_block,
930 AUTH_KEY_TYPE_CHAP_RSP,
931 client->scratch_key_value);
932 acl_set_key_value(&client->send_key_block,
933 AUTH_KEY_TYPE_CHAP_USERNAME,
934 client->username);
936 client->local_state = AUTH_LOCAL_STATE_DONE;
937 break;
938 case AUTH_LOCAL_STATE_DONE:
939 break;
940 case AUTH_LOCAL_STATE_ERROR:
941 default:
942 client->phase = AUTH_PHASE_ERROR;
946 static void
947 acl_rmt_auth(struct iscsi_acl *client)
949 unsigned char id_data[1];
950 unsigned char response_data[AUTH_STR_MAX_LEN];
951 unsigned int rsp_len = AUTH_STR_MAX_LEN;
952 unsigned char my_rsp_data[AUTH_CHAP_RSP_LEN];
953 int status;
954 enum auth_dbg_status dbg_status;
955 const char *chap_rsp_key_val;
956 const char *chap_username_key_val;
958 switch (client->rmt_state) {
959 case AUTH_RMT_STATE_SEND_ALG:
960 if (client->node_type == TYPE_INITIATOR) {
961 client->rmt_state = AUTH_RMT_STATE_SEND_CHALLENGE;
962 break;
964 /* Fall through */
965 case AUTH_RMT_STATE_SEND_CHALLENGE:
966 if (!client->auth_rmt) {
967 client->rmt_auth_status = AUTH_STATUS_PASS;
968 client->dbg_status = AUTH_DBG_STATUS_AUTH_RMT_FALSE;
969 client->rmt_state = AUTH_RMT_STATE_DONE;
970 break;
972 get_random_bytes(id_data, 1);
973 client->send_chap_identifier = id_data[0];
974 snprintf(client->scratch_key_value, AUTH_STR_MAX_LEN, "%lu",
975 (unsigned long)client->send_chap_identifier);
976 acl_set_key_value(&client->send_key_block,
977 AUTH_KEY_TYPE_CHAP_IDENTIFIER,
978 client->scratch_key_value);
980 client->send_chap_challenge.length = client->chap_challenge_len;
981 get_random_bytes(client->send_chap_challenge.large_binary,
982 client->send_chap_challenge.length);
983 acl_set_key_value(&client->send_key_block,
984 AUTH_KEY_TYPE_CHAP_CHALLENGE, "");
986 client->rmt_state = AUTH_RMT_STATE_RECV_RSP;
987 break;
988 case AUTH_RMT_STATE_RECV_RSP:
989 chap_rsp_key_val = acl_get_key_val(&client->recv_key_block,
990 AUTH_KEY_TYPE_CHAP_RSP);
991 chap_username_key_val = acl_get_key_val(&client->recv_key_block,
992 AUTH_KEY_TYPE_CHAP_USERNAME);
994 if (!chap_rsp_key_val) {
995 client->rmt_state = AUTH_RMT_STATE_ERROR;
996 client->dbg_status = AUTH_DBG_STATUS_CHAP_RSP_EXPECTED;
997 break;
1000 if (!chap_username_key_val) {
1001 client->rmt_state = AUTH_RMT_STATE_ERROR;
1002 client->dbg_status = AUTH_DBG_STATUS_CHAP_USERNAME_EXPECTED;
1003 break;
1006 status = acl_text_to_data(chap_rsp_key_val, response_data,
1007 &rsp_len);
1009 if (status) {
1010 client->rmt_state = AUTH_RMT_STATE_ERROR;
1011 client->dbg_status = AUTH_DBG_STATUS_CHAP_RSP_BAD;
1012 break;
1015 if (rsp_len == AUTH_CHAP_RSP_LEN) {
1016 dbg_status = acl_chap_compute_rsp(client, 1,
1017 client->send_chap_identifier,
1018 client->send_chap_challenge.large_binary,
1019 client->send_chap_challenge.length,
1020 my_rsp_data);
1022 if (dbg_status == AUTH_DBG_STATUS_NOT_SET &&
1023 memcmp(my_rsp_data, response_data,
1024 AUTH_CHAP_RSP_LEN) == 0) {
1025 client->rmt_state = AUTH_RMT_STATE_ERROR;
1026 client->dbg_status = AUTH_DBG_STATUS_PASSWD_IDENTICAL;
1027 break;
1031 strlcpy(client->chap_username, chap_username_key_val,
1032 AUTH_STR_MAX_LEN);
1034 status = acl_chap_auth_request(client, client->chap_username,
1035 client->send_chap_identifier,
1036 client->send_chap_challenge.
1037 large_binary,
1038 client->send_chap_challenge.
1039 length, response_data,
1040 rsp_len);
1042 client->rmt_auth_status = (enum auth_status) status;
1043 client->auth_rsp_flag = 1;
1045 if (client->auth_server_error_flag) {
1046 client->rmt_auth_status = AUTH_STATUS_FAIL;
1047 client->dbg_status = AUTH_DBG_STATUS_AUTH_SERVER_ERROR;
1048 } else if (client->rmt_auth_status == AUTH_STATUS_PASS)
1049 client->dbg_status = AUTH_DBG_STATUS_AUTH_PASS;
1050 else if (client->rmt_auth_status == AUTH_STATUS_FAIL)
1051 client->dbg_status = AUTH_DBG_STATUS_AUTH_FAIL;
1052 else {
1053 client->rmt_auth_status = AUTH_STATUS_FAIL;
1054 client->dbg_status = AUTH_DBG_STATUS_AUTH_STATUS_BAD;
1056 client->rmt_state = AUTH_RMT_STATE_DONE;
1058 /* Fall through */
1059 case AUTH_RMT_STATE_DONE:
1060 break;
1061 case AUTH_RMT_STATE_ERROR:
1062 default:
1063 client->phase = AUTH_PHASE_ERROR;
1067 static void
1068 acl_hand_shake(struct iscsi_acl *client)
1070 if (client->phase == AUTH_PHASE_DONE)
1073 * Should only happen if authentication
1074 * protocol error occured.
1076 return;
1078 if (client->node_type == TYPE_INITIATOR)
1081 * Target should only have set T bit on response if
1082 * initiator set it on previous message.
1084 if (client->recv_key_block.transit_bit &&
1085 !client->transit_bit_sent_flag) {
1086 client->rmt_auth_status = AUTH_STATUS_FAIL;
1087 client->phase = AUTH_PHASE_DONE;
1088 client->dbg_status =
1089 AUTH_DBG_STATUS_T_BIT_SET_ILLEGAL;
1090 return;
1093 if (client->phase == AUTH_PHASE_NEGOTIATE) {
1095 * Should only happen if waiting for peer
1096 * to send AuthMethod key or set Transit Bit.
1098 if (client->node_type == TYPE_INITIATOR)
1099 client->send_key_block.transit_bit = 1;
1100 return;
1103 if (client->rmt_state == AUTH_RMT_STATE_RECV_RSP ||
1104 client->rmt_state == AUTH_RMT_STATE_DONE) {
1105 if (client->node_type == TYPE_INITIATOR) {
1106 if (client->recv_key_block.transit_bit) {
1107 if (client->rmt_state !=
1108 AUTH_RMT_STATE_DONE)
1109 goto recv_transit_bit_err;
1110 acl_next_phase(client);
1111 } else
1112 client->send_key_block.transit_bit = 1;
1113 } else {
1114 if (client->rmt_state == AUTH_RMT_STATE_DONE &&
1115 client->rmt_auth_status != AUTH_STATUS_PASS)
1117 * Authentication failed, don't do T bit
1118 * handshake.
1120 acl_next_phase(client);
1121 else {
1123 * Target can only set T bit on response if
1124 * initiator set it on current message.
1126 if (client->recv_key_block.transit_bit) {
1127 client->send_key_block.transit_bit = 1;
1128 acl_next_phase(client);
1132 } else
1133 if (client->node_type == TYPE_INITIATOR)
1134 if (client->recv_key_block.transit_bit)
1135 goto recv_transit_bit_err;
1136 return;
1138 recv_transit_bit_err:
1140 * Target set T bit on response but
1141 * initiator was not done with authentication.
1143 client->rmt_auth_status = AUTH_STATUS_FAIL;
1144 client->phase = AUTH_PHASE_DONE;
1145 client->dbg_status = AUTH_DBG_STATUS_T_BIT_SET_PREMATURE;
1148 static int
1149 acl_rcv_end_status(struct iscsi_acl *client)
1151 int auth_status;
1152 int key_type;
1154 if (client->phase == AUTH_PHASE_ERROR)
1155 return AUTH_STATUS_ERROR;
1157 if (client->phase == AUTH_PHASE_DONE) {
1159 /* Perform sanity check against configured parameters. */
1160 if (client->auth_rmt && !client->auth_rsp_flag &&
1161 client->rmt_auth_status == AUTH_STATUS_PASS) {
1162 client->rmt_auth_status = AUTH_STATUS_FAIL;
1163 client->dbg_status = AUTH_DBG_STATUS_AUTHPASS_NOT_VALID;
1166 auth_status = client->rmt_auth_status;
1168 } else
1169 auth_status = AUTH_STATUS_CONTINUE;
1171 if (auth_status == AUTH_STATUS_CONTINUE ||
1172 auth_status == AUTH_STATUS_PASS) {
1173 if (client->send_key_block.dup_set) {
1174 client->rmt_auth_status = AUTH_STATUS_FAIL;
1175 client->phase = AUTH_PHASE_DONE;
1176 client->dbg_status =
1177 AUTH_DBG_STATUS_SEND_DUP_SET_KEY_VALUE;
1178 auth_status = AUTH_STATUS_FAIL;
1179 } else if (client->send_key_block.str_too_long) {
1180 client->rmt_auth_status = AUTH_STATUS_FAIL;
1181 client->phase = AUTH_PHASE_DONE;
1182 client->dbg_status =
1183 AUTH_DBG_STATUS_SEND_STR_TOO_LONG;
1184 auth_status = AUTH_STATUS_FAIL;
1185 } else if (client->send_key_block.too_much_data) {
1186 client->rmt_auth_status = AUTH_STATUS_FAIL;
1187 client->phase = AUTH_PHASE_DONE;
1188 client->dbg_status =
1189 AUTH_DBG_STATUS_SEND_TOO_MUCH_DATA;
1190 auth_status = AUTH_STATUS_FAIL;
1191 } else {
1192 /* Check that all incoming keys have been processed. */
1194 for (key_type = AUTH_KEY_TYPE_FIRST;
1195 key_type < AUTH_KEY_TYPE_MAX_COUNT; key_type++)
1196 if (client->recv_key_block.key[key_type].present &&
1197 !client->recv_key_block.key[key_type].
1198 processed)
1199 break;
1201 if (key_type < AUTH_KEY_TYPE_MAX_COUNT) {
1202 client->rmt_auth_status = AUTH_STATUS_FAIL;
1203 client->phase = AUTH_PHASE_DONE;
1204 client->dbg_status =
1205 AUTH_DBG_STATUS_UNEXPECTED_KEY_PRESENT;
1206 auth_status = AUTH_STATUS_FAIL;
1211 if (auth_status != AUTH_STATUS_PASS &&
1212 auth_status != AUTH_STATUS_CONTINUE) {
1213 int auth_method_key_present = 0;
1214 int chap_alg_key_present = 0;
1217 * Suppress send keys on error,
1218 * except for AuthMethod and CHAP_A.
1220 if (client->node_type == TYPE_TARGET) {
1221 if (acl_get_key_val(&client->send_key_block,
1222 AUTH_KEY_TYPE_AUTH_METHOD))
1223 auth_method_key_present = 1;
1224 else if (acl_get_key_val(&client->send_key_block,
1225 AUTH_KEY_TYPE_CHAP_ALG))
1226 chap_alg_key_present = 1;
1229 acl_init_key_blk(&client->send_key_block);
1231 if (client->node_type == TYPE_TARGET) {
1232 if (auth_method_key_present &&
1233 client->negotiated_auth_method ==
1234 AUTH_OPTION_REJECT)
1235 acl_set_key_value(&client->send_key_block,
1236 AUTH_KEY_TYPE_AUTH_METHOD,
1237 acl_reject_option_name);
1238 else if (chap_alg_key_present &&
1239 client->negotiated_chap_alg ==
1240 AUTH_OPTION_REJECT)
1241 acl_set_key_value(&client->send_key_block,
1242 AUTH_KEY_TYPE_CHAP_ALG,
1243 acl_reject_option_name);
1246 client->recv_in_progress_flag = 0;
1248 return auth_status;
1252 acl_recv_begin(struct iscsi_acl *client)
1254 if (!client || client->signature != ACL_SIGNATURE)
1255 return AUTH_STATUS_ERROR;
1257 if (client->phase == AUTH_PHASE_ERROR)
1258 return AUTH_STATUS_ERROR;
1260 if (client->phase == AUTH_PHASE_DONE) {
1261 client->phase = AUTH_PHASE_ERROR;
1262 return AUTH_STATUS_ERROR;
1265 if (client->recv_in_progress_flag) {
1266 client->phase = AUTH_PHASE_ERROR;
1267 return AUTH_STATUS_ERROR;
1270 client->recv_in_progress_flag = 1;
1272 if (client->phase == AUTH_PHASE_CONFIGURE)
1273 acl_next_phase(client);
1275 client->transit_bit_sent_flag = client->send_key_block.transit_bit;
1277 acl_init_key_blk(&client->recv_key_block);
1278 acl_init_key_blk(&client->send_key_block);
1280 return AUTH_STATUS_NO_ERROR;
1284 acl_recv_end(struct iscsi_acl *client, iscsi_session_t *session_handle)
1286 int next_phase_flag = 0;
1288 if (!client || client->signature != ACL_SIGNATURE)
1289 return AUTH_STATUS_ERROR;
1291 if (client->phase == AUTH_PHASE_ERROR)
1292 return AUTH_STATUS_ERROR;
1294 if (!client->recv_in_progress_flag) {
1295 client->phase = AUTH_PHASE_ERROR;
1296 return AUTH_STATUS_ERROR;
1299 if (client->recv_end_count > AUTH_RECV_END_MAX_COUNT) {
1300 client->rmt_auth_status = AUTH_STATUS_FAIL;
1301 client->phase = AUTH_PHASE_DONE;
1302 client->dbg_status = AUTH_DBG_STATUS_RECV_MSG_COUNT_LIMIT;
1303 } else if (client->recv_key_block.dup_set) {
1304 client->rmt_auth_status = AUTH_STATUS_FAIL;
1305 client->phase = AUTH_PHASE_DONE;
1306 client->dbg_status = AUTH_DBG_STATUS_RECV_DUP_SET_KEY_VALUE;
1307 } else if (client->recv_key_block.str_too_long) {
1308 client->rmt_auth_status = AUTH_STATUS_FAIL;
1309 client->phase = AUTH_PHASE_DONE;
1310 client->dbg_status = AUTH_DBG_STATUS_RECV_STR_TOO_LONG;
1311 } else if (client->recv_key_block.too_much_data) {
1312 client->rmt_auth_status = AUTH_STATUS_FAIL;
1313 client->phase = AUTH_PHASE_DONE;
1314 client->dbg_status = AUTH_DBG_STATUS_RECV_TOO_MUCH_DATA;
1317 client->recv_end_count++;
1318 client->session_handle = session_handle;
1320 switch (client->phase) {
1321 case AUTH_PHASE_NEGOTIATE:
1322 acl_chk_auth_method_key(client);
1323 if (client->auth_method_valid_neg_role ==
1324 AUTH_NEG_ROLE_RESPONDER) {
1325 if (client->negotiated_auth_method ==
1326 AUTH_OPTION_NOT_PRESENT) {
1327 if (client->auth_rmt ||
1328 !client->recv_key_block.transit_bit) {
1330 * No AuthMethod key from peer on
1331 * first message, try moving the
1332 * process along by sending the
1333 * AuthMethod key.
1336 client->auth_method_valid_neg_role =
1337 AUTH_NEG_ROLE_ORIGINATOR;
1338 acl_set_auth_method_key(client,
1339 client->auth_method_valid_count,
1340 client->auth_method_valid_list);
1341 break;
1345 * Special case if peer sent no AuthMethod key,
1346 * but did set Transit Bit, allowing this side
1347 * to do a null authentication, and compelete
1348 * the iSCSI security phase without either side
1349 * sending the AuthMethod key.
1351 } else
1352 /* Send response to AuthMethod key. */
1353 acl_set_auth_method_key(client, 1,
1354 &client->negotiated_auth_method);
1356 if (client->node_type == TYPE_INITIATOR)
1357 acl_next_phase(client);
1358 else
1359 next_phase_flag = 1;
1360 } else {
1362 if (client->negotiated_auth_method ==
1363 AUTH_OPTION_NOT_PRESENT) {
1364 client->rmt_auth_status = AUTH_STATUS_FAIL;
1365 client->phase = AUTH_PHASE_DONE;
1366 client->dbg_status =
1367 AUTH_DBG_STATUS_AUTH_METHOD_EXPECTED;
1368 break;
1371 acl_next_phase(client);
1373 break;
1374 case AUTH_PHASE_AUTHENTICATE:
1375 case AUTH_PHASE_DONE:
1376 break;
1377 default:
1378 client->phase = AUTH_PHASE_ERROR;
1379 return AUTH_STATUS_ERROR;
1382 switch (client->phase) {
1383 case AUTH_PHASE_NEGOTIATE:
1384 if (next_phase_flag)
1385 acl_next_phase(client);
1386 break;
1387 case AUTH_PHASE_AUTHENTICATE:
1389 * Must call acl_local_auth()
1390 * before acl_rmt_auth()
1391 * to insure processing of the CHAP algorithm key,
1392 * and to avoid leaving an in progress request to the
1393 * authentication service.
1395 acl_local_auth(client);
1397 if (client->local_state != AUTH_LOCAL_STATE_ERROR)
1398 acl_rmt_auth(client);
1400 if (client->local_state == AUTH_LOCAL_STATE_ERROR ||
1401 client->rmt_state == AUTH_RMT_STATE_ERROR) {
1403 client->rmt_auth_status = AUTH_STATUS_FAIL;
1404 client->phase = AUTH_PHASE_DONE;
1405 /* client->dbg_status should already be set. */
1407 break;
1408 case AUTH_PHASE_DONE:
1409 break;
1410 default:
1411 client->phase = AUTH_PHASE_ERROR;
1412 return AUTH_STATUS_ERROR;
1415 acl_hand_shake(client);
1417 return acl_rcv_end_status(client);
1420 const char *
1421 acl_get_key_name(int key_type)
1424 * Note: The ordering of this table must match the order
1425 * defined by enum auth_key_type in iscsi-auth-client.h.
1427 static char *const key_names[AUTH_KEY_TYPE_MAX_COUNT] = {
1428 "AuthMethod",
1429 "CHAP_A",
1430 "CHAP_N",
1431 "CHAP_R",
1432 "CHAP_I",
1433 "CHAP_C"
1436 if (key_type < AUTH_KEY_TYPE_FIRST || key_type > AUTH_KEY_TYPE_LAST)
1437 return NULL;
1439 return key_names[key_type];
1443 acl_get_next_key_type(int *key_type)
1445 if (*key_type >= AUTH_KEY_TYPE_LAST)
1446 return AUTH_STATUS_ERROR;
1448 if (*key_type < AUTH_KEY_TYPE_FIRST)
1449 *key_type = AUTH_KEY_TYPE_FIRST;
1450 else
1451 (*key_type)++;
1453 return AUTH_STATUS_NO_ERROR;
1457 acl_recv_key_value(struct iscsi_acl *client, int key_type,
1458 const char *user_key_val)
1460 if (!client || client->signature != ACL_SIGNATURE)
1461 return AUTH_STATUS_ERROR;
1463 if (client->phase != AUTH_PHASE_NEGOTIATE &&
1464 client->phase != AUTH_PHASE_AUTHENTICATE) {
1465 client->phase = AUTH_PHASE_ERROR;
1466 return AUTH_STATUS_ERROR;
1469 if (key_type < AUTH_KEY_TYPE_FIRST || key_type > AUTH_KEY_TYPE_LAST) {
1470 client->phase = AUTH_PHASE_ERROR;
1471 return AUTH_STATUS_ERROR;
1474 if (key_type == AUTH_KEY_TYPE_CHAP_CHALLENGE) {
1475 client->recv_chap_challenge.length =
1476 AUTH_LARGE_BINARY_MAX_LEN;
1477 client->recv_chap_challenge_status =
1478 acl_text_to_data(user_key_val,
1479 client->recv_chap_challenge.large_binary,
1480 &client->recv_chap_challenge.length);
1481 user_key_val = "";
1484 acl_set_key_value(&client->recv_key_block, key_type, user_key_val);
1486 return AUTH_STATUS_NO_ERROR;
1490 acl_send_key_val(struct iscsi_acl *client, int key_type, int *key_present,
1491 char *user_key_val, unsigned int max_length)
1493 const char *key_val;
1495 if (!client || client->signature != ACL_SIGNATURE)
1496 return AUTH_STATUS_ERROR;
1498 if (client->phase != AUTH_PHASE_CONFIGURE &&
1499 client->phase != AUTH_PHASE_NEGOTIATE &&
1500 client->phase != AUTH_PHASE_AUTHENTICATE &&
1501 client->phase != AUTH_PHASE_DONE) {
1502 client->phase = AUTH_PHASE_ERROR;
1503 return AUTH_STATUS_ERROR;
1506 if (key_type < AUTH_KEY_TYPE_FIRST || key_type > AUTH_KEY_TYPE_LAST) {
1507 client->phase = AUTH_PHASE_ERROR;
1508 return AUTH_STATUS_ERROR;
1511 key_val = acl_get_key_val(&client->send_key_block, key_type);
1512 if (key_val) {
1513 if (key_type == AUTH_KEY_TYPE_CHAP_CHALLENGE) {
1514 if (acl_data_to_text(client->send_chap_challenge.large_binary,
1515 client->send_chap_challenge.length, user_key_val,
1516 max_length)) {
1517 client->phase = AUTH_PHASE_ERROR;
1518 return AUTH_STATUS_ERROR;
1520 } else if (strlcpy(user_key_val, key_val, max_length) >=
1521 max_length) {
1522 client->phase = AUTH_PHASE_ERROR;
1523 return AUTH_STATUS_ERROR;
1525 *key_present = 1;
1526 } else
1527 *key_present = 0;
1529 return AUTH_STATUS_NO_ERROR;
1533 acl_recv_transit_bit(struct iscsi_acl *client, int value)
1535 if (!client || client->signature != ACL_SIGNATURE)
1536 return AUTH_STATUS_ERROR;
1538 if (client->phase != AUTH_PHASE_NEGOTIATE &&
1539 client->phase != AUTH_PHASE_AUTHENTICATE) {
1541 client->phase = AUTH_PHASE_ERROR;
1542 return AUTH_STATUS_ERROR;
1545 if (value)
1546 client->recv_key_block.transit_bit = 1;
1547 else
1548 client->recv_key_block.transit_bit = 0;
1550 return AUTH_STATUS_NO_ERROR;
1554 acl_send_transit_bit(struct iscsi_acl *client, int *value)
1556 if (!client || client->signature != ACL_SIGNATURE)
1557 return AUTH_STATUS_ERROR;
1559 if (client->phase != AUTH_PHASE_CONFIGURE &&
1560 client->phase != AUTH_PHASE_NEGOTIATE &&
1561 client->phase != AUTH_PHASE_AUTHENTICATE &&
1562 client->phase != AUTH_PHASE_DONE) {
1564 client->phase = AUTH_PHASE_ERROR;
1565 return AUTH_STATUS_ERROR;
1568 *value = client->send_key_block.transit_bit;
1570 return AUTH_STATUS_NO_ERROR;
1573 static int
1574 acl_set_option_list(struct iscsi_acl *client, unsigned int opt_count,
1575 const int *opt_list, unsigned int *clnt_optn_count,
1576 int *clnt_optn_list, unsigned int optn_max_count,
1577 int (*chk_option)(int),
1578 int (*chk_list)(unsigned int opt_count, const int *opt_list))
1580 unsigned int i, j;
1582 if (!client || client->signature != ACL_SIGNATURE)
1583 return AUTH_STATUS_ERROR;
1585 if (client->phase != AUTH_PHASE_CONFIGURE ||
1586 opt_count > optn_max_count) {
1587 client->phase = AUTH_PHASE_ERROR;
1588 return AUTH_STATUS_ERROR;
1591 for (i = 0; i < opt_count; i++)
1592 if (chk_option(opt_list[i])) {
1593 client->phase = AUTH_PHASE_ERROR;
1594 return AUTH_STATUS_ERROR;
1597 /* Check for duplicate entries. */
1598 for (i = 0; i < opt_count; i++)
1599 for (j = 0; j < opt_count; j++) {
1600 if (j == i)
1601 continue;
1602 if (opt_list[i] == opt_list[j]) {
1603 client->phase = AUTH_PHASE_ERROR;
1604 return AUTH_STATUS_ERROR;
1608 /* Check for key specific constraints. */
1609 if (chk_list)
1610 if (chk_list(opt_count, opt_list)) {
1611 client->phase = AUTH_PHASE_ERROR;
1612 return AUTH_STATUS_ERROR;
1615 for (i = 0; i < opt_count; i++)
1616 clnt_optn_list[i] = opt_list[i];
1618 *clnt_optn_count = opt_count;
1620 return AUTH_STATUS_NO_ERROR;
1623 static int
1624 acl_chk_auth_method_list(unsigned int option_count, const int *option_list)
1626 unsigned int i;
1628 if (!option_list || option_count < 2)
1629 return 1;
1631 if (option_list[option_count - 1] != AUTH_OPTION_NONE)
1632 return 1;
1634 for (i = 0; i < (option_count - 1); i++)
1635 if (option_list[i] != AUTH_OPTION_NONE)
1636 return 0;
1638 return 0;
1641 static void
1642 acl_set_auth_method_valid(struct iscsi_acl *client)
1644 unsigned int i, j = 0;
1645 int option = 0;
1648 * Following checks may need to be revised if
1649 * authentication options other than CHAP and none
1650 * are supported.
1652 if (client->node_type == TYPE_INITIATOR) {
1653 if (client->auth_rmt)
1655 * If initiator doing authentication,
1656 * don't offer authentication option none.
1658 option = 1;
1659 else if (!client->passwd_present)
1661 * If initiator password not set,
1662 * only offer authentication option none.
1664 option = 2;
1667 if (client->node_type == TYPE_TARGET) {
1668 if (client->auth_rmt)
1670 * If target doing authentication,
1671 * don't accept authentication option none.
1673 option = 1;
1674 else
1676 * If target not doing authentication,
1677 * only accept authentication option none.
1679 option = 2;
1682 for (i = 0; i < client->auth_method_count; i++) {
1683 if (option == 1) {
1684 if (client->auth_method_list[i] == AUTH_OPTION_NONE)
1685 continue;
1686 } else if (option == 2)
1687 if (client->auth_method_list[i] != AUTH_OPTION_NONE)
1688 continue;
1689 client->auth_method_valid_list[j++] = client->auth_method_list[i];
1692 client->auth_method_valid_count = j;
1694 acl_init_key_blk(&client->send_key_block);
1696 if (client->node_type == TYPE_INITIATOR) {
1697 if (client->auth_rmt) {
1699 * Initiator wants to authenticate target,
1700 * always send AuthMethod key.
1702 client->send_key_block.transit_bit = 0;
1703 client->auth_method_valid_neg_role =
1704 AUTH_NEG_ROLE_ORIGINATOR;
1705 } else {
1706 client->send_key_block.transit_bit = 1;
1707 client->auth_method_valid_neg_role =
1708 client->auth_method_neg_role;
1710 } else {
1711 client->send_key_block.transit_bit = 0;
1712 client->auth_method_valid_neg_role = AUTH_NEG_ROLE_RESPONDER;
1715 if (client->auth_method_valid_neg_role == AUTH_NEG_ROLE_ORIGINATOR)
1716 acl_set_auth_method_key(client, client->auth_method_valid_count,
1717 client->auth_method_valid_list);
1718 else {
1719 int value = AUTH_OPTION_NOT_PRESENT;
1720 acl_set_auth_method_key(client, 1, &value);
1724 static int
1725 acl_set_auth_method_list(struct iscsi_acl *client, unsigned int option_count,
1726 const int *option_list)
1728 int status;
1730 status = acl_set_option_list(client, option_count, option_list,
1731 &client->auth_method_count,
1732 client->auth_method_list,
1733 AUTH_METHOD_MAX_COUNT,
1734 acl_chk_auth_mthd_optn,
1735 acl_chk_auth_method_list);
1737 if (status != AUTH_STATUS_NO_ERROR)
1738 return status;
1740 /* Setting authMethod affects auth_method_valid. */
1741 acl_set_auth_method_valid(client);
1743 return AUTH_STATUS_NO_ERROR;
1746 static int
1747 acl_chk_chap_alg_list(unsigned int option_count, const int *option_list)
1749 if (!option_list || option_count < 1)
1750 return 1;
1752 return 0;
1755 static int
1756 acl_set_chap_alg_list(struct iscsi_acl *client, unsigned int option_count,
1757 const int *option_list)
1759 return acl_set_option_list(client, option_count, option_list,
1760 &client->chap_alg_count,
1761 client->chap_alg_list,
1762 AUTH_CHAP_ALG_MAX_COUNT,
1763 acl_chk_chap_alg_optn,
1764 acl_chk_chap_alg_list);
1768 acl_init(int node_type, int buf_desc_count, struct auth_buffer_desc *buff_desc)
1770 struct iscsi_acl *client;
1771 struct auth_str_block *recv_str_blk;
1772 struct auth_str_block *send_str_blk;
1773 struct auth_large_binary *recv_chap_challenge;
1774 struct auth_large_binary *send_chap_challenge;
1775 int value_list[2];
1777 if (buf_desc_count != 5 || !buff_desc)
1778 return AUTH_STATUS_ERROR;
1780 if (!buff_desc[0].address ||
1781 buff_desc[0].length != sizeof(*client))
1782 return AUTH_STATUS_ERROR;
1783 client = (struct iscsi_acl *)buff_desc[0].address;
1785 if (!buff_desc[1].address ||
1786 buff_desc[1].length != sizeof(*recv_str_blk))
1787 return AUTH_STATUS_ERROR;
1788 recv_str_blk = (struct auth_str_block *)buff_desc[1].address;
1790 if (!buff_desc[2].address ||
1791 buff_desc[2].length != sizeof(*send_str_blk))
1792 return AUTH_STATUS_ERROR;
1794 send_str_blk = (struct auth_str_block *)buff_desc[2].address;
1796 if (!buff_desc[3].address ||
1797 buff_desc[3].length != sizeof(*recv_chap_challenge))
1798 return AUTH_STATUS_ERROR;
1800 recv_chap_challenge = (struct auth_large_binary *)
1801 buff_desc[3].address;
1803 if (!buff_desc[4].address ||
1804 buff_desc[4].length != sizeof(*send_chap_challenge))
1805 return AUTH_STATUS_ERROR;
1806 send_chap_challenge = (struct auth_large_binary *)
1807 buff_desc[4].address;
1808 memset(client, 0, sizeof(*client));
1809 memset(recv_str_blk, 0, sizeof(*recv_str_blk));
1810 memset(send_str_blk, 0, sizeof(*send_str_blk));
1811 memset(recv_chap_challenge, 0, sizeof(*recv_chap_challenge));
1812 memset(send_chap_challenge, 0, sizeof(*send_chap_challenge));
1814 client->recv_key_block.str_block = recv_str_blk->str_block;
1815 client->send_key_block.str_block = send_str_blk->str_block;
1816 client->recv_chap_challenge.large_binary = recv_chap_challenge->large_binary;
1817 client->send_chap_challenge.large_binary = send_chap_challenge->large_binary;
1819 if (node_type != TYPE_INITIATOR && node_type != TYPE_TARGET) {
1820 client->phase = AUTH_PHASE_ERROR;
1821 return AUTH_STATUS_ERROR;
1824 client->signature = ACL_SIGNATURE;
1825 client->node_type = (enum auth_node_type) node_type;
1826 client->auth_rmt = 1;
1827 client->passwd_present = 0;
1828 client->chap_challenge_len = AUTH_CHAP_RSP_LEN;
1829 client->ip_sec = 0;
1831 client->phase = AUTH_PHASE_CONFIGURE;
1832 client->negotiated_auth_method = AUTH_OPTION_NOT_PRESENT;
1833 client->negotiated_chap_alg = AUTH_OPTION_NOT_PRESENT;
1835 if (client->node_type == TYPE_INITIATOR)
1836 client->auth_method_neg_role = AUTH_NEG_ROLE_ORIGINATOR;
1837 else
1838 /* Initial value ignored for Target. */
1839 client->auth_method_neg_role = AUTH_NEG_ROLE_RESPONDER;
1841 value_list[0] = AUTH_METHOD_CHAP;
1842 value_list[1] = AUTH_OPTION_NONE;
1845 * Must call after setting auth_rmt, password,
1846 * and auth_method_neg_role
1848 if (acl_set_auth_method_list(client, 2, value_list) !=
1849 AUTH_STATUS_NO_ERROR) {
1850 client->phase = AUTH_PHASE_ERROR;
1851 return AUTH_STATUS_ERROR;
1854 value_list[0] = AUTH_CHAP_ALG_MD5;
1856 if (acl_set_chap_alg_list(client, 1, value_list) !=
1857 AUTH_STATUS_NO_ERROR) {
1858 client->phase = AUTH_PHASE_ERROR;
1859 return AUTH_STATUS_ERROR;
1862 return AUTH_STATUS_NO_ERROR;
1866 acl_finish(struct iscsi_acl *client)
1868 if (!client || client->signature != ACL_SIGNATURE)
1869 return AUTH_STATUS_ERROR;
1871 memset(client, 0, sizeof(*client));
1873 return AUTH_STATUS_NO_ERROR;
1877 acl_set_user_name(struct iscsi_acl *client, const char *username)
1879 if (!client || client->signature != ACL_SIGNATURE)
1880 return AUTH_STATUS_ERROR;
1882 if (client->phase != AUTH_PHASE_CONFIGURE ||
1883 acl_chk_string(username, AUTH_STR_MAX_LEN, NULL)) {
1884 client->phase = AUTH_PHASE_ERROR;
1885 return AUTH_STATUS_ERROR;
1888 if (!username)
1889 client->username[0] = '\0';
1890 else if (strlcpy(client->username, username, AUTH_STR_MAX_LEN) >=
1891 AUTH_STR_MAX_LEN) {
1892 client->phase = AUTH_PHASE_ERROR;
1893 return AUTH_STATUS_ERROR;
1896 return AUTH_STATUS_NO_ERROR;
1900 acl_set_passwd(struct iscsi_acl *client, const unsigned char *passwd_data,
1901 unsigned int passwd_length)
1903 if (!client || client->signature != ACL_SIGNATURE)
1904 return AUTH_STATUS_ERROR;
1906 if (client->phase != AUTH_PHASE_CONFIGURE ||
1907 passwd_length > AUTH_STR_MAX_LEN) {
1908 client->phase = AUTH_PHASE_ERROR;
1909 return AUTH_STATUS_ERROR;
1912 memcpy(client->passwd_data, passwd_data, passwd_length);
1913 client->passwd_length = passwd_length;
1914 client->passwd_present = 1;
1916 /* Setting password may affect auth_method_valid. */
1917 acl_set_auth_method_valid(client);
1919 return AUTH_STATUS_NO_ERROR;
1923 acl_set_auth_rmt(struct iscsi_acl *client, int auth_rmt)
1925 if (!client || client->signature != ACL_SIGNATURE)
1926 return AUTH_STATUS_ERROR;
1928 if (client->phase != AUTH_PHASE_CONFIGURE) {
1929 client->phase = AUTH_PHASE_ERROR;
1930 return AUTH_STATUS_ERROR;
1933 client->auth_rmt = auth_rmt;
1935 /* Setting auth_rmt may affect auth_method_valid. */
1936 acl_set_auth_method_valid(client);
1938 return AUTH_STATUS_NO_ERROR;
1942 acl_set_ip_sec(struct iscsi_acl *client, int ip_sec)
1944 if (!client || client->signature != ACL_SIGNATURE)
1945 return AUTH_STATUS_ERROR;
1947 if (client->phase != AUTH_PHASE_CONFIGURE) {
1948 client->phase = AUTH_PHASE_ERROR;
1949 return AUTH_STATUS_ERROR;
1952 client->ip_sec = ip_sec;
1954 return AUTH_STATUS_NO_ERROR;
1958 acl_get_dbg_status(struct iscsi_acl *client, int *value)
1960 if (!client || client->signature != ACL_SIGNATURE)
1961 return AUTH_STATUS_ERROR;
1963 if (client->phase != AUTH_PHASE_DONE) {
1964 client->phase = AUTH_PHASE_ERROR;
1965 return AUTH_STATUS_ERROR;
1968 *value = client->dbg_status;
1970 return AUTH_STATUS_NO_ERROR;
1973 const char *
1974 acl_dbg_status_to_text(int dbg_status)
1977 * Note: The ordering of this table must match the order
1978 * defined by enum auth_dbg_status in iscsi-auth-client.h.
1980 static char *const dbg_text[AUTH_DBG_STATUS_MAX_COUNT] = {
1981 "Debug status not set",
1982 "Authentication request passed",
1983 "Authentication not enabled",
1984 "Authentication request failed",
1985 "AuthMethod bad",
1986 "CHAP algorithm bad",
1987 "Decrypt password failed",
1988 "Local password too short with no IPSec",
1989 "Unexpected error from authentication server",
1990 "Authentication request status bad",
1991 "Authentication pass status not valid",
1992 "Same key set more than once on send",
1993 "Key value too long on send",
1994 "Too much data on send",
1995 "AuthMethod key expected",
1996 "CHAP algorithm key expected",
1997 "CHAP identifier expected",
1998 "CHAP challenge expected",
1999 "CHAP response expected",
2000 "CHAP username expected",
2001 "AuthMethod key not present",
2002 "AuthMethod negotiation failed",
2003 "AuthMethod negotiated to none",
2004 "CHAP algorithm negotiation failed",
2005 "CHAP challange reflected",
2006 "Local password same as remote",
2007 "Local password not set",
2008 "CHAP identifier bad",
2009 "CHAP challenge bad",
2010 "CHAP response bad",
2011 "Unexpected key present",
2012 "T bit set on response, but not on previous message",
2013 "T bit set on response, but authenticaton not complete",
2014 "Message count limit reached on receive",
2015 "Same key set more than once on receive",
2016 "Key value too long on receive",
2017 "Too much data on receive"
2020 if (dbg_status < 0 || dbg_status >= AUTH_DBG_STATUS_MAX_COUNT)
2021 return "Unknown error";
2023 return dbg_text[dbg_status];
2027 acl_data(unsigned char *out_data, unsigned int *out_length,
2028 unsigned char *in_data, unsigned int in_length)
2030 if (*out_length < in_length)
2031 return 1; /* error */
2033 memcpy(out_data, in_data, in_length);
2034 *out_length = in_length;
2036 return 0; /* no error */