Browse Source

[iscsi] Include credentials in iBFT only if used during iSCSI login

Avoid passing credentials in the iBFT that were available but not
required for login.  This works around a problem in the Microsoft
iSCSI initiator, which will refuse to initiate sessions if the CHAP
password is fewer than 12 characters, even if the target ends up not
asking for CHAP authentication.
tags/v0.9.7
Michael Brown 15 years ago
parent
commit
4dd746a725
3 changed files with 73 additions and 17 deletions
  1. 53
    3
      src/arch/i386/interface/pcbios/ibft.c
  2. 9
    2
      src/include/gpxe/iscsi.h
  3. 11
    12
      src/net/tcp/iscsi.c

+ 53
- 3
src/arch/i386/interface/pcbios/ibft.c View File

136
 	ibft_set_ipaddr ( ipaddr, in );
136
 	ibft_set_ipaddr ( ipaddr, in );
137
 }
137
 }
138
 
138
 
139
+/**
140
+ * Read IP address from iBFT (for debugging)
141
+ *
142
+ * @v strings		iBFT string block descriptor
143
+ * @v string		String field
144
+ * @ret ipaddr		IP address string
145
+ */
146
+static const char * ibft_ipaddr ( struct ibft_ipaddr *ipaddr ) {
147
+	return inet_ntoa ( ipaddr->in );
148
+}
149
+
139
 /**
150
 /**
140
  * Allocate a string within iBFT
151
  * Allocate a string within iBFT
141
  *
152
  *
214
 	return 0;
225
 	return 0;
215
 }
226
 }
216
 
227
 
228
+/**
229
+ * Read string from iBFT (for debugging)
230
+ *
231
+ * @v strings		iBFT string block descriptor
232
+ * @v string		String field
233
+ * @ret data		String content (or "<empty>")
234
+ */
235
+static const char * ibft_string ( struct ibft_string_block *strings,
236
+				  struct ibft_string *string ) {
237
+	return ( ( ( char * ) strings->table ) + string->offset );
238
+}
239
+
217
 /**
240
 /**
218
  * Fill in NIC portion of iBFT
241
  * Fill in NIC portion of iBFT
219
  *
242
  *
231
 
254
 
232
 	/* Extract values from DHCP configuration */
255
 	/* Extract values from DHCP configuration */
233
 	ibft_set_ipaddr_option ( &nic->ip_address, &ip_setting );
256
 	ibft_set_ipaddr_option ( &nic->ip_address, &ip_setting );
257
+	DBG ( "iBFT NIC IP = %s\n", ibft_ipaddr ( &nic->ip_address ) );
234
 	ibft_set_ipaddr_option ( &nic->gateway, &gateway_setting );
258
 	ibft_set_ipaddr_option ( &nic->gateway, &gateway_setting );
259
+	DBG ( "iBFT NIC gateway = %s\n", ibft_ipaddr ( &nic->gateway ) );
235
 	ibft_set_ipaddr_option ( &nic->dns[0], &dns_setting );
260
 	ibft_set_ipaddr_option ( &nic->dns[0], &dns_setting );
261
+	DBG ( "iBFT NIC DNS = %s\n", ibft_ipaddr ( &nic->dns[0] ) );
236
 	if ( ( rc = ibft_set_string_option ( strings, &nic->hostname,
262
 	if ( ( rc = ibft_set_string_option ( strings, &nic->hostname,
237
 					     &hostname_setting ) ) != 0 )
263
 					     &hostname_setting ) ) != 0 )
238
 		return rc;
264
 		return rc;
265
+	DBG ( "iBFT NIC hostname = %s\n",
266
+	      ibft_string ( strings, &nic->hostname ) );
239
 
267
 
240
 	/* Derive subnet mask prefix from subnet mask */
268
 	/* Derive subnet mask prefix from subnet mask */
241
 	fetch_ipv4_setting ( NULL, &netmask_setting, &netmask_addr );
269
 	fetch_ipv4_setting ( NULL, &netmask_setting, &netmask_addr );
245
 		netmask_addr.s_addr >>= 1;
273
 		netmask_addr.s_addr >>= 1;
246
 	}
274
 	}
247
 	nic->subnet_mask_prefix = netmask_count;
275
 	nic->subnet_mask_prefix = netmask_count;
276
+	DBG ( "iBFT NIC subnet = /%d\n", nic->subnet_mask_prefix );
248
 
277
 
249
 	/* Extract values from net-device configuration */
278
 	/* Extract values from net-device configuration */
250
 	memcpy ( nic->mac_address, netdev->ll_addr,
279
 	memcpy ( nic->mac_address, netdev->ll_addr,
251
 		 sizeof ( nic->mac_address ) );
280
 		 sizeof ( nic->mac_address ) );
