| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123 |
- %%--------------------------------------------------------------------
- %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
- %%
- %% 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(emqttd_auth_clientid).
- -include("emqttd.hrl").
- -export([add_clientid/1, add_clientid/2, lookup_clientid/1, remove_clientid/1,
- all_clientids/0]).
- -behaviour(emqttd_auth_mod).
- %% emqttd_auth_mod callbacks
- -export([init/1, check/3, description/0]).
- -define(AUTH_CLIENTID_TAB, mqtt_auth_clientid).
- -record(?AUTH_CLIENTID_TAB, {client_id, ipaddr, password}).
- %%--------------------------------------------------------------------
- %% API
- %%--------------------------------------------------------------------
- %% @doc Add clientid
- -spec(add_clientid(binary()) -> {atomic, ok} | {aborted, any()}).
- add_clientid(ClientId) when is_binary(ClientId) ->
- R = #mqtt_auth_clientid{client_id = ClientId},
- mnesia:transaction(fun mnesia:write/1, [R]).
- %% @doc Add clientid with password
- -spec(add_clientid(binary(), binary()) -> {atomic, ok} | {aborted, any()}).
- add_clientid(ClientId, Password) ->
- R = #mqtt_auth_clientid{client_id = ClientId, password = Password},
- mnesia:transaction(fun mnesia:write/1, [R]).
- %% @doc Lookup clientid
- -spec(lookup_clientid(binary()) -> list(#mqtt_auth_clientid{})).
- lookup_clientid(ClientId) ->
- mnesia:dirty_read(?AUTH_CLIENTID_TAB, ClientId).
- %% @doc Lookup all clientids
- -spec(all_clientids() -> list(binary())).
- all_clientids() -> mnesia:dirty_all_keys(?AUTH_CLIENTID_TAB).
- %% @doc Remove clientid
- -spec(remove_clientid(binary()) -> {atomic, ok} | {aborted, any()}).
- remove_clientid(ClientId) ->
- mnesia:transaction(fun mnesia:delete/1, [{?AUTH_CLIENTID_TAB, ClientId}]).
- %%--------------------------------------------------------------------
- %% emqttd_auth_mod callbacks
- %%--------------------------------------------------------------------
- init(Opts) ->
- mnesia:create_table(?AUTH_CLIENTID_TAB, [
- {ram_copies, [node()]},
- {attributes, record_info(fields, ?AUTH_CLIENTID_TAB)}]),
- mnesia:add_table_copy(?AUTH_CLIENTID_TAB, node(), ram_copies),
- Clients = load_client_from(proplists:get_value(config, Opts)),
- mnesia:transaction(fun() -> [mnesia:write(C) || C<- Clients] end),
- {ok, Opts}.
- check(#mqtt_client{client_id = undefined}, _Password, _Opts) ->
- {error, clientid_undefined};
- check(#mqtt_client{client_id = ClientId, peername = {IpAddress, _}}, _Password, []) ->
- check_clientid_only(ClientId, IpAddress);
- check(#mqtt_client{client_id = ClientId, peername = {IpAddress, _}}, _Password, [{password, no}|_]) ->
- check_clientid_only(ClientId, IpAddress);
- check(_Client, undefined, [{password, yes}|_]) ->
- {error, password_undefined};
- check(#mqtt_client{client_id = ClientId}, Password, [{password, yes}|_]) ->
- case mnesia:dirty_read(?AUTH_CLIENTID_TAB, ClientId) of
- [] -> {error, clientid_not_found};
- [#?AUTH_CLIENTID_TAB{password = Password}] -> ok; %% TODO: plaintext??
- _ -> {error, password_error}
- end.
- description() -> "ClientId authentication module".
- %%--------------------------------------------------------------------
- %% Internal functions
- %%--------------------------------------------------------------------
- load_client_from(undefined) ->
- ok;
- load_client_from(File) ->
- {ok, Clients} = file:consult(File),
- [client(Client) || Client <- Clients].
- client(ClientId) when is_list(ClientId) ->
- #mqtt_auth_clientid{client_id = list_to_binary(ClientId)};
- client({ClientId, IpAddr}) when is_list(ClientId) ->
- #mqtt_auth_clientid{client_id = iolist_to_binary(ClientId),
- ipaddr = esockd_cidr:parse(IpAddr, true)}.
- check_clientid_only(ClientId, IpAddr) ->
- case mnesia:dirty_read(?AUTH_CLIENTID_TAB, ClientId) of
- [] ->
- {error, clientid_not_found};
- [#?AUTH_CLIENTID_TAB{ipaddr = undefined}] ->
- ok;
- [#?AUTH_CLIENTID_TAB{ipaddr = CIDR}] ->
- case esockd_cidr:match(IpAddr, CIDR) of
- true -> ok;
- false -> {error, wrong_ipaddr}
- end
- end.
|