Skip to content

Commit 1e57338

Browse files
logostmartinkpetersen
authored andcommitted
scsi: target: iscsi: Support base64 in CHAP
RFC7143 allows both Base64 and Hex encoding for CHAP binary entities like Challenge and Response. Currently the Linux iSCSI target supports only Hex encoding. Add support for Base64 encoded CHAP Challenge and CHAP Response required for CHAP tests in Windows HLK. Link: https://lore.kernel.org/r/[email protected] Reviewed-by: Mike Christie <[email protected]> Signed-off-by: Dmitry Bogdanov <[email protected]> Signed-off-by: Martin K. Petersen <[email protected]>
1 parent 8f1f7d2 commit 1e57338

File tree

3 files changed

+94
-24
lines changed

3 files changed

+94
-24
lines changed

drivers/target/iscsi/iscsi_target_auth.c

Lines changed: 90 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,38 @@ static struct iscsi_chap *chap_server_open(
205205
return chap;
206206
}
207207

208+
static const char base64_lookup_table[] =
209+
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
210+
211+
static int chap_base64_decode(u8 *dst, const char *src, size_t len)
212+
{
213+
int i, bits = 0, ac = 0;
214+
const char *p;
215+
u8 *cp = dst;
216+
217+
for (i = 0; i < len; i++) {
218+
if (src[i] == '=')
219+
return cp - dst;
220+
221+
p = strchr(base64_lookup_table, src[i]);
222+
if (p == NULL || src[i] == 0)
223+
return -2;
224+
225+
ac <<= 6;
226+
ac += (p - base64_lookup_table);
227+
bits += 6;
228+
if (bits >= 8) {
229+
*cp++ = (ac >> (bits - 8)) & 0xff;
230+
ac &= ~(BIT(16) - BIT(bits - 8));
231+
bits -= 8;
232+
}
233+
}
234+
if (ac)
235+
return -1;
236+
237+
return cp - dst;
238+
}
239+
208240
static int chap_server_compute_hash(
209241
struct iscsit_conn *conn,
210242
struct iscsi_node_auth *auth,
@@ -295,16 +327,27 @@ static int chap_server_compute_hash(
295327
pr_err("Could not find CHAP_R.\n");
296328
goto out;
297329
}
298-
if (type != HEX) {
299-
pr_err("Could not find CHAP_R.\n");
300-
goto out;
301-
}
302-
if (strlen(chap_r) != chap->digest_size * 2) {
303-
pr_err("Malformed CHAP_R\n");
304-
goto out;
305-
}
306-
if (hex2bin(client_digest, chap_r, chap->digest_size) < 0) {
307-
pr_err("Malformed CHAP_R\n");
330+
331+
switch (type) {
332+
case HEX:
333+
if (strlen(chap_r) != chap->digest_size * 2) {
334+
pr_err("Malformed CHAP_R\n");
335+
goto out;
336+
}
337+
if (hex2bin(client_digest, chap_r, chap->digest_size) < 0) {
338+
pr_err("Malformed CHAP_R: invalid HEX\n");
339+
goto out;
340+
}
341+
break;
342+
case BASE64:
343+
if (chap_base64_decode(client_digest, chap_r, strlen(chap_r)) !=
344+
chap->digest_size) {
345+
pr_err("Malformed CHAP_R: invalid BASE64\n");
346+
goto out;
347+
}
348+
break;
349+
default:
350+
pr_err("Could not find CHAP_R\n");
308351
goto out;
309352
}
310353

@@ -404,23 +447,46 @@ static int chap_server_compute_hash(
404447
goto out;
405448
}
406449

407-
if (type != HEX) {
450+
switch (type) {
451+
case HEX:
452+
initiatorchg_len = DIV_ROUND_UP(strlen(initiatorchg), 2);
453+
if (!initiatorchg_len) {
454+
pr_err("Unable to convert incoming challenge\n");
455+
goto out;
456+
}
457+
if (initiatorchg_len > 1024) {
458+
pr_err("CHAP_C exceeds maximum binary size of 1024 bytes\n");
459+
goto out;
460+
}
461+
462+
if (hex2bin(initiatorchg_binhex, initiatorchg,
463+
initiatorchg_len) < 0) {
464+
pr_err("Malformed CHAP_C: invalid HEX\n");
465+
goto out;
466+
}
467+
break;
468+
case BASE64:
469+
initiatorchg_len = chap_base64_decode(initiatorchg_binhex,
470+
initiatorchg,
471+
strlen(initiatorchg));
472+
if (initiatorchg_len < 0) {
473+
pr_err("Malformed CHAP_C: invalid BASE64\n");
474+
goto out;
475+
}
476+
if (!initiatorchg_len) {
477+
pr_err("Unable to convert incoming challenge\n");
478+
goto out;
479+
}
480+
if (initiatorchg_len > 1024) {
481+
pr_err("CHAP_C exceeds maximum binary size of 1024 bytes\n");
482+
goto out;
483+
}
484+
break;
485+
default:
408486
pr_err("Could not find CHAP_C.\n");
409487
goto out;
410488
}
411-
initiatorchg_len = DIV_ROUND_UP(strlen(initiatorchg), 2);
412-
if (!initiatorchg_len) {
413-
pr_err("Unable to convert incoming challenge\n");
414-
goto out;
415-
}
416-
if (initiatorchg_len > 1024) {
417-
pr_err("CHAP_C exceeds maximum binary size of 1024 bytes\n");
418-
goto out;
419-
}
420-
if (hex2bin(initiatorchg_binhex, initiatorchg, initiatorchg_len) < 0) {
421-
pr_err("Malformed CHAP_C\n");
422-
goto out;
423-
}
489+
424490
pr_debug("[server] Got CHAP_C=%s\n", initiatorchg);
425491
/*
426492
* During mutual authentication, the CHAP_C generated by the

drivers/target/iscsi/iscsi_target_nego.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,9 @@ int extract_param(
7676
if (*ptr == '0' && (*(ptr+1) == 'x' || *(ptr+1) == 'X')) {
7777
ptr += 2; /* skip 0x */
7878
*type = HEX;
79+
} else if (*ptr == '0' && (*(ptr+1) == 'b' || *(ptr+1) == 'B')) {
80+
ptr += 2; /* skip 0b */
81+
*type = BASE64;
7982
} else
8083
*type = DECIMAL;
8184

drivers/target/iscsi/iscsi_target_nego.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
#define DECIMAL 0
66
#define HEX 1
7+
#define BASE64 2
78

89
struct iscsit_conn;
910
struct iscsi_login;

0 commit comments

Comments
 (0)