ソースを参照

[iscsi] Fail immediately if target rejects any of our parameters

Some iSCSI targets (observed with stgt) can be configured to reject
connections that do not use header or data digests, and will respond
with "HeaderDigest=Reject" and/or "DataDigest=Reject", while still
allowing the connection to proceed to the full feature phase.

According to a strict reading of RFC3720, we are perfectly safe to
ignore these "Reject" messages: upon such a rejection "the negotiated
key is left at its current value (or default if no value was set)".
Since the default value for both HeaderDigest and DataDigest is
"None", then the only viable conclusion to be drawn is that the value
resulting from "Reject" is still "None".

Unfortunately, stgt doesn't seem to agree with this interpretation of
events, causing us to eventually report an unhelpful "connection timed
out" message to the user when we don't get any response to our first
PDU in full feature phase.

Fix by detecting any rejected parameters and immediately reporting an
error, which at least gives the user some insight as to what the real
problem may be.

Reported-by: Michal Suchanek <hramrach@centrum.cz>
Tested-by: Michal Suchanek <hramrach@centrum.cz>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 12年前
コミット
bd718b2110
1個のファイルの変更39行の追加12行の削除
  1. 39
    12
      src/net/tcp/iscsi.c

+ 39
- 12
src/net/tcp/iscsi.c ファイルの表示

131
 	__einfo_error ( EINFO_EPROTO_INVALID_CHAP_RESPONSE )
131
 	__einfo_error ( EINFO_EPROTO_INVALID_CHAP_RESPONSE )
132
 #define EINFO_EPROTO_INVALID_CHAP_RESPONSE \
132
 #define EINFO_EPROTO_INVALID_CHAP_RESPONSE \
133
 	__einfo_uniqify ( EINFO_EPROTO, 0x04, "Invalid CHAP response" )
133
 	__einfo_uniqify ( EINFO_EPROTO, 0x04, "Invalid CHAP response" )
134
+#define EPROTO_INVALID_KEY_VALUE_PAIR \
135
+	__einfo_error ( EINFO_EPROTO_INVALID_KEY_VALUE_PAIR )
136
+#define EINFO_EPROTO_INVALID_KEY_VALUE_PAIR \
137
+	__einfo_uniqify ( EINFO_EPROTO, 0x05, "Invalid key/value pair" )
138
+#define EPROTO_VALUE_REJECTED \
139
+	__einfo_error ( EINFO_EPROTO_VALUE_REJECTED )
140
+#define EINFO_EPROTO_VALUE_REJECTED					\
141
+	__einfo_uniqify ( EINFO_EPROTO, 0x06, "Parameter rejected" )
134
 
142
 
135
 static void iscsi_start_tx ( struct iscsi_session *iscsi );
143
 static void iscsi_start_tx ( struct iscsi_session *iscsi );
136
 static void iscsi_start_login ( struct iscsi_session *iscsi );
144
 static void iscsi_start_login ( struct iscsi_session *iscsi );
