Skip to content

Commit

Permalink
Accept expired credentials for TURN refreshes
Browse files Browse the repository at this point in the history
If the authentication function tags the returned password as 'expired',
let the behavior depend on the context: reject initial TURN allocation
but (if the credentials are valid otherwise) accept session refreshes.
Otherwise, the expiry timestamp of ephemeral credentials would impose a
hard limit on the call time, which may not be desired.
  • Loading branch information
weiss committed Jan 5, 2022
1 parent 4e4fe77 commit b8762e6
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 10 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Version 1.2.0

* Allow for whitelisting IP addresses/subnets.
* Accept expired credentials for TURN session refreshes.

# Version 1.1.0

Expand Down
37 changes: 27 additions & 10 deletions src/stun.erl
Original file line number Diff line number Diff line change
Expand Up @@ -244,12 +244,13 @@ process(#state{auth = user} = State,
<<"">> ->
?LOG_NOTICE("Failed long-term STUN/TURN authentication"),
send(NewState, R);
Pass ->
Pass0 ->
{Pass, IsExpired} = check_expired_tag(Pass0),
case check_integrity(User, Realm, Msg, Pass) of
{true, Key} ->
?LOG_INFO("Accepting long-term STUN/TURN "
"authentication"),
process(NewState, Msg, Key);
process(NewState, Msg, Key, IsExpired);
false ->
?LOG_NOTICE("Failed long-term STUN/TURN "
"authentication"),
Expand Down Expand Up @@ -288,8 +289,11 @@ process(State, Msg) when is_record(Msg, turn) ->
process(State, _Msg) ->
State.

process(State, Msg, Secret) ->
process(State, Msg, Secret, false).

process(State, #stun{class = request, unsupported = [_|_] = Unsupported} = Msg,
Secret) ->
Secret, _IsExpired) ->
?LOG_DEBUG("Rejecting request with unknown attribute(s): ~p",
[Unsupported]),
Resp = prepare_response(State, Msg),
Expand All @@ -298,7 +302,8 @@ process(State, #stun{class = request, unsupported = [_|_] = Unsupported} = Msg,
'ERROR-CODE' = stun_codec:error(420)},
send(State, R, Secret);
process(State, #stun{class = request,
method = ?STUN_METHOD_BINDING} = Msg, Secret) ->
method = ?STUN_METHOD_BINDING} = Msg, Secret,
_IsExpired) ->
Resp = prepare_response(State, Msg),
AddrPort = unmap_v4_addr(State#state.peer),
R = case stun_codec:version(Msg) of
Expand All @@ -312,21 +317,25 @@ process(State, #stun{class = request,
run_hook(stun_query, State, Msg),
send(State, R, Secret);
process(#state{use_turn = false} = State,
#stun{class = request} = Msg, Secret) ->
#stun{class = request} = Msg, Secret, _IsExpired) ->
?LOG_NOTICE("Rejecting TURN request: TURN is disabled"),
Resp = prepare_response(State, Msg),
R = Resp#stun{class = error, 'ERROR-CODE' = stun_codec:error(405)},
send(State, R, Secret);
process(State, #stun{class = request,
method = ?STUN_METHOD_ALLOCATE} = Msg,
Secret) ->
Secret, IsExpired) ->
Resp = prepare_response(State, Msg),
AddrPort = State#state.peer,
SockMod = State#state.sock_mod,
case turn_sm:find_allocation(AddrPort) of
{ok, Pid} ->
turn:route(Pid, Msg),
State;
_ when IsExpired ->
?LOG_NOTICE("Rejecting request: credentials expired"),
R = Resp#stun{class = error, 'ERROR-CODE' = stun_codec:error(401)},
send(State, R);
_ ->
Opts = [{sock, State#state.sock},
{sock_mod, SockMod},
Expand Down Expand Up @@ -373,15 +382,18 @@ process(State, #stun{class = request,
end
end;
process(State, #stun{class = request,
method = ?STUN_METHOD_REFRESH} = Msg, Secret) ->
method = ?STUN_METHOD_REFRESH} = Msg, Secret,
_IsExpired) ->
route_on_turn(State, Msg, Secret);
process(State, #stun{class = request,
method = ?STUN_METHOD_CREATE_PERMISSION} = Msg, Secret) ->
method = ?STUN_METHOD_CREATE_PERMISSION} = Msg, Secret,
_IsExpired) ->
route_on_turn(State, Msg, Secret);
process(State, #stun{class = request,
method = ?STUN_METHOD_CHANNEL_BIND} = Msg, Secret) ->
method = ?STUN_METHOD_CHANNEL_BIND} = Msg, Secret,
_IsExpired) ->
route_on_turn(State, Msg, Secret);
process(State, #stun{class = request} = Msg, Secret) ->
process(State, #stun{class = request} = Msg, Secret, _IsExpired) ->
?LOG_NOTICE("Rejecting request: Method not allowed"),
Resp = prepare_response(State, Msg),
R = Resp#stun{class = error, 'ERROR-CODE' = stun_codec:error(405)},
Expand Down Expand Up @@ -684,6 +696,11 @@ check_integrity(User, Realm, Msg, [Pass | T]) ->
check_integrity(User, Realm, Msg, T)
end.

check_expired_tag({expired, Pass}) ->
{Pass, true};
check_expired_tag(Pass) ->
{Pass, false}.

unmap_v4_addr({{0, 0, 0, 0, 0, 16#FFFF, D7, D8}, Port}) ->
{{D7 bsr 8, D7 band 255, D8 bsr 8, D8 band 255}, Port};
unmap_v4_addr(AddrPort) ->
Expand Down

0 comments on commit b8762e6

Please sign in to comment.