Blame usr/auth.c

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