281
+	DBG ( "iBFT NIC MAC = %s\n",
282
+	      netdev->ll_protocol->ntoa ( nic->mac_address ) );
252
 	nic->pci_bus_dev_func = netdev->dev->desc.location;
283
 	nic->pci_bus_dev_func = netdev->dev->desc.location;
284
+	DBG ( "iBFT NIC PCI = %04x\n", nic->pci_bus_dev_func );
253
 
285
 
254
 	return 0;
286
 	return 0;
255
 }
287
 }
269
 	if ( ( rc = ibft_set_string ( strings, &initiator->initiator_name,
301
 	if ( ( rc = ibft_set_string ( strings, &initiator->initiator_name,
270
 				      initiator_iqn ) ) != 0 )
302
 				      initiator_iqn ) ) != 0 )
271
 		return rc;
303
 		return rc;
304
+	DBG ( "iBFT initiator hostname = %s\n",
305
+	      ibft_string ( strings, &initiator->initiator_name ) );
272
 
306
 
273
 	return 0;
307
 	return 0;
274
 }
308
 }
286
 				   struct iscsi_session *iscsi ) {
320
 				   struct iscsi_session *iscsi ) {
287
 	int rc;
321
 	int rc;
288
 
322
 
289
-	if ( ! iscsi->initiator_username )
323
+	if ( ! ( iscsi->status & ISCSI_STATUS_AUTH_FORWARD_REQUIRED ) )
290
 		return 0;
324
 		return 0;
325
+
326
+	assert ( iscsi->initiator_username );
291
 	assert ( iscsi->initiator_password );
327
 	assert ( iscsi->initiator_password );
292
 
328
 
293
 	target->chap_type = IBFT_CHAP_ONE_WAY;
329
 	target->chap_type = IBFT_CHAP_ONE_WAY;
294
 	if ( ( rc = ibft_set_string ( strings, &target->chap_name,
330
 	if ( ( rc = ibft_set_string ( strings, &target->chap_name,
295
 				      iscsi->initiator_username ) ) != 0 )
331
 				      iscsi->initiator_username ) ) != 0 )
296
 		return rc;
332
 		return rc;
333
+	DBG ( "iBFT target username = %s\n",
334
+	      ibft_string ( strings, &target->chap_name ) );
297
 	if ( ( rc = ibft_set_string ( strings, &target->chap_secret,
335
 	if ( ( rc = ibft_set_string ( strings, &target->chap_secret,
298
 				      iscsi->initiator_password ) ) != 0 )
336
 				      iscsi->initiator_password ) ) != 0 )
299
 		return rc;
337
 		return rc;
338
+	DBG ( "iBFT target password = <redacted>\n" );
339
+
300
 	return 0;
340
 	return 0;
301
 }
341
 }
302
 
342
 
313
 					   struct iscsi_session *iscsi ) {
353
 					   struct iscsi_session *iscsi ) {
314
 	int rc;
354
 	int rc;
315
 
355
 
316
-	if ( ! iscsi->target_username )
356
+	if ( ! ( iscsi->status & ISCSI_STATUS_AUTH_REVERSE_REQUIRED ) )
317
 		return 0;
357
 		return 0;
318
-	assert ( iscsi->target_password );
358
+
319
 	assert ( iscsi->initiator_username );
359
 	assert ( iscsi->initiator_username );
320
 	assert ( iscsi->initiator_password );
360
 	assert ( iscsi->initiator_password );
361
+	assert ( iscsi->target_username );
362
+	assert ( iscsi->target_password );
321
 
363
 
322
 	target->chap_type = IBFT_CHAP_MUTUAL;
364
 	target->chap_type = IBFT_CHAP_MUTUAL;
323
 	if ( ( rc = ibft_set_string ( strings, &target->reverse_chap_name,
365
 	if ( ( rc = ibft_set_string ( strings, &target->reverse_chap_name,
324
 				      iscsi->target_username ) ) != 0 )
366
 				      iscsi->target_username ) ) != 0 )
325
 		return rc;
367
 		return rc;
368
+	DBG ( "iBFT target reverse username = %s\n",
369
+	      ibft_string ( strings, &target->chap_name ) );
326
 	if ( ( rc = ibft_set_string ( strings, &target->reverse_chap_secret,
370
 	if ( ( rc = ibft_set_string ( strings, &target->reverse_chap_secret,
327
 				      iscsi->target_password ) ) != 0 )
371
 				      iscsi->target_password ) ) != 0 )
328
 		return rc;
372
 		return rc;
373
+	DBG ( "iBFT target reverse password = <redacted>\n" );
374
+
329
 	return 0;
375
 	return 0;
330
 }
