Blame usr/auth.c

Packit eace71
/*
Packit eace71
 * iSCSI Authorization Library
Packit eace71
 *
Packit eace71
 * maintained by open-iscsi@@googlegroups.com
Packit eace71
 *
Packit eace71
 * Originally based on:
Packit eace71
 * Copyright (C) 2001 Cisco Systems, Inc.
Packit eace71
 *
Packit eace71
 * This program is free software; you can redistribute it and/or modify
Packit eace71
 * it under the terms of the GNU General Public License as published
Packit eace71
 * by the Free Software Foundation; either version 2 of the License, or
Packit eace71
 * (at your option) any later version.
Packit eace71
 *
Packit eace71
 * This program is distributed in the hope that it will be useful, but
Packit eace71
 * WITHOUT ANY WARRANTY; without even the implied warranty of
Packit eace71
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Packit eace71
 * General Public License for more details.
Packit eace71
 *
Packit eace71
 * This file implements the iSCSI CHAP authentication method based on
Packit eace71
 * RFC 3720.  The code in this file is meant to be common for both kernel and
Packit eace71
 * user level and makes use of only limited  library  functions, presently only
Packit eace71
 * string.h. Routines specific to kernel, user level are implemented in
Packit eace71
 * separate files under the appropriate directories.
Packit eace71
 * This code in this files assumes a single thread of execution
Packit eace71
 * for each iscsi_acl structure, and does no locking.
Packit eace71
 */
Packit eace71
Packit eace71
#include <stdio.h>
Packit eace71
#include <stdlib.h>
Packit eace71
#include <string.h>
Packit eace71
#include <unistd.h>
Packit eace71
#include <fcntl.h>
Packit eace71
Packit eace71
#include "sysdeps.h"
Packit eace71
#include "auth.h"
Packit eace71
#include "initiator.h"
Packit eace71
#include "log.h"
Packit eace71
Packit eace71
static const char acl_hexstring[] = "0123456789abcdefABCDEF";
Packit eace71
static const char acl_base64_string[] =
Packit eace71
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
Packit eace71
static const char acl_authmethod_set_chap_alg_list[] = "CHAP";
Packit eace71
static const char acl_reject_option_name[] = "Reject";
Packit eace71
Packit eace71
#include <openssl/evp.h>
Packit eace71
static int auth_hash_init(EVP_MD_CTX **context, int chap_alg);
Packit eace71
static void auth_hash_update(EVP_MD_CTX *context, unsigned char *md, unsigned int);
Packit eace71
static unsigned int auth_hash_final(unsigned char *, EVP_MD_CTX *context);
Packit eace71
Packit eace71
void get_random_bytes(unsigned char *data, unsigned int length);
Packit eace71
size_t strlcpy(char *, const char *, size_t);
Packit eace71
size_t strlcat(char *, const char *, size_t);
Packit eace71
Packit eace71
enum auth_dbg_status
Packit eace71
acl_chap_compute_rsp(struct iscsi_acl *client, int rmt_auth, unsigned int id,
Packit eace71
		     unsigned char *challenge_data,
Packit eace71
		     unsigned int challenge_length,
Packit eace71
		     unsigned char *response_data)
Packit eace71
{
Packit eace71
	unsigned char id_data[1];
Packit eace71
	EVP_MD_CTX *context = NULL;
Packit eace71
	unsigned char out_data[AUTH_STR_MAX_LEN];
Packit eace71
	unsigned int out_length = AUTH_STR_MAX_LEN;
Packit eace71
Packit eace71
	if (!client->passwd_present)
Packit eace71
		return AUTH_DBG_STATUS_LOCAL_PASSWD_NOT_SET;
Packit eace71
Packit eace71
	if (auth_hash_init(&context, client->negotiated_chap_alg) != 0)
Packit eace71
		return AUTH_DBG_STATUS_AUTH_FAIL;
Packit eace71
Packit eace71
	/* id byte */
Packit eace71
	id_data[0] = id;
Packit eace71
	auth_hash_update(context, id_data, 1);
Packit eace71
Packit eace71
	/* decrypt password */
Packit eace71
	if (acl_data(out_data, &out_length, client->passwd_data,
Packit eace71
		     client->passwd_length))
Packit eace71
		return AUTH_DBG_STATUS_PASSWD_DECRYPT_FAILED;
Packit eace71
Packit eace71
	if (!rmt_auth && !client->ip_sec && out_length < 12)
Packit eace71
		return AUTH_DBG_STATUS_PASSWD_TOO_SHORT_WITH_NO_IPSEC;
Packit eace71
Packit eace71
	/* shared secret */
Packit eace71
	auth_hash_update(context, out_data, out_length);
Packit eace71
Packit eace71
	/* clear decrypted password */
Packit eace71
	memset(out_data, 0, AUTH_STR_MAX_LEN);
Packit eace71
Packit eace71
	/* challenge value */
Packit eace71
	auth_hash_update(context, challenge_data, challenge_length);
Packit eace71
Packit eace71
	auth_hash_final(response_data, context);
Packit eace71
Packit eace71
	return AUTH_DBG_STATUS_NOT_SET;	/* no error */
Packit eace71
}
Packit eace71
Packit eace71
/*
Packit eace71
 * Authenticate a target's CHAP response.
Packit eace71
 */
Packit eace71
int
Packit eace71
acl_chap_auth_request(struct iscsi_acl *client, char *username, unsigned int id,
Packit eace71
		      unsigned char *challenge_data,
Packit eace71
		      unsigned int challenge_length,
Packit eace71
		      unsigned char *response_data,
Packit eace71
		      unsigned int rsp_length)
Packit eace71
{
Packit eace71
	iscsi_session_t *session = client->session_handle;
Packit eace71
	EVP_MD_CTX *context = NULL;
Packit eace71
	unsigned char verify_data[client->chap_challenge_len];
Packit eace71
Packit eace71
	/* the expected credentials are in the session */
Packit eace71
	if (session->username_in == NULL) {
Packit eace71
		log_error("failing authentication, no incoming username "
Packit eace71
			  "configured to authenticate target %s",
Packit eace71
			  session->target_name);
Packit eace71
		return AUTH_STATUS_FAIL;
Packit eace71
	}
Packit eace71
	if (strcmp(username, session->username_in) != 0) {
Packit eace71
		log_error("failing authentication, received incorrect "
Packit eace71
			  "username from target %s", session->target_name);
Packit eace71
		return AUTH_STATUS_FAIL;
Packit eace71
	}
Packit eace71
Packit eace71
	if ((session->password_in_length < 1) ||
Packit eace71
	    (session->password_in == NULL) ||
Packit eace71
	    (session->password_in[0] == '\0')) {
Packit eace71
		log_error("failing authentication, no incoming password "
Packit eace71
		       "configured to authenticate target %s",
Packit eace71
		       session->target_name);
Packit eace71
		return AUTH_STATUS_FAIL;
Packit eace71
	}
Packit eace71
Packit eace71
	/* challenge length is I->T, and shouldn't need to be checked */
Packit eace71
Packit eace71
	if (rsp_length != sizeof(verify_data)) {
Packit eace71
		log_error("failing authentication, received incorrect "
Packit eace71
			  "CHAP response length %u from target %s",
Packit eace71
			  rsp_length, session->target_name);
Packit eace71
		return AUTH_STATUS_FAIL;
Packit eace71
	}
Packit eace71
Packit eace71
	if (auth_hash_init(&context, client->negotiated_chap_alg) != 0)
Packit eace71
		return AUTH_STATUS_FAIL;
Packit eace71
Packit eace71
	/* id byte */
Packit eace71
	verify_data[0] = id;
Packit eace71
	auth_hash_update(context, verify_data, 1);
Packit eace71
Packit eace71
	/* shared secret */
Packit eace71
	auth_hash_update(context, (unsigned char *)session->password_in,
Packit eace71
			session->password_in_length);
Packit eace71
Packit eace71
	/* challenge value */
Packit eace71
	auth_hash_update(context, (unsigned char *)challenge_data,
Packit eace71
			challenge_length);
Packit eace71
Packit eace71
	auth_hash_final(verify_data, context);
Packit eace71
Packit eace71
	if (memcmp(response_data, verify_data, sizeof(verify_data)) == 0) {
Packit eace71
		log_debug(1, "initiator authenticated target %s",
Packit eace71
			  session->target_name);
Packit eace71
		return AUTH_STATUS_PASS;
Packit eace71
	}
Packit eace71
Packit eace71
	log_error("failing authentication, received incorrect CHAP "
Packit eace71
		  "response from target %s", session->target_name);
Packit eace71
	return AUTH_STATUS_FAIL;
Packit eace71
}
Packit eace71
Packit eace71
static int auth_hash_init(EVP_MD_CTX **context, int chap_alg) {
Packit eace71
	const EVP_MD *digest = NULL;
Packit eace71
	*context = EVP_MD_CTX_new();
Packit eace71
	int rc;
Packit eace71
Packit eace71
	switch (chap_alg) {
Packit eace71
	case AUTH_CHAP_ALG_MD5:
Packit eace71
		digest = EVP_md5();
Packit eace71
		break;
Packit eace71
	case AUTH_CHAP_ALG_SHA1:
Packit eace71
		digest = EVP_sha1();
Packit eace71
		break;
Packit eace71
	case AUTH_CHAP_ALG_SHA256:
Packit eace71
		digest = EVP_sha256();
Packit eace71
		break;
Packit eace71
	case AUTH_CHAP_ALG_SHA3_256:
Packit eace71
		digest = EVP_sha3_256();
Packit eace71
		break;
Packit eace71
	}
Packit eace71
Packit eace71
	if (*context == NULL)
Packit eace71
		goto fail_context;
Packit eace71
	if (digest == NULL)
Packit eace71
		goto fail_digest;
Packit eace71
	rc = EVP_DigestInit_ex(*context, digest, NULL);
Packit eace71
	if (!rc)
Packit eace71
		goto fail_init;
Packit eace71
Packit eace71
	return 0;
Packit eace71
Packit eace71
fail_init:
Packit eace71
fail_digest:
Packit eace71
	EVP_MD_CTX_free(*context);
Packit eace71
	*context = NULL;
Packit eace71
fail_context:
Packit eace71
	return -1;
Packit eace71
}
Packit eace71
Packit eace71
static void auth_hash_update(EVP_MD_CTX *context, unsigned char *data, unsigned int length) {
Packit eace71
	EVP_DigestUpdate(context, data, length);
Packit eace71
}
Packit eace71
Packit eace71
static unsigned int auth_hash_final(unsigned char *hash, EVP_MD_CTX *context) {
Packit eace71
	unsigned int md_len;
Packit eace71
	EVP_DigestFinal_ex(context, hash, &md_len);
Packit eace71
	EVP_MD_CTX_free(context);
Packit eace71
	context = NULL;
Packit eace71
	return md_len;
Packit eace71
}
Packit eace71
Packit eace71
void
Packit eace71
get_random_bytes(unsigned char *data, unsigned int length)
Packit eace71
{
Packit eace71
Packit eace71
	long r;
Packit eace71
        unsigned n;
Packit eace71
	int fd, r_size = sizeof(r);
Packit eace71
Packit eace71
	fd = open("/dev/urandom", O_RDONLY);
Packit eace71
        while (length > 0) {
Packit eace71
Packit eace71
		if (fd == -1 || read(fd, &r, r_size) != r_size)
Packit eace71
			r = rand();
Packit eace71
                r = r ^ (r >> 8);
Packit eace71
                r = r ^ (r >> 4);
Packit eace71
                n = r & 0x7;
Packit eace71
Packit eace71
		if (fd == -1 || read(fd, &r, r_size) != r_size)
Packit eace71
			r = rand();
Packit eace71
                r = r ^ (r >> 8);
Packit eace71
                r = r ^ (r >> 5);
Packit eace71
                n = (n << 3) | (r & 0x7);
Packit eace71
Packit eace71
		if (fd == -1 || read(fd, &r, r_size) != r_size)
Packit eace71
			r = rand();
Packit eace71
                r = r ^ (r >> 8);
Packit eace71
                r = r ^ (r >> 5);
Packit eace71
                n = (n << 2) | (r & 0x3);
Packit eace71
Packit eace71
                *data++ = n;
Packit eace71
                length--;
Packit eace71
        }
Packit eace71
	if (fd)
Packit eace71
		close(fd);
Packit eace71
}
Packit eace71
Packit eace71
static const char acl_none_option_name[] = "None";
Packit eace71
Packit eace71
static int
Packit eace71
acl_text_to_number(const char *text, unsigned long *num)
Packit eace71
{
Packit eace71
	char *end;
Packit eace71
	unsigned long number;
Packit eace71
Packit eace71
	if (text[0] == '0' && (text[1] == 'x' || text[1] == 'X'))
Packit eace71
		number = strtoul(text + 2, &end, 16);
Packit eace71
	else
Packit eace71
		number = strtoul(text, &end, 10);
Packit eace71
Packit eace71
	if (*text != '\0' && *end == '\0') {
Packit eace71
		*num = number;
Packit eace71
		return 0;	/* No error */
Packit eace71
	} else
Packit eace71
		return 1;	/* Error */
Packit eace71
}
Packit eace71
Packit eace71
static int
Packit eace71
acl_chk_string(const char *s, unsigned int max_len, unsigned int *out_len)
Packit eace71
{
Packit eace71
	unsigned int len;
Packit eace71
Packit eace71
	if (!s)
Packit eace71
		return 1;
Packit eace71
Packit eace71
	for (len = 0; len < max_len; len++)
Packit eace71
		if (*s++ == '\0') {
Packit eace71
			if (out_len)
Packit eace71
				*out_len = len;
Packit eace71
			return 0;
Packit eace71
		}
Packit eace71
Packit eace71
	return 1;
Packit eace71
}
Packit eace71
Packit eace71
static int
Packit eace71
acl_str_index(const char *s, int c)
Packit eace71
{
Packit eace71
	char *str = strchr(s, c);
Packit eace71
Packit eace71
	if (str)
Packit eace71
		return (str - s);
Packit eace71
	else
Packit eace71
		return -1;
Packit eace71
}
Packit eace71
Packit eace71
static int
Packit eace71
acl_chk_auth_mthd_optn(int val)
Packit eace71
{
Packit eace71
	if (val == AUTH_OPTION_NONE || val == AUTH_METHOD_CHAP)
Packit eace71
		return 0;
Packit eace71
Packit eace71
	return 1;
Packit eace71
}
Packit eace71
Packit eace71
static const char *
Packit eace71
acl_authmethod_optn_to_text(int value)
Packit eace71
{
Packit eace71
	const char *s;
Packit eace71
	switch (value) {
Packit eace71
	case AUTH_OPTION_REJECT:
Packit eace71
		s = acl_reject_option_name;
Packit eace71
		break;
Packit eace71
	case AUTH_OPTION_NONE:
Packit eace71
		s = acl_none_option_name;
Packit eace71
		break;
Packit eace71
	case AUTH_METHOD_CHAP:
Packit eace71
		s = acl_authmethod_set_chap_alg_list;
Packit eace71
		break;
Packit eace71
	default:
Packit eace71
		s = NULL;
Packit eace71
	}
Packit eace71
	return s;
Packit eace71
}
Packit eace71
Packit eace71
static int
Packit eace71
acl_chk_chap_alg_optn(int chap_algorithm)
Packit eace71
{
Packit eace71
	if (chap_algorithm == AUTH_OPTION_NONE ||
Packit eace71
	    chap_algorithm == AUTH_CHAP_ALG_SHA3_256 ||
Packit eace71
	    chap_algorithm == AUTH_CHAP_ALG_SHA256 ||
Packit eace71
	    chap_algorithm == AUTH_CHAP_ALG_SHA1 ||
Packit eace71
	    chap_algorithm == AUTH_CHAP_ALG_MD5)
Packit eace71
		return 0;
Packit eace71
Packit eace71
	return 1;
Packit eace71
}
Packit eace71
Packit eace71
static int
Packit eace71
acl_data_to_text(unsigned char *data, unsigned int data_length, char *text,
Packit eace71
		 unsigned int text_length)
