void old_nt_password_hash_encrypted_with_new_nt_password_hash( const u8 *new_password, size_t new_password_len, const u8 *old_password, size_t old_password_len, u8 *encrypted_password_hash) { u8 old_password_hash[16], new_password_hash[16]; nt_password_hash(old_password, old_password_len, old_password_hash); nt_password_hash(new_password, new_password_len, new_password_hash); nt_password_hash_encrypted_with_block(old_password_hash, new_password_hash, encrypted_password_hash); }
/** * old_nt_password_hash_encrypted_with_new_nt_password_hash - OldNtPasswordHashEncryptedWithNewNtPasswordHash() - RFC 2759, Sect. 8.12 * @new_password: 0-to-256-unicode-char NewPassword (IN; ASCII) * @new_password_len: Length of new_password * @old_password: 0-to-256-unicode-char OldPassword (IN; ASCII) * @old_password_len: Length of old_password * @encrypted_password_hash: 16-octet EncryptedPasswordHash (OUT) * Returns: 0 on success, -1 on failure */ int old_nt_password_hash_encrypted_with_new_nt_password_hash( const u8 *new_password, size_t new_password_len, const u8 *old_password, size_t old_password_len, u8 *encrypted_password_hash) { u8 old_password_hash[16], new_password_hash[16]; if (nt_password_hash(old_password, old_password_len, old_password_hash) || nt_password_hash(new_password, new_password_len, new_password_hash)) return -1; nt_password_hash_encrypted_with_block(old_password_hash, new_password_hash, encrypted_password_hash); return 0; }
static struct wpabuf * eap_mschapv2_change_password( struct eap_sm *sm, struct eap_mschapv2_data *data, struct eap_method_ret *ret, const struct eap_mschapv2_hdr *req, u8 id) { struct wpabuf *resp; int ms_len; const u8 *username, *password, *new_password; size_t username_len, password_len, new_password_len; struct eap_mschapv2_hdr *ms; struct ms_change_password *cp; u8 password_hash[16], password_hash_hash[16]; int pwhash; username = eap_get_config_identity(sm, &username_len); password = eap_get_config_password2(sm, &password_len, &pwhash); new_password = eap_get_config_new_password(sm, &new_password_len); if (username == NULL || password == NULL || new_password == NULL) return NULL; username = mschapv2_remove_domain(username, &username_len); ret->ignore = false; ret->methodState = METHOD_MAY_CONT; ret->decision = DECISION_COND_SUCC; ret->allowNotifications = TRUE; ms_len = sizeof(*ms) + sizeof(*cp); resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, ms_len, EAP_CODE_RESPONSE, id); if (resp == NULL) return NULL; ms = wpabuf_put(resp, sizeof(*ms)); ms->op_code = MSCHAPV2_OP_CHANGE_PASSWORD; ms->mschapv2_id = req->mschapv2_id + 1; WPA_PUT_BE16(ms->ms_length, ms_len); cp = wpabuf_put(resp, sizeof(*cp)); if (pwhash) { if (encrypt_pw_block_with_password_hash( new_password, new_password_len, password, cp->encr_password)) goto fail; } else { if (new_password_encrypted_with_old_nt_password_hash( new_password, new_password_len, password, password_len, cp->encr_password)) goto fail; } if (pwhash) { u8 new_password_hash[16]; nt_password_hash(new_password, new_password_len, new_password_hash); nt_password_hash_encrypted_with_block(password, new_password_hash, cp->encr_hash); } else { old_nt_password_hash_encrypted_with_new_nt_password_hash( new_password, new_password_len, password, password_len, cp->encr_hash); } if (random_get_bytes(cp->peer_challenge, MSCHAPV2_CHAL_LEN)) goto fail; os_memset(cp->reserved, 0, 8); generate_nt_response(data->passwd_change_challenge, cp->peer_challenge, username, username_len, new_password, new_password_len, cp->nt_response); generate_authenticator_response(new_password, new_password_len, cp->peer_challenge, data->passwd_change_challenge, username, username_len, cp->nt_response, data->auth_response); data->auth_response_valid = 1; nt_password_hash(new_password, new_password_len, password_hash); hash_nt_password_hash(password_hash, password_hash_hash); get_master_key(password_hash_hash, cp->nt_response, data->master_key); data->master_key_valid = 1; os_memset(cp->flags, 0, 2); return resp; fail: wpabuf_free(resp); return NULL; }
static struct wpabuf * eap_mschapv2_change_password( struct eap_sm *sm, struct eap_mschapv2_data *data, struct eap_method_ret *ret, const struct eap_mschapv2_hdr *req, u8 id) { struct wpabuf *resp; int ms_len; const u8 *username, *password, *new_password; size_t username_len, password_len, new_password_len; struct eap_mschapv2_hdr *ms; struct ms_change_password *cp; u8 password_hash[16], password_hash_hash[16]; int pwhash; username = eap_get_config_identity(sm, &username_len); password = eap_get_config_password2(sm, &password_len, &pwhash); new_password = eap_get_config_new_password(sm, &new_password_len); if (username == NULL || password == NULL || new_password == NULL) return NULL; username = mschapv2_remove_domain(username, &username_len); ret->ignore = FALSE; ret->methodState = METHOD_MAY_CONT; ret->decision = DECISION_COND_SUCC; ret->allowNotifications = TRUE; ms_len = sizeof(*ms) + sizeof(*cp); resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, ms_len, EAP_CODE_RESPONSE, id); if (resp == NULL) return NULL; ms = wpabuf_put(resp, sizeof(*ms)); ms->op_code = MSCHAPV2_OP_CHANGE_PASSWORD; ms->mschapv2_id = req->mschapv2_id + 1; WPA_PUT_BE16(ms->ms_length, ms_len); cp = wpabuf_put(resp, sizeof(*cp)); /* Encrypted-Password */ if (pwhash) { if (encrypt_pw_block_with_password_hash( new_password, new_password_len, password, cp->encr_password)) goto fail; } else { if (new_password_encrypted_with_old_nt_password_hash( new_password, new_password_len, password, password_len, cp->encr_password)) goto fail; } /* Encrypted-Hash */ if (pwhash) { u8 new_password_hash[16]; nt_password_hash(new_password, new_password_len, new_password_hash); nt_password_hash_encrypted_with_block(password, new_password_hash, cp->encr_hash); } else { old_nt_password_hash_encrypted_with_new_nt_password_hash( new_password, new_password_len, password, password_len, cp->encr_hash); } /* Peer-Challenge */ if (random_get_bytes(cp->peer_challenge, MSCHAPV2_CHAL_LEN)) goto fail; /* Reserved, must be zero */ os_memset(cp->reserved, 0, 8); /* NT-Response */ wpa_hexdump(MSG_DEBUG, "EAP-MSCHAPV2: auth_challenge", data->passwd_change_challenge, PASSWD_CHANGE_CHAL_LEN); wpa_hexdump(MSG_DEBUG, "EAP-MSCHAPV2: peer_challenge", cp->peer_challenge, MSCHAPV2_CHAL_LEN); wpa_hexdump_ascii(MSG_DEBUG, "EAP-MSCHAPV2: username", username, username_len); wpa_hexdump_ascii_key(MSG_DEBUG, "EAP-MSCHAPV2: new password", new_password, new_password_len); generate_nt_response(data->passwd_change_challenge, cp->peer_challenge, username, username_len, new_password, new_password_len, cp->nt_response); wpa_hexdump(MSG_DEBUG, "EAP-MSCHAPV2: NT-Response", cp->nt_response, MSCHAPV2_NT_RESPONSE_LEN); /* Authenticator response is not really needed yet, but calculate it * here so that challenges need not be saved. */ generate_authenticator_response(new_password, new_password_len, cp->peer_challenge, data->passwd_change_challenge, username, username_len, cp->nt_response, data->auth_response); data->auth_response_valid = 1; /* Likewise, generate master_key here since we have the needed data * available. */ nt_password_hash(new_password, new_password_len, password_hash); hash_nt_password_hash(password_hash, password_hash_hash); get_master_key(password_hash_hash, cp->nt_response, data->master_key); data->master_key_valid = 1; /* Flags */ os_memset(cp->flags, 0, 2); wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: TX identifier %d mschapv2_id %d " "(change pw)", id, ms->mschapv2_id); return resp; fail: wpabuf_free(resp); return NULL; }