376
 }
331
 
377
 
346
 
392
 
347
 	/* Fill in Target values */
393
 	/* Fill in Target values */
348
 	ibft_set_ipaddr ( &target->ip_address, sin_target->sin_addr );
394
 	ibft_set_ipaddr ( &target->ip_address, sin_target->sin_addr );
395
+	DBG ( "iBFT target IP = %s\n", ibft_ipaddr ( &target->ip_address ) );
349
 	target->socket = ntohs ( sin_target->sin_port );
396
 	target->socket = ntohs ( sin_target->sin_port );
397
+	DBG ( "iBFT target port = %d\n", target->socket );
350
 	if ( ( rc = ibft_set_string ( strings, &target->target_name,
398
 	if ( ( rc = ibft_set_string ( strings, &target->target_name,
351
 				      iscsi->target_iqn ) ) != 0 )
399
 				      iscsi->target_iqn ) ) != 0 )
352
 		return rc;
400
 		return rc;
401
+	DBG ( "iBFT target name = %s\n",
402
+	      ibft_string ( strings, &target->target_name ) );
353
 	if ( ( rc = ibft_fill_target_chap ( target, strings, iscsi ) ) != 0 )
403
 	if ( ( rc = ibft_fill_target_chap ( target, strings, iscsi ) ) != 0 )
354
 		return rc;
404
 		return rc;