Packit eace71
{
Packit eace71
	unsigned long n;
Packit eace71
Packit eace71
	if (!text || text_length == 0)
Packit eace71
		return 1;
Packit eace71
Packit eace71
	if (!data || data_length == 0) {
Packit eace71
		*text = '\0';
Packit eace71
		return 1;
Packit eace71
	}
Packit eace71
Packit eace71
	if (text_length < 3) {
Packit eace71
		*text = '\0';
Packit eace71
		return 1;
Packit eace71
	}
Packit eace71
Packit eace71
	*text++ = '0';
Packit eace71
	*text++ = 'x';
Packit eace71
Packit eace71
	text_length -= 2;
Packit eace71
Packit eace71
	while (data_length > 0) {
Packit eace71
Packit eace71
		if (text_length < 3) {
Packit eace71
			*text = '\0';
Packit eace71
			return 1;
Packit eace71
		}
Packit eace71
Packit eace71
		n = *data++;
Packit eace71
		data_length--;
Packit eace71
Packit eace71
		*text++ = acl_hexstring[(n >> 4) & 0xf];
Packit eace71
		*text++ = acl_hexstring[n & 0xf];
Packit eace71
Packit eace71
		text_length -= 2;
Packit eace71
	}
Packit eace71
Packit eace71
	*text = '\0';
Packit eace71
Packit eace71
	return 0;
Packit eace71
}
Packit eace71
Packit eace71
static int
Packit eace71
acl_hex_to_data(const char *text, unsigned int text_length, unsigned char *data,
Packit eace71
		unsigned int *data_lenp)
Packit eace71
{
Packit eace71
	int i;
Packit eace71
	unsigned int n1;
Packit eace71
	unsigned int n2;
Packit eace71
	unsigned int data_length = *data_lenp;
Packit eace71
Packit eace71
	if ((text_length % 2) == 1) {
Packit eace71
Packit eace71
		i = acl_str_index(acl_hexstring, *text++);
Packit eace71
		if (i < 0)
Packit eace71
			return 1;	/* error, bad character */
Packit eace71
Packit eace71
		if (i > 15)
Packit eace71
			i -= 6;
Packit eace71
		n2 = i;
Packit eace71
Packit eace71
		if (data_length < 1)
Packit eace71
			return 1;	/* error, too much data */
Packit eace71
Packit eace71
		*data++ = n2;
Packit eace71
		data_length--;
Packit eace71
	}
Packit eace71
Packit eace71
	while (*text != '\0') {
Packit eace71
		i = acl_str_index(acl_hexstring, *text++);
Packit eace71
		if (i < 0)
Packit eace71
			return 1;	/* error, bad character */
Packit eace71
Packit eace71
		if (i > 15)
Packit eace71
			i -= 6;
Packit eace71
		n1 = i;
Packit eace71
Packit eace71
		if (*text == '\0')
Packit eace71
			return 1;	/* error, odd string length */
Packit eace71
Packit eace71
		i = acl_str_index(acl_hexstring, *text++);
Packit eace71
		if (i < 0)
Packit eace71
			return 1;	/* error, bad character */
Packit eace71
Packit eace71
		if (i > 15)
Packit eace71
			i -= 6;
Packit eace71
		n2 = i;
Packit eace71
Packit eace71
		if (data_length < 1)
Packit eace71
			return 1;	/* error, too much data */
Packit eace71
Packit eace71
		*data++ = (n1 << 4) | n2;
Packit eace71
		data_length--;
Packit eace71
	}
Packit eace71
Packit eace71
	if (data_length >= *data_lenp)
Packit eace71
		return 1;	/* error, no data */
Packit eace71
Packit eace71
	*data_lenp = *data_lenp - data_length;
Packit eace71
Packit eace71
	return 0;		/* no error */
Packit eace71
}
Packit eace71
Packit eace71
static int
Packit eace71
acl_base64_to_data(const char *text, unsigned char *data,
Packit eace71
		   unsigned int *data_lenp)
Packit eace71
{
Packit eace71
	int i;
Packit eace71
	unsigned int n;
Packit eace71
	unsigned int count;
Packit eace71
	unsigned int data_length = *data_lenp;
Packit eace71
Packit eace71
	n = 0;
Packit eace71
	count = 0;
Packit eace71
Packit eace71
	while (*text != '\0' && *text != '=') {
Packit eace71
Packit eace71
		i = acl_str_index(acl_base64_string, *text++);
Packit eace71
		if (i < 0)
Packit eace71
			return 1;	/* error, bad character */
Packit eace71
Packit eace71
		n = (n << 6 | (unsigned int)i);
Packit eace71
		count++;
Packit eace71
Packit eace71
		if (count >= 4) {
Packit eace71
			if (data_length < 3)
Packit eace71
				return 1;	/* error, too much data */
Packit eace71
			*data++ = n >> 16;
Packit eace71
			*data++ = n >> 8;
Packit eace71
			*data++ = n;
Packit eace71
			data_length -= 3;
Packit eace71
			n = 0;
Packit eace71
			count = 0;
Packit eace71
		}
Packit eace71
	}
Packit eace71
Packit eace71
	while (*text != '\0')
Packit eace71
		if (*text++ != '=')
Packit eace71
			return 1;	/* error, bad pad */
Packit eace71
Packit eace71
	if (count == 0) {
Packit eace71
		/* do nothing */
Packit eace71
	} else if (count == 2) {
Packit eace71
		if (data_length < 1)
Packit eace71
			return 1;	/* error, too much data */
Packit eace71
		n = n >> 4;
Packit eace71
		*data++ = n;
Packit eace71
		data_length--;
Packit eace71
	} else if (count == 3) {
Packit eace71
		if (data_length < 2)
Packit eace71
			return 1;	/* error, too much data */
Packit eace71
		n = n >> 2;
Packit eace71
		*data++ = n >> 8;
Packit eace71
		*data++ = n;
Packit eace71
		data_length -= 2;
Packit eace71
	} else
Packit eace71
		return 1;	/* bad encoding */
Packit eace71
Packit eace71
	if (data_length >= *data_lenp)
Packit eace71
		return 1;	/* error, no data */
Packit eace71
Packit eace71
	*data_lenp = *data_lenp - data_length;
Packit eace71
Packit eace71
	return 0;		/* no error */
Packit eace71
}
Packit eace71
Packit eace71
static int
Packit eace71
acl_text_to_data(const char *text, unsigned char *data,
Packit eace71
		 unsigned int *data_length)
Packit eace71
{
Packit eace71
	int status;
Packit eace71
	unsigned int text_length;
Packit eace71
Packit eace71
	status = acl_chk_string(text, 2 + 2 * AUTH_LARGE_BINARY_MAX_LEN + 1,
Packit eace71
				&text_length);
Packit eace71
	if (status)
Packit eace71
		return status;
Packit eace71
Packit eace71
	if (text[0] == '0' && (text[1] == 'x' || text[1] == 'X')) {
Packit eace71
		/* skip prefix */
Packit eace71
		text += 2;
Packit eace71
		text_length -= 2;
Packit eace71
		status = acl_hex_to_data(text, text_length, data, data_length);
Packit eace71
	} else if (text[0] == '0' && (text[1] == 'b' || text[1] == 'B')) {
Packit eace71
		/* skip prefix */
Packit eace71
		text += 2;
Packit eace71
		text_length -= 2;
Packit eace71
		status = acl_base64_to_data(text, data, data_length);
Packit eace71
	} else
Packit eace71
		status = 1;	/* prefix not recognized. */
Packit eace71
Packit eace71
	return status;
Packit eace71
}
Packit eace71
Packit eace71
static void
Packit eace71
acl_init_key_blk(struct auth_key_block *key_blk)
Packit eace71
{
Packit eace71
	char *str_block = key_blk->str_block;
Packit eace71
Packit eace71
	memset(key_blk, 0, sizeof(*key_blk));
Packit eace71
	key_blk->str_block = str_block;
Packit eace71
}
Packit eace71
Packit eace71
static void
Packit eace71
acl_set_key_value(struct auth_key_block *key_blk, int key_type,
Packit eace71
		  const char *key_val)
Packit eace71
{
Packit eace71
	unsigned int length;
Packit eace71
	char *string;
Packit eace71
Packit eace71
	if (key_blk->key[key_type].value_set) {
Packit eace71
		key_blk->dup_set = 1;
Packit eace71
		return;
Packit eace71
	}
Packit eace71
Packit eace71
	key_blk->key[key_type].value_set = 1;
Packit eace71
Packit eace71
	if (!key_val)
Packit eace71
		return;
Packit eace71
Packit eace71
	if (acl_chk_string(key_val, AUTH_STR_MAX_LEN, &length)) {
Packit eace71
		key_blk->str_too_long = 1;
Packit eace71
		return;
Packit eace71
	}
Packit eace71
Packit eace71
	length += 1;
Packit eace71
Packit eace71
	if ((key_blk->blk_length + length) > AUTH_STR_BLOCK_MAX_LEN) {
Packit eace71
		key_blk->too_much_data = 1;
Packit eace71
		return;
Packit eace71
	}
Packit eace71
Packit eace71
	string = &key_blk->str_block[key_blk->blk_length];
Packit eace71
Packit eace71
	if (strlcpy(string, key_val, length) >= length) {
Packit eace71
		key_blk->too_much_data = 1;
Packit eace71
		return;
Packit eace71
	}
Packit eace71
	key_blk->blk_length += length;
Packit eace71
Packit eace71
	key_blk->key[key_type].string = string;
Packit eace71
	key_blk->key[key_type].present = 1;
Packit eace71
}
Packit eace71
Packit eace71
static const char *
Packit eace71
acl_get_key_val(struct auth_key_block *key_blk, int key_type)
Packit eace71
{
Packit eace71
	key_blk->key[key_type].processed = 1;
Packit eace71
Packit eace71
	if (!key_blk->key[key_type].present)
Packit eace71
		return NULL;
Packit eace71
Packit eace71
	return key_blk->key[key_type].string;
Packit eace71
}
Packit eace71
Packit eace71
static void
Packit eace71
acl_chk_key(struct iscsi_acl *client, int key_type, int *negotiated_option,
Packit eace71
	    unsigned int option_count, int *option_list,
Packit eace71
	    const char *(*value_to_text) (int))
