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 @@ -136,6 +136,17 @@ static void ibft_set_ipaddr_option ( struct ibft_ipaddr *ipaddr, ibft_set_ipaddr ( ipaddr, in ); } +/** + * 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 * @@ -214,6 +225,18 @@ static int ibft_set_string_option ( struct ibft_string_block *strings, return 0; } +/** + * Read string from iBFT (for debugging) + * + * @v strings iBFT string block descriptor + * @v string String field + * @ret data String content (or "") + */ +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 * @@ -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 = \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 = \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;