355
 	if ( ( rc = ibft_fill_target_reverse_chap ( target, strings,
405
 	if ( ( rc = ibft_fill_target_reverse_chap ( target, strings,

+ 9
- 2
src/include/gpxe/iscsi.h View File

530
 	char *target_username;
530
 	char *target_username;
531
 	/** Target password (if any) */
531
 	/** Target password (if any) */
532
 	char *target_password;
532
 	char *target_password;
533
-	/** Target has authenticated acceptably */
534
-	int target_auth_ok;
535
 	/** CHAP challenge (for target auth only)
533
 	/** CHAP challenge (for target auth only)
536
 	 *
534
 	 *
537
 	 * This is a block of random data; the first byte is used as
535
 	 * This is a block of random data; the first byte is used as
664
 /** Mask for all iSCSI "needs to send" flags */
662
 /** Mask for all iSCSI "needs to send" flags */
665
 #define ISCSI_STATUS_STRINGS_MASK 0xff00
663
 #define ISCSI_STATUS_STRINGS_MASK 0xff00
666
 
664
 
665
+/** Target has requested forward (initiator) authentication */
666
+#define ISCSI_STATUS_AUTH_FORWARD_REQUIRED 0x00010000
667
+
668
+/** Initiator requires target (reverse) authentication */
669
+#define ISCSI_STATUS_AUTH_REVERSE_REQUIRED 0x00020000
670
+
671
+/** Target authenticated itself correctly */
672
+#define ISCSI_STATUS_AUTH_REVERSE_OK 0x00040000
673
+
667
 /** Maximum number of retries at connecting */
674
 /** Maximum number of retries at connecting */
668
 #define ISCSI_MAX_RETRIES 2
675
 #define ISCSI_MAX_RETRIES 2
669
 
676
 

+ 11
- 12
src/net/tcp/iscsi.c View File

125
 	/* Enter security negotiation phase */
125
 	/* Enter security negotiation phase */
126
 	iscsi->status = ( ISCSI_STATUS_SECURITY_NEGOTIATION_PHASE |
126
 	iscsi->status = ( ISCSI_STATUS_SECURITY_NEGOTIATION_PHASE |
127
 			  ISCSI_STATUS_STRINGS_SECURITY );
127
 			  ISCSI_STATUS_STRINGS_SECURITY );
128
+	if ( iscsi->target_username )
129
+		iscsi->status |= ISCSI_STATUS_AUTH_REVERSE_REQUIRED;
128
 
130
 
129
 	/* Assign fresh initiator task tag */
131
 	/* Assign fresh initiator task tag */
130
 	iscsi->itt++;
132
 	iscsi->itt++;
152
 	/* Clear connection status */
154
 	/* Clear connection status */
153
 	iscsi->status = 0;
155
 	iscsi->status = 0;
154
 
156
 
155
-	/* Deauthenticate target */
156
-	iscsi->target_auth_ok = 0;
157
-
158
 	/* Reset TX and RX state machines */
157
 	/* Reset TX and RX state machines */
159
 	iscsi->tx_state = ISCSI_TX_IDLE;
158
 	iscsi->tx_state = ISCSI_TX_IDLE;
160
 	iscsi->rx_state = ISCSI_RX_BHS;
159
 	iscsi->rx_state = ISCSI_RX_BHS;
634
 static int iscsi_handle_authmethod_value ( struct iscsi_session *iscsi,
633
 static int iscsi_handle_authmethod_value ( struct iscsi_session *iscsi,
635
 					   const char *value ) {
634
 					   const char *value ) {
636
 
635
 
637
-	/* Mark target as authenticated if no authentication required */
638
-	if ( ! iscsi->target_username )
639
-		iscsi->target_auth_ok = 1;
640
-
641
 	/* If server requests CHAP, send the CHAP_A string */
636
 	/* If server requests CHAP, send the CHAP_A string */
642
 	if ( strcmp ( value, "CHAP" ) == 0 ) {
637
 	if ( strcmp ( value, "CHAP" ) == 0 ) {
643
 		DBGC ( iscsi, "iSCSI %p initiating CHAP authentication\n",
638
 		DBGC ( iscsi, "iSCSI %p initiating CHAP authentication\n",
644
 		       iscsi );
639
 		       iscsi );
645
-		iscsi->status |= ISCSI_STATUS_STRINGS_CHAP_ALGORITHM;
640
+		iscsi->status |= ( ISCSI_STATUS_STRINGS_CHAP_ALGORITHM |
641
+				   ISCSI_STATUS_AUTH_FORWARD_REQUIRED );
646
 	}
642
 	}
647
 
643
 
648
 	return 0;
644
 	return 0;
858
 	assert ( i == iscsi->chap.response_len );
854
 	assert ( i == iscsi->chap.response_len );
859
 
855
 
860
 	/* Mark session as authenticated */
856
 	/* Mark session as authenticated */
861
-	iscsi->target_auth_ok = 1;
857
+	iscsi->status |= ISCSI_STATUS_AUTH_REVERSE_OK;
862
 
858
 
863
 	return 0;
859
 	return 0;
864
 }
860
 }
1064
 
1060
 
1065
 	/* Handle login transitions */
1061
 	/* Handle login transitions */
1066
 	if ( response->flags & ISCSI_LOGIN_FLAG_TRANSITION ) {
1062
 	if ( response->flags & ISCSI_LOGIN_FLAG_TRANSITION ) {
1063
+		iscsi->status &= ~( ISCSI_STATUS_PHASE_MASK |
1064
+				    ISCSI_STATUS_STRINGS_MASK );
1067
 		switch ( response->flags & ISCSI_LOGIN_NSG_MASK ) {
1065
 		switch ( response->flags & ISCSI_LOGIN_NSG_MASK ) {
1068
 		case ISCSI_LOGIN_NSG_OPERATIONAL_NEGOTIATION:
1066
 		case ISCSI_LOGIN_NSG_OPERATIONAL_NEGOTIATION:
1069
-			iscsi->status =
1067
+			iscsi->status |=
1070
 				( ISCSI_STATUS_OPERATIONAL_NEGOTIATION_PHASE |
1068
 				( ISCSI_STATUS_OPERATIONAL_NEGOTIATION_PHASE |
1071
 				  ISCSI_STATUS_STRINGS_OPERATIONAL );
1069
 				  ISCSI_STATUS_STRINGS_OPERATIONAL );
1072
 			break;
1070
 			break;
1073
 		case ISCSI_LOGIN_NSG_FULL_FEATURE_PHASE:
1071
 		case ISCSI_LOGIN_NSG_FULL_FEATURE_PHASE:
1074
-			iscsi->status = ISCSI_STATUS_FULL_FEATURE_PHASE;
1072
+			iscsi->status |= ISCSI_STATUS_FULL_FEATURE_PHASE;
1075
 			break;
1073
 			break;
1076
 		default:
1074
 		default:
1077
 			DBGC ( iscsi, "iSCSI %p got invalid response flags "
1075
 			DBGC ( iscsi, "iSCSI %p got invalid response flags "
1090
 	}
1088
 	}
1091
 
1089
 
1092
 	/* Check that target authentication was successful (if required) */
1090
 	/* Check that target authentication was successful (if required) */
1093
-	if ( ! iscsi->target_auth_ok ) {
1091
+	if ( ( iscsi->status & ISCSI_STATUS_AUTH_REVERSE_REQUIRED ) &&
1092
+	     ! ( iscsi->status & ISCSI_STATUS_AUTH_REVERSE_OK ) ) {
1094
 		DBGC ( iscsi, "iSCSI %p nefarious target tried to bypass "
1093
 		DBGC ( iscsi, "iSCSI %p nefarious target tried to bypass "
1095
 		       "authentication\n", iscsi );
1094
 		       "authentication\n", iscsi );
1096
 		return -EPROTO;
1095
 		return -EPROTO;

Loading…
Cancel
Save