Преглед изворни кода

[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 година
родитељ
комит
4dd746a725
3 измењених фајлова са 73 додато и 17 уклоњено
  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 Прегледај датотеку

@@ -136,6 +136,17 @@ static void ibft_set_ipaddr_option ( struct ibft_ipaddr *ipaddr,
136 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 151
  * Allocate a string within iBFT
141 152
  *
@@ -214,6 +225,18 @@ static int ibft_set_string_option ( struct ibft_string_block *strings,
214 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 241
  * Fill in NIC portion of iBFT
219 242
  *
@@ -231,11 +254,16 @@ static int ibft_fill_nic ( struct ibft_nic *nic,
231 254
 
232 255
 	/* Extract values from DHCP configuration */
233 256
 	ibft_set_ipaddr_option ( &nic->ip_address, &ip_setting );
257
+	DBG ( "iBFT NIC IP = %s\n", ibft_ipaddr ( &nic->ip_address ) );
234 258
 	ibft_set_ipaddr_option ( &nic->gateway, &gateway_setting );
259
+	DBG ( "iBFT NIC gateway = %s\n", ibft_ipaddr ( &nic->gateway ) );
235 260
 	ibft_set_ipaddr_option ( &nic->dns[0], &dns_setting );
261
+	DBG ( "iBFT NIC DNS = %s\n", ibft_ipaddr ( &nic->dns[0] ) );
236 262
 	if ( ( rc = ibft_set_string_option ( strings, &nic->hostname,
237 263
 					     &hostname_setting ) ) != 0 )
238 264
 		return rc;
265
+	DBG ( "iBFT NIC hostname = %s\n",
266
+	      ibft_string ( strings, &nic->hostname ) );
239 267
 
240 268
 	/* Derive subnet mask prefix from subnet mask */
241 269
 	fetch_ipv4_setting ( NULL, &netmask_setting, &netmask_addr );
@@ -245,11 +273,15 @@ static int ibft_fill_nic ( struct ibft_nic *nic,
245 273
 		netmask_addr.s_addr >>= 1;
246 274
 	}
247 275
 	nic->subnet_mask_prefix = netmask_count;
276
+	DBG ( "iBFT NIC subnet = /%d\n", nic->subnet_mask_prefix );
248 277
 
249 278
 	/* Extract values from net-device configuration */
250 279
 	memcpy ( nic->mac_address, netdev->ll_addr,
251 280
 		 sizeof ( nic->mac_address ) );
281
+	DBG ( "iBFT NIC MAC = %s\n",
282
+	      netdev->ll_protocol->ntoa ( nic->mac_address ) );
252 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 286
 	return 0;
255 287
 }
@@ -269,6 +301,8 @@ static int ibft_fill_initiator ( struct ibft_initiator *initiator,
269 301
 	if ( ( rc = ibft_set_string ( strings, &initiator->initiator_name,
270 302
 				      initiator_iqn ) ) != 0 )
271 303
 		return rc;
304
+	DBG ( "iBFT initiator hostname = %s\n",
305
+	      ibft_string ( strings, &initiator->initiator_name ) );
272 306
 
273 307
 	return 0;
274 308
 }
@@ -286,17 +320,23 @@ static int ibft_fill_target_chap ( struct ibft_target *target,
286 320
 				   struct iscsi_session *iscsi ) {
287 321
 	int rc;
288 322
 
289
-	if ( ! iscsi->initiator_username )
323
+	if ( ! ( iscsi->status & ISCSI_STATUS_AUTH_FORWARD_REQUIRED ) )
290 324
 		return 0;
325
+
326
+	assert ( iscsi->initiator_username );
291 327
 	assert ( iscsi->initiator_password );
292 328
 
293 329
 	target->chap_type = IBFT_CHAP_ONE_WAY;
294 330
 	if ( ( rc = ibft_set_string ( strings, &target->chap_name,
295 331
 				      iscsi->initiator_username ) ) != 0 )
296 332
 		return rc;
333
+	DBG ( "iBFT target username = %s\n",
334
+	      ibft_string ( strings, &target->chap_name ) );
297 335
 	if ( ( rc = ibft_set_string ( strings, &target->chap_secret,
298 336
 				      iscsi->initiator_password ) ) != 0 )
299 337
 		return rc;
338
+	DBG ( "iBFT target password = <redacted>\n" );
339
+
300 340
 	return 0;
301 341
 }
302 342
 
@@ -313,19 +353,25 @@ static int ibft_fill_target_reverse_chap ( struct ibft_target *target,
313 353
 					   struct iscsi_session *iscsi ) {
314 354
 	int rc;
315 355
 
316
-	if ( ! iscsi->target_username )
356
+	if ( ! ( iscsi->status & ISCSI_STATUS_AUTH_REVERSE_REQUIRED ) )
317 357
 		return 0;
318
-	assert ( iscsi->target_password );
358
+
319 359
 	assert ( iscsi->initiator_username );
320 360
 	assert ( iscsi->initiator_password );
361
+	assert ( iscsi->target_username );
362
+	assert ( iscsi->target_password );
321 363
 
322 364
 	target->chap_type = IBFT_CHAP_MUTUAL;
323 365
 	if ( ( rc = ibft_set_string ( strings, &target->reverse_chap_name,
324 366
 				      iscsi->target_username ) ) != 0 )
325 367
 		return rc;
368
+	DBG ( "iBFT target reverse username = %s\n",
369
+	      ibft_string ( strings, &target->chap_name ) );
326 370
 	if ( ( rc = ibft_set_string ( strings, &target->reverse_chap_secret,
327 371
 				      iscsi->target_password ) ) != 0 )
328 372
 		return rc;
373
+	DBG ( "iBFT target reverse password = <redacted>\n" );
374
+
329 375
 	return 0;
330 376
 }
331 377
 
@@ -346,10 +392,14 @@ static int ibft_fill_target ( struct ibft_target *target,
346 392
 
347 393
 	/* Fill in Target values */
348 394
 	ibft_set_ipaddr ( &target->ip_address, sin_target->sin_addr );
395
+	DBG ( "iBFT target IP = %s\n", ibft_ipaddr ( &target->ip_address ) );
349 396
 	target->socket = ntohs ( sin_target->sin_port );
397
+	DBG ( "iBFT target port = %d\n", target->socket );
350 398
 	if ( ( rc = ibft_set_string ( strings, &target->target_name,
351 399
 				      iscsi->target_iqn ) ) != 0 )
352 400
 		return rc;
401
+	DBG ( "iBFT target name = %s\n",
402
+	      ibft_string ( strings, &target->target_name ) );
353 403
 	if ( ( rc = ibft_fill_target_chap ( target, strings, iscsi ) ) != 0 )
354 404
 		return rc;
355 405
 	if ( ( rc = ibft_fill_target_reverse_chap ( target, strings,

+ 9
- 2
src/include/gpxe/iscsi.h Прегледај датотеку

@@ -530,8 +530,6 @@ struct iscsi_session {
530 530
 	char *target_username;
531 531
 	/** Target password (if any) */
532 532
 	char *target_password;
533
-	/** Target has authenticated acceptably */
534
-	int target_auth_ok;
535 533
 	/** CHAP challenge (for target auth only)
536 534
 	 *
537 535
 	 * This is a block of random data; the first byte is used as
@@ -664,6 +662,15 @@ struct iscsi_session {
664 662
 /** Mask for all iSCSI "needs to send" flags */
665 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 674
 /** Maximum number of retries at connecting */
668 675
 #define ISCSI_MAX_RETRIES 2
669 676
 

+ 11
- 12
src/net/tcp/iscsi.c Прегледај датотеку

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

Loading…
Откажи
Сачувај