Packit eace71
{
Packit eace71
	const char *key_val;
Packit eace71
	int length;
Packit eace71
	unsigned int i;
Packit eace71
Packit eace71
	key_val = acl_get_key_val(&client->recv_key_block, key_type);
Packit eace71
	if (!key_val) {
Packit eace71
		*negotiated_option = AUTH_OPTION_NOT_PRESENT;
Packit eace71
		return;
Packit eace71
	}
Packit eace71
Packit eace71
	while (*key_val != '\0') {
Packit eace71
Packit eace71
		length = 0;
Packit eace71
Packit eace71
		while (*key_val != '\0' && *key_val != ',')
Packit eace71
			client->scratch_key_value[length++] = *key_val++;
Packit eace71
Packit eace71
		if (*key_val == ',')
Packit eace71
			key_val++;
Packit eace71
		client->scratch_key_value[length++] = '\0';
Packit eace71
Packit eace71
		for (i = 0; i < option_count; i++) {
Packit eace71
			const char *s = (*value_to_text)(option_list[i]);
Packit eace71
Packit eace71
			if (!s)
Packit eace71
				continue;
Packit eace71
Packit eace71
			if (strcmp(client->scratch_key_value, s) == 0) {
Packit eace71
				*negotiated_option = option_list[i];
Packit eace71
				return;
Packit eace71
			}
Packit eace71
		}
Packit eace71
	}
Packit eace71
Packit eace71
	*negotiated_option = AUTH_OPTION_REJECT;
Packit eace71
}
Packit eace71
Packit eace71
static void
Packit eace71
acl_set_key(struct iscsi_acl *client, int key_type, unsigned int option_count,
Packit eace71
	    int *option_list, const char *(*value_to_text)(int))
Packit eace71
{
Packit eace71
	unsigned int i;
Packit eace71
Packit eace71
	if (option_count == 0) {
Packit eace71
		/*
Packit eace71
		 * No valid options to send, but we always want to
Packit eace71
		 * send something.
Packit eace71
		 */
Packit eace71
		acl_set_key_value(&client->send_key_block, key_type,
Packit eace71
				  acl_none_option_name);
Packit eace71
		return;
Packit eace71
	}
Packit eace71
Packit eace71
	if (option_count == 1 && option_list[0] == AUTH_OPTION_NOT_PRESENT) {
Packit eace71
		acl_set_key_value(&client->send_key_block, key_type, NULL);
Packit eace71
		return;
Packit eace71
	}
Packit eace71
Packit eace71
	for (i = 0; i < option_count; i++) {
Packit eace71
		const char *s = (*value_to_text)(option_list[i]);
Packit eace71
Packit eace71
		if (!s)
Packit eace71
			continue;
Packit eace71
Packit eace71
		if (i == 0)
Packit eace71
			strlcpy(client->scratch_key_value, s,
Packit eace71
				   AUTH_STR_MAX_LEN);
Packit eace71
		else {
Packit eace71
			strlcat(client->scratch_key_value, ",",
Packit eace71
				   AUTH_STR_MAX_LEN);
Packit eace71
			strlcat(client->scratch_key_value, s,
Packit eace71
				   AUTH_STR_MAX_LEN);
Packit eace71
		}
Packit eace71
	}
Packit eace71
Packit eace71
	acl_set_key_value(&client->send_key_block, key_type,
Packit eace71
			  client->scratch_key_value);
Packit eace71
}
Packit eace71
Packit eace71
static void
Packit eace71
acl_chk_auth_method_key(struct iscsi_acl *client)
Packit eace71
{
Packit eace71
	acl_chk_key(client, AUTH_KEY_TYPE_AUTH_METHOD,
Packit eace71
		    &client->negotiated_auth_method,
Packit eace71
		    client->auth_method_valid_count,
Packit eace71
		    client->auth_method_valid_list,
Packit eace71
		    acl_authmethod_optn_to_text);
Packit eace71
}
Packit eace71
Packit eace71
static void
Packit eace71
acl_set_auth_method_key(struct iscsi_acl *client,
Packit eace71
			unsigned int auth_method_count, int *auth_method_list)
Packit eace71
{
Packit eace71
	acl_set_key(client, AUTH_KEY_TYPE_AUTH_METHOD, auth_method_count,
Packit eace71
		    auth_method_list, acl_authmethod_optn_to_text);
Packit eace71
}
Packit eace71
Packit eace71
static void
Packit eace71
acl_chk_chap_alg_key(struct iscsi_acl *client)
Packit eace71
{
Packit eace71
	const char *key_val;
Packit eace71
	int length;
Packit eace71
	unsigned long number;
Packit eace71
	unsigned int i;
Packit eace71
Packit eace71
	key_val = acl_get_key_val(&client->recv_key_block,
Packit eace71
				  AUTH_KEY_TYPE_CHAP_ALG);
Packit eace71
	if (!key_val) {
Packit eace71
		client->negotiated_chap_alg = AUTH_OPTION_NOT_PRESENT;
Packit eace71
		return;
Packit eace71
	}
Packit eace71
Packit eace71
	while (*key_val != '\0') {
Packit eace71
Packit eace71
		length = 0;
Packit eace71
Packit eace71
		while (*key_val != '\0' && *key_val != ',')
Packit eace71
			client->scratch_key_value[length++] = *key_val++;
Packit eace71
Packit eace71
		if (*key_val == ',')
Packit eace71
			key_val++;
Packit eace71
		client->scratch_key_value[length++] = '\0';
Packit eace71
Packit eace71
		if (acl_text_to_number(client->scratch_key_value, &number))
Packit eace71
			continue;
Packit eace71
Packit eace71
Packit eace71
		for (i = 0; i < client->chap_alg_count; i++)
Packit eace71
			if (number == (unsigned long)client->chap_alg_list[i])
Packit eace71
			{
Packit eace71
				client->negotiated_chap_alg = number;
Packit eace71
				switch (number) {
Packit eace71
				case AUTH_CHAP_ALG_MD5:
Packit eace71
					client->chap_challenge_len = AUTH_CHAP_MD5_RSP_LEN;
Packit eace71
					break;
Packit eace71
				case AUTH_CHAP_ALG_SHA1:
Packit eace71
					client->chap_challenge_len = AUTH_CHAP_SHA1_RSP_LEN;
Packit eace71
					break;
Packit eace71
				case AUTH_CHAP_ALG_SHA256:
Packit eace71
					client->chap_challenge_len = AUTH_CHAP_SHA256_RSP_LEN;
Packit eace71
					break;
Packit eace71
				case AUTH_CHAP_ALG_SHA3_256:
Packit eace71
					client->chap_challenge_len = AUTH_CHAP_SHA3_256_RSP_LEN;
Packit eace71
					break;
Packit eace71
				}
Packit eace71
				return;
Packit eace71
			}
Packit eace71
	}
Packit eace71
Packit eace71
	client->negotiated_chap_alg = AUTH_OPTION_REJECT;
Packit eace71
}
Packit eace71
Packit eace71
static void
Packit eace71
acl_set_chap_alg_key(struct iscsi_acl *client, unsigned int chap_alg_count,
Packit eace71
		     int *chap_alg_list)
