Просмотр исходного кода

chore(plugins): rm emqx-sasl plugin

Turtle 4 лет назад
Родитель
Сommit
8a3ac7c878

+ 0 - 26
apps/emqx_sasl/.gitignore

@@ -1,26 +0,0 @@
-.eunit
-deps
-*.o
-*.beam
-*.plt
-erl_crash.dump
-ebin
-rel/example_project
-.concrete/DEV_MODE
-.rebar
-data/
-*.swp
-*.swo
-.erlang.mk/
-emqx_sasl.d
-erlang.mk
-rebar3.crashdump
-_build
-cover/
-ct.coverdata
-eunit.coverdata
-logs/
-rebar.lock
-test/ct.cover.spec
-etc/emqx_sasl.conf.rendered
-.rebar3/

+ 0 - 2
apps/emqx_sasl/README.md

@@ -1,2 +0,0 @@
-# emqx-sasl
-Simple Authentication and Security Layer

+ 0 - 0
apps/emqx_sasl/etc/emqx_sasl.conf


+ 0 - 19
apps/emqx_sasl/include/emqx_sasl.hrl

@@ -1,19 +0,0 @@
-%%--------------------------------------------------------------------
-%% Copyright (c) 2020-2021 EMQ Technologies Co., Ltd. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%%     http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%--------------------------------------------------------------------
-
--define(APP, emqx_sasl).
-
--define(SCRAM_AUTH_TAB, scram_auth).

+ 0 - 0
apps/emqx_sasl/priv/emqx_sasl.schema


+ 0 - 19
apps/emqx_sasl/rebar.config

@@ -1,19 +0,0 @@
-{deps,
- [{pbkdf2, {git, "https://github.com/emqx/erlang-pbkdf2.git", {branch, "2.0.4"}}}
- ]}.
-
-{edoc_opts, [{preprocess, true}]}.
-{erl_opts, [warn_unused_vars,
-            warn_shadow_vars,
-            warnings_as_errors,
-            warn_unused_import,
-            warn_obsolete_guard,
-            debug_info,
-            {parse_transform}]}.
-
-{xref_checks, [undefined_function_calls, undefined_functions,
-               locals_not_used, deprecated_function_calls,
-               warnings_as_errors, deprecated_functions]}.
-{cover_enabled, true}.
-{cover_opts, [verbose]}.
-{cover_export_enabled, true}.

+ 0 - 14
apps/emqx_sasl/src/emqx_sasl.app.src

@@ -1,14 +0,0 @@
-{application, emqx_sasl,
- [{description, "EMQ X SASL"},
-  {vsn, "4.3.1"}, % strict semver, bump manually!
-  {modules, []},
-  {registered, [emqx_sasl_sup]},
-  {applications, [kernel,stdlib,pbkdf2]},
-  {mod, {emqx_sasl_app,[]}},
-  {env, []},
-  {licenses, ["Apache-2.0"]},
-  {maintainers, ["EMQ X Team <contact@emqx.io>"]},
-  {links, [{"Homepage", "https://emqx.io/"},
-           {"Github", "https://github.com/emqx/emqx-sasl"}
-          ]}
- ]}.

+ 0 - 13
apps/emqx_sasl/src/emqx_sasl.appup.src

@@ -1,13 +0,0 @@
-%% -*-: erlang -*-
-{VSN,
- [
-   {"4.3.0", [
-     {restart_application, emqx_sasl}
-   ]}
- ],
- [
-   {"4.3.0", [
-     {restart_application, emqx_sasl}
-   ]}
- ]
-}.

+ 0 - 56
apps/emqx_sasl/src/emqx_sasl.erl

@@ -1,56 +0,0 @@
-%%--------------------------------------------------------------------
-%% Copyright (c) 2020-2021 EMQ Technologies Co., Ltd. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%%     http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%--------------------------------------------------------------------
-
--module(emqx_sasl).
-
--include_lib("emqx/include/logger.hrl").
-
--export([ load/0
-        , unload/0
-        , init/0
-        , check/3
-        , supported/0
-        ]).
-
-load() ->
-    emqx:hook('client.enhanced_authenticate', {?MODULE, check, []}).
-
-unload() ->
-    emqx:unhook('client.enhanced_authenticate', {?MODULE, check}).
-
-init() ->
-    emqx_sasl_scram:init().
-
-check(Method, Data, Cache) ->
-    try
-        case Method of
-            <<"SCRAM-SHA-1">> ->
-                case emqx_sasl_scram:check(Data, Cache) of
-                    {ok, NData, NCache} -> {ok, {ok, NData, NCache}};
-                    {continue, NData, NCache} -> {ok, {continue, NData, NCache}};
-                    Re -> {stop, Re}
-                end;
-            _ ->
-                {error, unsupported_mechanism}
-        end
-    catch
-        _Class:_Reason:Stack ->
-            ?LOG(error, "[emqx_sasl] authentication failed: ~0p", [Stack]),
-            {error, authentication_failed}
-    end.
-
-supported() ->
-    [<<"SCRAM-SHA-1">>].

