Commit 6787ab81 authored by Jason A. Donenfeld's avatar Jason A. Donenfeld Committed by Theodore Ts'o

iscsi: ensure RNG is seeded before use

It's not safe to use weak random data here, especially for the challenge
response randomness. Since we're always in process context, it's safe to
simply wait until we have enough randomness to carry out the
authentication correctly.

While we're at it, we clean up a small memleak during an error
condition.
Signed-off-by: default avatarJason A. Donenfeld <Jason@zx2c4.com>
Cc: "Nicholas A. Bellinger" <nab@linux-iscsi.org>
Cc: Lee Duncan <lduncan@suse.com>
Cc: Chris Leech <cleech@redhat.com>
Signed-off-by: default avatarTheodore Ts'o <tytso@mit.edu>
parent 51b0817b
...@@ -47,18 +47,21 @@ static void chap_binaryhex_to_asciihex(char *dst, char *src, int src_len) ...@@ -47,18 +47,21 @@ static void chap_binaryhex_to_asciihex(char *dst, char *src, int src_len)
} }
} }
static void chap_gen_challenge( static int chap_gen_challenge(
struct iscsi_conn *conn, struct iscsi_conn *conn,
int caller, int caller,
char *c_str, char *c_str,
unsigned int *c_len) unsigned int *c_len)
{ {
int ret;
unsigned char challenge_asciihex[CHAP_CHALLENGE_LENGTH * 2 + 1]; unsigned char challenge_asciihex[CHAP_CHALLENGE_LENGTH * 2 + 1];
struct iscsi_chap *chap = conn->auth_protocol; struct iscsi_chap *chap = conn->auth_protocol;
memset(challenge_asciihex, 0, CHAP_CHALLENGE_LENGTH * 2 + 1); memset(challenge_asciihex, 0, CHAP_CHALLENGE_LENGTH * 2 + 1);
get_random_bytes(chap->challenge, CHAP_CHALLENGE_LENGTH); ret = get_random_bytes_wait(chap->challenge, CHAP_CHALLENGE_LENGTH);
if (unlikely(ret))
return ret;
chap_binaryhex_to_asciihex(challenge_asciihex, chap->challenge, chap_binaryhex_to_asciihex(challenge_asciihex, chap->challenge,
CHAP_CHALLENGE_LENGTH); CHAP_CHALLENGE_LENGTH);
/* /*
...@@ -69,6 +72,7 @@ static void chap_gen_challenge( ...@@ -69,6 +72,7 @@ static void chap_gen_challenge(
pr_debug("[%s] Sending CHAP_C=0x%s\n\n", (caller) ? "server" : "client", pr_debug("[%s] Sending CHAP_C=0x%s\n\n", (caller) ? "server" : "client",
challenge_asciihex); challenge_asciihex);
return 0;
} }
static int chap_check_algorithm(const char *a_str) static int chap_check_algorithm(const char *a_str)
...@@ -143,6 +147,7 @@ static struct iscsi_chap *chap_server_open( ...@@ -143,6 +147,7 @@ static struct iscsi_chap *chap_server_open(
case CHAP_DIGEST_UNKNOWN: case CHAP_DIGEST_UNKNOWN:
default: default:
pr_err("Unsupported CHAP_A value\n"); pr_err("Unsupported CHAP_A value\n");
kfree(conn->auth_protocol);
return NULL; return NULL;
} }
...@@ -156,7 +161,10 @@ static struct iscsi_chap *chap_server_open( ...@@ -156,7 +161,10 @@ static struct iscsi_chap *chap_server_open(
/* /*
* Generate Challenge. * Generate Challenge.
*/ */
chap_gen_challenge(conn, 1, aic_str, aic_len); if (chap_gen_challenge(conn, 1, aic_str, aic_len) < 0) {
kfree(conn->auth_protocol);
return NULL;
}
return chap; return chap;
} }
......
...@@ -245,22 +245,26 @@ int iscsi_check_for_session_reinstatement(struct iscsi_conn *conn) ...@@ -245,22 +245,26 @@ int iscsi_check_for_session_reinstatement(struct iscsi_conn *conn)
return 0; return 0;
} }
static void iscsi_login_set_conn_values( static int iscsi_login_set_conn_values(
struct iscsi_session *sess, struct iscsi_session *sess,
struct iscsi_conn *conn, struct iscsi_conn *conn,
__be16 cid) __be16 cid)
{ {
int ret;
conn->sess = sess; conn->sess = sess;
conn->cid = be16_to_cpu(cid); conn->cid = be16_to_cpu(cid);
/* /*
* Generate a random Status sequence number (statsn) for the new * Generate a random Status sequence number (statsn) for the new
* iSCSI connection. * iSCSI connection.
*/ */
get_random_bytes(&conn->stat_sn, sizeof(u32)); ret = get_random_bytes_wait(&conn->stat_sn, sizeof(u32));
if (unlikely(ret))
return ret;
mutex_lock(&auth_id_lock); mutex_lock(&auth_id_lock);
conn->auth_id = iscsit_global->auth_id++; conn->auth_id = iscsit_global->auth_id++;
mutex_unlock(&auth_id_lock); mutex_unlock(&auth_id_lock);
return 0;
} }
__printf(2, 3) int iscsi_change_param_sprintf( __printf(2, 3) int iscsi_change_param_sprintf(
...@@ -306,7 +310,11 @@ static int iscsi_login_zero_tsih_s1( ...@@ -306,7 +310,11 @@ static int iscsi_login_zero_tsih_s1(
return -ENOMEM; return -ENOMEM;
} }
iscsi_login_set_conn_values(sess, conn, pdu->cid); ret = iscsi_login_set_conn_values(sess, conn, pdu->cid);
if (unlikely(ret)) {
kfree(sess);
return ret;
}
sess->init_task_tag = pdu->itt; sess->init_task_tag = pdu->itt;
memcpy(&sess->isid, pdu->isid, 6); memcpy(&sess->isid, pdu->isid, 6);
sess->exp_cmd_sn = be32_to_cpu(pdu->cmdsn); sess->exp_cmd_sn = be32_to_cpu(pdu->cmdsn);
...@@ -497,8 +505,7 @@ static int iscsi_login_non_zero_tsih_s1( ...@@ -497,8 +505,7 @@ static int iscsi_login_non_zero_tsih_s1(
{ {
struct iscsi_login_req *pdu = (struct iscsi_login_req *)buf; struct iscsi_login_req *pdu = (struct iscsi_login_req *)buf;
iscsi_login_set_conn_values(NULL, conn, pdu->cid); return iscsi_login_set_conn_values(NULL, conn, pdu->cid);
return 0;
} }
/* /*
...@@ -554,9 +561,8 @@ static int iscsi_login_non_zero_tsih_s2( ...@@ -554,9 +561,8 @@ static int iscsi_login_non_zero_tsih_s2(
atomic_set(&sess->session_continuation, 1); atomic_set(&sess->session_continuation, 1);
spin_unlock_bh(&sess->conn_lock); spin_unlock_bh(&sess->conn_lock);
iscsi_login_set_conn_values(sess, conn, pdu->cid); if (iscsi_login_set_conn_values(sess, conn, pdu->cid) < 0 ||
iscsi_copy_param_list(&conn->param_list,
if (iscsi_copy_param_list(&conn->param_list,
conn->tpg->param_list, 0) < 0) { conn->tpg->param_list, 0) < 0) {
iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
ISCSI_LOGIN_STATUS_NO_RESOURCES); ISCSI_LOGIN_STATUS_NO_RESOURCES);
......
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