Packit eace71
{
Packit eace71
	unsigned int i;
Packit eace71
Packit eace71
	if (chap_alg_count == 0) {
Packit eace71
		acl_set_key_value(&client->send_key_block,
Packit eace71
				  AUTH_KEY_TYPE_CHAP_ALG, NULL);
Packit eace71
		return;
Packit eace71
	}
Packit eace71
Packit eace71
	if (chap_alg_count == 1 &&
Packit eace71
	    chap_alg_list[0] == AUTH_OPTION_NOT_PRESENT) {
Packit eace71
		acl_set_key_value(&client->send_key_block,
Packit eace71
				  AUTH_KEY_TYPE_CHAP_ALG, NULL);
Packit eace71
		return;
Packit eace71
	}
Packit eace71
Packit eace71
	if (chap_alg_count == 1 && chap_alg_list[0] == AUTH_OPTION_REJECT) {
Packit eace71
		acl_set_key_value(&client->send_key_block,
Packit eace71
				  AUTH_KEY_TYPE_CHAP_ALG,
Packit eace71
				  acl_reject_option_name);
Packit eace71
		return;
Packit eace71
	}
Packit eace71
Packit eace71
	for (i = 0; i < chap_alg_count; i++) {
Packit eace71
		char s[20];
Packit eace71
Packit eace71
		snprintf(s, sizeof(s), "%lu",(unsigned long)chap_alg_list[i]);
Packit eace71
Packit eace71
		if (i == 0)
Packit eace71
			strlcpy(client->scratch_key_value, s,
Packit eace71
				   AUTH_STR_MAX_LEN);
Packit eace71
		 else {
Packit eace71
			strlcat(client->scratch_key_value, ",",
Packit eace71
				   AUTH_STR_MAX_LEN);
Packit eace71
			strlcat(client->scratch_key_value, s,
Packit eace71
				   AUTH_STR_MAX_LEN);
Packit eace71
		}
Packit eace71
	}
Packit eace71
Packit eace71
	acl_set_key_value(&client->send_key_block, AUTH_KEY_TYPE_CHAP_ALG,
Packit eace71
			  client->scratch_key_value);
Packit eace71
}
Packit eace71
Packit eace71
static void
Packit eace71
acl_next_phase(struct iscsi_acl *client)
Packit eace71
{
Packit eace71
	switch (client->phase) {
Packit eace71
	case AUTH_PHASE_CONFIGURE:
Packit eace71
		client->phase = AUTH_PHASE_NEGOTIATE;
Packit eace71
		break;
Packit eace71
	case AUTH_PHASE_NEGOTIATE:
Packit eace71
		client->phase = AUTH_PHASE_AUTHENTICATE;
Packit eace71
Packit eace71
		if (client->negotiated_auth_method == AUTH_OPTION_REJECT ||
Packit eace71
		    client->negotiated_auth_method == AUTH_OPTION_NOT_PRESENT ||
Packit eace71
		    client->negotiated_auth_method == AUTH_OPTION_NONE) {
Packit eace71
Packit eace71
			client->local_state = AUTH_LOCAL_STATE_DONE;
Packit eace71
			client->rmt_state = AUTH_RMT_STATE_DONE;
Packit eace71
Packit eace71
			if (client->auth_rmt) {
Packit eace71
				client->rmt_auth_status = AUTH_STATUS_FAIL;
Packit eace71
				client->phase = AUTH_PHASE_DONE;
Packit eace71
			} else
Packit eace71
				client->rmt_auth_status = AUTH_STATUS_PASS;
Packit eace71
Packit eace71
			switch (client->negotiated_auth_method) {
Packit eace71
			case AUTH_OPTION_REJECT:
Packit eace71
				client->dbg_status =
Packit eace71
				    AUTH_DBG_STATUS_AUTH_METHOD_REJECT;
Packit eace71
				break;
Packit eace71
			case AUTH_OPTION_NOT_PRESENT:
Packit eace71
				client->dbg_status =
Packit eace71
				    AUTH_DBG_STATUS_AUTH_METHOD_NOT_PRESENT;
Packit eace71
				break;
Packit eace71
			case AUTH_OPTION_NONE:
Packit eace71
				client->dbg_status =
Packit eace71
				    AUTH_DBG_STATUS_AUTH_METHOD_NONE;
Packit eace71
			}
Packit eace71
Packit eace71
		} else if (client->negotiated_auth_method == AUTH_METHOD_CHAP) {
Packit eace71
			client->local_state = AUTH_LOCAL_STATE_SEND_ALG;
Packit eace71
			client->rmt_state = AUTH_RMT_STATE_SEND_ALG;
Packit eace71
		} else {
Packit eace71
Packit eace71
			client->local_state = AUTH_LOCAL_STATE_DONE;
Packit eace71
			client->rmt_state = AUTH_RMT_STATE_DONE;
Packit eace71
			client->rmt_auth_status = AUTH_STATUS_FAIL;
Packit eace71
			client->dbg_status = AUTH_DBG_STATUS_AUTH_METHOD_BAD;
Packit eace71
		}
Packit eace71
		break;
Packit eace71
	case AUTH_PHASE_AUTHENTICATE:
Packit eace71
		client->phase = AUTH_PHASE_DONE;
Packit eace71
		break;
Packit eace71
	case AUTH_PHASE_DONE:
Packit eace71
	case AUTH_PHASE_ERROR:
Packit eace71
	default:
Packit eace71
		client->phase = AUTH_PHASE_ERROR;
Packit eace71
	}
Packit eace71
}
Packit eace71
Packit eace71
static void
Packit eace71
acl_local_auth(struct iscsi_acl *client)
Packit eace71
{
Packit eace71
	unsigned int chap_identifier;
Packit eace71
	unsigned char response_data[AUTH_CHAP_RSP_MAX];
Packit eace71
	unsigned long number;
Packit eace71
	int status;
Packit eace71
	enum auth_dbg_status dbg_status;
Packit eace71
	const char *chap_identifier_key_val;
Packit eace71
	const char *chap_challenge_key_val;
Packit eace71
Packit eace71
	switch (client->local_state) {
Packit eace71
	case AUTH_LOCAL_STATE_SEND_ALG:
Packit eace71
		if (client->node_type == TYPE_INITIATOR) {
Packit eace71
			acl_set_chap_alg_key(client, client->chap_alg_count,
Packit eace71
					     client->chap_alg_list);
Packit eace71
			client->local_state = AUTH_LOCAL_STATE_RECV_ALG;
Packit eace71
			break;
Packit eace71
		}
Packit eace71
		/* Fall through */
Packit eace71
	case AUTH_LOCAL_STATE_RECV_ALG:
Packit eace71
		acl_chk_chap_alg_key(client);
Packit eace71
Packit eace71
		if (client->node_type == TYPE_TARGET)
Packit eace71
			acl_set_chap_alg_key(client, 1,
Packit eace71
					     &client->negotiated_chap_alg);
Packit eace71
Packit eace71
		/* Make sure only supported CHAP algorithm is used. */
Packit eace71
		if (client->negotiated_chap_alg == AUTH_OPTION_NOT_PRESENT) {
Packit eace71
			client->local_state = AUTH_LOCAL_STATE_ERROR;
Packit eace71
			client->dbg_status = AUTH_DBG_STATUS_CHAP_ALG_EXPECTED;
Packit eace71
			break;
Packit eace71
		} else if (client->negotiated_chap_alg == AUTH_OPTION_REJECT) {
Packit eace71
			client->local_state = AUTH_LOCAL_STATE_ERROR;
Packit eace71
			client->dbg_status = AUTH_DBG_STATUS_CHAP_ALG_REJECT;
Packit eace71
			break;
Packit eace71
		} else if ((client->negotiated_chap_alg != AUTH_CHAP_ALG_SHA3_256) &&
Packit eace71
			   (client->negotiated_chap_alg != AUTH_CHAP_ALG_SHA256) &&
Packit eace71
			   (client->negotiated_chap_alg != AUTH_CHAP_ALG_SHA1) &&
Packit eace71
			   (client->negotiated_chap_alg != AUTH_CHAP_ALG_MD5)) {
Packit eace71
			client->local_state = AUTH_LOCAL_STATE_ERROR;
Packit eace71
			client->dbg_status = AUTH_DBG_STATUS_CHAP_ALG_BAD;
Packit eace71
			break;
Packit eace71
		}
Packit eace71
		if (client->node_type == TYPE_TARGET) {
Packit eace71
			client->local_state = AUTH_LOCAL_STATE_RECV_CHALLENGE;
Packit eace71
			break;
Packit eace71
		}
Packit eace71
		/* Fall through */
Packit eace71
	case AUTH_LOCAL_STATE_RECV_CHALLENGE:
Packit eace71
		chap_identifier_key_val = acl_get_key_val(&client->recv_key_block,
Packit eace71
							  AUTH_KEY_TYPE_CHAP_IDENTIFIER);
Packit eace71
		chap_challenge_key_val = acl_get_key_val(&client->recv_key_block,
Packit eace71
							 AUTH_KEY_TYPE_CHAP_CHALLENGE);
Packit eace71
		if (client->node_type == TYPE_TARGET) {
Packit eace71
			if (!chap_identifier_key_val &&
Packit eace71
			    !chap_challenge_key_val) {
Packit eace71
				client->local_state = AUTH_LOCAL_STATE_DONE;
Packit eace71
				break;
Packit eace71
			}
Packit eace71
		}
Packit eace71
Packit eace71
		if (!chap_identifier_key_val) {
Packit eace71
			client->local_state = AUTH_LOCAL_STATE_ERROR;
Packit eace71
			client->dbg_status =
Packit eace71
			    AUTH_DBG_STATUS_CHAP_IDENTIFIER_EXPECTED;
Packit eace71
			break;
Packit eace71
		}
Packit eace71
Packit eace71
		if (!chap_challenge_key_val) {
Packit eace71
			client->local_state = AUTH_LOCAL_STATE_ERROR;
Packit eace71
			client->dbg_status =
Packit eace71
			    AUTH_DBG_STATUS_CHAP_CHALLENGE_EXPECTED;
Packit eace71
			break;
Packit eace71
		}
Packit eace71
Packit eace71
		status = acl_text_to_number(chap_identifier_key_val, &number);
Packit eace71
		if (status || (255 < number)) {
Packit eace71
			client->local_state = AUTH_LOCAL_STATE_ERROR;
Packit eace71
			client->dbg_status = AUTH_DBG_STATUS_CHAP_IDENTIFIER_BAD;
Packit eace71
			break;
Packit eace71
		}
Packit eace71
		chap_identifier = number;
Packit eace71
Packit eace71
		if (client->recv_chap_challenge_status) {
Packit eace71
			client->local_state = AUTH_LOCAL_STATE_ERROR;
Packit eace71
			client->dbg_status = AUTH_DBG_STATUS_CHALLENGE_BAD;
Packit eace71
			break;
Packit eace71
		}
Packit eace71
Packit eace71
		if (client->node_type == TYPE_TARGET &&
Packit eace71
		    client->recv_chap_challenge.length ==
Packit eace71
		    client->send_chap_challenge.length &&
Packit eace71
		    memcmp(client->recv_chap_challenge.large_binary,
Packit eace71
			   client->send_chap_challenge.large_binary,
Packit eace71
			   client->send_chap_challenge.length) == 0) {
Packit eace71
			client->local_state = AUTH_LOCAL_STATE_ERROR;
Packit eace71
			client->dbg_status =
Packit eace71
			    AUTH_DBG_STATUS_CHAP_CHALLENGE_REFLECTED;
Packit eace71
			break;
Packit eace71
		}
Packit eace71
Packit eace71
		dbg_status = acl_chap_compute_rsp(client, 0,
Packit eace71
						  chap_identifier,
Packit eace71
						  client->recv_chap_challenge.large_binary,
Packit eace71
						  client->recv_chap_challenge.length,
Packit eace71
						  response_data);
Packit eace71
Packit eace71
		if (dbg_status != AUTH_DBG_STATUS_NOT_SET) {
Packit eace71
			client->local_state = AUTH_LOCAL_STATE_ERROR;
Packit eace71
			client->dbg_status = dbg_status;
Packit eace71
			break;
Packit eace71
		}
Packit eace71
Packit eace71
		acl_data_to_text(response_data, client->chap_challenge_len,
Packit eace71
				 client->scratch_key_value,
Packit eace71
				 AUTH_STR_MAX_LEN);
Packit eace71
		acl_set_key_value(&client->send_key_block,
Packit eace71
				  AUTH_KEY_TYPE_CHAP_RSP,
Packit eace71
				  client->scratch_key_value);
Packit eace71
		acl_set_key_value(&client->send_key_block,
Packit eace71
				  AUTH_KEY_TYPE_CHAP_USERNAME,
Packit eace71
				  client->username);
Packit eace71
Packit eace71
		client->local_state = AUTH_LOCAL_STATE_DONE;
Packit eace71
		break;
Packit eace71
	case AUTH_LOCAL_STATE_DONE:
Packit eace71
		break;
Packit eace71
	case AUTH_LOCAL_STATE_ERROR:
Packit eace71
	default:
Packit eace71
		client->phase = AUTH_PHASE_ERROR;
Packit eace71
	}
Packit eace71
}
Packit eace71
Packit eace71
static void
Packit eace71
acl_rmt_auth(struct iscsi_acl *client)
Packit eace71
{
Packit eace71
	unsigned char id_data[1];
Packit eace71
	unsigned char response_data[AUTH_STR_MAX_LEN];
Packit eace71
	unsigned int rsp_len = AUTH_STR_MAX_LEN;
Packit eace71
	unsigned char my_rsp_data[AUTH_CHAP_RSP_MAX];
Packit eace71
	int status;
Packit eace71
	enum auth_dbg_status dbg_status;
Packit eace71
	const char *chap_rsp_key_val;
Packit eace71
	const char *chap_username_key_val;
Packit eace71
Packit eace71
	switch (client->rmt_state) {
Packit eace71
	case AUTH_RMT_STATE_SEND_ALG:
Packit eace71
		if (client->node_type == TYPE_INITIATOR) {
Packit eace71
			client->rmt_state = AUTH_RMT_STATE_SEND_CHALLENGE;
Packit eace71
			break;
Packit eace71
		}
Packit eace71
		/* Fall through */
Packit eace71
	case AUTH_RMT_STATE_SEND_CHALLENGE:
Packit eace71
		if (!client->auth_rmt) {
Packit eace71
			client->rmt_auth_status = AUTH_STATUS_PASS;
Packit eace71
			client->dbg_status = AUTH_DBG_STATUS_AUTH_RMT_FALSE;
Packit eace71
			client->rmt_state = AUTH_RMT_STATE_DONE;
Packit eace71
			break;
Packit eace71
		}
Packit eace71
		get_random_bytes(id_data, 1);
Packit eace71
		client->send_chap_identifier = id_data[0];
Packit eace71
		snprintf(client->scratch_key_value, AUTH_STR_MAX_LEN, "%lu",
Packit eace71
			 (unsigned long)client->send_chap_identifier);
Packit eace71
		acl_set_key_value(&client->send_key_block,
Packit eace71
				  AUTH_KEY_TYPE_CHAP_IDENTIFIER,
Packit eace71
				  client->scratch_key_value);
Packit eace71
Packit eace71
		client->send_chap_challenge.length = client->chap_challenge_len;
Packit eace71
		get_random_bytes(client->send_chap_challenge.large_binary,
Packit eace71
				 client->send_chap_challenge.length);
Packit eace71
		acl_set_key_value(&client->send_key_block,
Packit eace71
				  AUTH_KEY_TYPE_CHAP_CHALLENGE, "");
Packit eace71
Packit eace71
		client->rmt_state = AUTH_RMT_STATE_RECV_RSP;
Packit eace71
		break;
Packit eace71
	case AUTH_RMT_STATE_RECV_RSP:
Packit eace71
		chap_rsp_key_val = acl_get_key_val(&client->recv_key_block,
Packit eace71
						   AUTH_KEY_TYPE_CHAP_RSP);
Packit eace71
		chap_username_key_val = acl_get_key_val(&client->recv_key_block,
Packit eace71
							 AUTH_KEY_TYPE_CHAP_USERNAME);
Packit eace71
Packit eace71
		if (!chap_rsp_key_val) {
Packit eace71
			client->rmt_state = AUTH_RMT_STATE_ERROR;
Packit eace71
			client->dbg_status = AUTH_DBG_STATUS_CHAP_RSP_EXPECTED;
Packit eace71
			break;
Packit eace71
		}
Packit eace71
Packit eace71
		if (!chap_username_key_val) {
Packit eace71
			client->rmt_state = AUTH_RMT_STATE_ERROR;
Packit eace71
			client->dbg_status = AUTH_DBG_STATUS_CHAP_USERNAME_EXPECTED;
Packit eace71
			break;
Packit eace71
		}
Packit eace71
Packit eace71
		status = acl_text_to_data(chap_rsp_key_val, response_data,
Packit eace71
					  &rsp_len);
Packit eace71
Packit eace71
		if (status) {
Packit eace71
			client->rmt_state = AUTH_RMT_STATE_ERROR;
Packit eace71
			client->dbg_status = AUTH_DBG_STATUS_CHAP_RSP_BAD;
Packit eace71
			break;
Packit eace71
		}
Packit eace71
Packit eace71
		if (rsp_len == client->chap_challenge_len) {
Packit eace71
			dbg_status = acl_chap_compute_rsp(client, 1,
Packit eace71
							  client->send_chap_identifier,
Packit eace71
							  client->send_chap_challenge.large_binary,
Packit eace71
							  client->send_chap_challenge.length,
Packit eace71
							  my_rsp_data);
Packit eace71
Packit eace71
			if (dbg_status == AUTH_DBG_STATUS_NOT_SET &&
Packit eace71
			    memcmp(my_rsp_data, response_data,
Packit eace71
				   client->chap_challenge_len) == 0) {
Packit eace71
				client->rmt_state = AUTH_RMT_STATE_ERROR;
Packit eace71
				client->dbg_status = AUTH_DBG_STATUS_PASSWD_IDENTICAL;
Packit eace71
				break;
Packit eace71
			}
Packit eace71
		}
Packit eace71
Packit eace71
		strlcpy(client->chap_username, chap_username_key_val,
Packit eace71
			AUTH_STR_MAX_LEN);
Packit eace71
Packit eace71
		status = acl_chap_auth_request(client, client->chap_username,
Packit eace71
					       client->send_chap_identifier,
Packit eace71
					       client->send_chap_challenge.
Packit eace71
					       large_binary,
Packit eace71
					       client->send_chap_challenge.
Packit eace71
					       length, response_data,
Packit eace71
					       rsp_len);
Packit eace71
Packit eace71
		client->rmt_auth_status = (enum auth_status) status;
Packit eace71
		client->auth_rsp_flag = 1;
Packit eace71
Packit eace71
		if (client->auth_server_error_flag) {
Packit eace71
			client->rmt_auth_status = AUTH_STATUS_FAIL;
Packit eace71
			client->dbg_status = AUTH_DBG_STATUS_AUTH_SERVER_ERROR;
Packit eace71
		} else if (client->rmt_auth_status == AUTH_STATUS_PASS)
Packit eace71
			client->dbg_status = AUTH_DBG_STATUS_AUTH_PASS;
Packit eace71
		else if (client->rmt_auth_status == AUTH_STATUS_FAIL)
Packit eace71
			client->dbg_status = AUTH_DBG_STATUS_AUTH_FAIL;
Packit eace71
		else {
Packit eace71
			client->rmt_auth_status = AUTH_STATUS_FAIL;
Packit eace71
			client->dbg_status = AUTH_DBG_STATUS_AUTH_STATUS_BAD;
Packit eace71
		}
Packit eace71
		client->rmt_state = AUTH_RMT_STATE_DONE;
Packit eace71
Packit eace71
		/* Fall through */
Packit eace71
	case AUTH_RMT_STATE_DONE:
Packit eace71
		break;
Packit eace71
	case AUTH_RMT_STATE_ERROR:
Packit eace71
	default:
Packit eace71
		client->phase = AUTH_PHASE_ERROR;
Packit eace71
	}
Packit eace71
}
Packit eace71
Packit eace71
static void
Packit eace71
acl_hand_shake(struct iscsi_acl *client)
Packit eace71
{
Packit eace71
	if (client->phase == AUTH_PHASE_DONE)
Packit eace71
Packit eace71
		/*
Packit eace71
		 * Should only happen if authentication
Packit eace71
		 * protocol error occurred.
Packit eace71
		 */
Packit eace71
		return;
Packit eace71
Packit eace71
	if (client->node_type == TYPE_INITIATOR)
Packit eace71
Packit eace71
		/*
Packit eace71
		 * Target should only have set T bit on response if
Packit eace71
		 * initiator set it on previous message.
Packit eace71
		 */
Packit eace71
		if (client->recv_key_block.transit_bit &&
Packit eace71
		    !client->transit_bit_sent_flag) {
Packit eace71
			client->rmt_auth_status = AUTH_STATUS_FAIL;
Packit eace71
			client->phase = AUTH_PHASE_DONE;
Packit eace71
			client->dbg_status =
Packit eace71
			    AUTH_DBG_STATUS_T_BIT_SET_ILLEGAL;
Packit eace71
			return;
Packit eace71
		}
Packit eace71
Packit eace71
	if (client->phase == AUTH_PHASE_NEGOTIATE) {
Packit eace71
		/*
Packit eace71
		 * Should only happen if waiting for peer
Packit eace71
		 * to send AuthMethod key or set Transit Bit.
Packit eace71
		 */
Packit eace71
		if (client->node_type == TYPE_INITIATOR)
Packit eace71
			client->send_key_block.transit_bit = 1;
Packit eace71
		return;
Packit eace71
	}
Packit eace71
Packit eace71
	if (client->rmt_state == AUTH_RMT_STATE_RECV_RSP ||
Packit eace71
	    client->rmt_state == AUTH_RMT_STATE_DONE) {
Packit eace71
		if (client->node_type == TYPE_INITIATOR) {
Packit eace71
			if (client->recv_key_block.transit_bit) {
Packit eace71
				if (client->rmt_state !=
Packit eace71
				    AUTH_RMT_STATE_DONE)
Packit eace71
					goto recv_transit_bit_err;
Packit eace71
				acl_next_phase(client);
Packit eace71
			} else
Packit eace71
				client->send_key_block.transit_bit = 1;
Packit eace71
		} else {
Packit eace71
			if (client->rmt_state == AUTH_RMT_STATE_DONE &&
Packit eace71
			    client->rmt_auth_status != AUTH_STATUS_PASS)
Packit eace71
				/*
Packit eace71
				 * Authentication failed, don't do T bit
Packit eace71
				 * handshake.
Packit eace71
				 */
Packit eace71
				acl_next_phase(client);
Packit eace71
			else {
Packit eace71
				/*
Packit eace71
				 * Target can only set T bit on response if
Packit eace71
				 * initiator set it on current message.
Packit eace71
				 */
Packit eace71
				if (client->recv_key_block.transit_bit) {
Packit eace71
					client->send_key_block.transit_bit = 1;
Packit eace71
					acl_next_phase(client);
Packit eace71
				}
Packit eace71
			}
Packit eace71
		}
Packit eace71
	} else
Packit eace71
		if (client->node_type == TYPE_INITIATOR)
Packit eace71
			if (client->recv_key_block.transit_bit)
Packit eace71
				goto recv_transit_bit_err;
Packit eace71
	return;
Packit eace71
Packit eace71
 recv_transit_bit_err:
Packit eace71
	/*
Packit eace71
	 * Target set T bit on response but
Packit eace71
	 * initiator was not done with authentication.
Packit eace71
	 */
Packit eace71
	client->rmt_auth_status = AUTH_STATUS_FAIL;
Packit eace71
	client->phase = AUTH_PHASE_DONE;
Packit eace71
	client->dbg_status = AUTH_DBG_STATUS_T_BIT_SET_PREMATURE;
Packit eace71
}
Packit eace71
Packit eace71
static int
Packit eace71
acl_rcv_end_status(struct iscsi_acl *client)
Packit eace71
{
Packit eace71
	int auth_status;
Packit eace71
	int key_type;
Packit eace71
Packit eace71
	if (client->phase == AUTH_PHASE_ERROR)
Packit eace71
		return AUTH_STATUS_ERROR;
Packit eace71
Packit eace71
	if (client->phase == AUTH_PHASE_DONE) {
Packit eace71
Packit eace71
		/* Perform sanity check against configured parameters. */
Packit eace71
		if (client->auth_rmt && !client->auth_rsp_flag &&
Packit eace71
		    client->rmt_auth_status == AUTH_STATUS_PASS) {
Packit eace71
			client->rmt_auth_status = AUTH_STATUS_FAIL;
Packit eace71
			client->dbg_status = AUTH_DBG_STATUS_AUTHPASS_NOT_VALID;
Packit eace71
		}
Packit eace71
Packit eace71
		auth_status = client->rmt_auth_status;
Packit eace71
Packit eace71
	} else
Packit eace71
		auth_status = AUTH_STATUS_CONTINUE;
Packit eace71
Packit eace71
	if (auth_status == AUTH_STATUS_CONTINUE ||
Packit eace71
	    auth_status == AUTH_STATUS_PASS) {
Packit eace71
		if (client->send_key_block.dup_set) {
Packit eace71
			client->rmt_auth_status = AUTH_STATUS_FAIL;
Packit eace71
			client->phase = AUTH_PHASE_DONE;
Packit eace71
			client->dbg_status =
Packit eace71
			    AUTH_DBG_STATUS_SEND_DUP_SET_KEY_VALUE;
Packit eace71
			auth_status = AUTH_STATUS_FAIL;
Packit eace71
		} else if (client->send_key_block.str_too_long) {
Packit eace71
			client->rmt_auth_status = AUTH_STATUS_FAIL;
Packit eace71
			client->phase = AUTH_PHASE_DONE;
Packit eace71
			client->dbg_status =
Packit eace71
			    AUTH_DBG_STATUS_SEND_STR_TOO_LONG;
Packit eace71
			auth_status = AUTH_STATUS_FAIL;
Packit eace71
		} else if (client->send_key_block.too_much_data) {
Packit eace71
			client->rmt_auth_status = AUTH_STATUS_FAIL;
Packit eace71
			client->phase = AUTH_PHASE_DONE;
Packit eace71
			client->dbg_status =
Packit eace71
			    AUTH_DBG_STATUS_SEND_TOO_MUCH_DATA;
Packit eace71
			auth_status = AUTH_STATUS_FAIL;
Packit eace71
		} else {
Packit eace71
			/* Check that all incoming keys have been processed. */
Packit eace71
Packit eace71
			for (key_type = AUTH_KEY_TYPE_FIRST;
Packit eace71
			     key_type < AUTH_KEY_TYPE_MAX_COUNT; key_type++)
Packit eace71
				if (client->recv_key_block.key[key_type].present &&
Packit eace71
				    !client->recv_key_block.key[key_type].
Packit eace71
				    processed)
Packit eace71
					break;
Packit eace71
Packit eace71
			if (key_type < AUTH_KEY_TYPE_MAX_COUNT) {
Packit eace71
				client->rmt_auth_status = AUTH_STATUS_FAIL;
Packit eace71
				client->phase = AUTH_PHASE_DONE;
Packit eace71
				client->dbg_status =
Packit eace71
				    AUTH_DBG_STATUS_UNEXPECTED_KEY_PRESENT;
Packit eace71
				auth_status = AUTH_STATUS_FAIL;
Packit eace71
			}
Packit eace71
		}
Packit eace71
	}
Packit eace71
Packit eace71
	if (auth_status != AUTH_STATUS_PASS &&
Packit eace71
	    auth_status != AUTH_STATUS_CONTINUE) {
Packit eace71
		int auth_method_key_present = 0;
Packit eace71
		int chap_alg_key_present = 0;
Packit eace71
Packit eace71
		/*
Packit eace71
		 * Suppress send keys on error,
Packit eace71
		 * except for AuthMethod and CHAP_A.
Packit eace71
		 */
Packit eace71
		if (client->node_type == TYPE_TARGET) {
Packit eace71
			if (acl_get_key_val(&client->send_key_block,
Packit eace71
					    AUTH_KEY_TYPE_AUTH_METHOD))
Packit eace71
				auth_method_key_present = 1;
Packit eace71
			else if (acl_get_key_val(&client->send_key_block,
Packit eace71
						 AUTH_KEY_TYPE_CHAP_ALG))
Packit eace71
				chap_alg_key_present = 1;
Packit eace71
		}
Packit eace71
Packit eace71
		acl_init_key_blk(&client->send_key_block);
Packit eace71
Packit eace71
		if (client->node_type == TYPE_TARGET) {
Packit eace71
			if (auth_method_key_present &&
Packit eace71
			    client->negotiated_auth_method ==
Packit eace71
			    AUTH_OPTION_REJECT)
Packit eace71
				acl_set_key_value(&client->send_key_block,
Packit eace71
						  AUTH_KEY_TYPE_AUTH_METHOD,
Packit eace71
						  acl_reject_option_name);
Packit eace71
			else if (chap_alg_key_present &&
Packit eace71
				 client->negotiated_chap_alg ==
Packit eace71
				 AUTH_OPTION_REJECT)
Packit eace71
				acl_set_key_value(&client->send_key_block,
Packit eace71
						  AUTH_KEY_TYPE_CHAP_ALG,
Packit eace71
						  acl_reject_option_name);
Packit eace71
		}
Packit eace71
	}
Packit eace71
	client->recv_in_progress_flag = 0;
Packit eace71
Packit eace71
	return auth_status;
Packit eace71
}
Packit eace71
Packit eace71
int
Packit eace71
acl_recv_begin(struct iscsi_acl *client)
Packit eace71
{
Packit eace71
	if (!client || client->signature != ACL_SIGNATURE)
Packit eace71
		return AUTH_STATUS_ERROR;
Packit eace71
Packit eace71
	if (client->phase == AUTH_PHASE_ERROR)
Packit eace71
		return AUTH_STATUS_ERROR;
Packit eace71
Packit eace71
	if (client->phase == AUTH_PHASE_DONE) {
Packit eace71
		client->phase = AUTH_PHASE_ERROR;
Packit eace71
		return AUTH_STATUS_ERROR;
Packit eace71
	}
Packit eace71
Packit eace71
	if (client->recv_in_progress_flag) {
Packit eace71
		client->phase = AUTH_PHASE_ERROR;
Packit eace71
		return AUTH_STATUS_ERROR;
Packit eace71
	}
Packit eace71
Packit eace71
	client->recv_in_progress_flag = 1;
Packit eace71
Packit eace71
	if (client->phase == AUTH_PHASE_CONFIGURE)
Packit eace71
		acl_next_phase(client);
Packit eace71
Packit eace71
	client->transit_bit_sent_flag = client->send_key_block.transit_bit;
Packit eace71
Packit eace71
	acl_init_key_blk(&client->recv_key_block);
Packit eace71
	acl_init_key_blk(&client->send_key_block);
Packit eace71
Packit eace71
	return AUTH_STATUS_NO_ERROR;
Packit eace71
}
Packit eace71
Packit eace71
int
Packit eace71
acl_recv_end(struct iscsi_acl *client, iscsi_session_t *session_handle)
Packit eace71
{
Packit eace71
	int next_phase_flag = 0;
Packit eace71
Packit eace71
	if (!client || client->signature != ACL_SIGNATURE)
Packit eace71
		return AUTH_STATUS_ERROR;
Packit eace71
Packit eace71
	if (client->phase == AUTH_PHASE_ERROR)
Packit eace71
		return AUTH_STATUS_ERROR;
Packit eace71
Packit eace71
	if (!client->recv_in_progress_flag)  {
Packit eace71
		client->phase = AUTH_PHASE_ERROR;
Packit eace71
		return AUTH_STATUS_ERROR;
Packit eace71
	}
Packit eace71
Packit eace71
	if (client->recv_end_count > AUTH_RECV_END_MAX_COUNT) {
Packit eace71
		client->rmt_auth_status = AUTH_STATUS_FAIL;
Packit eace71
		client->phase = AUTH_PHASE_DONE;
Packit eace71
		client->dbg_status = AUTH_DBG_STATUS_RECV_MSG_COUNT_LIMIT;
Packit eace71
	} else if (client->recv_key_block.dup_set) {
Packit eace71
		client->rmt_auth_status = AUTH_STATUS_FAIL;
Packit eace71
		client->phase = AUTH_PHASE_DONE;
Packit eace71
		client->dbg_status = AUTH_DBG_STATUS_RECV_DUP_SET_KEY_VALUE;
Packit eace71
	} else if (client->recv_key_block.str_too_long) {
Packit eace71
		client->rmt_auth_status = AUTH_STATUS_FAIL;
Packit eace71
		client->phase = AUTH_PHASE_DONE;
Packit eace71
		client->dbg_status = AUTH_DBG_STATUS_RECV_STR_TOO_LONG;
Packit eace71
	} else if (client->recv_key_block.too_much_data) {
Packit eace71
		client->rmt_auth_status = AUTH_STATUS_FAIL;
Packit eace71
		client->phase = AUTH_PHASE_DONE;
Packit eace71
		client->dbg_status = AUTH_DBG_STATUS_RECV_TOO_MUCH_DATA;
Packit eace71
	}
Packit eace71
Packit eace71
	client->recv_end_count++;
Packit eace71
	client->session_handle = session_handle;
Packit eace71
Packit eace71
	switch (client->phase) {
Packit eace71
	case AUTH_PHASE_NEGOTIATE:
Packit eace71
		acl_chk_auth_method_key(client);
Packit eace71
		if (client->auth_method_valid_neg_role ==
Packit eace71
		    AUTH_NEG_ROLE_RESPONDER) {
Packit eace71
			if (client->negotiated_auth_method ==
Packit eace71
			    AUTH_OPTION_NOT_PRESENT) {
Packit eace71
				if (client->auth_rmt ||
Packit eace71
				    !client->recv_key_block.transit_bit) {
Packit eace71
					/*
Packit eace71
					 * No AuthMethod key from peer on
Packit eace71
					 * first message, try moving the
Packit eace71
					 * process along by sending the
Packit eace71
					 * AuthMethod key.
Packit eace71
					 */
Packit eace71
Packit eace71
					client->auth_method_valid_neg_role =
Packit eace71
					    AUTH_NEG_ROLE_ORIGINATOR;
Packit eace71
					acl_set_auth_method_key(client,
Packit eace71
								client->auth_method_valid_count,
Packit eace71
								client->auth_method_valid_list);
Packit eace71
					break;
Packit eace71
				}
Packit eace71
Packit eace71
				/*
Packit eace71
				 * Special case if peer sent no AuthMethod key,
Packit eace71
				 * but did set Transit Bit, allowing this side
Packit eace71
				 * to do a null authentication, and compelete
Packit eace71
				 * the iSCSI security phase without either side
Packit eace71
				 * sending the AuthMethod key.
Packit eace71
				 */
Packit eace71
			} else
Packit eace71
				/* Send response to AuthMethod key. */
Packit eace71
				acl_set_auth_method_key(client, 1,
Packit eace71
						        &client->negotiated_auth_method);
Packit eace71
Packit eace71
			if (client->node_type == TYPE_INITIATOR)
Packit eace71
				acl_next_phase(client);
Packit eace71
			else
Packit eace71
				next_phase_flag = 1;
Packit eace71
		} else {
Packit eace71
Packit eace71
			if (client->negotiated_auth_method ==
Packit eace71
			    AUTH_OPTION_NOT_PRESENT) {
Packit eace71
				client->rmt_auth_status = AUTH_STATUS_FAIL;
Packit eace71
				client->phase = AUTH_PHASE_DONE;
Packit eace71
				client->dbg_status =
Packit eace71
				    AUTH_DBG_STATUS_AUTH_METHOD_EXPECTED;
Packit eace71
				break;
Packit eace71
			}
Packit eace71
Packit eace71
			acl_next_phase(client);
Packit eace71
		}
Packit eace71
		break;
Packit eace71
	case AUTH_PHASE_AUTHENTICATE:
Packit eace71
	case AUTH_PHASE_DONE:
Packit eace71
		break;
Packit eace71
	default:
Packit eace71
		client->phase = AUTH_PHASE_ERROR;
Packit eace71
		return AUTH_STATUS_ERROR;
Packit eace71
	}
Packit eace71
Packit eace71
	switch (client->phase) {
Packit eace71
	case AUTH_PHASE_NEGOTIATE:
Packit eace71
		if (next_phase_flag)
Packit eace71
			acl_next_phase(client);
Packit eace71
		break;
Packit eace71
	case AUTH_PHASE_AUTHENTICATE:
Packit eace71
		/*
Packit eace71
		 * Must call acl_local_auth()
Packit eace71
		 * before acl_rmt_auth()
Packit eace71
		 * to insure processing of the CHAP algorithm key,
Packit eace71
		 * and to avoid leaving an in progress request to the
Packit eace71
		 * authentication service.
Packit eace71
		 */
Packit eace71
		acl_local_auth(client);
Packit eace71
Packit eace71
		if (client->local_state != AUTH_LOCAL_STATE_ERROR)
Packit eace71
			acl_rmt_auth(client);
Packit eace71
Packit eace71
		if (client->local_state == AUTH_LOCAL_STATE_ERROR ||
Packit eace71
		    client->rmt_state == AUTH_RMT_STATE_ERROR) {
Packit eace71
Packit eace71
			client->rmt_auth_status = AUTH_STATUS_FAIL;
Packit eace71
			client->phase = AUTH_PHASE_DONE;
Packit eace71
			/* client->dbg_status should already be set. */
Packit eace71
		}
Packit eace71
		break;
Packit eace71
	case AUTH_PHASE_DONE:
Packit eace71
		break;
Packit eace71
	default:
Packit eace71
		client->phase = AUTH_PHASE_ERROR;
Packit eace71
		return AUTH_STATUS_ERROR;
Packit eace71
	}
Packit eace71
Packit eace71
	acl_hand_shake(client);
Packit eace71
Packit eace71
	return acl_rcv_end_status(client);
Packit eace71
}
Packit eace71
Packit eace71
const char *
Packit eace71
acl_get_key_name(int key_type)
Packit eace71
{
Packit eace71
	/*
Packit eace71
	 * Note: The ordering of this table must match the order
Packit eace71
	 *       defined by enum auth_key_type in iscsi-auth-client.h.
Packit eace71
	 */
Packit eace71
	static char *const key_names[AUTH_KEY_TYPE_MAX_COUNT] = {
Packit eace71
		"AuthMethod",
Packit eace71
		"CHAP_A",
Packit eace71
		"CHAP_N",
Packit eace71
		"CHAP_R",
Packit eace71
		"CHAP_I",
Packit eace71
		"CHAP_C"
Packit eace71
	};
Packit eace71
Packit eace71
	if (key_type < AUTH_KEY_TYPE_FIRST || key_type > AUTH_KEY_TYPE_LAST)
Packit eace71
		return NULL;
Packit eace71
Packit eace71
	return key_names[key_type];
Packit eace71
}
Packit eace71
Packit eace71
int
Packit eace71
acl_get_next_key_type(int *key_type)
Packit eace71
{
Packit eace71
	if (*key_type >= AUTH_KEY_TYPE_LAST)
Packit eace71
		return AUTH_STATUS_ERROR;
Packit eace71
Packit eace71
	if (*key_type < AUTH_KEY_TYPE_FIRST)
Packit eace71
		*key_type = AUTH_KEY_TYPE_FIRST;
Packit eace71
	else
Packit eace71
		(*key_type)++;
Packit eace71
Packit eace71
	return AUTH_STATUS_NO_ERROR;
Packit eace71
}
Packit eace71
Packit eace71
int
Packit eace71
acl_recv_key_value(struct iscsi_acl *client, int key_type,
Packit eace71
		   const char *user_key_val)
