Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[iSCSI] Add support for mutual CHAP
Allow initiator to verify target authentication using CHAP.
  • Loading branch information
Michael Brown committed Aug 11, 2008
1 parent 7ad2f65 commit 5d4839b
Show file tree
Hide file tree
Showing 6 changed files with 390 additions and 82 deletions.
81 changes: 67 additions & 14 deletions src/core/ibft.c
Expand Up @@ -165,16 +165,19 @@ static int ibft_alloc_string ( struct ibft_string_block *strings,
*
* @v strings iBFT string block descriptor
* @v string String field
* @v data String to fill in
* @v data String to fill in, or NULL
* @ret rc Return status code
*/
static int ibft_set_string ( struct ibft_string_block *strings,
struct ibft_string *string, const char *data ) {
size_t len = strlen ( data );
char *dest;
int rc;

if ( ( rc = ibft_alloc_string ( strings, string, len ) ) != 0 )
if ( ! data )
return 0;

if ( ( rc = ibft_alloc_string ( strings, string,
strlen ( data ) ) ) != 0 )
return rc;
dest = ( ( ( char * ) strings->table ) + string->offset );
strcpy ( dest, data );
Expand Down Expand Up @@ -270,6 +273,62 @@ static int ibft_fill_initiator ( struct ibft_initiator *initiator,
return 0;
}

/**
* Fill in Target CHAP portion of iBFT
*
* @v target Target portion of iBFT
* @v strings iBFT string block descriptor
* @v iscsi iSCSI session
* @ret rc Return status code
*/
static int ibft_fill_target_chap ( struct ibft_target *target,
struct ibft_string_block *strings,
struct iscsi_session *iscsi ) {
int rc;

if ( ! iscsi->initiator_username )
return 0;
assert ( iscsi->initiator_password );

target->chap_type = IBFT_CHAP_ONE_WAY;
if ( ( rc = ibft_set_string ( strings, &target->chap_name,
iscsi->initiator_username ) ) != 0 )
return rc;
if ( ( rc = ibft_set_string ( strings, &target->chap_secret,
iscsi->initiator_password ) ) != 0 )
return rc;
return 0;
}

/**
* Fill in Target Reverse CHAP portion of iBFT
*
* @v target Target portion of iBFT
* @v strings iBFT string block descriptor
* @v iscsi iSCSI session
* @ret rc Return status code
*/
static int ibft_fill_target_reverse_chap ( struct ibft_target *target,
struct ibft_string_block *strings,
struct iscsi_session *iscsi ) {
int rc;

if ( ! iscsi->target_username )
return 0;
assert ( iscsi->target_password );
assert ( iscsi->initiator_username );
assert ( iscsi->initiator_password );

target->chap_type = IBFT_CHAP_MUTUAL;
if ( ( rc = ibft_set_string ( strings, &target->reverse_chap_name,
iscsi->target_username ) ) != 0 )
return rc;
if ( ( rc = ibft_set_string ( strings, &target->reverse_chap_secret,
iscsi->target_password ) ) != 0 )
return rc;
return 0;
}

/**
* Fill in Target portion of iBFT
*
Expand All @@ -291,17 +350,11 @@ static int ibft_fill_target ( struct ibft_target *target,
if ( ( rc = ibft_set_string ( strings, &target->target_name,
iscsi->target_iqn ) ) != 0 )
return rc;
if ( iscsi->username ) {
if ( ( rc = ibft_set_string ( strings, &target->chap_name,
iscsi->username ) ) != 0 )
return rc;
}
if ( iscsi->password ) {
if ( ( rc = ibft_set_string ( strings, &target->chap_secret,
iscsi->password ) ) != 0 )
return rc;
target->chap_type = IBFT_CHAP_ONE_WAY;
}
if ( ( rc = ibft_fill_target_chap ( target, strings, iscsi ) ) != 0 )
return rc;
if ( ( rc = ibft_fill_target_reverse_chap ( target, strings,
iscsi ) ) != 0 )
return rc;

return 0;
}
Expand Down
16 changes: 8 additions & 8 deletions src/crypto/chap.c
Expand Up @@ -41,7 +41,7 @@
* allocates memory, and so may fail. The allocated memory must
* eventually be freed by a call to chap_finish().
*/
int chap_init ( struct chap_challenge *chap,
int chap_init ( struct chap_response *chap,
struct crypto_algorithm *digest ) {
size_t state_len;
void *state;
Expand Down Expand Up @@ -71,11 +71,11 @@ int chap_init ( struct chap_challenge *chap,
/**
* Add data to the CHAP challenge
*
* @v chap CHAP challenge/response
* @v chap CHAP response
* @v data Data to add
* @v len Length of data to add
*/
void chap_update ( struct chap_challenge *chap, const void *data,
void chap_update ( struct chap_response *chap, const void *data,
size_t len ) {
assert ( chap->digest != NULL );
assert ( chap->digest_context != NULL );
Expand All @@ -89,12 +89,12 @@ void chap_update ( struct chap_challenge *chap, const void *data,
/**
* Respond to the CHAP challenge
*
* @v chap CHAP challenge/response
* @v chap CHAP response
*
* Calculates the final CHAP response value, and places it in @c
* chap->response, with a length of @c chap->response_len.
*/
void chap_respond ( struct chap_challenge *chap ) {
void chap_respond ( struct chap_response *chap ) {
assert ( chap->digest != NULL );
assert ( chap->digest_context != NULL );
assert ( chap->response != NULL );
Expand All @@ -108,11 +108,11 @@ void chap_respond ( struct chap_challenge *chap ) {
}

/**
* Free resources used by a CHAP challenge/response
* Free resources used by a CHAP response
*
* @v chap CHAP challenge/response
* @v chap CHAP response
*/
void chap_finish ( struct chap_challenge *chap ) {
void chap_finish ( struct chap_response *chap ) {
void *state = chap->digest_context;

DBG ( "CHAP %p finished\n", chap );
Expand Down
16 changes: 8 additions & 8 deletions src/include/gpxe/chap.h
Expand Up @@ -12,8 +12,8 @@

struct crypto_algorithm;

/** A CHAP challenge/response */
struct chap_challenge {
/** A CHAP response */
struct chap_response {
/** Digest algorithm used for the response */
struct crypto_algorithm *digest;
/** Context used by the digest algorithm */
Expand All @@ -24,24 +24,24 @@ struct chap_challenge {
size_t response_len;
};

extern int chap_init ( struct chap_challenge *chap,
extern int chap_init ( struct chap_response *chap,
struct crypto_algorithm *digest );
extern void chap_update ( struct chap_challenge *chap, const void *data,
extern void chap_update ( struct chap_response *chap, const void *data,
size_t len );
extern void chap_respond ( struct chap_challenge *chap );
extern void chap_finish ( struct chap_challenge *chap );
extern void chap_respond ( struct chap_response *chap );
extern void chap_finish ( struct chap_response *chap );

/**
* Add identifier data to the CHAP challenge
*
* @v chap CHAP challenge/response
* @v chap CHAP response
* @v identifier CHAP identifier
*
* The CHAP identifier is the first byte of the CHAP challenge. This
* function is a notational convenience for calling chap_update() for
* the identifier byte.
*/
static inline void chap_set_identifier ( struct chap_challenge *chap,
static inline void chap_set_identifier ( struct chap_response *chap,
unsigned int identifier ) {
uint8_t ident_byte = identifier;

Expand Down
18 changes: 18 additions & 0 deletions src/include/gpxe/dhcp.h
Expand Up @@ -241,6 +241,24 @@ struct dhcp_packet;
*/
#define DHCP_EB_PASSWORD DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0xbf )

/** Reverse username
*
* This will be used as the reverse username (i.e. the username
* provided by the server) for any required authentication. It is
* expected that this option's value will be held in non-volatile
* storage, rather than transmitted as part of a DHCP packet.
*/
#define DHCP_EB_REVERSE_USERNAME DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0xc0 )

/** Reverse password
*
* This will be used as the reverse password (i.e. the password
* provided by the server) for any required authentication. It is
* expected that this option's value will be held in non-volatile
* storage, rather than transmitted as part of a DHCP packet.
*/
#define DHCP_EB_REVERSE_PASSWORD DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0xc1 )

/** iSCSI primary target IQN */
#define DHCP_ISCSI_PRIMARY_TARGET_IQN 201

Expand Down
30 changes: 23 additions & 7 deletions src/include/gpxe/iscsi.h
Expand Up @@ -522,12 +522,25 @@ struct iscsi_session {
*/
int retry_count;

/** Username (if any) */
char *username;
/** Password (if any) */
char *password;
/** CHAP challenge/response */
struct chap_challenge chap;
/** Initiator username (if any) */
char *initiator_username;
/** Initiator password (if any) */
char *initiator_password;
/** Target username (if any) */
char *target_username;
/** Target password (if any) */
char *target_password;
/** Target has authenticated acceptably */
int target_auth_ok;
/** CHAP challenge (for target auth only)
*
* This is a block of random data; the first byte is used as
* the CHAP identifier (CHAP_I) and the remainder as the CHAP
* challenge (CHAP_C).
*/
unsigned char chap_challenge[17];
/** CHAP response (used for both initiator and target auth) */
struct chap_response chap;

/** Target session identifying handle
*
Expand Down Expand Up @@ -642,8 +655,11 @@ struct iscsi_session {
/** iSCSI session needs to send the CHAP response */
#define ISCSI_STATUS_STRINGS_CHAP_RESPONSE 0x0400

/** iSCSI session needs to send the mutual CHAP challenge */
#define ISCSI_STATUS_STRINGS_CHAP_CHALLENGE 0x0800

/** iSCSI session needs to send the operational negotiation strings */
#define ISCSI_STATUS_STRINGS_OPERATIONAL 0x0800
#define ISCSI_STATUS_STRINGS_OPERATIONAL 0x1000

/** Mask for all iSCSI "needs to send" flags */
#define ISCSI_STATUS_STRINGS_MASK 0xff00
Expand Down

0 comments on commit 5d4839b

Please sign in to comment.