diff options
| author | Tejas Vaykole <tejas.vaykole@calsoftinc.com> | 2014-05-30 01:43:47 -0400 |
|---|---|---|
| committer | Nicholas Bellinger <nab@linux-iscsi.org> | 2014-06-05 22:44:02 -0400 |
| commit | 3160723c49605965628c3ee7699e5e956c4f8f51 (patch) | |
| tree | fcba72fafb5e7e4e6908cb6238962585a60189a0 | |
| parent | cee6029ecfc2494e7869da20e3ff5aa7f5c4368e (diff) | |
iscsi-target: Fix CHAP_A parameter list handling
The target is failing to handle list of CHAP_A key-value pair form
initiator.The target is expecting CHAP_A=5 always. In other cases,
where initiator sends list (for example) CHAP_A=6,5 target is failing
the security negotiation. Which is incorrect.
This patch handles the case (RFC 3720 section 11.1.4).
where in the initiator may send list of CHAP_A values and target replies
with appropriate CHAP_A value in response
(Drop whitespaces + rename to chap_check_algorithm + save original
pointer + add explicit check for CHAP_A key - nab)
Signed-off-by: Tejas Vaykole <tejas.vaykole@calsoftinc.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
| -rw-r--r-- | drivers/target/iscsi/iscsi_target_auth.c | 64 | ||||
| -rw-r--r-- | drivers/target/iscsi/iscsi_target_auth.h | 1 |
2 files changed, 52 insertions, 13 deletions
diff --git a/drivers/target/iscsi/iscsi_target_auth.c b/drivers/target/iscsi/iscsi_target_auth.c index de77d9aa22c6..155f33848aa6 100644 --- a/drivers/target/iscsi/iscsi_target_auth.c +++ b/drivers/target/iscsi/iscsi_target_auth.c | |||
| @@ -71,6 +71,40 @@ static void chap_gen_challenge( | |||
| 71 | challenge_asciihex); | 71 | challenge_asciihex); |
| 72 | } | 72 | } |
| 73 | 73 | ||
| 74 | static int chap_check_algorithm(const char *a_str) | ||
| 75 | { | ||
| 76 | char *tmp, *orig, *token; | ||
| 77 | |||
| 78 | tmp = kstrdup(a_str, GFP_KERNEL); | ||
| 79 | if (!tmp) { | ||
| 80 | pr_err("Memory allocation failed for CHAP_A temporary buffer\n"); | ||
| 81 | return CHAP_DIGEST_UNKNOWN; | ||
| 82 | } | ||
| 83 | orig = tmp; | ||
| 84 | |||
| 85 | token = strsep(&tmp, "="); | ||
| 86 | if (!token) | ||
| 87 | goto out; | ||
| 88 | |||
| 89 | if (strcmp(token, "CHAP_A")) { | ||
| 90 | pr_err("Unable to locate CHAP_A key\n"); | ||
| 91 | goto out; | ||
| 92 | } | ||
| 93 | while (token) { | ||
| 94 | token = strsep(&tmp, ","); | ||
| 95 | if (!token) | ||
| 96 | goto out; | ||
| 97 | |||
| 98 | if (!strncmp(token, "5", 1)) { | ||
| 99 | pr_debug("Selected MD5 Algorithm\n"); | ||
| 100 | kfree(orig); | ||
| 101 | return CHAP_DIGEST_MD5; | ||
| 102 | } | ||
| 103 | } | ||
| 104 | out: | ||
| 105 | kfree(orig); | ||
| 106 | return CHAP_DIGEST_UNKNOWN; | ||
| 107 | } | ||
| 74 | 108 | ||
| 75 | static struct iscsi_chap *chap_server_open( | 109 | static struct iscsi_chap *chap_server_open( |
| 76 | struct iscsi_conn *conn, | 110 | struct iscsi_conn *conn, |
| @@ -79,6 +113,7 @@ static struct iscsi_chap *chap_server_open( | |||
| 79 | char *aic_str, | 113 | char *aic_str, |
| 80 | unsigned int *aic_len) | 114 | unsigned int *aic_len) |
| 81 | { | 115 | { |
| 116 | int ret; | ||
| 82 | struct iscsi_chap *chap; | 117 | struct iscsi_chap *chap; |
| 83 | 118 | ||
| 84 | if (!(auth->naf_flags & NAF_USERID_SET) || | 119 | if (!(auth->naf_flags & NAF_USERID_SET) || |
| @@ -93,21 +128,24 @@ static struct iscsi_chap *chap_server_open( | |||
| 93 | return NULL; | 128 | return NULL; |
| 94 | 129 | ||
| 95 | chap = conn->auth_protocol; | 130 | chap = conn->auth_protocol; |
| 96 | /* | 131 | ret = chap_check_algorithm(a_str); |
| 97 | * We only support MD5 MDA presently. | 132 | switch (ret) { |
| 98 | */ | 133 | case CHAP_DIGEST_MD5: |
| 99 | if (strncmp(a_str, "CHAP_A=5", 8)) { | 134 | pr_debug("[server] Got CHAP_A=5\n"); |
| 100 | pr_err("CHAP_A is not MD5.\n"); | 135 | /* |
| 136 | * Send back CHAP_A set to MD5. | ||
| 137 | */ | ||
| 138 | *aic_len = sprintf(aic_str, "CHAP_A=5"); | ||
| 139 | *aic_len += 1; | ||
| 140 | chap->digest_type = CHAP_DIGEST_MD5; | ||
| 141 | pr_debug("[server] Sending CHAP_A=%d\n", chap->digest_type); | ||
| 142 | break; | ||
| 143 | case CHAP_DIGEST_UNKNOWN: | ||
| 144 | default: | ||
| 145 | pr_err("Unsupported CHAP_A value\n"); | ||
| 101 | return NULL; | 146 | return NULL; |
| 102 | } | 147 | } |
| 103 | pr_debug("[server] Got CHAP_A=5\n"); | 148 | |
| 104 | /* | ||
| 105 | * Send back CHAP_A set to MD5. | ||
| 106 | */ | ||
| 107 | *aic_len = sprintf(aic_str, "CHAP_A=5"); | ||
| 108 | *aic_len += 1; | ||
| 109 | chap->digest_type = CHAP_DIGEST_MD5; | ||
| 110 | pr_debug("[server] Sending CHAP_A=%d\n", chap->digest_type); | ||
| 111 | /* | 149 | /* |
| 112 | * Set Identifier. | 150 | * Set Identifier. |
| 113 | */ | 151 | */ |
diff --git a/drivers/target/iscsi/iscsi_target_auth.h b/drivers/target/iscsi/iscsi_target_auth.h index 2f463c09626d..d22f7b96a06c 100644 --- a/drivers/target/iscsi/iscsi_target_auth.h +++ b/drivers/target/iscsi/iscsi_target_auth.h | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | #ifndef _ISCSI_CHAP_H_ | 1 | #ifndef _ISCSI_CHAP_H_ |
| 2 | #define _ISCSI_CHAP_H_ | 2 | #define _ISCSI_CHAP_H_ |
| 3 | 3 | ||
| 4 | #define CHAP_DIGEST_UNKNOWN 0 | ||
| 4 | #define CHAP_DIGEST_MD5 5 | 5 | #define CHAP_DIGEST_MD5 5 |
| 5 | #define CHAP_DIGEST_SHA 6 | 6 | #define CHAP_DIGEST_SHA 6 |
| 6 | 7 | ||
