📄 chap.c
字号:
SHA1_Init(&ctx); SHA1_Update(&ctx, &chap_id, 1); SHA1_Update(&ctx, secret, secret_len); SHA1_Update(&ctx, challenge, challenge_len); SHA1_Final(digest, &ctx);}static int chap_initiator_auth_create_challenge(struct connection *conn){ char *value, *p; char text[CHAP_CHALLENGE_MAX * 2 + 8]; static int chap_id; int i; value = text_key_find(conn, "CHAP_A"); if (!value) return CHAP_INITIATOR_ERROR; while ((p = strsep(&value, ","))) { if (!strcmp(p, "5")) { conn->auth.chap.digest_alg = CHAP_DIGEST_ALG_MD5; conn->auth_state = CHAP_AUTH_STATE_CHALLENGE; break; } else if (!strcmp(p, "7")) { conn->auth.chap.digest_alg = CHAP_DIGEST_ALG_SHA1; conn->auth_state = CHAP_AUTH_STATE_CHALLENGE; break; } } if (!p) return CHAP_INITIATOR_ERROR; text_key_add(conn, "CHAP_A", p); conn->auth.chap.id = ++chap_id; sprintf(text, "%u", (unsigned char)conn->auth.chap.id); text_key_add(conn, "CHAP_I", text); /* * FIXME: does a random challenge length provide any benefits security- * wise, or should we rather always use the max. allowed length of * 1024 for the (unencoded) challenge? */ conn->auth.chap.challenge_size = (rand() % (CHAP_CHALLENGE_MAX / 2)) + CHAP_CHALLENGE_MAX / 2; conn->auth.chap.challenge = malloc(conn->auth.chap.challenge_size); if (!conn->auth.chap.challenge) return CHAP_TARGET_ERROR; p = text; strcpy(p, "0x"); p += 2; for (i = 0; i < conn->auth.chap.challenge_size; i++) { conn->auth.chap.challenge[i] = rand(); sprintf(p, "%.2hhx", conn->auth.chap.challenge[i]); p += 2; } text_key_add(conn, "CHAP_C", text); return 0;}static int chap_initiator_auth_check_response(struct connection *conn){ char *value; u8 *his_digest = NULL, *our_digest = NULL; int digest_len = 0, retval = 0, encoding_format; char pass[ISCSI_NAME_LEN]; memset(pass, 0, sizeof(pass)); if (cops->account_query(conn->tid, AUTH_DIR_INCOMING, pass, pass) < 0) { log_warning("CHAP initiator auth.: " "No CHAP credentials configured"); retval = CHAP_TARGET_ERROR; goto out; } if (!(value = text_key_find(conn, "CHAP_N"))) { retval = CHAP_INITIATOR_ERROR; goto out; } memset(pass, 0, sizeof(pass)); if (cops->account_query(conn->tid, AUTH_DIR_INCOMING, value, pass) < 0) { log_warning("CHAP initiator auth.: " "No valid user/pass combination for initiator %s " "found", conn->initiator); retval = CHAP_AUTH_ERROR; goto out; } if (!(value = text_key_find(conn, "CHAP_R"))) { retval = CHAP_INITIATOR_ERROR; goto out; } if ((encoding_format = chap_check_encoding_format(value)) < 0) { retval = CHAP_INITIATOR_ERROR; goto out; } switch (conn->auth.chap.digest_alg) { case CHAP_DIGEST_ALG_MD5: digest_len = CHAP_MD5_DIGEST_LEN; break; case CHAP_DIGEST_ALG_SHA1: digest_len = CHAP_SHA1_DIGEST_LEN; break; default: retval = CHAP_TARGET_ERROR; goto out; } if (!(his_digest = malloc(digest_len))) { retval = CHAP_TARGET_ERROR; goto out; } if (!(our_digest = malloc(digest_len))) { retval = CHAP_TARGET_ERROR; goto out; } if (chap_decode_string(value, his_digest, digest_len, encoding_format) < 0) { retval = CHAP_INITIATOR_ERROR; goto out; } switch (conn->auth.chap.digest_alg) { case CHAP_DIGEST_ALG_MD5: chap_calc_digest_md5(conn->auth.chap.id, pass, strlen(pass), conn->auth.chap.challenge, conn->auth.chap.challenge_size, our_digest); break; case CHAP_DIGEST_ALG_SHA1: chap_calc_digest_sha1(conn->auth.chap.id, pass, strlen(pass), conn->auth.chap.challenge, conn->auth.chap.challenge_size, our_digest); break; default: retval = CHAP_TARGET_ERROR; goto out; } if (memcmp(our_digest, his_digest, digest_len)) { log_warning("CHAP initiator auth.: " "authentication of %s failed (wrong secret!?)", conn->initiator); retval = CHAP_AUTH_ERROR; goto out; } conn->state = CHAP_AUTH_STATE_RESPONSE; out: if (his_digest) free(his_digest); if (our_digest) free(our_digest); return retval;}static int chap_target_auth_create_response(struct connection *conn){ char chap_id, *value, *response = NULL; u8 *challenge = NULL, *digest = NULL; int encoding_format, response_len; int challenge_len = 0, digest_len = 0, retval = 0; char pass[ISCSI_NAME_LEN], name[ISCSI_NAME_LEN]; if (!(value = text_key_find(conn, "CHAP_I"))) { /* initiator doesn't want target auth!? */ conn->state = STATE_SECURITY_DONE; retval = 0; goto out; } chap_id = strtol(value, &value, 10); memset(pass, 0, sizeof(pass)); memset(name, 0, sizeof(name)); if (cops->account_query(conn->tid, AUTH_DIR_OUTGOING, name, pass) < 0) { log_warning("CHAP target auth.: " "no outgoing credentials configured%s", conn->tid ? "." : " for discovery."); retval = CHAP_AUTH_ERROR; goto out; } if (!(value = text_key_find(conn, "CHAP_C"))) { log_warning("CHAP target auth.: " "got no challenge from initiator %s", conn->initiator); retval = CHAP_INITIATOR_ERROR; goto out; } if ((encoding_format = chap_check_encoding_format(value)) < 0) { retval = CHAP_INITIATOR_ERROR; goto out; } retval = chap_alloc_decode_buffer(value, &challenge, encoding_format); if (retval <= 0) goto out; else if (retval > 1024) { log_warning("CHAP target auth.: " "initiator %s sent challenge of invalid length %d", conn->initiator, challenge_len); retval = CHAP_INITIATOR_ERROR; goto out; } challenge_len = retval; retval = 0; switch (conn->auth.chap.digest_alg) { case CHAP_DIGEST_ALG_MD5: digest_len = CHAP_MD5_DIGEST_LEN; break; case CHAP_DIGEST_ALG_SHA1: digest_len = CHAP_SHA1_DIGEST_LEN; break; default: retval = CHAP_TARGET_ERROR; goto out; } if (encoding_format == HEX_FORMAT) response_len = 2 * digest_len; else response_len = ((digest_len - 1) / 3 + 1) * 4; //"0x" / "0b" and "\0": response_len += 3; if (!(digest = malloc(digest_len))) { retval = CHAP_TARGET_ERROR; goto out; } if (!(response = malloc(response_len))) { retval = CHAP_TARGET_ERROR; goto out; } if (chap_decode_string(value, challenge, challenge_len, encoding_format) < 0) { retval = CHAP_INITIATOR_ERROR; goto out; } /* RFC 3720, 8.2.1: CHAP challenges MUST NOT be reused */ if (challenge_len == conn->auth.chap.challenge_size) { if (!memcmp(challenge, conn->auth.chap.challenge, challenge_len)) { //FIXME: RFC 3720 demands to close TCP conn. log_warning("CHAP target auth.: " "initiator %s reflected our challenge", conn->initiator); retval = CHAP_INITIATOR_ERROR; goto out; } } switch (conn->auth.chap.digest_alg) { case CHAP_DIGEST_ALG_MD5: chap_calc_digest_md5(chap_id, pass, strlen(pass), challenge, challenge_len, digest); break; case CHAP_DIGEST_ALG_SHA1: chap_calc_digest_sha1(chap_id, pass, strlen(pass), challenge, challenge_len, digest); break; default: retval = CHAP_TARGET_ERROR; goto out; } memset(response, 0x0, response_len); chap_encode_string(digest, digest_len, response, encoding_format); text_key_add(conn, "CHAP_N", name); text_key_add(conn, "CHAP_R", response); conn->state = STATE_SECURITY_DONE; out: if (challenge) free(challenge); if (digest) free(digest); if (response) free(response); return retval;}int cmnd_exec_auth_chap(struct connection *conn){ int res; switch(conn->auth_state) { case CHAP_AUTH_STATE_START: res = chap_initiator_auth_create_challenge(conn); break; case CHAP_AUTH_STATE_CHALLENGE: res = chap_initiator_auth_check_response(conn); if (res < 0) break; /* fall through */ case CHAP_AUTH_STATE_RESPONSE: res = chap_target_auth_create_response(conn); break; default: log_error("%s(%d): BUG. unknown conn->auth_state %d", __FUNCTION__, __LINE__, conn->auth_state); res = CHAP_TARGET_ERROR; } return res;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -