iscsit_auth.c revision 4558d122136f151d62acbbc02ddb42df89a5ef66
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
*/
#include <sys/sysmacros.h>
#include <sys/stmf_ioctl.h>
#include "iscsit.h"
#include "iscsit_auth.h"
static kv_status_t
const idm_kv_xlate_t *ikvx);
static kv_status_t
const idm_kv_xlate_t *ikvx);
static kv_status_t
const idm_kv_xlate_t *ikvx);
static kv_status_t
const idm_kv_xlate_t *ikvx);
static kv_status_t
const idm_kv_xlate_t *ikvx);
static kv_status_t
const idm_kv_xlate_t *ikvx);
static kv_status_t
const idm_kv_xlate_t *ikvx);
static kv_status_t
const idm_kv_xlate_t *ikvx);
static kv_status_t
const idm_kv_xlate_t *ikvx);
static kv_status_t
const idm_kv_xlate_t *ikvx);
static kv_status_t
const idm_kv_xlate_t *ikvx);
static kv_status_t
static kv_status_t
typedef struct {
/*
* This table defines all authentication phases which have valid
* handler. The entries which have a non-zero key index are for
* the rest of entries are for target checking the authentication
*/
static const auth_phase_entry_t apet[] = {
/* by key */
/* by target */
{ AP_AM_UNDECIDED, 0, iscsit_auth_propose },
{ AP_AM_DECIDED, 0, iscsit_auth_expect_key },
{ AP_CHAP_A_RCVD, 0, auth_chap_expect_r },
{ AP_CHAP_R_RCVD, 0, auth_chap_done }
};
typedef struct {
char *am_name;
/*
* a table of mapping from the authentication index to name.
*/
static const auth_id_name_t aint[] = {
{ AM_CHAP, "CHAP" },
{ AM_NONE, "None" },
/* { AM_KRB5, "KRB5" }, */ /* Not supported */
/* { AM_SPKM1, "SPKM1" }, */ /* Not supported */
/* { AM_SPKM2, "SPKM2" }, */ /* Not supported */
/* { AM_SRP, "SRP" }, */ /* Not supported */
};
/*
* get the authentication method name for the method id.
*/
static const char *
am_id_to_name(int id)
{
int i;
const auth_id_name_t *p;
i = 0;
while (i < ARRAY_LENGTH(aint)) {
p = &(aint[i]);
return (p->am_name);
}
i ++;
}
return (NULL);
}
/*
* Look for an apporiate function handler which is defined for
* current authentication phase and matches the key which is
* being handled. The key index is passed in as zero when it
* is looking for an handler for checking the authentication phase
* after all security keys are handled.
*/
{
int i;
const auth_phase_entry_t *p;
i = 0;
p = NULL;
while (i < ARRAY_LENGTH(apet)) {
p = &(apet[i]);
return (p->handler);
}
i ++;
}
/* No handler can be found, it must be an invalid requst. */
return (NULL);
}
/*
* Select an authentication method from a list of values proposed
* by initiator. After a valid method is selected, shift the
* authentication phase to AP_AM_DECIDED.
*/
static kv_status_t
const idm_kv_xlate_t *ikvx)
{
int nvrc;
char *am;
const char *am_name;
const char *text;
int i;
/* select a valid authentication method */
i = 0;
while (am_id != 0) {
goto am_decided;
}
i++;
}
}
/* none of authentication method is valid */
am_id = 0;
/* add the selected method to the response nvlist */
return (kvrc);
}
/*
* Initiator chooses to use CHAP after target proposed a list of
* authentication method. Set the authentication method to CHAP and
* continue on chap authentication phase.
*/
static kv_status_t
const idm_kv_xlate_t *ikvx)
{
}
/*
* Select a CHAP algorithm from a list of values proposed by
* initiator and shift the authentication phase to AP_CHAP_A_RCVD.
*/
static kv_status_t
const idm_kv_xlate_t *ikvx)
{
char *alg_string;
const char *text;
while (alg_choice != NULL) {
/* only MD5 is supported */
text = alg_string;
goto alg_selected;
}
}
/* none of algorithm is selected */
alg = 0;
/* save the selected algorithm or zero for none is selected */
/* add the selected algorithm to the response nvlist */
if (alg == 0) {
} else {
if (kvrc == 0) {
}
}
return (kvrc);
}
/*
* Validate and save the the chap name which is sent by initiator
* and shift the authentication phase to AP_CHAP_R_RCVD.
*
* pairs need to be received in one packet, we handle each of them
* separately, in order to track the authentication phase, we set
* the authentication phase to AP_CHAP_R_RCVD once one of them is
* handled. So both of AP_CHAP_R_WAITING and AP_CHAP_R_RCVD phases
* are valid for these keys. The function auth_chap_done is going
* to detect if any of these keys is missing.
*/
/*ARGSUSED*/
static kv_status_t
const idm_kv_xlate_t *ikvx)
{
int nvrc;
char *chap_name;
return (KV_HANDLED);
}
/*
* Validate and save the the chap response which is sent by initiator
* and shift the authentication phase to AP_CHAP_R_RCVD.
*
* Note: see function auth_chap_recv_n.
*/
/*ARGSUSED*/
static kv_status_t
const idm_kv_xlate_t *ikvx)
{
int nvrc;
unsigned char *chap_resp;
return (KV_HANDLED);
}
/*
* Validate and save the the chap identifier which is sent by initiator
* and shift the authentication phase to AP_CHAP_R_RCVD.
*
* Note: see function auth_chap_recv_n.
*/
/*ARGSUSED*/
static kv_status_t
const idm_kv_xlate_t *ikvx)
{
int nvrc;
chap_id);
return (KV_HANDLED);
}
/*
* Validate and save the the chap challenge which is sent by initiator
* and shift the authentication phase to AP_CHAP_R_RCVD.
*
* Note: see function auth_chap_recv_n.
*/
/*ARGSUSED*/
static kv_status_t
const idm_kv_xlate_t *ikvx)
{
int nvrc;
unsigned char *chap_challenge;
return (KV_HANDLED);
}
/*
* Shift the authentication phase to AP_CHAP_R_WAITING after target
* has successfully selected a chap algorithm.
*/
/*ARGSUSED*/
static kv_status_t
const idm_kv_xlate_t *ikvx)
{
&alg);
if (alg != 0) {
} else {
/* none of proposed algorithm is supported or understood. */
}
return (KV_HANDLED);
}
/*
* Initiator does not propose security negotiation, target needs to
* verify if we can bypass the security negotiation phase or propose
* a security negotiation for the initiator.
*/
/*ARGSUSED*/
static kv_status_t
const idm_kv_xlate_t *ikvx)
{
int nvrc;
const char *am_name;
}
if (lsm->icl_auth_pass == 0) {
/*
* It should be noted that the negotiation might also
* be directed by the target if the initiator does
* support security, but is not ready to direct the
* negotiation (propose options).
* - RFC3720 section 5.3.2.
*/
"AuthMethod", am_name);
} else {
kvrc = KV_HANDLED;
}
return (kvrc);
}
/*
* Shift the authentication phase according to the authentication
* method once it is selected.
*/
/*ARGSUSED*/
static kv_status_t
const idm_kv_xlate_t *ikvx)
{
if (client->negotiatedMethod != 0) {
/* Shift security negotiation phase. */
switch (client->negotiatedMethod) {
case AM_CHAP:
break;
case AM_NONE:
break;
default:
ASSERT(0);
break;
}
} else {
/* None of proposed method is supported or understood. */
}
return (KV_HANDLED);
}
/*
* The last step of the chap authentication. We will validate the
* chap parameters we received and authenticate the client here.
*/
/*ARGSUSED*/
static kv_status_t
const idm_kv_xlate_t *ikvx)
{
char *username_in;
unsigned char *chap_challenge;
unsigned int challenge_len;
char *chap_name;
unsigned char *chap_resp;
unsigned int resp_len;
int bi_auth;
if (username_in[0] == '\0')
return (KV_AUTH_FAILED);
/*
* Check if we have received a valid list of response keys.
*/
((bi_auth =
return (KV_MISSING_FIELDS);
}
&chap_name);
/* check username */
return (KV_AUTH_FAILED);
}
&chap_id);
return (KV_AUTH_FAILED);
}
/* bi-direction authentication is required */
if (bi_auth != 0) {
}
return (kvrc);
}
static kv_status_t
{
int nvrc;
unsigned char idData[1];
unsigned char *bin;
int len;
idData[0]);
/* send chap identifier */
"CHAP_I", idData[0]);
if (kvrc != 0) {
return (kvrc);
}
/* send chap challenge */
return (kvrc);
}
static kv_status_t
{
int nvrc;
char *tgt_username;
int tgt_password_length;
unsigned char *chap_challenge;
unsigned int challenge_len;
/*
* We can't know in advance whether the initiator will attempt
* mutual authentication, so now we need to check whether we
* have a target CHAP secret configured.
*/
if (tgt_password_length == 0) {
return (KV_AUTH_FAILED);
}
&chap_id);
&resp[0],
"CHAP_N", tgt_username);
if (nvrc == 0) {
}
return (kvrc);
}