From b63b99fa32c08da0429a616f36a6c048a4945e93 Mon Sep 17 00:00:00 2001 From: Mikhail Uvarov Date: Thu, 1 Jul 2021 16:23:12 +0200 Subject: [PATCH 1/2] Tag should be an atom, it's binary in ldap types Also, made some ldap types in eldap_utils --- src/auth/ejabberd_auth_ldap.erl | 77 +++++++++++++++------------------ src/auth/mongoose_gen_auth.erl | 2 +- src/eldap_pool.erl | 5 ++- src/eldap_utils.erl | 10 +++++ src/mod_shared_roster_ldap.erl | 51 +++++++++++----------- src/mod_vcard_ldap.erl | 31 +++++++------ 6 files changed, 89 insertions(+), 87 deletions(-) diff --git a/src/auth/ejabberd_auth_ldap.erl b/src/auth/ejabberd_auth_ldap.erl index b275927483..49a078ad16 100644 --- a/src/auth/ejabberd_auth_ldap.erl +++ b/src/auth/ejabberd_auth_ldap.erl @@ -57,18 +57,15 @@ -record(state, {host_type :: mongooseim:host_type(), - eldap_id :: {jid:lserver(), binary()}, - bind_eldap_id :: {jid:lserver(), binary()}, - base = <<"">> :: binary(), + eldap_id :: eldap_utils:eldap_id(), + bind_eldap_id :: eldap_utils:eldap_id(), + base = <<>> :: binary(), uids = [] :: [{binary()} | {binary(), binary()}], - ufilter = <<"">> :: binary(), - sfilter = <<"">> :: binary(), + ufilter = <<>> :: binary(), + sfilter = <<>> :: binary(), lfilter :: {any(), any()} | undefined, - deref = neverDerefAliases :: neverDerefAliases | - derefInSearching | - derefFindingBaseObj | - derefAlways, - dn_filter :: binary() | undefined, + deref = neverDerefAliases :: eldap_utils:deref(), + dn_filter :: eldap_utils:dn() | undefined, dn_filter_attrs = [] :: [binary()] }). -type state() :: #state{}. @@ -151,14 +148,13 @@ check_password(HostType, LUser, LServer, Password, _Digest, LUser :: jid:luser(), LServer :: jid:lserver(), Password :: binary()) - -> ok | {error, not_allowed | invalid_jid}. + -> ok | {error, not_allowed | invalid_jid | user_not_found}. set_password(HostType, LUser, LServer, Password) -> {ok, State} = eldap_utils:get_state(HostType, ?MODULE), case find_user_dn(LUser, LServer, State) of false -> {error, user_not_found}; DN -> - eldap_pool:modify_passwd(State#state.eldap_id, DN, - Password) + eldap_pool:modify_passwd(State#state.eldap_id, DN, Password) end. %% TODO Support multiple domains @@ -285,7 +281,7 @@ get_users_from_ldap_entries(LDAPEntries, UIDs, LServer, State) -> object_name = DN}) -> case is_valid_dn(DN, LServer, Attrs, State) of false -> []; - _ -> + true -> get_user_from_ldap_attributes(UIDs, Attrs, LServer) end end, @@ -322,21 +318,15 @@ handle_call(stop, _From, State) -> handle_call(_Request, _From, State) -> {reply, bad_request, State}. - -spec find_user_dn(LUser :: jid:luser(), LServer :: jid:lserver(), - State :: state()) -> 'false' | binary(). + State :: state()) -> false | eldap_utils:dn(). find_user_dn(LUser, LServer, State) -> ResAttrs = result_attrs(State), - case eldap_filter:parse(State#state.ufilter, - [{<<"%u">>, LUser}]) - of + case eldap_filter:parse(State#state.ufilter, [{<<"%u">>, LUser}]) of {ok, Filter} -> - case eldap_pool:search(State#state.eldap_id, - [{base, State#state.base}, {filter, Filter}, - {deref, State#state.deref}, - {attributes, ResAttrs}]) - of + SearchOpts = find_user_opts(Filter, ResAttrs, State), + case eldap_pool:search(State#state.eldap_id, SearchOpts) of #eldap_search_result{entries = [#eldap_entry{attributes = Attrs, object_name = DN} @@ -347,45 +337,46 @@ find_user_dn(LUser, LServer, State) -> _ -> false end. +find_user_opts(Filter, ResAttrs, State) -> + [{base, State#state.base}, {filter, Filter}, + {deref, State#state.deref}, {attributes, ResAttrs}]. + %% @doc apply the dn filter and the local filter: --spec dn_filter(DN :: binary(), +-spec dn_filter(DN :: eldap_utils:dn(), LServer :: jid:lserver(), Attrs :: [{binary(), [any()]}], - State :: state()) -> 'false' | binary(). + State :: state()) -> false | eldap_utils:dn(). dn_filter(DN, LServer, Attrs, State) -> case check_local_filter(Attrs, State) of false -> false; - true -> is_valid_dn(DN, LServer, Attrs, State) + true -> + case is_valid_dn(DN, LServer, Attrs, State) of + true -> DN; + false -> false + end end. - %% @doc Check that the DN is valid, based on the dn filter --spec is_valid_dn(DN :: binary(), +-spec is_valid_dn(DN :: eldap_utils:dn(), LServer :: jid:lserver(), Attrs :: [{binary(), [any()]}], - State :: state()) -> 'false' | binary(). -is_valid_dn(DN, _LServer, _, #state{dn_filter = undefined}) -> DN; + State :: state()) -> boolean(). +is_valid_dn(_DN, _LServer, _, #state{dn_filter = undefined}) -> true; is_valid_dn(DN, LServer, Attrs, State) -> DNAttrs = State#state.dn_filter_attrs, UIDs = State#state.uids, - Values = [{<<"%s">>, - eldap_utils:get_ldap_attr(Attr, Attrs), 1} + Values = [{<<"%s">>, eldap_utils:get_ldap_attr(Attr, Attrs), 1} || Attr <- DNAttrs], - SubstValues = case eldap_utils:find_ldap_attrs(UIDs, - Attrs) - of - <<"">> -> Values; + SubstValues = case eldap_utils:find_ldap_attrs(UIDs, Attrs) of + <<>> -> Values; {S, UAF} -> case eldap_utils:get_user_part(S, UAF) of {ok, U} -> [{<<"%u">>, U} | Values]; _ -> Values end - end - ++ [{<<"%d">>, LServer}, {<<"%D">>, DN}], - case eldap_filter:parse(State#state.dn_filter, - SubstValues) - of + end ++ [{<<"%d">>, LServer}, {<<"%D">>, DN}], + case eldap_filter:parse(State#state.dn_filter, SubstValues) of {ok, EldapFilter} -> case eldap_pool:search(State#state.eldap_id, [{base, State#state.base}, @@ -393,7 +384,7 @@ is_valid_dn(DN, LServer, Attrs, State) -> {deref, State#state.deref}, {attributes, [<<"dn">>]}]) of - #eldap_search_result{entries = [_ | _]} -> DN; + #eldap_search_result{entries = [_ | _]} -> true; _ -> false end; _ -> false diff --git a/src/auth/mongoose_gen_auth.erl b/src/auth/mongoose_gen_auth.erl index e15aa8f842..dec6d744d9 100644 --- a/src/auth/mongoose_gen_auth.erl +++ b/src/auth/mongoose_gen_auth.erl @@ -69,7 +69,7 @@ User :: jid:luser(), Server :: jid:lserver(), Password :: binary()) -> - ok | {error, not_allowed | invalid_jid}. + ok | {error, not_allowed | invalid_jid | user_not_found}. -callback remove_user(HostType :: mongooseim:host_type(), User :: jid:luser(), diff --git a/src/eldap_pool.erl b/src/eldap_pool.erl index d781d04a61..66d4e7201e 100644 --- a/src/eldap_pool.erl +++ b/src/eldap_pool.erl @@ -78,6 +78,7 @@ delete(PoolName, DN) -> R -> R end. +%% Applies eldap:add/3 add(PoolName, DN, Attrs) -> do_request(PoolName, {add, [maybe_b2list(DN), parse_add_atrs(Attrs)]}). @@ -92,5 +93,7 @@ parse_add_attr({N, List}) -> %% Internal functions %%==================================================================== -do_request({Host, PoolTag}, Request) -> +%% Calls mongoose_ldap_worker +%% Which calls eldap:F +do_request({Host, PoolTag}, {_F, _Args} = Request) -> mongoose_wpool:call(ldap, Host, PoolTag, Request). diff --git a/src/eldap_utils.erl b/src/eldap_utils.erl index 735104db7c..2b94ad39b7 100644 --- a/src/eldap_utils.erl +++ b/src/eldap_utils.erl @@ -52,6 +52,16 @@ -include("mongoose.hrl"). -include("eldap.hrl"). +-type dn() :: binary(). +-type deref() :: neverDerefAliases | derefInSearching + | derefFindingBaseObj | derefAlways. +%% Used to access mongoose_wpool +-type eldap_id() :: {HostType :: mongooseim:host_type(), Tag :: mongoose_wpool:tag()}. + +-export_type([dn/0, + deref/0, + eldap_id/0]). + %% @doc Generate an 'or' LDAP query on one or several attributes %% If there is only one attribute -spec generate_subfilter([{binary()} | {binary(), binary()}]) -> binary(). diff --git a/src/mod_shared_roster_ldap.erl b/src/mod_shared_roster_ldap.erl index 029946b679..b4fa386e9b 100644 --- a/src/mod_shared_roster_ldap.erl +++ b/src/mod_shared_roster_ldap.erl @@ -61,24 +61,21 @@ -define(LDAP_SEARCH_TIMEOUT, 5). -record(state, - {host = <<"">> :: binary(), - eldap_id :: {jid:lserver(), binary()}, - base = <<"">> :: binary(), - uid = <<"">> :: binary(), - deref = neverDerefAliases :: neverDerefAliases | - derefInSearching | - derefFindingBaseObj | - derefAlways, - group_attr = <<"">> :: binary(), - group_desc = <<"">> :: binary(), - user_desc = <<"">> :: binary(), - user_uid = <<"">> :: binary(), - uid_format = <<"">> :: binary(), - uid_format_re = <<"">> :: binary(), - filter = <<"">> :: binary(), - ufilter = <<"">> :: binary(), - rfilter = <<"">> :: binary(), - gfilter = <<"">> :: binary(), + {host = <<>> :: binary(), + eldap_id :: eldap_utils:eldap_id(), + base = <<>> :: binary(), + uid = <<>> :: binary(), + deref = neverDerefAliases :: eldap_utils:deref(), + group_attr = <<>> :: binary(), + group_desc = <<>> :: binary(), + user_desc = <<>> :: binary(), + user_uid = <<>> :: binary(), + uid_format = <<>> :: binary(), + uid_format_re = <<>> :: binary(), + filter = <<>> :: binary(), + ufilter = <<>> :: binary(), + rfilter = <<>> :: binary(), + gfilter = <<>> :: binary(), auth_check = true :: boolean(), user_cache_size = ?CACHE_SIZE :: non_neg_integer(), group_cache_size = ?CACHE_SIZE :: non_neg_integer(), @@ -189,7 +186,7 @@ get_subscription_lists(Acc, #jid{lserver = LServer} = JID) -> get_group_users(LServer, Group) end, DisplayedGroups)), - SRJIDs = [{U1, S1, <<"">>} || {U1, S1} <- SRUsers], + SRJIDs = [{U1, S1, <<>>} || {U1, S1} <- SRUsers], NewLists = {lists:usort(SRJIDs ++ F), lists:usort(SRJIDs ++ T), P}, mongoose_acc:set(roster, subscription_lists, NewLists, Acc). @@ -351,13 +348,8 @@ get_user_to_groups_map({_, Server} = US, SkipUS) -> eldap_search(State, FilterParseArgs, AttributesList) -> case apply(eldap_filter, parse, FilterParseArgs) of {ok, EldapFilter} -> - case eldap_pool:search(State#state.eldap_id, - [{base, State#state.base}, - {filter, EldapFilter}, - {timeout, ?LDAP_SEARCH_TIMEOUT}, - {deref, State#state.deref}, - {attributes, AttributesList}]) - of + SearchOpts = search_opts(EldapFilter, AttributesList, State), + case eldap_pool:search(State#state.eldap_id, SearchOpts) of #eldap_search_result{entries = Es} -> %% A result with entries. Return their list. Es; @@ -370,6 +362,13 @@ eldap_search(State, FilterParseArgs, AttributesList) -> [] end. +search_opts(EldapFilter, AttributesList, State) -> + [{base, State#state.base}, + {filter, EldapFilter}, + {timeout, ?LDAP_SEARCH_TIMEOUT}, + {deref, State#state.deref}, + {attributes, AttributesList}]. + get_user_displayed_groups({User, Host}) -> {ok, State} = eldap_utils:get_state(Host, ?MODULE), GroupAttr = State#state.group_attr, diff --git a/src/mod_vcard_ldap.erl b/src/mod_vcard_ldap.erl index 95801550e3..6f27566c96 100644 --- a/src/mod_vcard_ldap.erl +++ b/src/mod_vcard_ldap.erl @@ -57,23 +57,22 @@ -define(PROCNAME, ejabberd_mod_vcard_ldap). -record(state, - {serverhost = <<"">> :: binary(), - myhost = <<"">> :: binary(), - eldap_id :: {jid:lserver(), binary()}, - base = <<"">> :: binary(), - password = <<"">> :: binary(), + {serverhost = <<>> :: binary(), + myhost = <<>> :: binary(), + eldap_id :: mongoose_utils:eldap_id(), + base = <<>> :: binary(), + password = <<>> :: binary(), uids = [] :: [{binary()} | {binary(), binary()}], vcard_map = [] :: [{binary(), binary(), [binary()]}], vcard_map_attrs = [] :: [binary()], - user_filter = <<"">> :: binary(), + user_filter = <<>> :: binary(), search_filter :: eldap:filter(), search_fields = [] :: [{binary(), binary()}], search_reported = [] :: [{binary(), binary()}], search_reported_attrs = [] :: [binary()], search_operator :: 'or' | 'and', binary_search_fields :: [binary()], - deref = neverDerefAliases :: neverDerefAliases | derefInSearching - | derefFindingBaseObj | derefAlways, + deref = neverDerefAliases :: mongoose_utils:deref(), matches = 0 :: non_neg_integer() | infinity}). -define(VCARD_MAP, @@ -244,15 +243,15 @@ find_ldap_user(User, State) -> end. eldap_pool_search(EldapID, Base, EldapFilter, Deref, Attrs, NoResultRes) -> - case eldap_pool:search(EldapID, + SearchOpts = search_opts(Base, EldapFilter, Deref, Attrs), + case eldap_pool:search(EldapID, SearchOpts) of + #eldap_search_result{entries = E} -> E; + _ -> NoResultRes + end. + +search_opts(Base, EldapFilter, Deref, Attrs) -> [{base, Base}, {filter, EldapFilter}, - {deref, Deref}, - {attributes, Attrs}]) - of - #eldap_search_result{entries = E} -> E; - _ -> - NoResultRes - end. + {deref, Deref}, {attributes, Attrs}]. ldap_attributes_to_vcard(Attributes, VCardMap, UD) -> Attrs = lists:map(fun ({VCardName, _, _}) -> From 5b35e43daa257a02cfdbd96d596b1f148a616d5e Mon Sep 17 00:00:00 2001 From: Mikhail Uvarov Date: Mon, 12 Jul 2021 12:14:26 +0200 Subject: [PATCH 2/2] Fix eldap_utils instead of mongoose_utils --- src/mod_vcard_ldap.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mod_vcard_ldap.erl b/src/mod_vcard_ldap.erl index 6f27566c96..0b445fdd7a 100644 --- a/src/mod_vcard_ldap.erl +++ b/src/mod_vcard_ldap.erl @@ -59,7 +59,7 @@ -record(state, {serverhost = <<>> :: binary(), myhost = <<>> :: binary(), - eldap_id :: mongoose_utils:eldap_id(), + eldap_id :: eldap_utils:eldap_id(), base = <<>> :: binary(), password = <<>> :: binary(), uids = [] :: [{binary()} | {binary(), binary()}], @@ -72,7 +72,7 @@ search_reported_attrs = [] :: [binary()], search_operator :: 'or' | 'and', binary_search_fields :: [binary()], - deref = neverDerefAliases :: mongoose_utils:deref(), + deref = neverDerefAliases :: eldap_utils:deref(), matches = 0 :: non_neg_integer() | infinity}). -define(VCARD_MAP,