emqx_utils_scram.erl 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. %%--------------------------------------------------------------------
  2. %% Copyright (c) 2021-2024 EMQ Technologies Co., Ltd. All Rights Reserved.
  3. %%
  4. %% Licensed under the Apache License, Version 2.0 (the "License");
  5. %% you may not use this file except in compliance with the License.
  6. %% You may obtain a copy of the License at
  7. %%
  8. %% http://www.apache.org/licenses/LICENSE-2.0
  9. %%
  10. %% Unless required by applicable law or agreed to in writing, software
  11. %% distributed under the License is distributed on an "AS IS" BASIS,
  12. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. %% See the License for the specific language governing permissions and
  14. %% limitations under the License.
  15. %%--------------------------------------------------------------------
  16. -module(emqx_utils_scram).
  17. -export([authenticate/7]).
  18. %%------------------------------------------------------------------------------
  19. %% Authentication
  20. %%------------------------------------------------------------------------------
  21. authenticate(AuthMethod, AuthData, AuthCache, Conf, RetrieveFun, OnErrFun, ResultKeys) ->
  22. case ensure_auth_method(AuthMethod, AuthData, Conf) of
  23. true ->
  24. case AuthCache of
  25. #{next_step := client_final} ->
  26. check_client_final_message(AuthData, AuthCache, Conf, OnErrFun, ResultKeys);
  27. _ ->
  28. check_client_first_message(AuthData, AuthCache, Conf, RetrieveFun, OnErrFun)
  29. end;
  30. false ->
  31. ignore
  32. end.
  33. ensure_auth_method(_AuthMethod, undefined, _Conf) ->
  34. false;
  35. ensure_auth_method(<<"SCRAM-SHA-256">>, _AuthData, #{algorithm := sha256}) ->
  36. true;
  37. ensure_auth_method(<<"SCRAM-SHA-512">>, _AuthData, #{algorithm := sha512}) ->
  38. true;
  39. ensure_auth_method(_AuthMethod, _AuthData, _Conf) ->
  40. false.
  41. check_client_first_message(
  42. Bin, _Cache, #{iteration_count := IterationCount}, RetrieveFun, OnErrFun
  43. ) ->
  44. case
  45. sasl_auth_scram:check_client_first_message(
  46. Bin,
  47. #{
  48. iteration_count => IterationCount,
  49. retrieve => RetrieveFun
  50. }
  51. )
  52. of
  53. {continue, ServerFirstMessage, Cache} ->
  54. {continue, ServerFirstMessage, Cache};
  55. ignore ->
  56. ignore;
  57. {error, Reason} ->
  58. OnErrFun("check_client_first_message_error", Reason),
  59. {error, not_authorized}
  60. end.
  61. check_client_final_message(Bin, Cache, #{algorithm := Alg}, OnErrFun, ResultKeys) ->
  62. case
  63. sasl_auth_scram:check_client_final_message(
  64. Bin,
  65. Cache#{algorithm => Alg}
  66. )
  67. of
  68. {ok, ServerFinalMessage} ->
  69. {ok, maps:with(ResultKeys, Cache), ServerFinalMessage};
  70. {error, Reason} ->
  71. OnErrFun("check_client_final_message_error", Reason),
  72. {error, not_authorized}
  73. end.