|
@@ -49,11 +49,17 @@ static char *iscsi_explicit_initiator_iqn;
|
49
|
49
|
/** Default iSCSI initiator name (constructed from hostname) */
|
50
|
50
|
static char *iscsi_default_initiator_iqn;
|
51
|
51
|
|
52
|
|
-/** iSCSI username */
|
53
|
|
-static char *iscsi_username;
|
|
52
|
+/** iSCSI initiator username */
|
|
53
|
+static char *iscsi_initiator_username;
|
54
|
54
|
|
55
|
|
-/** iSCSI password */
|
56
|
|
-static char *iscsi_password;
|
|
55
|
+/** iSCSI initiator password */
|
|
56
|
+static char *iscsi_initiator_password;
|
|
57
|
+
|
|
58
|
+/** iSCSI target username */
|
|
59
|
+static char *iscsi_target_username;
|
|
60
|
+
|
|
61
|
+/** iSCSI target password */
|
|
62
|
+static char *iscsi_target_password;
|
57
|
63
|
|
58
|
64
|
static void iscsi_start_tx ( struct iscsi_session *iscsi );
|
59
|
65
|
static void iscsi_start_login ( struct iscsi_session *iscsi );
|
|
@@ -81,8 +87,10 @@ static void iscsi_free ( struct refcnt *refcnt ) {
|
81
|
87
|
|
82
|
88
|
free ( iscsi->target_address );
|
83
|
89
|
free ( iscsi->target_iqn );
|
84
|
|
- free ( iscsi->username );
|
85
|
|
- free ( iscsi->password );
|
|
90
|
+ free ( iscsi->initiator_username );
|
|
91
|
+ free ( iscsi->initiator_password );
|
|
92
|
+ free ( iscsi->target_username );
|
|
93
|
+ free ( iscsi->target_password );
|
86
|
94
|
chap_finish ( &iscsi->chap );
|
87
|
95
|
iscsi_rx_buffered_data_done ( iscsi );
|
88
|
96
|
free ( iscsi );
|
|
@@ -144,6 +152,9 @@ static void iscsi_close_connection ( struct iscsi_session *iscsi, int rc ) {
|
144
|
152
|
/* Clear connection status */
|
145
|
153
|
iscsi->status = 0;
|
146
|
154
|
|
|
155
|
+ /* Deauthenticate target */
|
|
156
|
+ iscsi->target_auth_ok = 0;
|
|
157
|
+
|
147
|
158
|
/* Reset TX and RX state machines */
|
148
|
159
|
iscsi->tx_state = ISCSI_TX_IDLE;
|
149
|
160
|
iscsi->rx_state = ISCSI_RX_BHS;
|
|
@@ -213,11 +224,12 @@ static void iscsi_start_command ( struct iscsi_session *iscsi ) {
|
213
|
224
|
command->cmdsn = htonl ( iscsi->cmdsn );
|
214
|
225
|
command->expstatsn = htonl ( iscsi->statsn + 1 );
|
215
|
226
|
memcpy ( &command->cdb, &iscsi->command->cdb, sizeof ( command->cdb ));
|
216
|
|
- DBGC ( iscsi, "iSCSI %p start " SCSI_CDB_FORMAT " %s %#zx\n",
|
217
|
|
- iscsi, SCSI_CDB_DATA ( command->cdb ),
|
218
|
|
- ( iscsi->command->data_in ? "in" : "out" ),
|
219
|
|
- ( iscsi->command->data_in ?
|
220
|
|
- iscsi->command->data_in_len : iscsi->command->data_out_len ));
|
|
227
|
+ DBGC2 ( iscsi, "iSCSI %p start " SCSI_CDB_FORMAT " %s %#zx\n",
|
|
228
|
+ iscsi, SCSI_CDB_DATA ( command->cdb ),
|
|
229
|
+ ( iscsi->command->data_in ? "in" : "out" ),
|
|
230
|
+ ( iscsi->command->data_in ?
|
|
231
|
+ iscsi->command->data_in_len :
|
|
232
|
+ iscsi->command->data_out_len ) );
|
221
|
233
|
}
|
222
|
234
|
|
223
|
235
|
/**
|
|
@@ -450,17 +462,25 @@ static int iscsi_build_login_request_strings ( struct iscsi_session *iscsi,
|
450
|
462
|
void *data, size_t len ) {
|
451
|
463
|
unsigned int used = 0;
|
452
|
464
|
unsigned int i;
|
|
465
|
+ const char *auth_method;
|
453
|
466
|
|
454
|
467
|
if ( iscsi->status & ISCSI_STATUS_STRINGS_SECURITY ) {
|
|
468
|
+ /* Default to allowing no authentication */
|
|
469
|
+ auth_method = "None";
|
|
470
|
+ /* If we have a credential to supply, permit CHAP */
|
|
471
|
+ if ( iscsi->initiator_username )
|
|
472
|
+ auth_method = "CHAP,None";
|
|
473
|
+ /* If we have a credential to check, force CHAP */
|
|
474
|
+ if ( iscsi->target_username )
|
|
475
|
+ auth_method = "CHAP";
|
455
|
476
|
used += ssnprintf ( data + used, len - used,
|
456
|
477
|
"InitiatorName=%s%c"
|
457
|
478
|
"TargetName=%s%c"
|
458
|
479
|
"SessionType=Normal%c"
|
459
|
|
- "AuthMethod=%sNone%c",
|
|
480
|
+ "AuthMethod=%s%c",
|
460
|
481
|
iscsi_initiator_iqn(), 0,
|
461
|
482
|
iscsi->target_iqn, 0, 0,
|
462
|
|
- ( ( iscsi->username && iscsi->password ) ?
|
463
|
|
- "CHAP," : "" ), 0 );
|
|
483
|
+ auth_method, 0 );
|
464
|
484
|
}
|
465
|
485
|
|
466
|
486
|
if ( iscsi->status & ISCSI_STATUS_STRINGS_CHAP_ALGORITHM ) {
|
|
@@ -468,9 +488,10 @@ static int iscsi_build_login_request_strings ( struct iscsi_session *iscsi,
|
468
|
488
|
}
|
469
|
489
|
|
470
|
490
|
if ( ( iscsi->status & ISCSI_STATUS_STRINGS_CHAP_RESPONSE ) ) {
|
|
491
|
+ assert ( iscsi->initiator_username != NULL );
|
471
|
492
|
used += ssnprintf ( data + used, len - used,
|
472
|
493
|
"CHAP_N=%s%cCHAP_R=0x",
|
473
|
|
- iscsi->username, 0 );
|
|
494
|
+ iscsi->initiator_username, 0 );
|
474
|
495
|
for ( i = 0 ; i < iscsi->chap.response_len ; i++ ) {
|
475
|
496
|
used += ssnprintf ( data + used, len - used, "%02x",
|
476
|
497
|
iscsi->chap.response[i] );
|
|
@@ -478,6 +499,17 @@ static int iscsi_build_login_request_strings ( struct iscsi_session *iscsi,
|
478
|
499
|
used += ssnprintf ( data + used, len - used, "%c", 0 );
|
479
|
500
|
}
|
480
|
501
|
|
|
502
|
+ if ( ( iscsi->status & ISCSI_STATUS_STRINGS_CHAP_CHALLENGE ) ) {
|
|
503
|
+ used += ssnprintf ( data + used, len - used,
|
|
504
|
+ "CHAP_I=%d%cCHAP_C=0x",
|
|
505
|
+ iscsi->chap_challenge[0], 0 );
|
|
506
|
+ for ( i = 1 ; i < sizeof ( iscsi->chap_challenge ) ; i++ ) {
|
|
507
|
+ used += ssnprintf ( data + used, len - used, "%02x",
|
|
508
|
+ iscsi->chap_challenge[i] );
|
|
509
|
+ }
|
|
510
|
+ used += ssnprintf ( data + used, len - used, "%c", 0 );
|
|
511
|
+ }
|
|
512
|
+
|
481
|
513
|
if ( iscsi->status & ISCSI_STATUS_STRINGS_OPERATIONAL ) {
|
482
|
514
|
used += ssnprintf ( data + used, len - used,
|
483
|
515
|
"HeaderDigest=None%c"
|
|
@@ -602,12 +634,17 @@ static int iscsi_handle_targetaddress_value ( struct iscsi_session *iscsi,
|
602
|
634
|
static int iscsi_handle_authmethod_value ( struct iscsi_session *iscsi,
|
603
|
635
|
const char *value ) {
|
604
|
636
|
|
|
637
|
+ /* Mark target as authenticated if no authentication required */
|
|
638
|
+ if ( ! iscsi->target_username )
|
|
639
|
+ iscsi->target_auth_ok = 1;
|
|
640
|
+
|
605
|
641
|
/* If server requests CHAP, send the CHAP_A string */
|
606
|
642
|
if ( strcmp ( value, "CHAP" ) == 0 ) {
|
607
|
643
|
DBGC ( iscsi, "iSCSI %p initiating CHAP authentication\n",
|
608
|
644
|
iscsi );
|
609
|
645
|
iscsi->status |= ISCSI_STATUS_STRINGS_CHAP_ALGORITHM;
|
610
|
646
|
}
|
|
647
|
+
|
611
|
648
|
return 0;
|
612
|
649
|
}
|
613
|
650
|
|
|
@@ -620,7 +657,6 @@ static int iscsi_handle_authmethod_value ( struct iscsi_session *iscsi,
|
620
|
657
|
*/
|
621
|
658
|
static int iscsi_handle_chap_a_value ( struct iscsi_session *iscsi,
|
622
|
659
|
const char *value ) {
|
623
|
|
- int rc;
|
624
|
660
|
|
625
|
661
|
/* We only ever offer "5" (i.e. MD5) as an algorithm, so if
|
626
|
662
|
* the server responds with anything else it is a protocol
|
|
@@ -632,13 +668,6 @@ static int iscsi_handle_chap_a_value ( struct iscsi_session *iscsi,
|
632
|
668
|
return -EPROTO;
|
633
|
669
|
}
|
634
|
670
|
|
635
|
|
- /* Prepare for CHAP with MD5 */
|
636
|
|
- if ( ( rc = chap_init ( &iscsi->chap, &md5_algorithm ) ) != 0 ) {
|
637
|
|
- DBGC ( iscsi, "iSCSI %p could not initialise CHAP: %s\n",
|
638
|
|
- iscsi, strerror ( rc ) );
|
639
|
|
- return rc;
|
640
|
|
- }
|
641
|
|
-
|
642
|
671
|
return 0;
|
643
|
672
|
}
|
644
|
673
|
|
|
@@ -653,6 +682,7 @@ static int iscsi_handle_chap_i_value ( struct iscsi_session *iscsi,
|
653
|
682
|
const char *value ) {
|
654
|
683
|
unsigned int identifier;
|
655
|
684
|
char *endp;
|
|
685
|
+ int rc;
|
656
|
686
|
|
657
|
687
|
/* The CHAP identifier is an integer value */
|
658
|
688
|
identifier = strtoul ( value, &endp, 0 );
|
|
@@ -662,13 +692,21 @@ static int iscsi_handle_chap_i_value ( struct iscsi_session *iscsi,
|
662
|
692
|
return -EPROTO;
|
663
|
693
|
}
|
664
|
694
|
|
|
695
|
+ /* Prepare for CHAP with MD5 */
|
|
696
|
+ chap_finish ( &iscsi->chap );
|
|
697
|
+ if ( ( rc = chap_init ( &iscsi->chap, &md5_algorithm ) ) != 0 ) {
|
|
698
|
+ DBGC ( iscsi, "iSCSI %p could not initialise CHAP: %s\n",
|
|
699
|
+ iscsi, strerror ( rc ) );
|
|
700
|
+ return rc;
|
|
701
|
+ }
|
|
702
|
+
|
665
|
703
|
/* Identifier and secret are the first two components of the
|
666
|
704
|
* challenge.
|
667
|
705
|
*/
|
668
|
706
|
chap_set_identifier ( &iscsi->chap, identifier );
|
669
|
|
- if ( iscsi->password ) {
|
670
|
|
- chap_update ( &iscsi->chap, iscsi->password,
|
671
|
|
- strlen ( iscsi->password ) );
|
|
707
|
+ if ( iscsi->initiator_password ) {
|
|
708
|
+ chap_update ( &iscsi->chap, iscsi->initiator_password,
|
|
709
|
+ strlen ( iscsi->initiator_password ) );
|
672
|
710
|
}
|
673
|
711
|
|
674
|
712
|
return 0;
|
|
@@ -686,11 +724,13 @@ static int iscsi_handle_chap_c_value ( struct iscsi_session *iscsi,
|
686
|
724
|
char buf[3];
|
687
|
725
|
char *endp;
|
688
|
726
|
uint8_t byte;
|
|
727
|
+ unsigned int i;
|
689
|
728
|
|
690
|
729
|
/* Check and strip leading "0x" */
|
691
|
730
|
if ( ( value[0] != '0' ) || ( value[1] != 'x' ) ) {
|
692
|
731
|
DBGC ( iscsi, "iSCSI %p saw invalid CHAP challenge \"%s\"\n",
|
693
|
732
|
iscsi, value );
|
|
733
|
+ return -EPROTO;
|
694
|
734
|
}
|
695
|
735
|
value += 2;
|
696
|
736
|
|
|
@@ -712,6 +752,114 @@ static int iscsi_handle_chap_c_value ( struct iscsi_session *iscsi,
|
712
|
752
|
chap_respond ( &iscsi->chap );
|
713
|
753
|
iscsi->status |= ISCSI_STATUS_STRINGS_CHAP_RESPONSE;
|
714
|
754
|
|
|
755
|
+ /* Send CHAP challenge, if applicable */
|
|
756
|
+ if ( iscsi->target_username ) {
|
|
757
|
+ iscsi->status |= ISCSI_STATUS_STRINGS_CHAP_CHALLENGE;
|
|
758
|
+ /* Generate CHAP challenge data */
|
|
759
|
+ for ( i = 0 ; i < sizeof ( iscsi->chap_challenge ) ; i++ ) {
|
|
760
|
+ iscsi->chap_challenge[i] = random();
|
|
761
|
+ }
|
|
762
|
+ }
|
|
763
|
+
|
|
764
|
+ return 0;
|
|
765
|
+}
|
|
766
|
+
|
|
767
|
+/**
|
|
768
|
+ * Handle iSCSI CHAP_N text value
|
|
769
|
+ *
|
|
770
|
+ * @v iscsi iSCSI session
|
|
771
|
+ * @v value CHAP_N value
|
|
772
|
+ * @ret rc Return status code
|
|
773
|
+ */
|
|
774
|
+static int iscsi_handle_chap_n_value ( struct iscsi_session *iscsi,
|
|
775
|
+ const char *value ) {
|
|
776
|
+
|
|
777
|
+ /* The target username isn't actually involved at any point in
|
|
778
|
+ * the authentication process; it merely serves to identify
|
|
779
|
+ * which password the target is using to generate the CHAP
|
|
780
|
+ * response. We unnecessarily verify that the username is as
|
|
781
|
+ * expected, in order to provide mildly helpful diagnostics if
|
|
782
|
+ * the target is supplying the wrong username/password
|
|
783
|
+ * combination.
|
|
784
|
+ */
|
|
785
|
+ if ( iscsi->target_username &&
|
|
786
|
+ ( strcmp ( iscsi->target_username, value ) != 0 ) ) {
|
|
787
|
+ DBGC ( iscsi, "iSCSI %p target username \"%s\" incorrect "
|
|
788
|
+ "(wanted \"%s\")\n",
|
|
789
|
+ iscsi, value, iscsi->target_username );
|
|
790
|
+ return -EACCES;
|
|
791
|
+ }
|
|
792
|
+
|
|
793
|
+ return 0;
|
|
794
|
+}
|
|
795
|
+
|
|
796
|
+/**
|
|
797
|
+ * Handle iSCSI CHAP_R text value
|
|
798
|
+ *
|
|
799
|
+ * @v iscsi iSCSI session
|
|
800
|
+ * @v value CHAP_R value
|
|
801
|
+ * @ret rc Return status code
|
|
802
|
+ */
|
|
803
|
+static int iscsi_handle_chap_r_value ( struct iscsi_session *iscsi,
|
|
804
|
+ const char *value ) {
|
|
805
|
+ char buf[3];
|
|
806
|
+ char *endp;
|
|
807
|
+ uint8_t byte;
|
|
808
|
+ unsigned int i;
|
|
809
|
+ int rc;
|
|
810
|
+
|
|
811
|
+ /* Generate CHAP response for verification */
|
|
812
|
+ chap_finish ( &iscsi->chap );
|
|
813
|
+ if ( ( rc = chap_init ( &iscsi->chap, &md5_algorithm ) ) != 0 ) {
|
|
814
|
+ DBGC ( iscsi, "iSCSI %p could not initialise CHAP: %s\n",
|
|
815
|
+ iscsi, strerror ( rc ) );
|
|
816
|
+ return rc;
|
|
817
|
+ }
|
|
818
|
+ chap_set_identifier ( &iscsi->chap, iscsi->chap_challenge[0] );
|
|
819
|
+ if ( iscsi->target_password ) {
|
|
820
|
+ chap_update ( &iscsi->chap, iscsi->target_password,
|
|
821
|
+ strlen ( iscsi->target_password ) );
|
|
822
|
+ }
|
|
823
|
+ chap_update ( &iscsi->chap, &iscsi->chap_challenge[1],
|
|
824
|
+ ( sizeof ( iscsi->chap_challenge ) - 1 ) );
|
|
825
|
+ chap_respond ( &iscsi->chap );
|
|
826
|
+
|
|
827
|
+ /* Check and strip leading "0x" */
|
|
828
|
+ if ( ( value[0] != '0' ) || ( value[1] != 'x' ) ) {
|
|
829
|
+ DBGC ( iscsi, "iSCSI %p saw invalid CHAP response \"%s\"\n",
|
|
830
|
+ iscsi, value );
|
|
831
|
+ return -EPROTO;
|
|
832
|
+ }
|
|
833
|
+ value += 2;
|
|
834
|
+
|
|
835
|
+ /* Check CHAP response length */
|
|
836
|
+ if ( strlen ( value ) != ( 2 * iscsi->chap.response_len ) ) {
|
|
837
|
+ DBGC ( iscsi, "iSCSI %p invalid CHAP response length\n",
|
|
838
|
+ iscsi );
|
|
839
|
+ return -EPROTO;
|
|
840
|
+ }
|
|
841
|
+
|
|
842
|
+ /* Process response an octet at a time */
|
|
843
|
+ for ( i = 0 ; ( value[0] && value[1] ) ; value += 2, i++ ) {
|
|
844
|
+ memcpy ( buf, value, 2 );
|
|
845
|
+ buf[2] = 0;
|
|
846
|
+ byte = strtoul ( buf, &endp, 16 );
|
|
847
|
+ if ( *endp != '\0' ) {
|
|
848
|
+ DBGC ( iscsi, "iSCSI %p saw invalid CHAP response "
|
|
849
|
+ "byte \"%s\"\n", iscsi, buf );
|
|
850
|
+ return -EPROTO;
|
|
851
|
+ }
|
|
852
|
+ if ( byte != iscsi->chap.response[i] ) {
|
|
853
|
+ DBGC ( iscsi, "iSCSI %p saw incorrect CHAP "
|
|
854
|
+ "response\n", iscsi );
|
|
855
|
+ return -EACCES;
|
|
856
|
+ }
|
|
857
|
+ }
|
|
858
|
+ assert ( i == iscsi->chap.response_len );
|
|
859
|
+
|
|
860
|
+ /* Mark session as authenticated */
|
|
861
|
+ iscsi->target_auth_ok = 1;
|
|
862
|
+
|
715
|
863
|
return 0;
|
716
|
864
|
}
|
717
|
865
|
|
|
@@ -739,6 +887,8 @@ static struct iscsi_string_type iscsi_string_types[] = {
|
739
|
887
|
{ "CHAP_A=", iscsi_handle_chap_a_value },
|
740
|
888
|
{ "CHAP_I=", iscsi_handle_chap_i_value },
|
741
|
889
|
{ "CHAP_C=", iscsi_handle_chap_c_value },
|
|
890
|
+ { "CHAP_N=", iscsi_handle_chap_n_value },
|
|
891
|
+ { "CHAP_R=", iscsi_handle_chap_r_value },
|
742
|
892
|
{ NULL, NULL }
|
743
|
893
|
};
|
744
|
894
|
|
|
@@ -939,6 +1089,13 @@ static int iscsi_rx_login_response ( struct iscsi_session *iscsi,
|
939
|
1089
|
return 0;
|
940
|
1090
|
}
|
941
|
1091
|
|
|
1092
|
+ /* Check that target authentication was successful (if required) */
|
|
1093
|
+ if ( ! iscsi->target_auth_ok ) {
|
|
1094
|
+ DBGC ( iscsi, "iSCSI %p nefarious target tried to bypass "
|
|
1095
|
+ "authentication\n", iscsi );
|
|
1096
|
+ return -EPROTO;
|
|
1097
|
+ }
|
|
1098
|
+
|
942
|
1099
|
/* Reset retry count */
|
943
|
1100
|
iscsi->retry_count = 0;
|
944
|
1101
|
|
|
@@ -1148,9 +1305,9 @@ static int iscsi_rx_bhs ( struct iscsi_session *iscsi, const void *data,
|
1148
|
1305
|
size_t len, size_t remaining __unused ) {
|
1149
|
1306
|
memcpy ( &iscsi->rx_bhs.bytes[iscsi->rx_offset], data, len );
|
1150
|
1307
|
if ( ( iscsi->rx_offset + len ) >= sizeof ( iscsi->rx_bhs ) ) {
|
1151
|
|
- DBGC ( iscsi, "iSCSI %p received PDU opcode %#x len %#lx\n",
|
1152
|
|
- iscsi, iscsi->rx_bhs.common.opcode,
|
1153
|
|
- ISCSI_DATA_LEN ( iscsi->rx_bhs.common.lengths ) );
|
|
1308
|
+ DBGC2 ( iscsi, "iSCSI %p received PDU opcode %#x len %#lx\n",
|
|
1309
|
+ iscsi, iscsi->rx_bhs.common.opcode,
|
|
1310
|
+ ISCSI_DATA_LEN ( iscsi->rx_bhs.common.lengths ) );
|
1154
|
1311
|
}
|
1155
|
1312
|
return 0;
|
1156
|
1313
|
}
|
|
@@ -1546,26 +1703,61 @@ static int iscsi_parse_root_path ( struct iscsi_session *iscsi,
|
1546
|
1703
|
* Set iSCSI authentication details
|
1547
|
1704
|
*
|
1548
|
1705
|
* @v iscsi iSCSI session
|
1549
|
|
- * @v username Username, if any
|
1550
|
|
- * @v password Password, if any
|
|
1706
|
+ * @v initiator_username Initiator username, if any
|
|
1707
|
+ * @v initiator_password Initiator password, if any
|
|
1708
|
+ * @v target_username Target username, if any
|
|
1709
|
+ * @v target_password Target password, if any
|
1551
|
1710
|
* @ret rc Return status code
|
1552
|
1711
|
*/
|
1553
|
1712
|
static int iscsi_set_auth ( struct iscsi_session *iscsi,
|
1554
|
|
- const char *username, const char *password ) {
|
1555
|
|
-
|
1556
|
|
- if ( username ) {
|
1557
|
|
- iscsi->username = strdup ( username );
|
1558
|
|
- if ( ! iscsi->username )
|
|
1713
|
+ const char *initiator_username,
|
|
1714
|
+ const char *initiator_password,
|
|
1715
|
+ const char *target_username,
|
|
1716
|
+ const char *target_password ) {
|
|
1717
|
+
|
|
1718
|
+ /* Check for initiator or target credentials */
|
|
1719
|
+ if ( initiator_username || initiator_password ||
|
|
1720
|
+ target_username || target_password ) {
|
|
1721
|
+
|
|
1722
|
+ /* We must have at least an initiator username+password */
|
|
1723
|
+ if ( ! ( initiator_username && initiator_password ) )
|
|
1724
|
+ goto invalid_auth;
|
|
1725
|
+
|
|
1726
|
+ /* Store initiator credentials */
|
|
1727
|
+ iscsi->initiator_username = strdup ( initiator_username );
|
|
1728
|
+ if ( ! iscsi->initiator_username )
|
1559
|
1729
|
return -ENOMEM;
|
1560
|
|
- }
|
1561
|
|
-
|
1562
|
|
- if ( password ) {
|
1563
|
|
- iscsi->password = strdup ( password );
|
1564
|
|
- if ( ! iscsi->password )
|
|
1730
|
+ iscsi->initiator_password = strdup ( initiator_password );
|
|
1731
|
+ if ( ! iscsi->initiator_password )
|
1565
|
1732
|
return -ENOMEM;
|
|
1733
|
+
|
|
1734
|
+ /* Check for target credentials */
|
|
1735
|
+ if ( target_username || target_password ) {
|
|
1736
|
+
|
|
1737
|
+ /* We must have target username+password */
|
|
1738
|
+ if ( ! ( target_username && target_password ) )
|
|
1739
|
+ goto invalid_auth;
|
|
1740
|
+
|
|
1741
|
+ /* Store target credentials */
|
|
1742
|
+ iscsi->target_username = strdup ( target_username );
|
|
1743
|
+ if ( ! iscsi->target_username )
|
|
1744
|
+ return -ENOMEM;
|
|
1745
|
+ iscsi->target_password = strdup ( target_password );
|
|
1746
|
+ if ( ! iscsi->target_password )
|
|
1747
|
+ return -ENOMEM;
|
|
1748
|
+ }
|
1566
|
1749
|
}
|
1567
|
1750
|
|
1568
|
1751
|
return 0;
|
|
1752
|
+
|
|
1753
|
+ invalid_auth:
|
|
1754
|
+ DBGC ( iscsi, "iSCSI %p invalid credentials: initiator "
|
|
1755
|
+ "%sname,%spw, target %sname,%spw\n", iscsi,
|
|
1756
|
+ ( initiator_username ? "" : "no " ),
|
|
1757
|
+ ( initiator_password ? "" : "no " ),
|
|
1758
|
+ ( target_username ? "" : "no " ),
|
|
1759
|
+ ( target_password ? "" : "no " ) );
|
|
1760
|
+ return -EINVAL;
|
1569
|
1761
|
}
|
1570
|
1762
|
|
1571
|
1763
|
/**
|
|
@@ -1591,8 +1783,11 @@ int iscsi_attach ( struct scsi_device *scsi, const char *root_path ) {
|
1591
|
1783
|
if ( ( rc = iscsi_parse_root_path ( iscsi, root_path ) ) != 0 )
|
1592
|
1784
|
goto err;
|
1593
|
1785
|
/* Set fields not specified by root path */
|
1594
|
|
- if ( ( rc = iscsi_set_auth ( iscsi, iscsi_username,
|
1595
|
|
- iscsi_password ) ) != 0 )
|
|
1786
|
+ if ( ( rc = iscsi_set_auth ( iscsi,
|
|
1787
|
+ iscsi_initiator_username,
|
|
1788
|
+ iscsi_initiator_password,
|
|
1789
|
+ iscsi_target_username,
|
|
1790
|
+ iscsi_target_password ) ) != 0 )
|
1596
|
1791
|
goto err;
|
1597
|
1792
|
|
1598
|
1793
|
/* Sanity checks */
|
|
@@ -1635,6 +1830,22 @@ struct setting initiator_iqn_setting __setting = {
|
1635
|
1830
|
.type = &setting_type_string,
|
1636
|
1831
|
};
|
1637
|
1832
|
|
|
1833
|
+/** iSCSI reverse username setting */
|
|
1834
|
+struct setting reverse_username_setting __setting = {
|
|
1835
|
+ .name = "reverse-username",
|
|
1836
|
+ .description = "Reverse user name",
|
|
1837
|
+ .tag = DHCP_EB_REVERSE_USERNAME,
|
|
1838
|
+ .type = &setting_type_string,
|
|
1839
|
+};
|
|
1840
|
+
|
|
1841
|
+/** iSCSI reverse password setting */
|
|
1842
|
+struct setting reverse_password_setting __setting = {
|
|
1843
|
+ .name = "reverse-password",
|
|
1844
|
+ .description = "Reverse password",
|
|
1845
|
+ .tag = DHCP_EB_REVERSE_PASSWORD,
|
|
1846
|
+ .type = &setting_type_string,
|
|
1847
|
+};
|
|
1848
|
+
|
1638
|
1849
|
/** An iSCSI string setting */
|
1639
|
1850
|
struct iscsi_string_setting {
|
1640
|
1851
|
/** Setting */
|
|
@@ -1654,12 +1865,22 @@ static struct iscsi_string_setting iscsi_string_settings[] = {
|
1654
|
1865
|
},
|
1655
|
1866
|
{
|
1656
|
1867
|
.setting = &username_setting,
|
1657
|
|
- .string = &iscsi_username,
|
|
1868
|
+ .string = &iscsi_initiator_username,
|
1658
|
1869
|
.prefix = "",
|
1659
|
1870
|
},
|
1660
|
1871
|
{
|
1661
|
1872
|
.setting = &password_setting,
|
1662
|
|
- .string = &iscsi_password,
|
|
1873
|
+ .string = &iscsi_initiator_password,
|
|
1874
|
+ .prefix = "",
|
|
1875
|
+ },
|
|
1876
|
+ {
|
|
1877
|
+ .setting = &reverse_username_setting,
|
|
1878
|
+ .string = &iscsi_target_username,
|
|
1879
|
+ .prefix = "",
|
|
1880
|
+ },
|
|
1881
|
+ {
|
|
1882
|
+ .setting = &reverse_password_setting,
|
|
1883
|
+ .string = &iscsi_target_password,
|
1663
|
1884
|
.prefix = "",
|
1664
|
1885
|
},
|
1665
|
1886
|
{
|