Packit eace71
{
Packit eace71
	if (!client || client->signature != ACL_SIGNATURE)
Packit eace71
		return AUTH_STATUS_ERROR;
Packit eace71
Packit eace71
	if (client->phase != AUTH_PHASE_NEGOTIATE &&
Packit eace71
	    client->phase != AUTH_PHASE_AUTHENTICATE) {
Packit eace71
		client->phase = AUTH_PHASE_ERROR;
Packit eace71
		return AUTH_STATUS_ERROR;
Packit eace71
	}
Packit eace71
Packit eace71
	if (key_type < AUTH_KEY_TYPE_FIRST || key_type > AUTH_KEY_TYPE_LAST) {
Packit eace71
		client->phase = AUTH_PHASE_ERROR;
Packit eace71
		return AUTH_STATUS_ERROR;
Packit eace71
	}
Packit eace71
Packit eace71
	if (key_type == AUTH_KEY_TYPE_CHAP_CHALLENGE) {
Packit eace71
		client->recv_chap_challenge.length =
Packit eace71
		    AUTH_LARGE_BINARY_MAX_LEN;
Packit eace71
		client->recv_chap_challenge_status =
Packit eace71
		    acl_text_to_data(user_key_val,
Packit eace71
				     client->recv_chap_challenge.large_binary,
Packit eace71
				     &client->recv_chap_challenge.length);
Packit eace71
		user_key_val = "";
Packit eace71
	}
Packit eace71
Packit eace71
	acl_set_key_value(&client->recv_key_block, key_type, user_key_val);
Packit eace71
Packit eace71
	return AUTH_STATUS_NO_ERROR;
Packit eace71
}
Packit eace71
Packit eace71
int
Packit eace71
acl_send_key_val(struct iscsi_acl *client, int key_type, int *key_present,
Packit eace71
		 char *user_key_val, unsigned int max_length)