1083
 struct iscsi_string_type {
1091
 struct iscsi_string_type {
1084
 	/** String key
1092
 	/** String key
1085
 	 *
1093
 	 *
1086
-	 * This is the portion up to and including the "=" sign,
1087
-	 * e.g. "InitiatorName=", "CHAP_A=", etc.
1094
+	 * This is the portion preceding the "=" sign,
1095
+	 * e.g. "InitiatorName", "CHAP_A", etc.
1088
 	 */
1096
 	 */
1089
 	const char *key;
1097
 	const char *key;
1090
 	/** Handle iSCSI string value
1098
 	/** Handle iSCSI string value
1098
 
1106
 
1099
 /** iSCSI text strings that we want to handle */
1107
 /** iSCSI text strings that we want to handle */
1100
 static struct iscsi_string_type iscsi_string_types[] = {
1108
 static struct iscsi_string_type iscsi_string_types[] = {
1101
-	{ "TargetAddress=", iscsi_handle_targetaddress_value },
1102
-	{ "AuthMethod=", iscsi_handle_authmethod_value },
1103
-	{ "CHAP_A=", iscsi_handle_chap_a_value },
1104
-	{ "CHAP_I=", iscsi_handle_chap_i_value },
1105
-	{ "CHAP_C=", iscsi_handle_chap_c_value },
1106
-	{ "CHAP_N=", iscsi_handle_chap_n_value },
1107
-	{ "CHAP_R=", iscsi_handle_chap_r_value },
1109
+	{ "TargetAddress", iscsi_handle_targetaddress_value },
1110
+	{ "AuthMethod", iscsi_handle_authmethod_value },
1111
+	{ "CHAP_A", iscsi_handle_chap_a_value },
1112
+	{ "CHAP_I", iscsi_handle_chap_i_value },
1113
+	{ "CHAP_C", iscsi_handle_chap_c_value },
1114
+	{ "CHAP_N", iscsi_handle_chap_n_value },
1115
+	{ "CHAP_R", iscsi_handle_chap_r_value },
1108
 	{ NULL, NULL }
1116
 	{ NULL, NULL }
1109
 };
1117
 };
1110
 
1118
 
1118
 static int iscsi_handle_string ( struct iscsi_session *iscsi,
1126
 static int iscsi_handle_string ( struct iscsi_session *iscsi,
1119
 				 const char *string ) {
1127
 				 const char *string ) {
1120
 	struct iscsi_string_type *type;
1128
 	struct iscsi_string_type *type;
1129
+	const char *separator;
1130
+	const char *value;
1121
 	size_t key_len;
1131
 	size_t key_len;
1122
 	int rc;
1132
 	int rc;
1123
 
1133
 
1134
+	/* Find separator */
1135
+	separator = strchr ( string, '=' );
1136
+	if ( ! separator ) {
1137
+		DBGC ( iscsi, "iSCSI %p malformed string %s\n",
1138
+		       iscsi, string );
1139
+		return -EPROTO_INVALID_KEY_VALUE_PAIR;
1140
+	}
1141
+	key_len = ( separator - string );
1142
+	value = ( separator + 1 );
1143
+
1144
+	/* Check for rejections.  Since we send only non-rejectable
1145
+	 * values, any rejection is a fatal protocol error.
1146
+	 */
1147
+	if ( strcmp ( value, "Reject" ) == 0 ) {
1148
+		DBGC ( iscsi, "iSCSI %p rejection: %s\n", iscsi, string );
1149
+		return -EPROTO_VALUE_REJECTED;
1150
+	}
1151
+
1152
+	/* Handle key/value pair */
1124
 	for ( type = iscsi_string_types ; type->key ; type++ ) {
1153
 	for ( type = iscsi_string_types ; type->key ; type++ ) {
1125
-		key_len = strlen ( type->key );
1126
 		if ( strncmp ( string, type->key, key_len ) != 0 )
1154
 		if ( strncmp ( string, type->key, key_len ) != 0 )
1127
 			continue;
1155
 			continue;
1128
 		DBGC ( iscsi, "iSCSI %p handling %s\n", iscsi, string );
1156
 		DBGC ( iscsi, "iSCSI %p handling %s\n", iscsi, string );
1129
-		if ( ( rc = type->handle ( iscsi,
1130
-					   ( string + key_len ) ) ) != 0 ) {
1157
+		if ( ( rc = type->handle ( iscsi, value ) ) != 0 ) {
1131
 			DBGC ( iscsi, "iSCSI %p could not handle %s: %s\n",
1158
 			DBGC ( iscsi, "iSCSI %p could not handle %s: %s\n",
1132
 			       iscsi, string, strerror ( rc ) );
1159
 			       iscsi, string, strerror ( rc ) );
1133
 			return rc;
1160
 			return rc;

読み込み中…
キャンセル
保存