From 274122b7fc2ed5e4ec650715ad3d0ad50321cd6f Mon Sep 17 00:00:00 2001 From: Fouille Date: Sun, 3 May 2026 14:53:50 +0200 Subject: [PATCH] fix: check static credentials before shared secret for numeric usernames --- src/eturnal.erl | 43 ++++++++++++++------- test/eturnal_SUITE.erl | 9 ++++- test/eturnal_SUITE_data/eturnal-new-otp.yml | 1 + test/eturnal_SUITE_data/eturnal-old-otp.yml | 1 + 4 files changed, 37 insertions(+), 17 deletions(-) diff --git a/src/eturnal.erl b/src/eturnal.erl index d5253767e..776dc6b48 100644 --- a/src/eturnal.erl +++ b/src/eturnal.erl @@ -140,15 +140,15 @@ handle_call({set_loglevel, Level}, _From, State) -> {reply, Err, State} end; handle_call({get_password, Username}, _From, State) -> - case {get_opt(secret), is_dynamic_username(Username)} of - {[Secret | _Secrets], true} -> - Password = derive_password(Username, [Secret]), + case lookup_static_password(Username) of + {ok, Password} -> {reply, {ok, Password}, State}; - {_, _} -> - case maps:get(Username, get_opt(credentials), undefined) of - Password when is_binary(Password) -> + error -> + case {get_opt(secret), is_dynamic_username(Username)} of + {[Secret | _Secrets], true} -> + Password = derive_password(Username, [Secret]), {reply, {ok, Password}, State}; - undefined -> + {_, _} -> {reply, {error, no_credentials}, State} end end; @@ -237,6 +237,16 @@ run_hook(Event, Info) -> -spec get_password(binary(), binary()) -> binary() | [binary()] | {expired, binary() | [binary()]}. get_password(Username, _Realm) -> + case lookup_static_password(Username) of + {ok, Password} -> + ?LOG_DEBUG("Found static password for: ~ts", [Username]), + Password; + error -> + get_dynamic_password(Username) + end. + +-spec get_dynamic_password(binary()) -> binary() | [binary()] | {expired, binary() | [binary()]}. +get_dynamic_password(Username) -> [Expiration | _Suffix] = binary:split(Username, <<$:>>), try binary_to_integer(Expiration) of ExpireTime -> @@ -256,14 +266,8 @@ get_password(Username, _Realm) -> end end catch _:badarg -> - ?LOG_DEBUG("Looking up password for: ~ts", [Username]), - case maps:get(Username, get_opt(credentials), undefined) of - Password when is_binary(Password) -> - Password; - undefined -> - ?LOG_INFO("Have no password for: ~ts", [Username]), - <<>> - end + ?LOG_INFO("Have no password for: ~ts", [Username]), + <<>> end. %% API: retrieve option value. @@ -314,6 +318,15 @@ reload_config() -> %% Internal functions: authentication. +-spec lookup_static_password(binary()) -> {ok, binary()} | error. +lookup_static_password(Username) -> + case maps:get(Username, get_opt(credentials), undefined) of + Password when is_binary(Password) -> + {ok, Password}; + undefined -> + error + end. + -spec is_dynamic_username(binary()) -> boolean(). is_dynamic_username(Username) -> case string:to_integer(Username) of diff --git a/test/eturnal_SUITE.erl b/test/eturnal_SUITE.erl index c79a25974..0d58a6ec3 100644 --- a/test/eturnal_SUITE.erl +++ b/test/eturnal_SUITE.erl @@ -185,7 +185,9 @@ check_credentials(_Config) -> ct:pal("Checking invalid suffix"), {error, _Reason} = eturnal_ctl:get_credentials(Username, invalid), ct:pal("Checking static credentials"), - {ok, "l0vesBob"} = eturnal_ctl:get_password("alice"). + {ok, "l0vesBob"} = eturnal_ctl:get_password("alice"), + ct:pal("Checking numeric static credentials"), + {ok, "numericPass"} = eturnal_ctl:get_password("00002063954332"). -spec check_loglevel(config()) -> any(). check_loglevel(_Config) -> @@ -244,10 +246,13 @@ turn_udp(Config) -> Password1 = <<"l0vesBob">>, Username2 = <<"2145913200">>, Password2 = <<"cLwpKS2/9bWHf+agUImD47PIXNE=">>, + Username3 = <<"00002063954332">>, + Password3 = <<"numericPass">>, Realm = <<"eturnal.net">>, ct:pal("Allocating TURN relay on 127.0.0.1:~B (UDP)", [Port]), ok = stun_test:allocate_udp(Addr, Port, Username1, Realm, Password1), - ok = stun_test:allocate_udp(Addr, Port, Username2, Realm, Password2). + ok = stun_test:allocate_udp(Addr, Port, Username2, Realm, Password2), + ok = stun_test:allocate_udp(Addr, Port, Username3, Realm, Password3). -spec stun_udp(config()) -> any(). stun_udp(Config) -> diff --git a/test/eturnal_SUITE_data/eturnal-new-otp.yml b/test/eturnal_SUITE_data/eturnal-new-otp.yml index caf69100d..cb1448ea2 100644 --- a/test/eturnal_SUITE_data/eturnal-new-otp.yml +++ b/test/eturnal_SUITE_data/eturnal-new-otp.yml @@ -23,6 +23,7 @@ eturnal: secret: "crypt1c" credentials: alice: l0vesBob + "00002063954332": numericPass log_level: debug tls_options: - no_tlsv1 diff --git a/test/eturnal_SUITE_data/eturnal-old-otp.yml b/test/eturnal_SUITE_data/eturnal-old-otp.yml index 755b1264e..639183e91 100644 --- a/test/eturnal_SUITE_data/eturnal-old-otp.yml +++ b/test/eturnal_SUITE_data/eturnal-old-otp.yml @@ -18,6 +18,7 @@ eturnal: secret: "crypt1c" credentials: alice: l0vesBob + "00002063954332": numericPass log_level: debug tls_options: - no_tlsv1