From b41c41570a1f030e8854aac52eecea257acabb25 Mon Sep 17 00:00:00 2001 From: JimMoen Date: Fri, 26 Nov 2021 15:14:53 +0800 Subject: [PATCH] fix(authz): placehodler regular escape --- apps/emqx/src/emqx_topic.erl | 1 - apps/emqx/test/emqx_topic_SUITE.erl | 5 +++-- apps/emqx_authz/README.md | 6 +++--- apps/emqx_authz/etc/emqx_authz.conf | 8 ++++---- apps/emqx_authz/src/emqx_authz.erl | 5 +++++ apps/emqx_authz/src/emqx_authz_http.erl | 14 +++++++------- apps/emqx_authz/src/emqx_authz_mongodb.erl | 6 +++--- apps/emqx_authz/src/emqx_authz_redis.erl | 9 +++++---- 8 files changed, 30 insertions(+), 24 deletions(-) diff --git a/apps/emqx/src/emqx_topic.erl b/apps/emqx/src/emqx_topic.erl index 00d26d147..5e0f2d43b 100644 --- a/apps/emqx/src/emqx_topic.erl +++ b/apps/emqx/src/emqx_topic.erl @@ -218,4 +218,3 @@ parse(TopicFilter = <<"$share/", Rest/binary>>, Options) -> end; parse(TopicFilter, Options) -> {TopicFilter, Options}. - diff --git a/apps/emqx/test/emqx_topic_SUITE.erl b/apps/emqx/test/emqx_topic_SUITE.erl index 76b95d9bc..e0d80c4a5 100644 --- a/apps/emqx/test/emqx_topic_SUITE.erl +++ b/apps/emqx/test/emqx_topic_SUITE.erl @@ -20,6 +20,7 @@ -compile(nowarn_export_all). -include_lib("eunit/include/eunit.hrl"). +-include_lib("emqx/include/emqx_placeholder.hrl"). -import(emqx_topic, [ wildcard/1 @@ -183,9 +184,9 @@ t_feed_var(_) -> ?assertEqual(<<"$queue/client/clientId">>, feed_var(<<"$c">>, <<"clientId">>, <<"$queue/client/$c">>)), ?assertEqual(<<"username/test/client/x">>, - feed_var(<<"%u">>, <<"test">>, <<"username/%u/client/x">>)), + feed_var(?PH_USERNAME, <<"test">>, <<"username/", ?PH_USERNAME/binary, "/client/x">>)), ?assertEqual(<<"username/test/client/clientId">>, - feed_var(<<"%c">>, <<"clientId">>, <<"username/test/client/%c">>)). + feed_var(?PH_CLIENTID, <<"clientId">>, <<"username/test/client/", ?PH_CLIENTID/binary>>)). long_topic() -> iolist_to_binary([[integer_to_list(I), "/"] || I <- lists:seq(0, 66666)]). diff --git a/apps/emqx_authz/README.md b/apps/emqx_authz/README.md index a44297a55..bda09481a 100644 --- a/apps/emqx_authz/README.md +++ b/apps/emqx_authz/README.md @@ -23,7 +23,7 @@ authz:{ keyfile: "etc/certs/client-key.pem" } } - sql: "select ipaddress, username, clientid, action, permission, topic from mqtt_authz where ipaddr = '%a' or username = '%u' or clientid = '%c'" + sql: "select ipaddress, username, clientid, action, permission, topic from mqtt_authz where ipaddr = ${peerhost} or username = ${username} or clientid = ${clientid}" }, { type: postgresql @@ -36,7 +36,7 @@ authz:{ auto_reconnect: true ssl: {enable: false} } - sql: "select ipaddress, username, clientid, action, permission, topic from mqtt_authz where ipaddr = '%a' or username = '%u' or username = '$all' or clientid = '%c'" + sql: "select ipaddress, username, clientid, action, permission, topic from mqtt_authz where ipaddr = ${peerhost} or username = ${username} or username = '$all' or clientid = ${clientid}" }, { type: redis @@ -48,7 +48,7 @@ authz:{ auto_reconnect: true ssl: {enable: false} } - cmd: "HGETALL mqtt_authz:%u" + cmd: "HGETALL mqtt_authz:${username}" }, { principal: {username: "^admin?"} diff --git a/apps/emqx_authz/etc/emqx_authz.conf b/apps/emqx_authz/etc/emqx_authz.conf index 3469aad3a..5bb6ab841 100644 --- a/apps/emqx_authz/etc/emqx_authz.conf +++ b/apps/emqx_authz/etc/emqx_authz.conf @@ -22,7 +22,7 @@ authorization { # certfile: "{{ platform_etc_dir }}/certs/client-cert.pem" # keyfile: "{{ platform_etc_dir }}/certs/client-key.pem" # } - # query: "select ipaddress, username, clientid, action, permission, topic from mqtt_authz where ipaddr = '%a' or username = '%u' or clientid = '%c'" + # query: "select ipaddress, username, clientid, action, permission, topic from mqtt_authz where ipaddr = ${peerhost} or username = ${username} or clientid = ${clientid}" # }, # { # type: postgresql @@ -33,7 +33,7 @@ authorization { # password: public # auto_reconnect: true # ssl: {enable: false} - # query: "select ipaddress, username, clientid, action, permission, topic from mqtt_authz where ipaddr = '%a' or username = '%u' or username = '$all' or clientid = '%c'" + # query: "select ipaddress, username, clientid, action, permission, topic from mqtt_authz where ipaddr = ${peerhost} or username = ${username} or username = '$all' or clientid = ${clientid}" # }, # { # type: redis @@ -43,7 +43,7 @@ authorization { # password: public # auto_reconnect: true # ssl: {enable: false} - # cmd: "HGETALL mqtt_authz:%u" + # cmd: "HGETALL mqtt_authz:${username}" # }, # { # type: mongodb @@ -53,7 +53,7 @@ authorization { # database: mqtt # ssl: {enable: false} # collection: mqtt_authz - # selector: { "$or": [ { "username": "%u" }, { "clientid": "%c" } ] } + # selector: { "$or": [ { "username": "${username}" }, { "clientid": "${clientid}" } ] } # }, { type: built-in-database diff --git a/apps/emqx_authz/src/emqx_authz.erl b/apps/emqx_authz/src/emqx_authz.erl index 4496e0299..a5efbe8f7 100644 --- a/apps/emqx_authz/src/emqx_authz.erl +++ b/apps/emqx_authz/src/emqx_authz.erl @@ -40,6 +40,8 @@ -export([acl_conf_file/0]). +-export([ph_to_re/1]). + -spec(register_metrics() -> ok). register_metrics() -> lists:foreach(fun emqx_metrics:ensure/1, ?AUTHZ_METRICS). @@ -386,3 +388,6 @@ type(Unknown) -> error({unknown_authz_source_type, Unknown}). % should never hap %% @doc where the acl.conf file is stored. acl_conf_file() -> filename:join([emqx:data_dir(), "authz", "acl.conf"]). + +ph_to_re(VarPH) -> + re:replace(VarPH, "[\\$\\{\\}]", "\\\\&", [global, {return, list}]). diff --git a/apps/emqx_authz/src/emqx_authz_http.erl b/apps/emqx_authz/src/emqx_authz_http.erl index 4c6af402c..4c17f90ec 100644 --- a/apps/emqx_authz/src/emqx_authz_http.erl +++ b/apps/emqx_authz/src/emqx_authz_http.erl @@ -87,19 +87,19 @@ replvar(Str0, PubSub, Topic, }) when is_list(Str0); is_binary(Str0) -> NTopic = emqx_http_lib:uri_encode(Topic), - Str1 = re:replace( Str0, ?PH_S_CLIENTID + Str1 = re:replace( Str0, emqx_authz:ph_to_re(?PH_S_CLIENTID) , Clientid, [global, {return, binary}]), - Str2 = re:replace( Str1, ?PH_S_USERNAME + Str2 = re:replace( Str1, emqx_authz:ph_to_re(?PH_S_USERNAME) , bin(Username), [global, {return, binary}]), - Str3 = re:replace( Str2, ?PH_S_HOST + Str3 = re:replace( Str2, emqx_authz:ph_to_re(?PH_S_HOST) , inet_parse:ntoa(IpAddress), [global, {return, binary}]), - Str4 = re:replace( Str3, ?PH_S_PROTONAME + Str4 = re:replace( Str3, emqx_authz:ph_to_re(?PH_S_PROTONAME) , bin(Protocol), [global, {return, binary}]), - Str5 = re:replace( Str4, ?PH_S_MOUNTPOINT + Str5 = re:replace( Str4, emqx_authz:ph_to_re(?PH_S_MOUNTPOINT) , Mountpoint, [global, {return, binary}]), - Str6 = re:replace( Str5, ?PH_S_TOPIC + Str6 = re:replace( Str5, emqx_authz:ph_to_re(?PH_S_TOPIC) , NTopic, [global, {return, binary}]), - Str7 = re:replace( Str6, ?PH_S_ACTION + Str7 = re:replace( Str6, emqx_authz:ph_to_re(?PH_S_ACTION) , bin(PubSub), [global, {return, binary}]), Str7. diff --git a/apps/emqx_authz/src/emqx_authz_mongodb.erl b/apps/emqx_authz/src/emqx_authz_mongodb.erl index ec34a266c..5b55c23b7 100644 --- a/apps/emqx_authz/src/emqx_authz_mongodb.erl +++ b/apps/emqx_authz/src/emqx_authz_mongodb.erl @@ -76,11 +76,11 @@ replvar(Selector, #{clientid := Clientid, end || M <- V], AccIn); InFun(K, V, AccIn) when is_binary(V) -> - V1 = re:replace( V, ?PH_S_CLIENTID + V1 = re:replace( V, emqx_authz:ph_to_re(?PH_S_CLIENTID) , bin(Clientid), [global, {return, binary}]), - V2 = re:replace( V1, ?PH_S_USERNAME + V2 = re:replace( V1, emqx_authz:ph_to_re(?PH_S_USERNAME) , bin(Username), [global, {return, binary}]), - V3 = re:replace( V2, ?PH_S_HOST + V3 = re:replace( V2, emqx_authz:ph_to_re(?PH_S_HOST) , inet_parse:ntoa(IpAddress), [global, {return, binary}]), maps:put(K, V3, AccIn); InFun(K, V, AccIn) -> maps:put(K, V, AccIn) diff --git a/apps/emqx_authz/src/emqx_authz_redis.erl b/apps/emqx_authz/src/emqx_authz_redis.erl index 50e8c9a7d..8fa1e94c3 100644 --- a/apps/emqx_authz/src/emqx_authz_redis.erl +++ b/apps/emqx_authz/src/emqx_authz_redis.erl @@ -71,8 +71,9 @@ replvar(Cmd, Client = #{username := Username}) -> replvar(Cmd, _) -> Cmd. -repl(S, _Var, undefined) -> +repl(S, _VarPH, undefined) -> S; -repl(S, Var, Val) -> - NVal = re:replace(Val, "&", "\\\\&", [global, {return, list}]), - re:replace(S, Var, NVal, [{return, list}]). +repl(S, VarPH, Val) -> + NVal = re:replace(Val, "&", "\\\\&", [global, {return, list}]), + NVarPH = emqx_authz:ph_to_re(VarPH), + re:replace(S, NVarPH, NVal, [{return, list}]).