ldap_dn_filter option is documented; now fetching only needed attributes in LDAP...
authorEvgeniy Khramtsov <ekhramtsov@process-one.net>
Mon, 8 Mar 2010 07:44:14 +0000 (16:44 +0900)
committerEvgeniy Khramtsov <ekhramtsov@process-one.net>
Mon, 8 Mar 2010 07:44:14 +0000 (16:44 +0900)
doc/guide.tex
src/ejabberd_auth_ldap.erl

index a6c289ed07ccdd0ea9df94bd1a67a9c84527a29a..20f6b17c08f4402dccbadbc2cb3534595a2686c9 100644 (file)
@@ -2238,7 +2238,22 @@ You can authenticate users against an LDAP directory. Available options are:
   not forget to close brackets and do not use superfluous whitespaces. Also you
   \emph{must not} use \option{ldap\_uidattr} attribute in filter because this
   attribute will be substituted in LDAP filter automatically.
-
+  \titem{\{ldap\_dn\_filter, \{ Filter, FilterAttrs \}\}}\ind{options!ldap\_dn\_filter}
+  This filter is applied on the results returned by the main filter. This filter
+  performs additional LDAP lookup to make the complete result. This is useful
+  when you are unable to define all filter rules in \term{ldap\_filter}. You
+  can define \term{"\%u"}, \term{"\%d"}, \term{"\%s"} and \term{"\%D"} pattern
+  variables in Filter: \term{"\%u"} is replaced by a user's part of a JID,
+  \term{"\%d"} is replaced by the corresponding domain (virtual host),
+  all \term{"\%s"} variables are consecutively replaced by values of FilterAttrs
+  attributes and \term{"\%D"} is replaced by Distinguished Name. By default
+  \term{ldap\_dn\_filter} is undefined.
+  Example:
+\begin{verbatim}
+{ldap_dn_filter, {"(&(name=%s)(owner=%D)(user=%u@%d))", ["sn"]}}.
+\end{verbatim}
+  Since this filter makes additional LDAP lookups, use it only in the
+  last resort: try to define all filter rules in \term{ldap\_filter} if possible.
   \titem{\{ldap\_local\_filter, Filter\}}\ind{options!ldap\_local\_filter}
   If you can't use \term{ldap\_filter} due to performance reasons
   (the LDAP server has many users registered),
index 13d1172bc4a775117eec341d5a912aef27f5e9c8..8be61f65b60365b1dc91cde14ed91ac0ffbc141a 100644 (file)
@@ -217,13 +217,13 @@ get_vh_registered_users_ldap(Server) ->
     UIDs = State#state.uids,
     Eldap_ID = State#state.eldap_id,
     Server = State#state.host,
-    SortedDNAttrs = eldap_utils:usort_attrs(State#state.dn_filter_attrs),
+    ResAttrs = result_attrs(State),
     case eldap_filter:parse(State#state.sfilter) of
                {ok, EldapFilter} ->
                    case eldap_pool:search(Eldap_ID, [{base, State#state.base},
                                                 {filter, EldapFilter},
                                                 {timeout, ?LDAP_SEARCH_TIMEOUT},
-                                                {attributes, SortedDNAttrs}]) of
+                                                {attributes, ResAttrs}]) of
                        #eldap_search_result{entries = Entries} ->
                            lists:flatmap(
                              fun(#eldap_entry{attributes = Attrs,
@@ -269,15 +269,16 @@ handle_call(_Request, _From, State) ->
     {reply, bad_request, State}.
 
 find_user_dn(User, State) ->
-    DNAttrs = eldap_utils:usort_attrs(State#state.dn_filter_attrs),
+    ResAttrs = result_attrs(State),
     case eldap_filter:parse(State#state.ufilter, [{"%u", User}]) of
        {ok, Filter} ->
-           case eldap_pool:search(State#state.eldap_id, [{base, State#state.base},
-                                                    {filter, Filter},
-                                                    {attributes, DNAttrs}]) of
+           case eldap_pool:search(State#state.eldap_id,
+                                  [{base, State#state.base},
+                                   {filter, Filter},
+                                   {attributes, ResAttrs}]) of
                #eldap_search_result{entries = [#eldap_entry{attributes = Attrs,
                                                             object_name = DN} | _]} ->
-                       dn_filter(DN, Attrs, State);
+                   dn_filter(DN, Attrs, State);
                _ ->
                    false
            end;
@@ -346,6 +347,14 @@ local_filter(equal, Attrs, FilterMatch) ->
 local_filter(notequal, Attrs, FilterMatch) ->
     not local_filter(equal, Attrs, FilterMatch).
 
+result_attrs(#state{uids = UIDs, dn_filter_attrs = DNFilterAttrs}) ->
+    lists:foldl(
+      fun({UID}, Acc) ->
+             [UID | Acc];
+        ({UID, _}, Acc) ->
+             [UID | Acc]
+      end, DNFilterAttrs, UIDs).
+
 %%%----------------------------------------------------------------------
 %%% Auxiliary functions
 %%%----------------------------------------------------------------------
@@ -388,8 +397,12 @@ parse_options(Host) ->
     LDAPBase = ejabberd_config:get_local_option({ldap_base, Host}),
     {DNFilter, DNFilterAttrs} =
        case ejabberd_config:get_local_option({ldap_dn_filter, Host}) of
-           undefined -> {undefined, undefined};
-           {DNF, DNFA} -> {DNF, DNFA}
+           undefined ->
+               {undefined, []};
+           {DNF, undefined} ->
+               {DNF, []};
+           {DNF, DNFA} ->
+               {DNF, DNFA}
        end,
        LocalFilter = ejabberd_config:get_local_option({ldap_local_filter, Host}),
     #state{host = Host,