1 /******************************************************************************* 2 * This file houses the main functions for the iSCSI CHAP support 3 * 4 * (c) Copyright 2007-2013 Datera, Inc. 5 * 6 * Author: Nicholas A. Bellinger <nab@linux-iscsi.org> 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 ******************************************************************************/ 18 19 #include <crypto/hash.h> 20 #include <linux/kernel.h> 21 #include <linux/string.h> 22 #include <linux/err.h> 23 #include <linux/random.h> 24 #include <linux/scatterlist.h> 25 #include <target/iscsi/iscsi_target_core.h> 26 #include "iscsi_target_nego.h" 27 #include "iscsi_target_auth.h" 28 29 static int chap_gen_challenge( 30 struct iscsi_conn *conn, 31 int caller, 32 char *c_str, 33 unsigned int *c_len) 34 { 35 int ret; 36 unsigned char challenge_asciihex[CHAP_CHALLENGE_LENGTH * 2 + 1]; 37 struct iscsi_chap *chap = conn->auth_protocol; 38 39 memset(challenge_asciihex, 0, CHAP_CHALLENGE_LENGTH * 2 + 1); 40 41 ret = get_random_bytes_wait(chap->challenge, CHAP_CHALLENGE_LENGTH); 42 if (unlikely(ret)) 43 return ret; 44 bin2hex(challenge_asciihex, chap->challenge, 45 CHAP_CHALLENGE_LENGTH); 46 /* 47 * Set CHAP_C, and copy the generated challenge into c_str. 48 */ 49 *c_len += sprintf(c_str + *c_len, "CHAP_C=0x%s", challenge_asciihex); 50 *c_len += 1; 51 52 pr_debug("[%s] Sending CHAP_C=0x%s\n\n", (caller) ? "server" : "client", 53 challenge_asciihex); 54 return 0; 55 } 56 57 static int chap_check_algorithm(const char *a_str) 58 { 59 char *tmp, *orig, *token; 60 61 tmp = kstrdup(a_str, GFP_KERNEL); 62 if (!tmp) { 63 pr_err("Memory allocation failed for CHAP_A temporary buffer\n"); 64 return CHAP_DIGEST_UNKNOWN; 65 } 66 orig = tmp; 67 68 token = strsep(&tmp, "="); 69 if (!token) 70 goto out; 71 72 if (strcmp(token, "CHAP_A")) { 73 pr_err("Unable to locate CHAP_A key\n"); 74 goto out; 75 } 76 while (token) { 77 token = strsep(&tmp, ","); 78 if (!token) 79 goto out; 80 81 if (!strncmp(token, "5", 1)) { 82 pr_debug("Selected MD5 Algorithm\n"); 83 kfree(orig); 84 return CHAP_DIGEST_MD5; 85 } 86 } 87 out: 88 kfree(orig); 89 return CHAP_DIGEST_UNKNOWN; 90 } 91 92 static struct iscsi_chap *chap_server_open( 93 struct iscsi_conn *conn, 94 struct iscsi_node_auth *auth, 95 const char *a_str, 96 char *aic_str, 97 unsigned int *aic_len) 98 { 99 int ret; 100 struct iscsi_chap *chap; 101 102 if (!(auth->naf_flags & NAF_USERID_SET) || 103 !(auth->naf_flags & NAF_PASSWORD_SET)) { 104 pr_err("CHAP user or password not set for" 105 " Initiator ACL\n"); 106 return NULL; 107 } 108 109 conn->auth_protocol = kzalloc(sizeof(struct iscsi_chap), GFP_KERNEL); 110 if (!conn->auth_protocol) 111 return NULL; 112 113 chap = conn->auth_protocol; 114 ret = chap_check_algorithm(a_str); 115 switch (ret) { 116 case CHAP_DIGEST_MD5: 117 pr_debug("[server] Got CHAP_A=5\n"); 118 /* 119 * Send back CHAP_A set to MD5. 120 */ 121 *aic_len = sprintf(aic_str, "CHAP_A=5"); 122 *aic_len += 1; 123 chap->digest_type = CHAP_DIGEST_MD5; 124 pr_debug("[server] Sending CHAP_A=%d\n", chap->digest_type); 125 break; 126 case CHAP_DIGEST_UNKNOWN: 127 default: 128 pr_err("Unsupported CHAP_A value\n"); 129 kfree(conn->auth_protocol); 130 return NULL; 131 } 132 133 /* 134 * Set Identifier. 135 */ 136 chap->id = conn->tpg->tpg_chap_id++; 137 *aic_len += sprintf(aic_str + *aic_len, "CHAP_I=%d", chap->id); 138 *aic_len += 1; 139 pr_debug("[server] Sending CHAP_I=%d\n", chap->id); 140 /* 141 * Generate Challenge. 142 */ 143 if (chap_gen_challenge(conn, 1, aic_str, aic_len) < 0) { 144 kfree(conn->auth_protocol); 145 return NULL; 146 } 147 148 return chap; 149 } 150 151 static void chap_close(struct iscsi_conn *conn) 152 { 153 kfree(conn->auth_protocol); 154 conn->auth_protocol = NULL; 155 } 156 157 static int chap_server_compute_md5( 158 struct iscsi_conn *conn, 159 struct iscsi_node_auth *auth, 160 char *nr_in_ptr, 161 char *nr_out_ptr, 162 unsigned int *nr_out_len) 163 { 164 unsigned long id; 165 unsigned char id_as_uchar; 166 unsigned char digest[MD5_SIGNATURE_SIZE]; 167 unsigned char type, response[MD5_SIGNATURE_SIZE * 2 + 2]; 168 unsigned char identifier[10], *challenge = NULL; 169 unsigned char *challenge_binhex = NULL; 170 unsigned char client_digest[MD5_SIGNATURE_SIZE]; 171 unsigned char server_digest[MD5_SIGNATURE_SIZE]; 172 unsigned char chap_n[MAX_CHAP_N_SIZE], chap_r[MAX_RESPONSE_LENGTH]; 173 size_t compare_len; 174 struct iscsi_chap *chap = conn->auth_protocol; 175 struct crypto_shash *tfm = NULL; 176 struct shash_desc *desc = NULL; 177 int auth_ret = -1, ret, challenge_len; 178 179 memset(identifier, 0, 10); 180 memset(chap_n, 0, MAX_CHAP_N_SIZE); 181 memset(chap_r, 0, MAX_RESPONSE_LENGTH); 182 memset(digest, 0, MD5_SIGNATURE_SIZE); 183 memset(response, 0, MD5_SIGNATURE_SIZE * 2 + 2); 184 memset(client_digest, 0, MD5_SIGNATURE_SIZE); 185 memset(server_digest, 0, MD5_SIGNATURE_SIZE); 186 187 challenge = kzalloc(CHAP_CHALLENGE_STR_LEN, GFP_KERNEL); 188 if (!challenge) { 189 pr_err("Unable to allocate challenge buffer\n"); 190 goto out; 191 } 192 193 challenge_binhex = kzalloc(CHAP_CHALLENGE_STR_LEN, GFP_KERNEL); 194 if (!challenge_binhex) { 195 pr_err("Unable to allocate challenge_binhex buffer\n"); 196 goto out; 197 } 198 /* 199 * Extract CHAP_N. 200 */ 201 if (extract_param(nr_in_ptr, "CHAP_N", MAX_CHAP_N_SIZE, chap_n, 202 &type) < 0) { 203 pr_err("Could not find CHAP_N.\n"); 204 goto out; 205 } 206 if (type == HEX) { 207 pr_err("Could not find CHAP_N.\n"); 208 goto out; 209 } 210 211 /* Include the terminating NULL in the compare */ 212 compare_len = strlen(auth->userid) + 1; 213 if (strncmp(chap_n, auth->userid, compare_len) != 0) { 214 pr_err("CHAP_N values do not match!\n"); 215 goto out; 216 } 217 pr_debug("[server] Got CHAP_N=%s\n", chap_n); 218 /* 219 * Extract CHAP_R. 220 */ 221 if (extract_param(nr_in_ptr, "CHAP_R", MAX_RESPONSE_LENGTH, chap_r, 222 &type) < 0) { 223 pr_err("Could not find CHAP_R.\n"); 224 goto out; 225 } 226 if (type != HEX) { 227 pr_err("Could not find CHAP_R.\n"); 228 goto out; 229 } 230 if (strlen(chap_r) != MD5_SIGNATURE_SIZE * 2) { 231 pr_err("Malformed CHAP_R\n"); 232 goto out; 233 } 234 if (hex2bin(client_digest, chap_r, MD5_SIGNATURE_SIZE) < 0) { 235 pr_err("Malformed CHAP_R\n"); 236 goto out; 237 } 238 239 pr_debug("[server] Got CHAP_R=%s\n", chap_r); 240 241 tfm = crypto_alloc_shash("md5", 0, 0); 242 if (IS_ERR(tfm)) { 243 tfm = NULL; 244 pr_err("Unable to allocate struct crypto_shash\n"); 245 goto out; 246 } 247 248 desc = kmalloc(sizeof(*desc) + crypto_shash_descsize(tfm), GFP_KERNEL); 249 if (!desc) { 250 pr_err("Unable to allocate struct shash_desc\n"); 251 goto out; 252 } 253 254 desc->tfm = tfm; 255 desc->flags = 0; 256 257 ret = crypto_shash_init(desc); 258 if (ret < 0) { 259 pr_err("crypto_shash_init() failed\n"); 260 goto out; 261 } 262 263 ret = crypto_shash_update(desc, &chap->id, 1); 264 if (ret < 0) { 265 pr_err("crypto_shash_update() failed for id\n"); 266 goto out; 267 } 268 269 ret = crypto_shash_update(desc, (char *)&auth->password, 270 strlen(auth->password)); 271 if (ret < 0) { 272 pr_err("crypto_shash_update() failed for password\n"); 273 goto out; 274 } 275 276 ret = crypto_shash_finup(desc, chap->challenge, 277 CHAP_CHALLENGE_LENGTH, server_digest); 278 if (ret < 0) { 279 pr_err("crypto_shash_finup() failed for challenge\n"); 280 goto out; 281 } 282 283 bin2hex(response, server_digest, MD5_SIGNATURE_SIZE); 284 pr_debug("[server] MD5 Server Digest: %s\n", response); 285 286 if (memcmp(server_digest, client_digest, MD5_SIGNATURE_SIZE) != 0) { 287 pr_debug("[server] MD5 Digests do not match!\n\n"); 288 goto out; 289 } else 290 pr_debug("[server] MD5 Digests match, CHAP connection" 291 " successful.\n\n"); 292 /* 293 * One way authentication has succeeded, return now if mutual 294 * authentication is not enabled. 295 */ 296 if (!auth->authenticate_target) { 297 auth_ret = 0; 298 goto out; 299 } 300 /* 301 * Get CHAP_I. 302 */ 303 if (extract_param(nr_in_ptr, "CHAP_I", 10, identifier, &type) < 0) { 304 pr_err("Could not find CHAP_I.\n"); 305 goto out; 306 } 307 308 if (type == HEX) 309 ret = kstrtoul(&identifier[2], 0, &id); 310 else 311 ret = kstrtoul(identifier, 0, &id); 312 313 if (ret < 0) { 314 pr_err("kstrtoul() failed for CHAP identifier: %d\n", ret); 315 goto out; 316 } 317 if (id > 255) { 318 pr_err("chap identifier: %lu greater than 255\n", id); 319 goto out; 320 } 321 /* 322 * RFC 1994 says Identifier is no more than octet (8 bits). 323 */ 324 pr_debug("[server] Got CHAP_I=%lu\n", id); 325 /* 326 * Get CHAP_C. 327 */ 328 if (extract_param(nr_in_ptr, "CHAP_C", CHAP_CHALLENGE_STR_LEN, 329 challenge, &type) < 0) { 330 pr_err("Could not find CHAP_C.\n"); 331 goto out; 332 } 333 334 if (type != HEX) { 335 pr_err("Could not find CHAP_C.\n"); 336 goto out; 337 } 338 challenge_len = DIV_ROUND_UP(strlen(challenge), 2); 339 if (!challenge_len) { 340 pr_err("Unable to convert incoming challenge\n"); 341 goto out; 342 } 343 if (challenge_len > 1024) { 344 pr_err("CHAP_C exceeds maximum binary size of 1024 bytes\n"); 345 goto out; 346 } 347 if (hex2bin(challenge_binhex, challenge, challenge_len) < 0) { 348 pr_err("Malformed CHAP_C\n"); 349 goto out; 350 } 351 pr_debug("[server] Got CHAP_C=%s\n", challenge); 352 /* 353 * During mutual authentication, the CHAP_C generated by the 354 * initiator must not match the original CHAP_C generated by 355 * the target. 356 */ 357 if (!memcmp(challenge_binhex, chap->challenge, CHAP_CHALLENGE_LENGTH)) { 358 pr_err("initiator CHAP_C matches target CHAP_C, failing" 359 " login attempt\n"); 360 goto out; 361 } 362 /* 363 * Generate CHAP_N and CHAP_R for mutual authentication. 364 */ 365 ret = crypto_shash_init(desc); 366 if (ret < 0) { 367 pr_err("crypto_shash_init() failed\n"); 368 goto out; 369 } 370 371 /* To handle both endiannesses */ 372 id_as_uchar = id; 373 ret = crypto_shash_update(desc, &id_as_uchar, 1); 374 if (ret < 0) { 375 pr_err("crypto_shash_update() failed for id\n"); 376 goto out; 377 } 378 379 ret = crypto_shash_update(desc, auth->password_mutual, 380 strlen(auth->password_mutual)); 381 if (ret < 0) { 382 pr_err("crypto_shash_update() failed for" 383 " password_mutual\n"); 384 goto out; 385 } 386 /* 387 * Convert received challenge to binary hex. 388 */ 389 ret = crypto_shash_finup(desc, challenge_binhex, challenge_len, 390 digest); 391 if (ret < 0) { 392 pr_err("crypto_shash_finup() failed for ma challenge\n"); 393 goto out; 394 } 395 396 /* 397 * Generate CHAP_N and CHAP_R. 398 */ 399 *nr_out_len = sprintf(nr_out_ptr, "CHAP_N=%s", auth->userid_mutual); 400 *nr_out_len += 1; 401 pr_debug("[server] Sending CHAP_N=%s\n", auth->userid_mutual); 402 /* 403 * Convert response from binary hex to ascii hext. 404 */ 405 bin2hex(response, digest, MD5_SIGNATURE_SIZE); 406 *nr_out_len += sprintf(nr_out_ptr + *nr_out_len, "CHAP_R=0x%s", 407 response); 408 *nr_out_len += 1; 409 pr_debug("[server] Sending CHAP_R=0x%s\n", response); 410 auth_ret = 0; 411 out: 412 kzfree(desc); 413 if (tfm) 414 crypto_free_shash(tfm); 415 kfree(challenge); 416 kfree(challenge_binhex); 417 return auth_ret; 418 } 419 420 static int chap_got_response( 421 struct iscsi_conn *conn, 422 struct iscsi_node_auth *auth, 423 char *nr_in_ptr, 424 char *nr_out_ptr, 425 unsigned int *nr_out_len) 426 { 427 struct iscsi_chap *chap = conn->auth_protocol; 428 429 switch (chap->digest_type) { 430 case CHAP_DIGEST_MD5: 431 if (chap_server_compute_md5(conn, auth, nr_in_ptr, 432 nr_out_ptr, nr_out_len) < 0) 433 return -1; 434 return 0; 435 default: 436 pr_err("Unknown CHAP digest type %d!\n", 437 chap->digest_type); 438 return -1; 439 } 440 } 441 442 u32 chap_main_loop( 443 struct iscsi_conn *conn, 444 struct iscsi_node_auth *auth, 445 char *in_text, 446 char *out_text, 447 int *in_len, 448 int *out_len) 449 { 450 struct iscsi_chap *chap = conn->auth_protocol; 451 452 if (!chap) { 453 chap = chap_server_open(conn, auth, in_text, out_text, out_len); 454 if (!chap) 455 return 2; 456 chap->chap_state = CHAP_STAGE_SERVER_AIC; 457 return 0; 458 } else if (chap->chap_state == CHAP_STAGE_SERVER_AIC) { 459 convert_null_to_semi(in_text, *in_len); 460 if (chap_got_response(conn, auth, in_text, out_text, 461 out_len) < 0) { 462 chap_close(conn); 463 return 2; 464 } 465 if (auth->authenticate_target) 466 chap->chap_state = CHAP_STAGE_SERVER_NR; 467 else 468 *out_len = 0; 469 chap_close(conn); 470 return 1; 471 } 472 473 return 2; 474 } 475