Commit 1e573388 authored by Dmitry Bogdanov's avatar Dmitry Bogdanov Committed by Martin K. Petersen

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.comReviewed-by: default avatarMike Christie <michael.christie@oracle.com>
Signed-off-by: default avatarDmitry Bogdanov <d.bogdanov@yadro.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 8f1f7d29
...@@ -205,6 +205,38 @@ static struct iscsi_chap *chap_server_open( ...@@ -205,6 +205,38 @@ static struct iscsi_chap *chap_server_open(
return chap; 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( static int chap_server_compute_hash(
struct iscsit_conn *conn, struct iscsit_conn *conn,
struct iscsi_node_auth *auth, struct iscsi_node_auth *auth,
...@@ -295,16 +327,27 @@ static int chap_server_compute_hash( ...@@ -295,16 +327,27 @@ static int chap_server_compute_hash(
pr_err("Could not find CHAP_R.\n"); pr_err("Could not find CHAP_R.\n");
goto out; goto out;
} }
if (type != HEX) {
pr_err("Could not find CHAP_R.\n"); switch (type) {
goto out; case HEX:
} if (strlen(chap_r) != chap->digest_size * 2) {
if (strlen(chap_r) != chap->digest_size * 2) { pr_err("Malformed CHAP_R\n");
pr_err("Malformed CHAP_R\n"); goto out;
goto out; }
} if (hex2bin(client_digest, chap_r, chap->digest_size) < 0) {
if (hex2bin(client_digest, chap_r, chap->digest_size) < 0) { pr_err("Malformed CHAP_R: invalid HEX\n");
pr_err("Malformed CHAP_R\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; goto out;
} }
...@@ -404,23 +447,46 @@ static int chap_server_compute_hash( ...@@ -404,23 +447,46 @@ static int chap_server_compute_hash(
goto out; 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"); pr_err("Could not find CHAP_C.\n");
goto out; 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); pr_debug("[server] Got CHAP_C=%s\n", initiatorchg);
/* /*
* During mutual authentication, the CHAP_C generated by the * During mutual authentication, the CHAP_C generated by the
......
...@@ -76,6 +76,9 @@ int extract_param( ...@@ -76,6 +76,9 @@ int extract_param(
if (*ptr == '0' && (*(ptr+1) == 'x' || *(ptr+1) == 'X')) { if (*ptr == '0' && (*(ptr+1) == 'x' || *(ptr+1) == 'X')) {
ptr += 2; /* skip 0x */ ptr += 2; /* skip 0x */
*type = HEX; *type = HEX;
} else if (*ptr == '0' && (*(ptr+1) == 'b' || *(ptr+1) == 'B')) {
ptr += 2; /* skip 0b */
*type = BASE64;
} else } else
*type = DECIMAL; *type = DECIMAL;
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#define DECIMAL 0 #define DECIMAL 0
#define HEX 1 #define HEX 1
#define BASE64 2
struct iscsit_conn; struct iscsit_conn;
struct iscsi_login; struct iscsi_login;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment