1: -module(auth_internal_SUITE). 2: 3: -compile([export_all, nowarn_export_all]). 4: -include_lib("eunit/include/eunit.hrl"). 5: -include("scram.hrl"). 6: 7: all() -> 8: [passwords_as_records_are_still_supported, 9: passwords_in_plain_can_be_converted_to_scram]. 10: 11: init_per_suite(C) -> 12: application:ensure_all_started(jid), 13: ok = mnesia:create_schema([node()]), 14: ok = mnesia:start(), 15: ejabberd_auth_internal:start(<<"server">>), 16: C. 17: 18: end_per_suite(_C) -> 19: mnesia:stop(), 20: mnesia:delete_schema([node()]). 21: 22: passwords_as_records_are_still_supported(_C) -> 23: %% given in mnesia there is a user with password in old scram format 24: {U, S, P} = gen_user(), 25: OldScramFormat = old_password_to_scram(P, 340), 26: UserRecord = {passwd, {U, S}, OldScramFormat}, 27: mnesia:dirty_write(UserRecord), 28: %% when we read the password via ejabberd_auth_internal:get_password/3 29: NewScramMap = ejabberd_auth_internal:get_password(host_type(), U, S), 30: %% then new map with sha key is returned 31: ?assertMatch(#{iteration_count := _, 32: sha := #{salt := _, 33: server_key := _, 34: stored_key := _}}, NewScramMap), 35: %% even though in db there is old record stored 36: OldScram = mnesia:dirty_read({passwd, {U, S}}), 37: ?assertMatch([{passwd, _, {scram, _, _, _, _}}], OldScram). 38: 39: passwords_in_plain_can_be_converted_to_scram(_C) -> 40: %% Given there in mnesia there are users 41: %% with plain text password 42: {U, S, P} = gen_user(), 43: UserRecord = {passwd, {U, S}, P}, 44: mnesia:dirty_write(UserRecord), 45: %% and password in the old record format 46: {U2, S2, P2} = gen_user(), 47: OldScramFormat = old_password_to_scram(P2, 340), 48: UserRecord2 = {passwd, {U2, S2}, OldScramFormat}, 49: mnesia:dirty_write(UserRecord2), 50: %% when the migration function is run 51: ejabberd_auth_internal:scram_passwords(), 52: AfterMigrationPlain = mnesia:dirty_read({passwd, {U, S}}), 53: %% then plain text passwords are converted to new map with sha and sha256 54: ?assertMatch([{passwd, _, 55: #{iteration_count := _, 56: sha := #{salt := _, 57: server_key := _, 58: stored_key := _}, 59: sha224 := #{salt := _, 60: server_key := _, 61: stored_key := _}, 62: sha256 := #{salt := _, 63: server_key := _, 64: stored_key := _}, 65: sha384 := #{salt := _, 66: server_key := _, 67: stored_key := _}, 68: sha512 := #{salt := _, 69: server_key := _, 70: stored_key := _}}}], AfterMigrationPlain), 71: %% and the old scram format remains the same 72: AfterMigrationScram = mnesia:dirty_read({passwd, {U2, S2}}), 73: ?assertMatch([{passwd, _, 74: #{iteration_count := _, 75: sha := #{salt := _, 76: server_key := _, 77: stored_key := _}}}], AfterMigrationScram). 78: 79: gen_user() -> 80: {base64:encode(crypto:strong_rand_bytes(5)), 81: <<"server">>, 82: base64:encode(crypto:strong_rand_bytes(6))}. 83: 84: old_password_to_scram(Password, IterationCount) -> 85: Salt = crypto:strong_rand_bytes(16), 86: SaltedPassword = fast_scram:salted_password(sha, jid:resourceprep(Password), Salt, IterationCount), 87: ClientKey = fast_scram:client_key(sha, SaltedPassword), 88: StoredKey = fast_scram:stored_key(sha, ClientKey), 89: ServerKey = fast_scram:server_key(sha, SaltedPassword), 90: #scram{storedkey = base64:encode(StoredKey), 91: serverkey = base64:encode(ServerKey), 92: salt = base64:encode(Salt), 93: iterationcount = IterationCount}. 94: 95: host_type() -> 96: <<"test host type">>.