Re: [RFC-v3 07/12] iscsi-target: Add CHAP Authentication support using libcrypto
From: Jesper Juhl <hidden>
Date: 2011-03-17 22:46:33
Also in:
lkml
On Thu, 17 Mar 2011, Nicholas A. Bellinger wrote:
From: Nicholas Bellinger <redacted>
Minor nitpicks below.
quoted hunk ↗ jump to hunk
This patch adds support for libcrypto md5 based iSCSI CHAP authentication support for iscsi_target_mod. This includes support for mutual and one-way NodeACL authentication for SessionType=Normal and SessionType=Discovery via /sys/kernel/config/target/iscsi. Signed-off-by: Nicholas A. Bellinger <redacted> --- drivers/target/iscsi/iscsi_target_auth.c | 500 ++++++++++++++++++++++++++++++ drivers/target/iscsi/iscsi_target_auth.h | 33 ++ 2 files changed, 533 insertions(+), 0 deletions(-) create mode 100644 drivers/target/iscsi/iscsi_target_auth.c create mode 100644 drivers/target/iscsi/iscsi_target_auth.hdiff --git a/drivers/target/iscsi/iscsi_target_auth.c b/drivers/target/iscsi/iscsi_target_auth.c new file mode 100644 index 0000000..d3711f4 --- /dev/null +++ b/drivers/target/iscsi/iscsi_target_auth.c@@ -0,0 +1,500 @@ +/******************************************************************************* + * This file houses the main functions for the iSCSI CHAP support + * + * ?? Copyright 2007-2011 RisingTide Systems LLC.
"??" ?
+int chap_string_to_hex(unsigned char *dst, unsigned char *src, int len)
+{
+ int i = 0, j = 0;
+
+ for (i = 0; i < len; i += 2)Initializing 'i' to zero twice is a little needless.
+void chap_binaryhex_to_asciihex(char *dst, char *src, int src_len)
+{
+ int i;
+
+ for (i = 0; i < src_len; i++)Do we still support compiler versions that don't understand 'for-scope'? for (int i = 0; ...
+void chap_set_random(char *data, int length)
+{
+ long r;
+ unsigned n;
+
+ while (length > 0) {
+Pointless newline IMHO.
+ get_random_bytes(&r, sizeof(long)); + r = r ^ (r >> 8); + r = r ^ (r >> 4); + n = r & 0x7; + + get_random_bytes(&r, sizeof(long)); + r = r ^ (r >> 8); + r = r ^ (r >> 5); + n = (n << 3) | (r & 0x7); + + get_random_bytes(&r, sizeof(long)); + r = r ^ (r >> 8); + r = r ^ (r >> 5); + n = (n << 2) | (r & 0x3); + + *data++ = n; + length--;
Mixing space and tab in indentation here.
+int chap_gen_challenge(
+ struct iscsi_conn *conn,
+ int caller,
+ char *C_str,
+ unsigned int *C_len)
+{
+ unsigned char challenge_asciihex[CHAP_CHALLENGE_LENGTH * 2 + 1];
+ struct iscsi_chap *chap = (struct iscsi_chap *) conn->auth_protocol;
+
+ memset(challenge_asciihex, 0, CHAP_CHALLENGE_LENGTH * 2 + 1);
+
+ chap_set_random(chap->challenge, CHAP_CHALLENGE_LENGTH);
+ chap_binaryhex_to_asciihex(challenge_asciihex, chap->challenge,
+ CHAP_CHALLENGE_LENGTH);
+ /*
+ * Set CHAP_C, and copy the generated challenge into C_str.
+ */
+ *C_len += sprintf(C_str + *C_len, "CHAP_C=0x%s", challenge_asciihex);
+ *C_len += 1;
+
+ PRINT("[%s] Sending CHAP_C=0x%s\n\n", (caller) ? "server" : "client",
+ challenge_asciihex);
+ return 0;You only ever return '0', so why couldn't this function just return 'void'? - sorry, didn't bother to actually check how its used :-/
+int chap_server_compute_md5(
+ struct iscsi_conn *conn,
+ struct iscsi_node_auth *auth,
+ char *NR_in_ptr,
+ char *NR_out_ptr,
+ unsigned int *NR_out_len)
+{
+ char *endptr;
+ unsigned char id, digest[MD5_SIGNATURE_SIZE];
+ unsigned char type, response[MD5_SIGNATURE_SIZE * 2 + 2];
+ unsigned char identifier[10], *challenge, *challenge_binhex;If you changed the above line to unsigned char identifier[10], *challenge; unsigned char *challenge_binhex = 0;
+ unsigned char client_digest[MD5_SIGNATURE_SIZE];
+ unsigned char server_digest[MD5_SIGNATURE_SIZE];
+ unsigned char chap_n[MAX_CHAP_N_SIZE], chap_r[MAX_RESPONSE_LENGTH];
+ struct iscsi_chap *chap = (struct iscsi_chap *) conn->auth_protocol;
+ struct crypto_hash *tfm;
+ struct hash_desc desc;
+ struct scatterlist sg;
+ int auth_ret = -1, ret, challenge_len;
+
+ memset(identifier, 0, 10);
+ memset(chap_n, 0, MAX_CHAP_N_SIZE);
+ memset(chap_r, 0, MAX_RESPONSE_LENGTH);
+ memset(digest, 0, MD5_SIGNATURE_SIZE);
+ memset(response, 0, MD5_SIGNATURE_SIZE * 2 + 2);
+ memset(client_digest, 0, MD5_SIGNATURE_SIZE);
+ memset(server_digest, 0, MD5_SIGNATURE_SIZE);
+
+ challenge = kzalloc(CHAP_CHALLENGE_STR_LEN, GFP_KERNEL);
+ if (!(challenge)) {
+ printk(KERN_ERR "Unable to allocate challenge buffer\n");
+ return -1;this could become "goto out;"
+ }
+
+ challenge_binhex = kzalloc(CHAP_CHALLENGE_STR_LEN, GFP_KERNEL);
+ if (!(challenge_binhex)) {
+ printk(KERN_ERR "Unable to allocate challenge_binhex buffer\n");
+ kfree(challenge);
+ return -1;and here the kfree() call could go away and the return be converted to "goto out;". kfree(0) is a no-op. ...
+ * One way authentication has succeeded, return now if mutual
+ * authentication is not enabled.
+ */
+ if (!auth->authenticate_target) {
+ kfree(challenge);
+ kfree(challenge_binhex);
+ return 0;and here the two kfree() calls would also go away and "return 0" would be replaced with auth_ret = 0; goto out; ...
+out: + kfree(challenge); + kfree(challenge_binhex); + return auth_ret; +}
That would nicely consolidate *all* exits from the function in one place.
+
+int chap_got_response(
+ struct iscsi_conn *conn,
+ struct iscsi_node_auth *auth,
+ char *NR_in_ptr,
+ char *NR_out_ptr,
+ unsigned int *NR_out_len)
+{
+ struct iscsi_chap *chap = (struct iscsi_chap *) conn->auth_protocol;
+
+ switch (chap->digest_type) {
+ case CHAP_DIGEST_MD5:
+ if (chap_server_compute_md5(conn, auth, NR_in_ptr,
+ NR_out_ptr, NR_out_len) < 0)
+ return -1;
+ break;
+ default:
+ printk(KERN_ERR "Unknown CHAP digest type %d!\n",
+ chap->digest_type);
+ return -1;
+ }
+
+ return 0;You could kill the 'return 0' and replace the 'break' above with 'return 0'. No difference in behaviour, but you'd save a few lines and it would be just as readable IMHO. -- Jesper Juhl [off-list ref] http://www.chaosbits.net/ Don't top-post http://www.catb.org/~esr/jargon/html/T/top-post.html Plain text mails only, please.