Packit eace71
{
Packit eace71
	const char *key_val;
Packit eace71
Packit eace71
	if (!client || client->signature != ACL_SIGNATURE)
Packit eace71
		return AUTH_STATUS_ERROR;
Packit eace71
Packit eace71
	if (client->phase != AUTH_PHASE_CONFIGURE &&
Packit eace71
	    client->phase != AUTH_PHASE_NEGOTIATE &&
Packit eace71
	    client->phase != AUTH_PHASE_AUTHENTICATE &&
Packit eace71
	    client->phase != AUTH_PHASE_DONE) {
Packit eace71
		client->phase = AUTH_PHASE_ERROR;
Packit eace71
		return AUTH_STATUS_ERROR;
Packit eace71
	}
Packit eace71
Packit eace71
	if (key_type < AUTH_KEY_TYPE_FIRST || key_type > AUTH_KEY_TYPE_LAST) {
Packit eace71
		client->phase = AUTH_PHASE_ERROR;
Packit eace71
		return AUTH_STATUS_ERROR;
Packit eace71
	}
Packit eace71
Packit eace71
	key_val = acl_get_key_val(&client->send_key_block, key_type);
Packit eace71
	if (key_val) {
Packit eace71
		if (key_type == AUTH_KEY_TYPE_CHAP_CHALLENGE) {
Packit eace71
			if (acl_data_to_text(client->send_chap_challenge.large_binary,
Packit eace71
					     client->send_chap_challenge.length, user_key_val,
Packit eace71
					     max_length)) {
Packit eace71
				client->phase = AUTH_PHASE_ERROR;
Packit eace71
				return AUTH_STATUS_ERROR;
Packit eace71
			}
Packit eace71
		} else if (strlcpy(user_key_val, key_val, max_length) >=
Packit eace71
			   max_length) {
Packit eace71
				client->phase = AUTH_PHASE_ERROR;
Packit eace71
				return AUTH_STATUS_ERROR;
Packit eace71
			}
Packit eace71
		*key_present = 1;
Packit eace71
	} else
Packit eace71
		*key_present = 0;
Packit eace71
Packit eace71
	return AUTH_STATUS_NO_ERROR;
Packit eace71
}
Packit eace71
Packit eace71
int
Packit eace71
acl_recv_transit_bit(struct iscsi_acl *client, int value)
Packit eace71
{
Packit eace71
	if (!client || client->signature != ACL_SIGNATURE)
Packit eace71
		return AUTH_STATUS_ERROR;
Packit eace71
Packit eace71
	if (client->phase != AUTH_PHASE_NEGOTIATE &&
Packit eace71
	    client->phase != AUTH_PHASE_AUTHENTICATE) {
Packit eace71
Packit eace71
		client->phase = AUTH_PHASE_ERROR;
Packit eace71
		return AUTH_STATUS_ERROR;
Packit eace71
	}
Packit eace71
Packit eace71
	if (value)
Packit eace71
		client->recv_key_block.transit_bit = 1;
Packit eace71
	else
Packit eace71
		client->recv_key_block.transit_bit = 0;
Packit eace71
Packit eace71
	return AUTH_STATUS_NO_ERROR;
Packit eace71
}
Packit eace71
Packit eace71
int
Packit eace71
acl_send_transit_bit(struct iscsi_acl *client, int *value)
Packit eace71
{
Packit eace71
	if (!client || client->signature != ACL_SIGNATURE)
Packit eace71
		return AUTH_STATUS_ERROR;
Packit eace71
Packit eace71
	if (client->phase != AUTH_PHASE_CONFIGURE &&
Packit eace71
	    client->phase != AUTH_PHASE_NEGOTIATE &&
Packit eace71
	    client->phase != AUTH_PHASE_AUTHENTICATE &&
Packit eace71
	    client->phase != AUTH_PHASE_DONE) {
Packit eace71
Packit eace71
		client->phase = AUTH_PHASE_ERROR;
Packit eace71
		return AUTH_STATUS_ERROR;
Packit eace71
	}
Packit eace71
Packit eace71
	*value = client->send_key_block.transit_bit;
Packit eace71
Packit eace71
	return AUTH_STATUS_NO_ERROR;
Packit eace71
}
Packit eace71
Packit eace71
static int
Packit eace71
acl_set_option_list(struct iscsi_acl *client, unsigned int opt_count,
Packit eace71
		    const int *opt_list, unsigned int *clnt_optn_count,
Packit eace71
		    int *clnt_optn_list, unsigned int optn_max_count,
Packit eace71
		    int (*chk_option)(int),
Packit eace71
		    int (*chk_list)(unsigned int opt_count, const int *opt_list))
