From f3f80ea0ea10cca5ae62c92161a982cbf47ccd71 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Mon, 19 Sep 2011 16:58:55 +1000 Subject: [PATCH] New option support: ldap_deref_aliases (EJAB-639) Conflicts: src/ejabberd_auth_ldap.erl --- doc/guide.tex | 6 ++++-- src/ejabberd_auth_ldap.erl | 26 +++++++++++++++++++------- src/eldap/eldap.erl | 10 +++++++++- src/eldap/eldap.hrl | 1 + src/mod_shared_roster_ldap.erl | 12 ++++++++++++ src/mod_vcard_ldap.erl | 29 ++++++++++++++++++++++------- 6 files changed, 67 insertions(+), 17 deletions(-) diff --git a/doc/guide.tex b/doc/guide.tex index 28be76c66..e4d4c9264 100644 --- a/doc/guide.tex +++ b/doc/guide.tex @@ -2355,6 +2355,7 @@ the value previously stored in the database will be used instead of the default is~\term{""} which means `anonymous connection'. \titem{\{ldap\_password, Password\}} \ind{options!ldap\_password}Bind password. The default value is \term{""}. +\titem{\{ldap\_deref\_aliases, never|always|finding|searching\}} \ind{options!ldap\_deref\_aliases} Whether or not to dereference aliases. The default is \term{never}. \end{description} Example: @@ -4783,8 +4784,9 @@ The \modvcardldap{} module has its own optional parameters. The first group of parameters has the same meaning as the top-level LDAP parameters to set the authentication method: \option{ldap\_servers}, \option{ldap\_port}, \option{ldap\_rootdn}, -\option{ldap\_password}, \option{ldap\_base}, \option{ldap\_uids}, and -\option{ldap\_filter}. See section~\ref{ldapauth} for detailed information +\option{ldap\_password}, \option{ldap\_base}, \option{ldap\_uids}, +\option{ldap\_deref\_aliases} and \option{ldap\_filter}. +See section~\ref{ldapauth} for detailed information about these options. If one of these options is not set, \ejabberd{} will look for the top-level option with the same name. diff --git a/src/ejabberd_auth_ldap.erl b/src/ejabberd_auth_ldap.erl index 5db6187e1..5395df197 100644 --- a/src/ejabberd_auth_ldap.erl +++ b/src/ejabberd_auth_ldap.erl @@ -74,6 +74,7 @@ uids, ufilter, lfilter, %% Local filter (performed by ejabberd, not LDAP) + deref_aliases, dn_filter, dn_filter_attrs }). @@ -352,10 +353,12 @@ get_vh_registered_users_ldap(Server) -> ResAttrs = result_attrs(State), case eldap_filter:parse(SearchFilter) of {ok, EldapFilter} -> - case eldap_pool:search(Eldap_ID, [{base, State#state.base}, - {filter, EldapFilter}, - {timeout, ?LDAP_SEARCH_TIMEOUT}, - {attributes, ResAttrs}]) of + case eldap_pool:search(Eldap_ID, + [{base, State#state.base}, + {filter, EldapFilter}, + {timeout, ?LDAP_SEARCH_TIMEOUT}, + {deref_aliases, State#state.deref_aliases}, + {attributes, ResAttrs}]) of #eldap_search_result{entries = Entries} -> lists:flatmap( fun(#eldap_entry{attributes = Attrs, @@ -411,9 +414,11 @@ find_user_dn(User, Server, State) -> UserFilter = build_ufilter(State, Server), case eldap_filter:parse(UserFilter, [{"%u", User}]) of {ok, Filter} -> - case eldap_pool:search(State#state.eldap_id, [{base, State#state.base}, - {filter, Filter}, - {attributes, ResAttrs}]) of + case eldap_pool:search(State#state.eldap_id, + [{base, State#state.base}, + {filter, Filter}, + {deref_aliases, State#state.deref_aliases}, + {attributes, ResAttrs}]) of #eldap_search_result{entries = [#eldap_entry{attributes = Attrs, object_name = DN} | _]} -> dn_filter(DN, Server, Attrs, State); @@ -453,6 +458,7 @@ is_valid_dn(DN, Server, Attrs, State) -> case eldap_pool:search(State#state.eldap_id, [{base, State#state.base}, {filter, EldapFilter}, + {deref_aliases, State#state.deref_aliases}, {attributes, ["dn"]}]) of #eldap_search_result{entries = [_|_]} -> DN; @@ -564,6 +570,11 @@ parse_options(Host) -> end, eldap_utils:check_filter(DNFilter), LocalFilter = ejabberd_config:get_local_option({ldap_local_filter, Host}), + DerefAliases = case ejabberd_config:get_local_option( + {ldap_deref_aliases, Host}) of + undefined -> never; + Val -> Val + end, #state{host = Host, eldap_id = Eldap_ID, bind_eldap_id = Bind_Eldap_ID, @@ -580,6 +591,7 @@ parse_options(Host) -> uids = UIDs, ufilter = UserFilter, lfilter = LocalFilter, + deref_aliases = DerefAliases, dn_filter = DNFilter, dn_filter_attrs = DNFilterAttrs }. diff --git a/src/eldap/eldap.erl b/src/eldap/eldap.erl index f14c8aca6..fb7e264c3 100644 --- a/src/eldap/eldap.erl +++ b/src/eldap/eldap.erl @@ -322,6 +322,14 @@ parse_search_args([{timeout, Timeout}|T],A) when is_integer(Timeout) -> parse_search_args(T,A#eldap_search{timeout = Timeout}); parse_search_args([{limit, Limit}|T],A) when is_integer(Limit) -> parse_search_args(T,A#eldap_search{limit = Limit}); +parse_search_args([{deref_aliases, never}|T],A) -> + parse_search_args(T,A#eldap_search{deref_aliases = neverDerefAliases}); +parse_search_args([{deref_aliases, searching}|T],A) -> + parse_search_args(T,A#eldap_search{deref_aliases = derefInSearching}); +parse_search_args([{deref_aliases, finding}|T],A) -> + parse_search_args(T,A#eldap_search{deref_aliases = derefFindingBaseObj}); +parse_search_args([{deref_aliases, always}|T],A) -> + parse_search_args(T,A#eldap_search{deref_aliases = derefAlways}); parse_search_args([H|_],_) -> throw({error,{unknown_arg, H}}); parse_search_args([],A) -> @@ -699,7 +707,7 @@ gen_req({search, A}) -> {searchRequest, #'SearchRequest'{baseObject = A#eldap_search.base, scope = v_scope(A#eldap_search.scope), - derefAliases = neverDerefAliases, + derefAliases = A#eldap_search.deref_aliases, sizeLimit = A#eldap_search.limit, timeLimit = v_timeout(A#eldap_search.timeout), typesOnly = v_bool(A#eldap_search.types_only), diff --git a/src/eldap/eldap.hrl b/src/eldap/eldap.hrl index 5436fa794..23b498435 100644 --- a/src/eldap/eldap.hrl +++ b/src/eldap/eldap.hrl @@ -28,6 +28,7 @@ limit = 0, attributes = [], types_only = false, + deref_aliases = neverDerefAliases, timeout = 0}). diff --git a/src/mod_shared_roster_ldap.erl b/src/mod_shared_roster_ldap.erl index 0e1ce887d..e5aa4c64e 100644 --- a/src/mod_shared_roster_ldap.erl +++ b/src/mod_shared_roster_ldap.erl @@ -63,6 +63,7 @@ base, password, uid, + deref_aliases, group_attr, group_desc, user_desc, @@ -330,6 +331,7 @@ eldap_search(State, FilterParseArgs, AttributesList) -> [{base, State#state.base}, {filter, EldapFilter}, {timeout, ?LDAP_SEARCH_TIMEOUT}, + {deref_aliases, State#state.deref_aliases}, {attributes, AttributesList}]) of #eldap_search_result{entries = Es} -> %% A result with entries. Return their list. @@ -671,6 +673,15 @@ parse_options(Host, Opts) -> "" -> GroupSubFilter; _ -> "(&" ++ GroupSubFilter ++ ConfigFilter ++ ")" end, + DerefAliases = case gen_mod:get_opt(deref_aliases, Opts, undefined) of + undefined -> + case ejabberd_config:get_local_option( + {deref_aliases, Host}) of + undefined -> never; + D -> D + end; + D -> D + end, #state{host = Host, eldap_id = Eldap_ID, servers = LDAPServers, @@ -684,6 +695,7 @@ parse_options(Host, Opts) -> base = LDAPBase, password = Password, uid = UIDAttr, + deref_aliases = DerefAliases, group_attr = GroupAttr, group_desc = GroupDesc, user_desc = UserDesc, diff --git a/src/mod_vcard_ldap.erl b/src/mod_vcard_ldap.erl index 4a7d1ef76..ee580085f 100644 --- a/src/mod_vcard_ldap.erl +++ b/src/mod_vcard_ldap.erl @@ -75,6 +75,7 @@ search_fields, search_reported, search_reported_attrs, + deref_aliases, matches }). @@ -285,9 +286,11 @@ find_ldap_user(User, State) -> VCardAttrs = State#state.vcard_map_attrs, case eldap_filter:parse(RFC2254_Filter, [{"%u", User}]) of {ok, EldapFilter} -> - case eldap_pool:search(Eldap_ID, [{base, Base}, - {filter, EldapFilter}, - {attributes, VCardAttrs}]) of + case eldap_pool:search(Eldap_ID, + [{base, Base}, + {filter, EldapFilter}, + {deref_aliases, State#state.deref_aliases}, + {attributes, VCardAttrs}]) of #eldap_search_result{entries = [E | _]} -> E; _ -> @@ -557,10 +560,12 @@ search(State, Data) -> Limit = State#state.matches, ReportedAttrs = State#state.search_reported_attrs, Filter = eldap:'and'([SearchFilter, eldap_utils:make_filter(Data, UIDs)]), - case eldap_pool:search(Eldap_ID, [{base, Base}, - {filter, Filter}, - {limit, Limit}, - {attributes, ReportedAttrs}]) of + case eldap_pool:search(Eldap_ID, + [{base, Base}, + {filter, Filter}, + {limit, Limit}, + {deref_aliases, State#state.deref_aliases}, + {attributes, ReportedAttrs}]) of #eldap_search_result{entries = E} -> search_items(E, State); _ -> @@ -760,6 +765,15 @@ parse_options(Host, Opts) -> _ -> [] end end, SearchReported) ++ UIDAttrs), + DerefAliases = case gen_mod:get_opt(deref_aliases, Opts, undefined) of + undefined -> + case ejabberd_config:get_local_option( + {deref_aliases, Host}) of + undefined -> never; + D -> D + end; + D -> D + end, #state{serverhost = Host, myhost = MyHost, eldap_id = Eldap_ID, @@ -782,5 +796,6 @@ parse_options(Host, Opts) -> search_fields = SearchFields, search_reported = SearchReported, search_reported_attrs = SearchReportedAttrs, + deref_aliases = DerefAliases, matches = Matches }.