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/20220718152555.17084-3-d.bogdanov@yadro.com Reviewed-by: Mike Christie <michael.christie@oracle.com> Signed-off-by: Dmitry Bogdanov <d.bogdanov@yadro.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
parent
8f1f7d297b
commit
1e57338834
|
@ -205,6 +205,38 @@ static struct iscsi_chap *chap_server_open(
|
|||
return chap;
|
||||
}
|
||||
|
||||
static const char base64_lookup_table[] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
static int chap_base64_decode(u8 *dst, const char *src, size_t len)
|
||||
{
|
||||
int i, bits = 0, ac = 0;
|
||||
const char *p;
|
||||
u8 *cp = dst;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
if (src[i] == '=')
|
||||
return cp - dst;
|
||||
|
||||
p = strchr(base64_lookup_table, src[i]);
|
||||
if (p == NULL || src[i] == 0)
|
||||
return -2;
|
||||
|
||||
ac <<= 6;
|
||||
ac += (p - base64_lookup_table);
|
||||
bits += 6;
|
||||
if (bits >= 8) {
|
||||
*cp++ = (ac >> (bits - 8)) & 0xff;
|
||||
ac &= ~(BIT(16) - BIT(bits - 8));
|
||||
bits -= 8;
|
||||
}
|
||||
}
|
||||
if (ac)
|
||||
return -1;
|
||||
|
||||
return cp - dst;
|
||||
}
|
||||
|
||||
static int chap_server_compute_hash(
|
||||
struct iscsit_conn *conn,
|
||||
struct iscsi_node_auth *auth,
|
||||
|
@ -295,16 +327,27 @@ static int chap_server_compute_hash(
|
|||
pr_err("Could not find CHAP_R.\n");
|
||||
goto out;
|
||||
}
|
||||
if (type != HEX) {
|
||||
pr_err("Could not find CHAP_R.\n");
|
||||
goto out;
|
||||
}
|
||||
if (strlen(chap_r) != chap->digest_size * 2) {
|
||||
pr_err("Malformed CHAP_R\n");
|
||||
goto out;
|
||||
}
|
||||
if (hex2bin(client_digest, chap_r, chap->digest_size) < 0) {
|
||||
pr_err("Malformed CHAP_R\n");
|
||||
|
||||
switch (type) {
|
||||
case HEX:
|
||||
if (strlen(chap_r) != chap->digest_size * 2) {
|
||||
pr_err("Malformed CHAP_R\n");
|
||||
goto out;
|
||||
}
|
||||
if (hex2bin(client_digest, chap_r, chap->digest_size) < 0) {
|
||||
pr_err("Malformed CHAP_R: invalid HEX\n");
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
case BASE64:
|
||||
if (chap_base64_decode(client_digest, chap_r, strlen(chap_r)) !=
|
||||
chap->digest_size) {
|
||||
pr_err("Malformed CHAP_R: invalid BASE64\n");
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
pr_err("Could not find CHAP_R\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -404,23 +447,46 @@ static int chap_server_compute_hash(
|
|||
goto out;
|
||||
}
|
||||
|
||||
if (type != HEX) {
|
||||
switch (type) {
|
||||
case HEX:
|
||||
initiatorchg_len = DIV_ROUND_UP(strlen(initiatorchg), 2);
|
||||
if (!initiatorchg_len) {
|
||||
pr_err("Unable to convert incoming challenge\n");
|
||||
goto out;
|
||||
}
|
||||
if (initiatorchg_len > 1024) {
|
||||
pr_err("CHAP_C exceeds maximum binary size of 1024 bytes\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (hex2bin(initiatorchg_binhex, initiatorchg,
|
||||
initiatorchg_len) < 0) {
|
||||
pr_err("Malformed CHAP_C: invalid HEX\n");
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
case BASE64:
|
||||
initiatorchg_len = chap_base64_decode(initiatorchg_binhex,
|
||||
initiatorchg,
|
||||
strlen(initiatorchg));
|
||||
if (initiatorchg_len < 0) {
|
||||
pr_err("Malformed CHAP_C: invalid BASE64\n");
|
||||
goto out;
|
||||
}
|
||||
if (!initiatorchg_len) {
|
||||
pr_err("Unable to convert incoming challenge\n");
|
||||
goto out;
|
||||
}
|
||||
if (initiatorchg_len > 1024) {
|
||||
pr_err("CHAP_C exceeds maximum binary size of 1024 bytes\n");
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
pr_err("Could not find CHAP_C.\n");
|
||||
goto out;
|
||||
}
|
||||
initiatorchg_len = DIV_ROUND_UP(strlen(initiatorchg), 2);
|
||||
if (!initiatorchg_len) {
|
||||
pr_err("Unable to convert incoming challenge\n");
|
||||
goto out;
|
||||
}
|
||||
if (initiatorchg_len > 1024) {
|
||||
pr_err("CHAP_C exceeds maximum binary size of 1024 bytes\n");
|
||||
goto out;
|
||||
}
|
||||
if (hex2bin(initiatorchg_binhex, initiatorchg, initiatorchg_len) < 0) {
|
||||
pr_err("Malformed CHAP_C\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
pr_debug("[server] Got CHAP_C=%s\n", initiatorchg);
|
||||
/*
|
||||
* During mutual authentication, the CHAP_C generated by the
|
||||
|
|
|
@ -76,6 +76,9 @@ int extract_param(
|
|||
if (*ptr == '0' && (*(ptr+1) == 'x' || *(ptr+1) == 'X')) {
|
||||
ptr += 2; /* skip 0x */
|
||||
*type = HEX;
|
||||
} else if (*ptr == '0' && (*(ptr+1) == 'b' || *(ptr+1) == 'B')) {
|
||||
ptr += 2; /* skip 0b */
|
||||
*type = BASE64;
|
||||
} else
|
||||
*type = DECIMAL;
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#define DECIMAL 0
|
||||
#define HEX 1
|
||||
#define BASE64 2
|
||||
|
||||
struct iscsit_conn;
|
||||
struct iscsi_login;
|
||||
|
|
Loading…
Reference in New Issue