Packit eace71
{
Packit eace71
	unsigned int i, j;
Packit eace71
Packit eace71
	if (!client || client->signature != ACL_SIGNATURE)
Packit eace71
		return AUTH_STATUS_ERROR;
Packit eace71
Packit eace71
	if (client->phase != AUTH_PHASE_CONFIGURE ||
Packit eace71
	    opt_count > optn_max_count) {
Packit eace71
		client->phase = AUTH_PHASE_ERROR;
Packit eace71
		return AUTH_STATUS_ERROR;
Packit eace71
	}
Packit eace71
Packit eace71
	for (i = 0; i < opt_count; i++)
Packit eace71
		if (chk_option(opt_list[i])) {
Packit eace71
			client->phase = AUTH_PHASE_ERROR;
Packit eace71
			return AUTH_STATUS_ERROR;
Packit eace71
		}
Packit eace71
Packit eace71
	/* Check for duplicate entries. */
Packit eace71
	for (i = 0; i < opt_count; i++)
Packit eace71
		for (j = 0; j < opt_count; j++) {
Packit eace71
			if (j == i)
Packit eace71
				continue;
Packit eace71
			if (opt_list[i] == opt_list[j]) {
Packit eace71
				client->phase = AUTH_PHASE_ERROR;
Packit eace71
				return AUTH_STATUS_ERROR;
Packit eace71
			}
Packit eace71
		}
Packit eace71
Packit eace71
	/* Check for key specific constraints. */
Packit eace71
	if (chk_list)
Packit eace71
		if (chk_list(opt_count, opt_list)) {
Packit eace71
			client->phase = AUTH_PHASE_ERROR;
Packit eace71
			return AUTH_STATUS_ERROR;
Packit eace71
		}
Packit eace71
Packit eace71
	for (i = 0; i < opt_count; i++)
Packit eace71
		clnt_optn_list[i] = opt_list[i];
Packit eace71
Packit eace71
	*clnt_optn_count = opt_count;
Packit eace71
Packit eace71
	return AUTH_STATUS_NO_ERROR;
Packit eace71
}
Packit eace71
Packit eace71
static int
Packit eace71
acl_chk_auth_method_list(unsigned int option_count, const int *option_list)
Packit eace71
{
Packit eace71
	unsigned int i;
Packit eace71
Packit eace71
	if (!option_list || option_count < 2)
Packit eace71
		return 1;
Packit eace71
Packit eace71
	if (option_list[option_count - 1] != AUTH_OPTION_NONE)
Packit eace71
		return 1;
Packit eace71
Packit eace71
	for (i = 0; i < (option_count - 1); i++)
Packit eace71
		if (option_list[i] != AUTH_OPTION_NONE)
Packit eace71
			return 0;
Packit eace71
Packit eace71
	return 0;
Packit eace71
}
Packit eace71
Packit eace71
static void
Packit eace71
acl_set_auth_method_valid(struct iscsi_acl *client)
Packit eace71
{
Packit eace71
	unsigned int i, j = 0;
Packit eace71
	int option = 0;
Packit eace71
Packit eace71
	/*
Packit eace71
	 * Following checks may need to be revised if
Packit eace71
	 * authentication options other than CHAP and none
Packit eace71
	 * are supported.
Packit eace71
	 */
Packit eace71
	if (client->node_type == TYPE_INITIATOR) {
Packit eace71
		if (client->auth_rmt)
Packit eace71
			/*
Packit eace71
			 * If initiator doing authentication,
Packit eace71
			 * don't offer authentication option none.
Packit eace71
			 */
Packit eace71
			option = 1;
Packit eace71
		else if (!client->passwd_present)
Packit eace71
			/*
Packit eace71
			 * If initiator password not set,
Packit eace71
			 * only offer authentication option none.
Packit eace71
			 */
Packit eace71
			option = 2;
Packit eace71
	}
Packit eace71
Packit eace71
	if (client->node_type == TYPE_TARGET) {
Packit eace71
		if (client->auth_rmt)
Packit eace71
			/*
Packit eace71
			 * If target doing authentication,
Packit eace71
			 * don't accept authentication option none.
Packit eace71
			 */
Packit eace71
			option = 1;
Packit eace71
		else
Packit eace71
			/*
Packit eace71
			 * If target not doing authentication,
Packit eace71
			 * only accept authentication option none.
Packit eace71
			 */
Packit eace71
			option = 2;
Packit eace71
	}
Packit eace71
Packit eace71
	for (i = 0; i < client->auth_method_count; i++) {
Packit eace71
		if (option == 1) {
Packit eace71
			if (client->auth_method_list[i] == AUTH_OPTION_NONE)
Packit eace71
				continue;
Packit eace71
		} else if (option == 2)
Packit eace71
			if (client->auth_method_list[i] != AUTH_OPTION_NONE)
Packit eace71
				continue;
Packit eace71
		client->auth_method_valid_list[j++] = client->auth_method_list[i];
Packit eace71
	}
Packit eace71
Packit eace71
	client->auth_method_valid_count = j;
Packit eace71
Packit eace71
	acl_init_key_blk(&client->send_key_block);
Packit eace71
Packit eace71
	if (client->node_type == TYPE_INITIATOR) {
Packit eace71
		if (client->auth_rmt) {
Packit eace71
			/*
Packit eace71
			 * Initiator wants to authenticate target,
Packit eace71
			 * always send AuthMethod key.
Packit eace71
			 */
Packit eace71
			client->send_key_block.transit_bit = 0;
Packit eace71
			client->auth_method_valid_neg_role =
Packit eace71
			    AUTH_NEG_ROLE_ORIGINATOR;
Packit eace71
		} else {
Packit eace71
			client->send_key_block.transit_bit = 1;
Packit eace71
			client->auth_method_valid_neg_role =
Packit eace71
			    client->auth_method_neg_role;
Packit eace71
		}
Packit eace71
	} else {
Packit eace71
		client->send_key_block.transit_bit = 0;
Packit eace71
		client->auth_method_valid_neg_role = AUTH_NEG_ROLE_RESPONDER;
Packit eace71
	}
Packit eace71
Packit eace71
	if (client->auth_method_valid_neg_role == AUTH_NEG_ROLE_ORIGINATOR)
Packit eace71
		acl_set_auth_method_key(client, client->auth_method_valid_count,
Packit eace71
				        client->auth_method_valid_list);
Packit eace71
	else {
Packit eace71
		int value = AUTH_OPTION_NOT_PRESENT;
Packit eace71
		acl_set_auth_method_key(client, 1, &value);
Packit eace71
	}
Packit eace71
}
Packit eace71
Packit eace71
static int
Packit eace71
acl_set_auth_method_list(struct iscsi_acl *client, unsigned int option_count,
Packit eace71
			 const int *option_list)
Packit eace71
{
Packit eace71
	int status;
Packit eace71
Packit eace71
	status = acl_set_option_list(client, option_count, option_list,
Packit eace71
				     &client->auth_method_count,
Packit eace71
				     client->auth_method_list,
Packit eace71
				     AUTH_METHOD_MAX_COUNT,
Packit eace71
				     acl_chk_auth_mthd_optn,
Packit eace71
				     acl_chk_auth_method_list);
Packit eace71
Packit eace71
	if (status != AUTH_STATUS_NO_ERROR)
Packit eace71
		return status;
Packit eace71
Packit eace71
	/* Setting authMethod affects auth_method_valid. */
Packit eace71
	acl_set_auth_method_valid(client);
Packit eace71
Packit eace71
	return AUTH_STATUS_NO_ERROR;
Packit eace71
}
Packit eace71
Packit eace71
static int
Packit eace71
acl_chk_chap_alg_list(unsigned int option_count, const int *option_list)
Packit eace71
{
Packit eace71
	if (!option_list || option_count < 1)
Packit eace71
		return 1;
Packit eace71
Packit eace71
	return 0;
Packit eace71
}
Packit eace71
Packit eace71
static int
Packit eace71
acl_set_chap_alg_list(struct iscsi_acl *client, unsigned int option_count,
Packit eace71
		      const int *option_list)
