fix(authn): fix password hash algorithm for mysql and pgsql authn

This commit is contained in:
zhouzb 2021-07-28 14:26:26 +08:00
parent a6b95afda8
commit 76d6949cd1
4 changed files with 31 additions and 40 deletions

View File

@ -16,7 +16,7 @@
-module(emqx_authn_utils).
-export([ replace_placeholder/2
-export([ replace_placeholders/2
, gen_salt/0
]).
@ -24,23 +24,23 @@
%% APIs
%%------------------------------------------------------------------------------
replace_placeholder(PlaceHolders, Data) ->
replace_placeholder(PlaceHolders, Data, []).
replace_placeholders(PlaceHolders, Data) ->
replace_placeholders(PlaceHolders, Data, []).
replace_placeholder([], _Data, Acc) ->
replace_placeholders([], _Data, Acc) ->
lists:reverse(Acc);
replace_placeholder([<<"${mqtt-username}">> | More], #{username := Username} = Data, Acc) ->
replace_placeholder(More, Data, [convert_to_sql_param(Username) | Acc]);
replace_placeholder([<<"${mqtt-clientid}">> | More], #{clientid := ClientID} = Data, Acc) ->
replace_placeholder(More, Data, [convert_to_sql_param(ClientID) | Acc]);
replace_placeholder([<<"${ip-address}">> | More], #{peerhost := IPAddress} = Data, Acc) ->
replace_placeholder(More, Data, [convert_to_sql_param(IPAddress) | Acc]);
replace_placeholder([<<"${cert-subject}">> | More], #{dn := Subject} = Data, Acc) ->
replace_placeholder(More, Data, [convert_to_sql_param(Subject) | Acc]);
replace_placeholder([<<"${cert-common-name}">> | More], #{cn := CommonName} = Data, Acc) ->
replace_placeholder(More, Data, [convert_to_sql_param(CommonName) | Acc]);
replace_placeholder([_ | More], Data, Acc) ->
replace_placeholder(More, Data, [null | Acc]).
replace_placeholders([<<"${mqtt-username}">> | More], #{username := Username} = Data, Acc) ->
replace_placeholders(More, Data, [convert_to_sql_param(Username) | Acc]);
replace_placeholders([<<"${mqtt-clientid}">> | More], #{clientid := ClientID} = Data, Acc) ->
replace_placeholders(More, Data, [convert_to_sql_param(ClientID) | Acc]);
replace_placeholders([<<"${ip-address}">> | More], #{peerhost := IPAddress} = Data, Acc) ->
replace_placeholders(More, Data, [convert_to_sql_param(IPAddress) | Acc]);
replace_placeholders([<<"${cert-subject}">> | More], #{dn := Subject} = Data, Acc) ->
replace_placeholders(More, Data, [convert_to_sql_param(Subject) | Acc]);
replace_placeholders([<<"${cert-common-name}">> | More], #{cn := CommonName} = Data, Acc) ->
replace_placeholders(More, Data, [convert_to_sql_param(CommonName) | Acc]);
replace_placeholders([_ | More], Data, Acc) ->
replace_placeholders(More, Data, [null | Acc]).
gen_salt() ->
<<X:128/big-unsigned-integer>> = crypto:strong_rand_bytes(16),

View File

@ -46,25 +46,12 @@ fields(config) ->
, {query, fun query/1}
, {query_timeout, fun query_timeout/1}
] ++ emqx_connector_schema_lib:relational_db_fields()
++ emqx_connector_schema_lib:ssl_fields();
++ emqx_connector_schema_lib:ssl_fields().
fields(bcrypt) ->
[ {name, {enum, [bcrypt]}}
, {salt_rounds, fun salt_rounds/1}
];
fields(other_algorithms) ->
[ {name, {enum, [plain, md5, sha, sha256, sha512]}}
].
password_hash_algorithm(type) -> {union, [hoconsc:ref(bcrypt), hoconsc:ref(other_algorithms)]};
password_hash_algorithm(default) -> #{<<"name">> => sha256};
password_hash_algorithm(type) -> {enum, [plain, md5, sha, sha256, sha512, bcrypt]};
password_hash_algorithm(default) -> sha256;
password_hash_algorithm(_) -> undefined.
salt_rounds(type) -> integer();
salt_rounds(default) -> 10;
salt_rounds(_) -> undefined.
salt_position(type) -> {enum, [prefix, suffix]};
salt_position(default) -> prefix;
salt_position(_) -> undefined.
@ -118,7 +105,7 @@ authenticate(#{password := Password} = Credential,
placeholders := PlaceHolders,
query := Query,
query_timeout := Timeout} = State) ->
Params = emqx_authn_utils:replace_placeholder(PlaceHolders, Credential),
Params = emqx_authn_utils:replace_placeholders(PlaceHolders, Credential),
case emqx_resource:query(ResourceID, {sql, Query, Params, Timeout}) of
{ok, _Columns, []} -> ignore;
{ok, Columns, Rows} ->
@ -137,7 +124,7 @@ destroy(#{resource_id := ResourceID}) ->
%% Internal functions
%%------------------------------------------------------------------------------
check_password(undefined, _Algorithm, _Selected) ->
check_password(undefined, _Selected, _State) ->
{error, bad_username_or_password};
check_password(Password,
#{password_hash := Hash},

View File

@ -45,7 +45,8 @@ fields(config) ->
] ++ emqx_connector_schema_lib:relational_db_fields()
++ emqx_connector_schema_lib:ssl_fields().
password_hash_algorithm(type) -> string();
password_hash_algorithm(type) -> {enum, [plain, md5, sha, sha256, sha512, bcrypt]};
password_hash_algorithm(default) -> sha256;
password_hash_algorithm(_) -> undefined.
query(type) -> string();
@ -90,7 +91,7 @@ authenticate(#{password := Password} = Credential,
#{resource_id := ResourceID,
query := Query,
placeholders := PlaceHolders} = State) ->
Params = emqx_authn_utils:replace_placeholder(PlaceHolders, Credential),
Params = emqx_authn_utils:replace_placeholders(PlaceHolders, Credential),
case emqx_resource:query(ResourceID, {sql, Query, Params}) of
{ok, _Columns, []} -> ignore;
{ok, Columns, Rows} ->
@ -109,7 +110,7 @@ destroy(#{resource_id := ResourceID}) ->
%% Internal functions
%%------------------------------------------------------------------------------
check_password(undefined, _Algorithm, _Selected) ->
check_password(undefined, _Selected, _State) ->
{error, bad_username_or_password};
check_password(Password,
#{password_hash := Hash},

View File

@ -149,11 +149,14 @@ connect(Opts) ->
WorkerOptions = proplists:get_value(worker_options, Opts, []),
mongo_api:connect(Type, Hosts, Options, WorkerOptions).
mongo_query(Conn, find, Collection, Selector, Docs) ->
mongo_api:find(Conn, Collection, Selector, Docs);
mongo_query(Conn, find, Collection, Selector, Projector) ->
mongo_api:find(Conn, Collection, Selector, Projector);
mongo_query(Conn, find_one, Collection, Selector, Projector) ->
mongo_api:find_one(Conn, Collection, Selector, Projector);
%% Todo xxx
mongo_query(_Conn, _Action, _Collection, _Selector, _Docs) ->
mongo_query(_Conn, _Action, _Collection, _Selector, _Projector) ->
ok.
do_start(InstId, Opts0, Config = #{mongo_type := Type,