+ 0 - 227
apps/emqx_sasl/src/emqx_sasl_api.erl

@@ -1,227 +0,0 @@
-%%--------------------------------------------------------------------
-%% Copyright (c) 2020-2021 EMQ Technologies Co., Ltd. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%%     http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%--------------------------------------------------------------------
-
--module(emqx_sasl_api).
-
--include("emqx_sasl.hrl").
-
--import(minirest, [ return/0
-                  , return/1
-                  ]).
-
--rest_api(#{name   => add,
-            method => 'POST',
-            path   => "/sasl",
-            func   => add,
-            descr  => "Add authentication information"}).
-
--rest_api(#{name   => delete,
-            method => 'DELETE',
-            path   => "/sasl",
-            func   => delete,
-            descr  => "Delete authentication information"}).
-
--rest_api(#{name   => update,
-            method => 'PUT',
-            path   => "/sasl",
-            func   => update,
-            descr  => "Update authentication information"}).
-
--rest_api(#{name   => get,
-            method => 'GET',
-            path   => "/sasl",
-            func   => get,
-            descr  => "Get authentication information"}).
-
--export([ add/2
-        , delete/2
-        , update/2
-        , get/2
-        ]).
-
-add(_Bindings, Params) ->
-    case pipeline([fun ensure_required_add_params/1,
-                   fun validate_params/1,
-                   fun do_add/1], Params) of
-        ok ->
-            return();
-        {error, Reason} ->
-            return({error, Reason})
-    end.
-
-delete(_Bindings, Params) ->
-    case pipeline([fun ensure_required_delete_params/1,
-                   fun validate_params/1,
-                   fun do_delete/1], Params) of
-        ok ->
-            return();
-        {error, Reason} ->
-            return({error, Reason})
-    end.
-
-update(_Bindings, Params) ->
-    case pipeline([fun ensure_required_add_params/1,
-                   fun validate_params/1,
-                   fun do_update/1], Params) of
-        ok ->
-            return();
-        {error, Reason} ->
-            return({error, Reason})
-    end.
-
-get(Bindings, Params) when is_list(Params) ->
-    get(Bindings, maps:from_list(Params));
-
-get(_Bindings, #{<<"mechanism">> := Mechanism0,
-                 <<"username">> := Username0}) ->
-    Mechanism = urldecode(Mechanism0),
-    Username = urldecode(Username0),
-    case Mechanism of
-        <<"SCRAM-SHA-1">> ->
-            case emqx_sasl_scram:lookup(Username) of
-                {ok, AuthInfo = #{salt := Salt}} ->
-                    return({ok, AuthInfo#{salt => base64:decode(Salt)}});
-                {error, Reason} ->
-                    return({error, Reason})
-            end;
-        _ ->
-            return({error, unsupported_mechanism})
-    end;
-get(_Bindings, #{<<"mechanism">> := Mechanism}) ->
-    case urldecode(Mechanism) of
-        <<"SCRAM-SHA-1">> ->
-            Data = #{Mechanism => mnesia:dirty_all_keys(?SCRAM_AUTH_TAB)},
-            return({ok, Data});
-        _ ->
-            return({error, <<"Unsupported mechanism">>})
-    end;
-
-get(_Bindings, _Params) ->
-    Data = lists:foldl(fun(Mechanism, Acc) ->
-                           case Mechanism of
-                               <<"SCRAM-SHA-1">> ->
-                                   [#{Mechanism => mnesia:dirty_all_keys(?SCRAM_AUTH_TAB)} | Acc]
-                           end
-                       end, [], emqx_sasl:supported()),
-    return({ok, Data}).
-
-ensure_required_add_params(Params) when is_list(Params) ->
-    case proplists:get_value(<<"mechanism">>, Params) of
-        undefined ->
-            {missing, missing_required_param};
-        Mechaism ->
-            ensure_required_add_params(Mechaism, Params)
-    end.
-
-ensure_required_add_params(<<"SCRAM-SHA-1">>, Params) ->
-    Required = [<<"username">>, <<"password">>, <<"salt">>],
-    case erlang:map_size(maps:with(Required, maps:from_list(Params))) =:= erlang:length(Required) of
-        true -> ok;
-        false -> {missing, missing_required_param}
-    end;
-ensure_required_add_params(_, _) ->
-    {error, unsupported_mechanism}.
-
-ensure_required_delete_params(Params) when is_list(Params) ->
-    case proplists:get_value(<<"mechanism">>, Params) of
-        undefined ->
-            {missing, missing_required_param};
-        Mechaism ->
-            ensure_required_delete_params(Mechaism, Params)
-    end.
-
-ensure_required_delete_params(<<"SCRAM-SHA-1">>, Params) ->
-    Required = [<<"username">>],
-    case erlang:map_size(maps:with(Required, maps:from_list(Params))) =:= erlang:length(Required) of
-        true -> ok;
-        false -> {missing, missing_required_param}
-    end;
-ensure_required_delete_params(_, _) ->
-    {error, unsupported_mechanism}.
-
-validate_params(Params) ->
-    Mechaism = proplists:get_value(<<"mechanism">>, Params),
-    validate_params(Mechaism, Params).
-
-validate_params(<<"SCRAM-SHA-1">>, []) ->
-    ok;
-validate_params(<<"SCRAM-SHA-1">>, [{<<"username">>, Username} | More]) when is_binary(Username) ->
-    validate_params(<<"SCRAM-SHA-1">>, More);
-validate_params(<<"SCRAM-SHA-1">>, [{<<"username">>, _} | _]) ->
-    {error, invalid_username};
-validate_params(<<"SCRAM-SHA-1">>, [{<<"password">>, Password} | More]) when is_binary(Password) ->
-    validate_params(<<"SCRAM-SHA-1">>, More);
-validate_params(<<"SCRAM-SHA-1">>, [{<<"password">>, _} | _]) ->
-    {error, invalid_password};
-validate_params(<<"SCRAM-SHA-1">>, [{<<"salt">>, Salt} | More]) when is_binary(Salt) ->
-    validate_params(<<"SCRAM-SHA-1">>, More);
-validate_params(<<"SCRAM-SHA-1">>, [{<<"salt">>, _} | _]) ->
-    {error, invalid_salt};
-validate_params(<<"SCRAM-SHA-1">>, [{<<"iteration_count">>, IterationCount} | More]) when is_integer(IterationCount) ->
-    validate_params(<<"SCRAM-SHA-1">>, More);
-validate_params(<<"SCRAM-SHA-1">>, [{<<"iteration_count">>, _} | _]) ->
-    {error, invalid_iteration_count};
-validate_params(<<"SCRAM-SHA-1">>, [_ | More]) ->
-    validate_params(<<"SCRAM-SHA-1">>, More).
-
-do_add(Params) ->
-    Mechaism = proplists:get_value(<<"mechanism">>, Params),
-    do_add(Mechaism, Params).
-
-do_add(<<"SCRAM-SHA-1">>, Params) ->
-    Username = proplists:get_value(<<"username">>, Params),
-    Password = proplists:get_value(<<"password">>, Params),
-    Salt = proplists:get_value(<<"salt">>, Params),
-    IterationCount = proplists:get_value(<<"iteration_count">>, Params, 4096),
-    emqx_sasl_scram:add(Username, Password, Salt, IterationCount);
-do_add(_, _) ->
-    {error, unsupported_mechanism}.
-
-do_delete(Params) ->
-    Mechaism = proplists:get_value(<<"mechanism">>, Params),
-    do_delete(Mechaism, Params).
-
-do_delete(<<"SCRAM-SHA-1">>, Params) ->
-    Username = proplists:get_value(<<"username">>, Params),
-    emqx_sasl_scram:delete(Username);
-do_delete(_, _) ->
-    {error, unsupported_mechanism}.
-
-do_update(Params) ->
-    Mechaism = proplists:get_value(<<"mechanism">>, Params),
-    do_update(Mechaism, Params).
-
-do_update(<<"SCRAM-SHA-1">>, Params) ->
-    Username = proplists:get_value(<<"username">>, Params),
-    Password = proplists:get_value(<<"password">>, Params),
-    Salt = proplists:get_value(<<"salt">>, Params),
-    IterationCount = proplists:get_value(<<"iteration_count">>, Params, 4096),
-    emqx_sasl_scram:update(Username, Password, Salt, IterationCount);
-do_update(_, _) ->
-    {error, unsupported_mechanism}.
-
-pipeline([], _) ->
-    ok;
-pipeline([Fun | More], Params) ->
-    case Fun(Params) of
-        ok ->
-            pipeline(More, Params);
-        {error, Reason} ->
-            {error, Reason}
-    end.
-
-urldecode(S) ->
-    emqx_http_lib:uri_decode(S).

+ 0 - 46
apps/emqx_sasl/src/emqx_sasl_app.erl

@@ -1,46 +0,0 @@
-%%--------------------------------------------------------------------
-%% Copyright (c) 2020-2021 EMQ Technologies Co., Ltd. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%%     http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%--------------------------------------------------------------------
-
--module(emqx_sasl_app).
-
--behaviour(application).
-
--emqx_plugin(?MODULE).
-
--export([ start/2
-        , stop/1
-        ]).
-
--behaviour(supervisor).
-
--export([init/1]).
-
-start(_Type, _Args) ->
-    ok = emqx_sasl:init(),
-    _ = emqx_sasl:load(),
-    emqx_sasl_cli:load(),
-    supervisor:start_link({local, ?MODULE}, ?MODULE, []).
-
-stop(_State) ->
-    emqx_sasl_cli:unload(),
-    emqx_sasl:unload().
-
-%%--------------------------------------------------------------------
-%% Dummy supervisor
-%%--------------------------------------------------------------------
-
-init([]) ->
-    {ok, { {one_for_all, 1, 10}, []} }.

+ 0 - 82
apps/emqx_sasl/src/emqx_sasl_cli.erl

@@ -1,82 +0,0 @@
-%%--------------------------------------------------------------------
-%% Copyright (c) 2020-2021 EMQ Technologies Co., Ltd. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%%     http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%--------------------------------------------------------------------
-
--module(emqx_sasl_cli).
-
--include("emqx_sasl.hrl").
-
-%% APIs
--export([ load/0
-        , unload/0
-        , cli/1
-        ]).
-
-load() ->
-    emqx_ctl:register_command(sasl, {?MODULE, cli}, []).
-
-unload() ->
-    emqx_ctl:unregister_command(sasl).
-
-cli(["scram", "add", Username, Password, Salt]) ->
-    cli(["scram", "add", Username, Password, Salt, "4096"]);
-cli(["scram", "add", Username, Password, Salt, IterationCount]) ->
-    case emqx_sasl_scram:add(list_to_binary(Username),
-                                list_to_binary(Password),
-                                list_to_binary(Salt),
-                                list_to_integer(IterationCount)) of
-        ok ->
-            emqx_ctl:print("Authentication information added successfully~n");
-        {error, already_existed} ->
-            emqx_ctl:print("Authentication information already exists~n")
-    end;
-
-cli(["scram", "delete", Username0]) ->
-    Username = list_to_binary(Username0),
-    ok = emqx_sasl_scram:delete(Username),
-    emqx_ctl:print("Authentication information deleted successfully~n");
-
-cli(["scram", "update", Username, Password, Salt]) ->
-    cli(["scram", "update", Username, Password, Salt, "4096"]); 
-cli(["scram", "update", Username, Password, Salt, IterationCount]) ->
-    case emqx_sasl_scram:update(list_to_binary(Username),
-                                list_to_binary(Password),
-                                list_to_binary(Salt),
-                                list_to_integer(IterationCount)) of
-        ok ->
-            emqx_ctl:print("Authentication information updated successfully~n");
-        {error, not_found} ->
-            emqx_ctl:print("Authentication information not found~n")
-    end;
-
-cli(["scram", "lookup", Username0]) ->
-    Username = list_to_binary(Username0),
-    case emqx_sasl_scram:lookup(Username) of
-        {ok, #{username := Username,
-                stored_key := StoredKey,
-                server_key := ServerKey,
-                salt := Salt,
-                iteration_count := IterationCount}} ->
-            emqx_ctl:print("Username: ~s, Stored Key: ~s, Server Key: ~s, Salt: ~s, Iteration Count: ~p~n",
-                            [Username, StoredKey, ServerKey, base64:decode(Salt), IterationCount]);
-        {error, not_found} ->
-            emqx_ctl:print("Authentication information not found~n")
-    end;
-
-cli(_) ->
-    emqx_ctl:usage([{"sasl scram add <Username> <Password> <Salt> [<IterationCount>]", "Add SCRAM-SHA-1 authentication information"},
-                    {"sasl scram delete <Username>", "Delete SCRAM-SHA-1 authentication information"},
-                    {"sasl scram update <Username> <Password> <Salt> [<IterationCount>]", "Update SCRAM-SHA-1 authentication information"},
-                    {"sasl scram lookup <Username>", "Check if SCRAM-SHA-1 authentication information exists"}]).

+ 0 - 310
apps/emqx_sasl/src/emqx_sasl_scram.erl

@@ -1,310 +0,0 @@
-%%--------------------------------------------------------------------
-%% Copyright (c) 2020-2021 EMQ Technologies Co., Ltd. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%%     http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%--------------------------------------------------------------------
-
--module(emqx_sasl_scram).
-
--include("emqx_sasl.hrl").
-
--export([ init/0
-        , add/3
-        , add/4
-        , update/3
-        , update/4
-        , delete/1
-        , lookup/1
-        , check/2
-        , make_client_first/1]).
-
--record(?SCRAM_AUTH_TAB, {
-            username,
-            stored_key,
-            server_key,
-            salt,
-            iteration_count :: integer()
-        }).
-
--ifdef(TEST).
--compile(export_all).
--compile(nowarn_export_all).
--endif.
-
-init() ->
-    ok = ekka_mnesia:create_table(?SCRAM_AUTH_TAB, [
-            {disc_copies, [node()]},
-            {attributes, record_info(fields, ?SCRAM_AUTH_TAB)},
-            {storage_properties, [{ets, [{read_concurrency, true}]}]}]),
-    ok = ekka_mnesia:copy_table(?SCRAM_AUTH_TAB, disc_copies).
-
-add(Username, Password, Salt) ->
-    add(Username, Password, Salt, 4096).
-
-add(Username, Password, Salt, IterationCount) ->
-    case lookup(Username) of
-        {error, not_found} ->
-            do_add(Username, Password, Salt, IterationCount);
-        _ ->
-            {error, already_existed}
-    end.
-
-update(Username, Password, Salt) ->
-    update(Username, Password, Salt, 4096).
-
-update(Username, Password, Salt, IterationCount) ->
-    case lookup(Username) of
-        {error, not_found} ->
-            {error, not_found};
-        _ ->
-            do_add(Username, Password, Salt, IterationCount)
-    end.
-
-delete(Username) ->
-    ret(mnesia:transaction(fun mnesia:delete/3, [?SCRAM_AUTH_TAB, Username, write])).
-
-lookup(Username) ->
-    case mnesia:dirty_read(?SCRAM_AUTH_TAB, Username) of
-        [#scram_auth{username = Username,
-                     stored_key = StoredKey,
-                     server_key = ServerKey,
-                     salt = Salt,
-                     iteration_count = IterationCount}] ->
-            {ok, #{username => Username,
-                   stored_key => StoredKey,
-                   server_key => ServerKey,
-                   salt => Salt,
-                   iteration_count => IterationCount}};
-        [] ->
-            {error, not_found}
-    end.
-
-do_add(Username, Password, Salt, IterationCount) ->
-    SaltedPassword = pbkdf2_sha_1(Password, Salt, IterationCount),
-    ClientKey = client_key(SaltedPassword),
-    ServerKey = server_key(SaltedPassword),
-    StoredKey = crypto:hash(sha, ClientKey),
-    AuthInfo = #scram_auth{username = Username,
-                           stored_key = base64:encode(StoredKey),
-                           server_key = base64:encode(ServerKey),
-                           salt = base64:encode(Salt),
-                           iteration_count = IterationCount},
-    ret(mnesia:transaction(fun mnesia:write/3, [?SCRAM_AUTH_TAB, AuthInfo, write])).
-
-ret({atomic, ok})     -> ok;
-ret({aborted, Error}) -> {error, Error}.
-
-check(Data, Cache) when map_size(Cache) =:= 0 ->
-    check_client_first(Data);
-check(Data, Cache) ->
-    case maps:get(next_step, Cache, undefined) of
-        undefined -> check_server_first(Data, Cache);
-        check_client_final -> check_client_final(Data, Cache);
-        check_server_final -> check_server_final(Data, Cache)
-    end.
-
-check_client_first(ClientFirst) ->
-    ClientFirstWithoutHeader = without_header(ClientFirst),
-    Attributes = parse(ClientFirstWithoutHeader),
-    Username = proplists:get_value(username, Attributes),
-    ClientNonce = proplists:get_value(nonce, Attributes),
-    case lookup(Username) of
-        {error, not_found} ->
-            {error, not_found};
-        {ok, #{stored_key := StoredKey0,
-               server_key := ServerKey0,
-               salt := Salt0,
-               iteration_count := IterationCount}} ->
-            StoredKey = base64:decode(StoredKey0), 
-            ServerKey = base64:decode(ServerKey0),
-            Salt = base64:decode(Salt0),
-            ServerNonce = nonce(),
-            Nonce = list_to_binary(binary_to_list(ClientNonce) ++ binary_to_list(ServerNonce)),
-            ServerFirst = make_server_first(Nonce, Salt, IterationCount),
-            {continue, ServerFirst, #{next_step => check_client_final,
-                                      client_first_without_header => ClientFirstWithoutHeader,
-                                      server_first => ServerFirst,
-                                      stored_key => StoredKey,
-                                      server_key => ServerKey,
-                                      nonce => Nonce}}
-    end.
-
-check_client_final(ClientFinal, #{client_first_without_header := ClientFirstWithoutHeader,
-                                  server_first := ServerFirst,
-                                  server_key := ServerKey,
-                                  stored_key := StoredKey,
-                                  nonce := OldNonce}) ->
-    ClientFinalWithoutProof = without_proof(ClientFinal),
-    Attributes = parse(ClientFinal),
-    ClientProof = base64:decode(proplists:get_value(proof, Attributes)),
-    NewNonce = proplists:get_value(nonce, Attributes),
-    Auth0 = io_lib:format("~s,~s,~s", [ClientFirstWithoutHeader, ServerFirst, ClientFinalWithoutProof]),
-    Auth = iolist_to_binary(Auth0),
-    ClientSignature = hmac(StoredKey, Auth),
-    ClientKey = crypto:exor(ClientProof, ClientSignature),
-    case NewNonce =:= OldNonce andalso crypto:hash(sha, ClientKey) =:= StoredKey of
-        true ->
-            ServerSignature = hmac(ServerKey, Auth),
-            ServerFinal = make_server_final(ServerSignature),
-            {ok, ServerFinal, #{}};
-        false ->
-            {error, invalid_client_final}
-    end.
-
-check_server_first(ServerFirst, #{password := Password,
-                                  client_first := ClientFirst}) ->
-    Attributes = parse(ServerFirst),
-    Nonce = proplists:get_value(nonce, Attributes),
-    ClientFirstWithoutHeader = without_header(ClientFirst),
-    ClientFinalWithoutProof = serialize([{channel_binding, <<"biws">>}, {nonce, Nonce}]),
-    Auth = list_to_binary(io_lib:format("~s,~s,~s", [ClientFirstWithoutHeader, ServerFirst, ClientFinalWithoutProof])),
-    Salt = base64:decode(proplists:get_value(salt, Attributes)),
-    IterationCount = binary_to_integer(proplists:get_value(iteration_count, Attributes)),
-    SaltedPassword = pbkdf2_sha_1(Password, Salt, IterationCount),
-    ClientKey = client_key(SaltedPassword),
-    StoredKey = crypto:hash(sha, ClientKey),
-    ClientSignature = hmac(StoredKey, Auth),
-    ClientProof = base64:encode(crypto:exor(ClientKey, ClientSignature)),
-    ClientFinal = serialize([{channel_binding, <<"biws">>},
-                             {nonce, Nonce},
-                             {proof, ClientProof}]),
-    {continue, ClientFinal, #{next_step => check_server_final,
-                              password => Password,
-                              client_first => ClientFirst,
-                              server_first => ServerFirst}}.
-
-check_server_final(ServerFinal, #{password := Password,
-                                  client_first := ClientFirst,
-                                  server_first := ServerFirst}) ->
-    NewAttributes = parse(ServerFinal),
-    Attributes = parse(ServerFirst),
-    Nonce = proplists:get_value(nonce, Attributes),
-    ClientFirstWithoutHeader = without_header(ClientFirst),
-    ClientFinalWithoutProof = serialize([{channel_binding, <<"biws">>}, {nonce, Nonce}]),
-    Auth = list_to_binary(io_lib:format("~s,~s,~s", [ClientFirstWithoutHeader, ServerFirst, ClientFinalWithoutProof])),
-    Salt = base64:decode(proplists:get_value(salt, Attributes)),
-    IterationCount = binary_to_integer(proplists:get_value(iteration_count, Attributes)),
-    SaltedPassword = pbkdf2_sha_1(Password, Salt, IterationCount),
-    ServerKey = server_key(SaltedPassword),
-    ServerSignature = hmac(ServerKey, Auth),
-    case base64:encode(ServerSignature) =:= proplists:get_value(verifier, NewAttributes) of
-        true ->
-            {ok, <<>>, #{}};
-        false -> 
-            {stop, invalid_server_final}
-    end.
-
-make_client_first(Username) ->
-    list_to_binary("n,," ++ binary_to_list(serialize([{username, Username}, {nonce, nonce()}]))).
-
-make_server_first(Nonce, Salt, IterationCount) ->
-    serialize([{nonce, Nonce}, {salt, base64:encode(Salt)}, {iteration_count, IterationCount}]).
-
-make_server_final(ServerSignature) ->
-    serialize([{verifier, base64:encode(ServerSignature)}]).
-
-nonce() ->
-    base64:encode([$a + rand:uniform(26) || _ <- lists:seq(1, 10)]).
-
-pbkdf2_sha_1(Password, Salt, IterationCount) ->
-    {ok, Bin} = pbkdf2:pbkdf2(sha, Password, Salt, IterationCount),
-    pbkdf2:to_hex(Bin).
-
--if(?OTP_RELEASE >= 23).
-hmac(Key, Data) ->
-    HMAC = crypto:mac_init(hmac, sha, Key),
-    HMAC1 = crypto:mac_update(HMAC, Data),
-    crypto:mac_final(HMAC1).
--else.
-hmac(Key, Data) ->
-    HMAC = crypto:hmac_init(sha, Key),
-    HMAC1 = crypto:hmac_update(HMAC, Data),
-    crypto:hmac_final(HMAC1).
--endif.
-
-client_key(SaltedPassword) ->
-    hmac(<<"Client Key">>, SaltedPassword).
-
-server_key(SaltedPassword) ->
-    hmac(<<"Server Key">>, SaltedPassword).
-
-without_header(<<"n,,", ClientFirstWithoutHeader/binary>>) ->
-    ClientFirstWithoutHeader;
-without_header(<<GS2CbindFlag:1/binary, _/binary>>) ->
-    error({unsupported_gs2_cbind_flag, binary_to_atom(GS2CbindFlag, utf8)}).
-
-without_proof(ClientFinal) ->
-    [ClientFinalWithoutProof | _] = binary:split(ClientFinal, <<",p=">>, [global, trim_all]),
-    ClientFinalWithoutProof.
-
-parse(Message) ->
-    Attributes = binary:split(Message, <<$,>>, [global, trim_all]),
-    lists:foldl(fun(<<Key:1/binary, "=", Value/binary>>, Acc) ->
-                    [{to_long(Key), Value} | Acc]
-                end, [], Attributes).
-
-serialize(Attributes) ->
-    iolist_to_binary(
-        lists:foldl(fun({Key, Value}, []) ->
-                        [to_short(Key), "=", to_list(Value)];
-                       ({Key, Value}, Acc) ->
-                        Acc ++ [",", to_short(Key), "=", to_list(Value)]
-                     end, [], Attributes)).
-
-to_long(<<"a">>) ->
-    authzid;
-to_long(<<"c">>) ->
-    channel_binding;
-to_long(<<"n">>) ->
-    username;
-to_long(<<"p">>) ->
-    proof;
-to_long(<<"r">>) ->
-    nonce;
-to_long(<<"s">>) ->
-    salt;
-to_long(<<"v">>) ->
-    verifier;
-to_long(<<"i">>) ->
-    iteration_count;
-to_long(_) ->
-    error(test).
-
-to_short(authzid) ->
-    "a";
-to_short(channel_binding) ->
-    "c";
-to_short(username) ->
-    "n";
-to_short(proof) ->
-    "p";
-to_short(nonce) ->
-    "r";
-to_short(salt) ->
-    "s";
-to_short(verifier) ->
-    "v";
-to_short(iteration_count) ->
-    "i";
-to_short(_) ->
-    error(test).
-
-to_list(V) when is_binary(V) ->
-    binary_to_list(V);
-to_list(V) when is_list(V) ->
-    V;
-to_list(V) when is_integer(V) ->
-    integer_to_list(V);
-to_list(_) ->
-    error(bad_type).
-

+ 0 - 140
apps/emqx_sasl/test/emqx_sasl_scram_SUITE.erl

@@ -1,140 +0,0 @@
-%%--------------------------------------------------------------------
-%% Copyright (c) 2020-2021 EMQ Technologies Co., Ltd. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%%     http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%--------------------------------------------------------------------
-
--module(emqx_sasl_scram_SUITE).
-
--compile(export_all).
--compile(nowarn_export_all).
-
--include_lib("common_test/include/ct.hrl").
--include_lib("eunit/include/eunit.hrl").
-
-init_per_suite(Config) ->
-    emqx_ct_helpers:start_apps([emqx_sasl]),
-    Config.
-
-end_per_suite(_Config) ->
-    emqx_ct_helpers:stop_apps([]).
-
-all() -> emqx_ct:all(?MODULE).
-
-t_crud(_) ->
-    Username = <<"test">>,
-    Password = <<"public">>,
-    Salt = <<"emqx">>,
-    IterationCount = 4096,
-    EncodedSalt = base64:encode(Salt),
-    SaltedPassword = emqx_sasl_scram:pbkdf2_sha_1(Password, Salt, IterationCount),
-    ClientKey = emqx_sasl_scram:client_key(SaltedPassword),
-    ServerKey = base64:encode(emqx_sasl_scram:server_key(SaltedPassword)),
-    StoredKey = base64:encode(crypto:hash(sha, ClientKey)),
-
-    {error, not_found} = emqx_sasl_scram:lookup(Username),
-    ok = emqx_sasl_scram:add(Username, Password, Salt),
-    {error, already_existed} = emqx_sasl_scram:add(Username, Password, Salt),
-
-    {ok, #{username := Username,
-           stored_key := StoredKey,
-           server_key := ServerKey,
-           salt := EncodedSalt,
-           iteration_count := IterationCount}} = emqx_sasl_scram:lookup(Username),
-
-    NewSalt = <<"new salt">>,
-    NewEncodedSalt = base64:encode(NewSalt),
-    emqx_sasl_scram:update(Username, Password, NewSalt),
-    {ok, #{username := Username,
-           salt := NewEncodedSalt}} = emqx_sasl_scram:lookup(Username),
-    emqx_sasl_scram:delete(Username),
-    {error, not_found} = emqx_sasl_scram:lookup(Username).
-
-t_scram(_) ->
-    AuthMethod = <<"SCRAM-SHA-1">>,
-    [AuthMethod] = emqx_sasl:supported(),
-
-    Username = <<"test">>,
-    Password = <<"public">>,
-    Salt = <<"emqx">>,
-    ok = emqx_sasl_scram:add(Username, Password, Salt),
-    ClientFirst = emqx_sasl_scram:make_client_first(Username),
-
-    {ok, {continue, ServerFirst, Cache}} = emqx_sasl:check(AuthMethod, ClientFirst, #{}),
-
-    {ok, {continue, ClientFinal, ClientCache}} = emqx_sasl:check(AuthMethod, ServerFirst, #{password => Password, client_first => ClientFirst}),
-
-    {ok, {ok, ServerFinal, #{}}} = emqx_sasl:check(AuthMethod, ClientFinal, Cache),
-
-    {ok, _} = emqx_sasl:check(AuthMethod, ServerFinal, ClientCache).
-
-%t_proto(_) ->
-%    process_flag(trap_exit, true),
-%
-%    Username = <<"username">>,
-%    Password = <<"password">>,
-%    Salt = <<"emqx">>,
-%    AuthMethod = <<"SCRAM-SHA-1">>,
-%
-%    {ok, Client0} = emqtt:start_link([{clean_start, true},
-%                                     {proto_ver, v5},
-%                                     {enhanced_auth, #{method => AuthMethod,
-%                                                       params => #{username => Username,
-%                                                                   password => Password,
-%                                                                   salt => Salt}}},
-%                                     {connect_timeout, 6000}]),
-%    {error,{not_authorized,#{}}} = emqtt:connect(Client0),
-%
-%    ok = emqx_sasl_scram:add(Username, Password, Salt),
-%    {ok, Client1} = emqtt:start_link([{clean_start, true},
-%                                     {proto_ver, v5},
-%                                     {enhanced_auth, #{method => AuthMethod,
-%                                                       params => #{username => Username,
-%                                                                   password => Password,
-%                                                                   salt => Salt}}},
-%                                     {connect_timeout, 6000}]),
-%    {ok, _} = emqtt:connect(Client1),
-%
-%    timer:sleep(200),
-%    ok = emqtt:reauthentication(Client1, #{params => #{username => Username,
-%                                                       password => Password,
-%                                                       salt => Salt}}),
-%
-%    timer:sleep(200),
-%    ErrorFun = fun (_State) -> {ok, <<>>, #{}} end,
-%    ok = emqtt:reauthentication(Client1, #{params => #{},function => ErrorFun}),
-%    receive
-%        {disconnected,ReasonCode2,#{}} ->
-%            ?assertEqual(ReasonCode2, 135)
-%    after 500 ->
-%        error("emqx re-authentication failed")
-%    end,
-%
-%    {ok, Client2} = emqtt:start_link([{clean_start, true},
-%                                     {proto_ver, v5},
-%                                     {enhanced_auth, #{method => AuthMethod,
-%                                                       params => #{},
-%                                                       function =>fun (_State) -> {ok, <<>>, #{}} end}},
-%                                     {connect_timeout, 6000}]),
-%    {error,{not_authorized,#{}}} = emqtt:connect(Client2),
-%
-%    receive_msg(),
-%    process_flag(trap_exit, false).
-
-receive_msg() ->
-    receive
-        {'EXIT', Msg} -> 
-            ct:print("==========+~p~n", [Msg]), 
-            receive_msg()
-    after 200 -> ok
-    end.

+ 0 - 1
rebar.config.erl

@@ -280,7 +280,6 @@ relx_plugin_apps(ReleaseType) ->
     , emqx_authentication
     , emqx_web_hook
     , emqx_rule_engine
-    , emqx_sasl
     , emqx_statsd
     ]
     ++ relx_plugin_apps_per_rel(ReleaseType)