summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/arch/i386/interface/pcbios/ibft.c56
-rw-r--r--src/include/gpxe/iscsi.h11
-rw-r--r--src/net/tcp/iscsi.c23
3 files changed, 73 insertions, 17 deletions
diff --git a/src/arch/i386/interface/pcbios/ibft.c b/src/arch/i386/interface/pcbios/ibft.c
index ffa65964..43d1f85f 100644
--- a/src/arch/i386/interface/pcbios/ibft.c
+++ b/src/arch/i386/interface/pcbios/ibft.c
@@ -137,6 +137,17 @@ static void ibft_set_ipaddr_option ( struct ibft_ipaddr *ipaddr,
}
/**
+ * Read IP address from iBFT (for debugging)
+ *
+ * @v strings iBFT string block descriptor
+ * @v string String field
+ * @ret ipaddr IP address string
+ */
+static const char * ibft_ipaddr ( struct ibft_ipaddr *ipaddr ) {
+ return inet_ntoa ( ipaddr->in );
+}
+
+/**
* Allocate a string within iBFT
*
* @v strings iBFT string block descriptor
@@ -215,6 +226,18 @@ static int ibft_set_string_option ( struct ibft_string_block *strings,
}
/**
+ * Read string from iBFT (for debugging)
+ *
+ * @v strings iBFT string block descriptor
+ * @v string String field
+ * @ret data String content (or "<empty>")
+ */
+static const char * ibft_string ( struct ibft_string_block *strings,
+ struct ibft_string *string ) {
+ return ( ( ( char * ) strings->table ) + string->offset );
+}
+
+/**
* Fill in NIC portion of iBFT
*
* @v nic NIC portion of iBFT
@@ -231,11 +254,16 @@ static int ibft_fill_nic ( struct ibft_nic *nic,
/* Extract values from DHCP configuration */
ibft_set_ipaddr_option ( &nic->ip_address, &ip_setting );
+ DBG ( "iBFT NIC IP = %s\n", ibft_ipaddr ( &nic->ip_address ) );
ibft_set_ipaddr_option ( &nic->gateway, &gateway_setting );
+ DBG ( "iBFT NIC gateway = %s\n", ibft_ipaddr ( &nic->gateway ) );
ibft_set_ipaddr_option ( &nic->dns[0], &dns_setting );
+ DBG ( "iBFT NIC DNS = %s\n", ibft_ipaddr ( &nic->dns[0] ) );
if ( ( rc = ibft_set_string_option ( strings, &nic->hostname,
&hostname_setting ) ) != 0 )
return rc;
+ DBG ( "iBFT NIC hostname = %s\n",
+ ibft_string ( strings, &nic->hostname ) );
/* Derive subnet mask prefix from subnet mask */
fetch_ipv4_setting ( NULL, &netmask_setting, &netmask_addr );
@@ -245,11 +273,15 @@ static int ibft_fill_nic ( struct ibft_nic *nic,
netmask_addr.s_addr >>= 1;
}
nic->subnet_mask_prefix = netmask_count;
+ DBG ( "iBFT NIC subnet = /%d\n", nic->subnet_mask_prefix );
/* Extract values from net-device configuration */
memcpy ( nic->mac_address, netdev->ll_addr,
sizeof ( nic->mac_address ) );
+ DBG ( "iBFT NIC MAC = %s\n",
+ netdev->ll_protocol->ntoa ( nic->mac_address ) );
nic->pci_bus_dev_func = netdev->dev->desc.location;
+ DBG ( "iBFT NIC PCI = %04x\n", nic->pci_bus_dev_func );
return 0;
}
@@ -269,6 +301,8 @@ static int ibft_fill_initiator ( struct ibft_initiator *initiator,
if ( ( rc = ibft_set_string ( strings, &initiator->initiator_name,
initiator_iqn ) ) != 0 )
return rc;
+ DBG ( "iBFT initiator hostname = %s\n",
+ ibft_string ( strings, &initiator->initiator_name ) );
return 0;
}
@@ -286,17 +320,23 @@ static int ibft_fill_target_chap ( struct ibft_target *target,
struct iscsi_session *iscsi ) {
int rc;
- if ( ! iscsi->initiator_username )
+ if ( ! ( iscsi->status & ISCSI_STATUS_AUTH_FORWARD_REQUIRED ) )
return 0;
+
+ assert ( iscsi->initiator_username );
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;
+ DBG ( "iBFT target username = %s\n",
+ ibft_string ( strings, &target->chap_name ) );
if ( ( rc = ibft_set_string ( strings, &target->chap_secret,
iscsi->initiator_password ) ) != 0 )
return rc;
+ DBG ( "iBFT target password = <redacted>\n" );
+
return 0;
}
@@ -313,19 +353,25 @@ static int ibft_fill_target_reverse_chap ( struct ibft_target *target,
struct iscsi_session *iscsi ) {
int rc;
- if ( ! iscsi->target_username )
+ if ( ! ( iscsi->status & ISCSI_STATUS_AUTH_REVERSE_REQUIRED ) )
return 0;
- assert ( iscsi->target_password );
+
assert ( iscsi->initiator_username );
assert ( iscsi->initiator_password );
+ assert ( iscsi->target_username );
+ assert ( iscsi->target_password );
target->chap_type = IBFT_CHAP_MUTUAL;
if ( ( rc = ibft_set_string ( strings, &target->reverse_chap_name,
iscsi->target_username ) ) != 0 )
return rc;
+ DBG ( "iBFT target reverse username = %s\n",
+ ibft_string ( strings, &target->chap_name ) );
if ( ( rc = ibft_set_string ( strings, &target->reverse_chap_secret,
iscsi->target_password ) ) != 0 )
return rc;
+ DBG ( "iBFT target reverse password = <redacted>\n" );
+
return 0;
}
@@ -346,10 +392,14 @@ static int ibft_fill_target ( struct ibft_target *target,
/* Fill in Target values */
ibft_set_ipaddr ( &target->ip_address, sin_target->sin_addr );
+ DBG ( "iBFT target IP = %s\n", ibft_ipaddr ( &target->ip_address ) );
target->socket = ntohs ( sin_target->sin_port );
+ DBG ( "iBFT target port = %d\n", target->socket );
if ( ( rc = ibft_set_string ( strings, &target->target_name,
iscsi->target_iqn ) ) != 0 )
return rc;
+ DBG ( "iBFT target name = %s\n",
+ ibft_string ( strings, &target->target_name ) );
if ( ( rc = ibft_fill_target_chap ( target, strings, iscsi ) ) != 0 )
return rc;
if ( ( rc = ibft_fill_target_reverse_chap ( target, strings,
diff --git a/src/include/gpxe/iscsi.h b/src/include/gpxe/iscsi.h
index fd96fdfe..0510974e 100644
--- a/src/include/gpxe/iscsi.h
+++ b/src/include/gpxe/iscsi.h
@@ -530,8 +530,6 @@ struct iscsi_session {
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
@@ -664,6 +662,15 @@ struct iscsi_session {
/** Mask for all iSCSI "needs to send" flags */
#define ISCSI_STATUS_STRINGS_MASK 0xff00
+/** Target has requested forward (initiator) authentication */
+#define ISCSI_STATUS_AUTH_FORWARD_REQUIRED 0x00010000
+
+/** Initiator requires target (reverse) authentication */
+#define ISCSI_STATUS_AUTH_REVERSE_REQUIRED 0x00020000
+
+/** Target authenticated itself correctly */
+#define ISCSI_STATUS_AUTH_REVERSE_OK 0x00040000
+
/** Maximum number of retries at connecting */
#define ISCSI_MAX_RETRIES 2
diff --git a/src/net/tcp/iscsi.c b/src/net/tcp/iscsi.c
index aa99db71..45519e66 100644
--- a/src/net/tcp/iscsi.c
+++ b/src/net/tcp/iscsi.c
@@ -125,6 +125,8 @@ static int iscsi_open_connection ( struct iscsi_session *iscsi ) {
/* Enter security negotiation phase */
iscsi->status = ( ISCSI_STATUS_SECURITY_NEGOTIATION_PHASE |
ISCSI_STATUS_STRINGS_SECURITY );
+ if ( iscsi->target_username )
+ iscsi->status |= ISCSI_STATUS_AUTH_REVERSE_REQUIRED;
/* Assign fresh initiator task tag */
iscsi->itt++;
@@ -152,9 +154,6 @@ static void iscsi_close_connection ( struct iscsi_session *iscsi, int rc ) {
/* Clear connection status */
iscsi->status = 0;
- /* Deauthenticate target */
- iscsi->target_auth_ok = 0;
-
/* Reset TX and RX state machines */
iscsi->tx_state = ISCSI_TX_IDLE;
iscsi->rx_state = ISCSI_RX_BHS;
@@ -634,15 +633,12 @@ static int iscsi_handle_targetaddress_value ( struct iscsi_session *iscsi,
static int iscsi_handle_authmethod_value ( struct iscsi_session *iscsi,
const char *value ) {
- /* Mark target as authenticated if no authentication required */
- if ( ! iscsi->target_username )
- iscsi->target_auth_ok = 1;
-
/* If server requests CHAP, send the CHAP_A string */
if ( strcmp ( value, "CHAP" ) == 0 ) {
DBGC ( iscsi, "iSCSI %p initiating CHAP authentication\n",
iscsi );
- iscsi->status |= ISCSI_STATUS_STRINGS_CHAP_ALGORITHM;
+ iscsi->status |= ( ISCSI_STATUS_STRINGS_CHAP_ALGORITHM |
+ ISCSI_STATUS_AUTH_FORWARD_REQUIRED );
}
return 0;
@@ -858,7 +854,7 @@ static int iscsi_handle_chap_r_value ( struct iscsi_session *iscsi,
assert ( i == iscsi->chap.response_len );
/* Mark session as authenticated */
- iscsi->target_auth_ok = 1;
+ iscsi->status |= ISCSI_STATUS_AUTH_REVERSE_OK;
return 0;
}
@@ -1064,14 +1060,16 @@ static int iscsi_rx_login_response ( struct iscsi_session *iscsi,
/* Handle login transitions */
if ( response->flags & ISCSI_LOGIN_FLAG_TRANSITION ) {
+ iscsi->status &= ~( ISCSI_STATUS_PHASE_MASK |
+ ISCSI_STATUS_STRINGS_MASK );
switch ( response->flags & ISCSI_LOGIN_NSG_MASK ) {
case ISCSI_LOGIN_NSG_OPERATIONAL_NEGOTIATION:
- iscsi->status =
+ iscsi->status |=
( ISCSI_STATUS_OPERATIONAL_NEGOTIATION_PHASE |
ISCSI_STATUS_STRINGS_OPERATIONAL );
break;
case ISCSI_LOGIN_NSG_FULL_FEATURE_PHASE:
- iscsi->status = ISCSI_STATUS_FULL_FEATURE_PHASE;
+ iscsi->status |= ISCSI_STATUS_FULL_FEATURE_PHASE;
break;
default:
DBGC ( iscsi, "iSCSI %p got invalid response flags "
@@ -1090,7 +1088,8 @@ static int iscsi_rx_login_response ( struct iscsi_session *iscsi,
}
/* Check that target authentication was successful (if required) */
- if ( ! iscsi->target_auth_ok ) {
+ if ( ( iscsi->status & ISCSI_STATUS_AUTH_REVERSE_REQUIRED ) &&
+ ! ( iscsi->status & ISCSI_STATUS_AUTH_REVERSE_OK ) ) {
DBGC ( iscsi, "iSCSI %p nefarious target tried to bypass "
"authentication\n", iscsi );
return -EPROTO;