Packit eace71
{
Packit eace71
	return acl_set_option_list(client, option_count, option_list,
Packit eace71
				   &client->chap_alg_count,
Packit eace71
				   client->chap_alg_list,
Packit eace71
				   AUTH_CHAP_ALG_MAX_COUNT,
Packit eace71
				   acl_chk_chap_alg_optn,
Packit eace71
				   acl_chk_chap_alg_list);
Packit eace71
}
Packit eace71
Packit eace71
int
Packit eace71
acl_init_chap_digests(int *value_list) {
Packit eace71
	EVP_MD_CTX *context = EVP_MD_CTX_new();
Packit eace71
	int i = 0;
Packit eace71
Packit eace71
	if (EVP_DigestInit_ex(context, EVP_sha3_256(), NULL)) {
Packit eace71
		value_list[i++] = AUTH_CHAP_ALG_SHA3_256;
Packit eace71
	}
Packit eace71
	if (EVP_DigestInit_ex(context, EVP_sha256(), NULL)) {
Packit eace71
		value_list[i++] = AUTH_CHAP_ALG_SHA256;
Packit eace71
	}
Packit eace71
	if (EVP_DigestInit_ex(context, EVP_sha1(), NULL)) {
Packit eace71
		value_list[i++] = AUTH_CHAP_ALG_SHA1;
Packit eace71
	}
Packit eace71
	if (EVP_DigestInit_ex(context, EVP_md5(), NULL)) {
Packit eace71
		value_list[i++] = AUTH_CHAP_ALG_MD5;
Packit eace71
	}
Packit eace71
	return i;
Packit eace71
}
Packit eace71
Packit eace71
#define MAX(a,b) ((a) > (b) ? (a) : (b))
Packit eace71
Packit eace71
int
Packit eace71
acl_init(int node_type, int buf_desc_count, struct auth_buffer_desc *buff_desc)
Packit eace71
{
Packit eace71
	struct iscsi_acl *client;
Packit eace71
	struct auth_str_block *recv_str_blk;
Packit eace71
	struct auth_str_block *send_str_blk;
Packit eace71
	struct auth_large_binary *recv_chap_challenge;
Packit eace71
	struct auth_large_binary *send_chap_challenge;
Packit eace71
	int value_list[MAX(AUTH_METHOD_MAX_COUNT, AUTH_CHAP_ALG_MAX_COUNT)];
Packit eace71
Packit eace71
	if (buf_desc_count != 5 || !buff_desc)
Packit eace71
		return AUTH_STATUS_ERROR;
Packit eace71
Packit eace71
	if (!buff_desc[0].address ||
Packit eace71
	    buff_desc[0].length != sizeof(*client))
Packit eace71
		return AUTH_STATUS_ERROR;
Packit eace71
	client = (struct iscsi_acl *)buff_desc[0].address;
Packit eace71
Packit eace71
	if (!buff_desc[1].address ||
Packit eace71
	    buff_desc[1].length != sizeof(*recv_str_blk))
Packit eace71
		return AUTH_STATUS_ERROR;
Packit eace71
	recv_str_blk = (struct auth_str_block *)buff_desc[1].address;
Packit eace71
Packit eace71
	if (!buff_desc[2].address ||
Packit eace71
	    buff_desc[2].length != sizeof(*send_str_blk))
Packit eace71
		return AUTH_STATUS_ERROR;
Packit eace71
Packit eace71
	send_str_blk = (struct auth_str_block *)buff_desc[2].address;
Packit eace71
Packit eace71
	if (!buff_desc[3].address ||
Packit eace71
	    buff_desc[3].length != sizeof(*recv_chap_challenge))
Packit eace71
		return AUTH_STATUS_ERROR;
Packit eace71
Packit eace71
	recv_chap_challenge = (struct auth_large_binary *)
Packit eace71
			     buff_desc[3].address;
Packit eace71
Packit eace71
	if (!buff_desc[4].address ||
Packit eace71
	    buff_desc[4].length != sizeof(*send_chap_challenge))
Packit eace71
		return AUTH_STATUS_ERROR;
Packit eace71
	send_chap_challenge = (struct auth_large_binary *)
Packit eace71
			    buff_desc[4].address;
Packit eace71
	memset(client, 0, sizeof(*client));
Packit eace71
	memset(recv_str_blk, 0, sizeof(*recv_str_blk));
Packit eace71
	memset(send_str_blk, 0, sizeof(*send_str_blk));
Packit eace71
	memset(recv_chap_challenge, 0, sizeof(*recv_chap_challenge));
Packit eace71
	memset(send_chap_challenge, 0, sizeof(*send_chap_challenge));
Packit eace71
Packit eace71
	client->recv_key_block.str_block = recv_str_blk->str_block;
Packit eace71
	client->send_key_block.str_block = send_str_blk->str_block;
Packit eace71
	client->recv_chap_challenge.large_binary = recv_chap_challenge->large_binary;
Packit eace71
	client->send_chap_challenge.large_binary = send_chap_challenge->large_binary;
Packit eace71
Packit eace71
	if (node_type != TYPE_INITIATOR  && node_type != TYPE_TARGET) {
Packit eace71
		client->phase = AUTH_PHASE_ERROR;
Packit eace71
		return AUTH_STATUS_ERROR;
Packit eace71
	}
Packit eace71
Packit eace71
	client->signature = ACL_SIGNATURE;
Packit eace71
	client->node_type = (enum auth_node_type) node_type;
Packit eace71
	client->auth_rmt = 1;
Packit eace71
	client->passwd_present = 0;
Packit eace71
	client->ip_sec = 0;
Packit eace71
Packit eace71
	client->phase = AUTH_PHASE_CONFIGURE;
Packit eace71
	client->negotiated_auth_method = AUTH_OPTION_NOT_PRESENT;
Packit eace71
	client->negotiated_chap_alg = AUTH_OPTION_NOT_PRESENT;
Packit eace71
Packit eace71
	if (client->node_type == TYPE_INITIATOR)
Packit eace71
		client->auth_method_neg_role = AUTH_NEG_ROLE_ORIGINATOR;
Packit eace71
	else
Packit eace71
		/* Initial value ignored for Target. */
Packit eace71
		client->auth_method_neg_role = AUTH_NEG_ROLE_RESPONDER;
Packit eace71
Packit eace71
	value_list[0] = AUTH_METHOD_CHAP;
Packit eace71
	value_list[1] = AUTH_OPTION_NONE;
Packit eace71
Packit eace71
	/*
Packit eace71
	 * Must call after setting auth_rmt, password,
Packit eace71
	 * and auth_method_neg_role
Packit eace71
	 */
Packit eace71
	if (acl_set_auth_method_list(client, 2, value_list) !=
Packit eace71
	    AUTH_STATUS_NO_ERROR) {
Packit eace71
		client->phase = AUTH_PHASE_ERROR;
Packit eace71
		return AUTH_STATUS_ERROR;
Packit eace71
	}
Packit eace71
Packit eace71
	if (acl_set_chap_alg_list(client, acl_init_chap_digests(value_list),
Packit eace71
					value_list) != AUTH_STATUS_NO_ERROR) {
Packit eace71
		client->phase = AUTH_PHASE_ERROR;
Packit eace71
		return AUTH_STATUS_ERROR;
Packit eace71
	}
Packit eace71
Packit eace71
	return AUTH_STATUS_NO_ERROR;
Packit eace71
}
Packit eace71
Packit eace71
int
Packit eace71
acl_finish(struct iscsi_acl *client)
Packit eace71
{
Packit eace71
	if (!client || client->signature != ACL_SIGNATURE)
Packit eace71
		return AUTH_STATUS_ERROR;
Packit eace71
Packit eace71
	memset(client, 0, sizeof(*client));
Packit eace71
Packit eace71
	return AUTH_STATUS_NO_ERROR;
Packit eace71
}
Packit eace71
Packit eace71
int
Packit eace71
acl_set_user_name(struct iscsi_acl *client, const char *username)
Packit eace71
{
Packit eace71
	if (!client || client->signature != ACL_SIGNATURE)
Packit eace71
		return AUTH_STATUS_ERROR;
Packit eace71
Packit eace71
	if (client->phase != AUTH_PHASE_CONFIGURE ||
Packit eace71
	    acl_chk_string(username, AUTH_STR_MAX_LEN, NULL)) {
Packit eace71
		client->phase = AUTH_PHASE_ERROR;
Packit eace71
		return AUTH_STATUS_ERROR;
Packit eace71
	}
Packit eace71
Packit eace71
	if (!username)
Packit eace71
		client->username[0] = '\0';
Packit eace71
	else if (strlcpy(client->username, username, AUTH_STR_MAX_LEN) >=
Packit eace71
		 AUTH_STR_MAX_LEN) {
Packit eace71
		client->phase = AUTH_PHASE_ERROR;
Packit eace71
		return AUTH_STATUS_ERROR;
Packit eace71
	}
Packit eace71
Packit eace71
	return AUTH_STATUS_NO_ERROR;
Packit eace71
}
Packit eace71
Packit eace71
int
Packit eace71
acl_set_passwd(struct iscsi_acl *client, const unsigned char *passwd_data,
Packit eace71
	       unsigned int passwd_length)
Packit eace71
{
Packit eace71
	if (!client || client->signature != ACL_SIGNATURE)
Packit eace71
		return AUTH_STATUS_ERROR;
Packit eace71
Packit eace71
	if (client->phase != AUTH_PHASE_CONFIGURE ||
Packit eace71
	    passwd_length > AUTH_STR_MAX_LEN) {
Packit eace71
		client->phase = AUTH_PHASE_ERROR;
Packit eace71
		return AUTH_STATUS_ERROR;
Packit eace71
	}
Packit eace71
Packit eace71
	memcpy(client->passwd_data, passwd_data, passwd_length);
Packit eace71
	client->passwd_length = passwd_length;
Packit eace71
	client->passwd_present = 1;
Packit eace71
Packit eace71
	/* Setting password may affect auth_method_valid. */
Packit eace71
	acl_set_auth_method_valid(client);
Packit eace71
Packit eace71
	return AUTH_STATUS_NO_ERROR;
Packit eace71
}
Packit eace71
Packit eace71
int
Packit eace71
acl_set_auth_rmt(struct iscsi_acl *client, int auth_rmt)
Packit eace71
{
Packit eace71
	if (!client || client->signature != ACL_SIGNATURE)
Packit eace71
		return AUTH_STATUS_ERROR;
Packit eace71
Packit eace71
	if (client->phase != AUTH_PHASE_CONFIGURE) {
Packit eace71
		client->phase = AUTH_PHASE_ERROR;
Packit eace71
		return AUTH_STATUS_ERROR;
Packit eace71
	}
Packit eace71
Packit eace71
	client->auth_rmt = auth_rmt;
Packit eace71
Packit eace71
	/* Setting auth_rmt may affect auth_method_valid. */
Packit eace71
	acl_set_auth_method_valid(client);
Packit eace71
Packit eace71
	return AUTH_STATUS_NO_ERROR;
Packit eace71
}
Packit eace71
Packit eace71
int
Packit eace71
acl_set_ip_sec(struct iscsi_acl *client, int ip_sec)
Packit eace71
{
Packit eace71
	if (!client || client->signature != ACL_SIGNATURE)
Packit eace71
		return AUTH_STATUS_ERROR;
Packit eace71
Packit eace71
	if (client->phase != AUTH_PHASE_CONFIGURE) {
Packit eace71
		client->phase = AUTH_PHASE_ERROR;
Packit eace71
		return AUTH_STATUS_ERROR;
Packit eace71
	}
Packit eace71
Packit eace71
	client->ip_sec = ip_sec;
Packit eace71
Packit eace71
	return AUTH_STATUS_NO_ERROR;
Packit eace71
}
Packit eace71
Packit eace71
int
Packit eace71
acl_get_dbg_status(struct iscsi_acl *client, int *value)
Packit eace71
{
Packit eace71
	if (!client || client->signature != ACL_SIGNATURE)
Packit eace71
		return AUTH_STATUS_ERROR;
Packit eace71
Packit eace71
	if (client->phase != AUTH_PHASE_DONE) {
Packit eace71
		client->phase = AUTH_PHASE_ERROR;
Packit eace71
		return AUTH_STATUS_ERROR;
Packit eace71
	}
Packit eace71
Packit eace71
	*value = client->dbg_status;
Packit eace71
Packit eace71
	return AUTH_STATUS_NO_ERROR;
Packit eace71
}
Packit eace71
Packit eace71
const char *
Packit eace71
acl_dbg_status_to_text(int dbg_status)
Packit eace71
{
Packit eace71
	/*
Packit eace71
	 * Note: The ordering of this table must match the order
Packit eace71
	 *       defined by enum auth_dbg_status in iscsi-auth-client.h.
Packit eace71
	 */
Packit eace71
	static char *const dbg_text[AUTH_DBG_STATUS_MAX_COUNT] = {
Packit eace71
		"Debug status not set",
Packit eace71
		"Authentication request passed",
Packit eace71
		"Authentication not enabled",
Packit eace71
		"Authentication request failed",
Packit eace71
		"AuthMethod bad",
Packit eace71
		"CHAP algorithm bad",
Packit eace71
		"Decrypt password failed",
Packit eace71
		"Local password too short with no IPSec",
Packit eace71
		"Unexpected error from authentication server",
Packit eace71
		"Authentication request status bad",
Packit eace71
		"Authentication pass status not valid",
Packit eace71
		"Same key set more than once on send",
Packit eace71
		"Key value too long on send",
Packit eace71
		"Too much data on send",
Packit eace71
		"AuthMethod key expected",
Packit eace71
		"CHAP algorithm key expected",
Packit eace71
		"CHAP identifier expected",
Packit eace71
		"CHAP challenge expected",
Packit eace71
		"CHAP response expected",
Packit eace71
		"CHAP username expected",
Packit eace71
		"AuthMethod key not present",
Packit eace71
		"AuthMethod negotiation failed",
Packit eace71
		"AuthMethod negotiated to none",
Packit eace71
		"CHAP algorithm negotiation failed",
Packit eace71
		"CHAP challenge reflected",
Packit eace71
		"Local password same as remote",
Packit eace71
		"Local password not set",
Packit eace71
		"CHAP identifier bad",
Packit eace71
		"CHAP challenge bad",
Packit eace71
		"CHAP response bad",
Packit eace71
		"Unexpected key present",
Packit eace71
		"T bit set on response, but not on previous message",
Packit eace71
		"T bit set on response, but authenticaton not complete",
Packit eace71
		"Message count limit reached on receive",
Packit eace71
		"Same key set more than once on receive",
Packit eace71
		"Key value too long on receive",
Packit eace71
		"Too much data on receive"
Packit eace71
	};
Packit eace71
Packit eace71
	if (dbg_status < 0 || dbg_status >= AUTH_DBG_STATUS_MAX_COUNT)
Packit eace71
		return "Unknown error";
Packit eace71
Packit eace71
	return dbg_text[dbg_status];
Packit eace71
}
Packit eace71
Packit eace71
int
Packit eace71
acl_data(unsigned char *out_data, unsigned int *out_length,
Packit eace71
         unsigned char *in_data, unsigned int in_length)
Packit eace71
{
Packit eace71
	if (*out_length < in_length)
Packit eace71
		return 1;       /* error */
Packit eace71
Packit eace71
	memcpy(out_data, in_data, in_length);
Packit eace71
	*out_length = in_length;
Packit eace71
Packit eace71
	return 0;               /* no error */
Packit eace71
}
Packit eace71