./ct_report/coverage/mod_shared_roster_ldap.COVER.html

1 %%%-------------------------------------------------------------------
2 %%% File : mod_shared_roster_ldap.erl
3 %%% Author : Realloc <realloc@realloc.spb.ru>
4 %%% Marcin Owsiany <marcin@owsiany.pl>
5 %%% Evgeniy Khramtsov <ekhramtsov@process-one.net>
6 %%% Description : LDAP shared roster management
7 %%% Created : 5 Mar 2005 by Alexey Shchepin <alexey@process-one.net>
8 %%%
9 %%%
10 %%% ejabberd, Copyright (C) 2002-2013 ProcessOne
11 %%%
12 %%% This program is free software; you can redistribute it and/or
13 %%% modify it under the terms of the GNU General Public License as
14 %%% published by the Free Software Foundation; either version 2 of the
15 %%% License, or (at your option) any later version.
16 %%%
17 %%% This program is distributed in the hope that it will be useful,
18 %%% but WITHOUT ANY WARRANTY; without even the implied warranty of
19 %%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 %%% General Public License for more details.
21 %%%
22 %%% You should have received a copy of the GNU General Public License
23 %%% along with this program; if not, write to the Free Software
24 %%% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 %%%
26 %%%-------------------------------------------------------------------
27 -module(mod_shared_roster_ldap).
28
29 -behaviour(gen_server).
30
31 -behaviour(gen_mod).
32
33 -behaviour(mongoose_module_metrics).
34
35 %% API
36 -export([start_link/2, start/2, stop/1, config_spec/0]).
37
38 %% gen_server callbacks
39 -export([init/1, handle_call/3, handle_cast/2,
40 handle_info/2, terminate/2, code_change/3]).
41
42 -export([get_user_roster/2, get_subscription_lists/2,
43 get_jid_info/4, process_item/2, in_subscription/5,
44 out_subscription/4]).
45
46 -ignore_xref([config_change/4, get_jid_info/4, get_subscription_lists/2, get_user_roster/2,
47 in_subscription/5, out_subscription/4, process_item/2, start_link/2]).
48
49 -include("mongoose.hrl").
50 -include("jlib.hrl").
51 -include("mod_roster.hrl").
52 -include("mongoose_config_spec.hrl").
53
54 -include("eldap.hrl").
55
56 -define(CACHE_SIZE, 1000).
57
58 -define(USER_CACHE_VALIDITY, 300).
59
60 -define(GROUP_CACHE_VALIDITY, 300).
61
62 -define(LDAP_SEARCH_TIMEOUT, 5).
63
64 -record(state,
65 {host = <<>> :: binary(),
66 eldap_id :: eldap_utils:eldap_id(),
67 base = <<>> :: binary(),
68 uid = <<>> :: binary(),
69 deref = neverDerefAliases :: eldap_utils:deref(),
70 group_attr = <<>> :: binary(),
71 group_desc = <<>> :: binary(),
72 user_desc = <<>> :: binary(),
73 user_uid = <<>> :: binary(),
74 uid_format = <<>> :: binary(),
75 uid_format_re = <<>> :: binary(),
76 filter = <<>> :: binary(),
77 ufilter = <<>> :: binary(),
78 rfilter = <<>> :: binary(),
79 gfilter = <<>> :: binary(),
80 auth_check = true :: boolean(),
81 user_cache_size = ?CACHE_SIZE :: non_neg_integer(),
82 group_cache_size = ?CACHE_SIZE :: non_neg_integer(),
83 user_cache_validity = ?USER_CACHE_VALIDITY :: non_neg_integer(),
84 group_cache_validity = ?GROUP_CACHE_VALIDITY :: non_neg_integer()}).
85
86 -record(group_info, {desc, members}).
87
88 %%====================================================================
89 %% API
90 %%====================================================================
91 start_link(Host, Opts) ->
92 1 Proc = gen_mod:get_module_proc(Host, ?MODULE),
93 1 gen_server:start_link({local, Proc}, ?MODULE,
94 [Host, Opts], []).
95
96 start(Host, Opts) ->
97 1 Proc = gen_mod:get_module_proc(Host, ?MODULE),
98 1 ChildSpec = {Proc, {?MODULE, start_link, [Host, Opts]},
99 permanent, 1000, worker, [?MODULE]},
100 1 ejabberd_sup:start_child(ChildSpec).
101
102 stop(Host) ->
103 1 Proc = gen_mod:get_module_proc(Host, ?MODULE),
104 1 ejabberd_sup:stop_child(Proc).
105
106 -spec config_spec() -> mongoose_config_spec:config_section().
107 config_spec() ->
108 160 #section{
109 items = #{<<"ldap_pool_tag">> => #option{type = atom,
110 validate = pool_name},
111 <<"ldap_base">> => #option{type = string},
112 <<"ldap_deref">> => #option{type = atom,
113 validate = {enum, [never, always, finding, searching]}},
114 <<"ldap_groupattr">> => #option{type = string},
115 <<"ldap_groupdesc">> => #option{type = string},
116 <<"ldap_userdesc">> => #option{type = string},
117 <<"ldap_useruid">> => #option{type = string},
118 <<"ldap_memberattr">> => #option{type = string},
119 <<"ldap_memberattr_format">> => #option{type = string},
120 <<"ldap_memberattr_format_re">> => #option{type = string},
121 <<"ldap_auth_check">> => #option{type = boolean},
122 <<"ldap_user_cache_validity">> => #option{type = integer,
123 validate = positive},
124 <<"ldap_group_cache_validity">> => #option{type = integer,
125 validate = positive},
126 <<"ldap_user_cache_size">> => #option{type = integer,
127 validate = positive},
128 <<"ldap_group_cache_size">> => #option{type = integer,
129 validate = positive},
130 <<"ldap_rfilter">> => #option{type = string},
131 <<"ldap_gfilter">> => #option{type = string},
132 <<"ldap_ufilter">> => #option{type = string},
133 <<"ldap_filter">> => #option{type = string}
134 }
135 }.
136
137 %%--------------------------------------------------------------------
138 %% Hooks
139 %%--------------------------------------------------------------------
140 get_user_roster(Acc, #jid{luser = U, lserver = S} = JID) ->
141 3 US = jid:to_lus(JID),
142 3 Items = mongoose_acc:get(roster, items, [], Acc),
143 3 SRUsers = get_user_to_groups_map(US, true),
144 3 {NewItems1, SRUsersRest} =
145 lists:mapfoldl(
146 fun (Item, SRUsers1) ->
147
:-(
{_, _, {U1, S1, _}} = Item#roster.usj,
148
:-(
US1 = {U1, S1},
149
:-(
case dict:find(US1, SRUsers1) of
150 {ok, _GroupNames} ->
151
:-(
{Item#roster{subscription = both, ask = none},
152 dict:erase(US1, SRUsers1)};
153 error ->
154
:-(
{Item, SRUsers1}
155 end
156 end,
157 SRUsers, Items),
158 3 SRItems = [#roster{usj = {U, S, {U1, S1, <<"">>}},
159 us = US, jid = {U1, S1, <<"">>},
160 name = get_user_name(U1, S1), subscription = both,
161 ask = none, groups = GroupNames}
162 3 || {{U1, S1}, GroupNames} <- dict:to_list(SRUsersRest)],
163 3 mongoose_acc:set(roster, items, SRItems ++ NewItems1, Acc).
164
165 %% This function in use to rewrite the roster entries when moving or renaming
166 %% them in the user contact list.
167 process_item(RosterItem, _Host) ->
168
:-(
USFrom = RosterItem#roster.us,
169
:-(
{User, Server, _Resource} = RosterItem#roster.jid,
170
:-(
USTo = {User, Server},
171
:-(
Map = get_user_to_groups_map(USFrom, false),
172
:-(
case dict:find(USTo, Map) of
173
:-(
error -> RosterItem;
174
:-(
{ok, []} -> RosterItem;
175 {ok, GroupNames}
176 when RosterItem#roster.subscription == remove ->
177
:-(
RosterItem#roster{subscription = both, ask = none,
178 groups = GroupNames};
179
:-(
_ -> RosterItem#roster{subscription = both, ask = none}
180 end.
181
182 get_subscription_lists(Acc, #jid{lserver = LServer} = JID) ->
183 10 {F, T, P} = mongoose_acc:get(roster, subscription_lists, {[], [], []}, Acc),
184 10 US = jid:to_lus(JID),
185 10 DisplayedGroups = get_user_displayed_groups(US),
186 10 SRUsers = lists:usort(lists:flatmap(fun (Group) ->
187 10 get_group_users(LServer, Group)
188 end,
189 DisplayedGroups)),
190 10 SRJIDs = [{U1, S1, <<>>} || {U1, S1} <- SRUsers],
191 10 NewLists = {lists:usort(SRJIDs ++ F), lists:usort(SRJIDs ++ T), P},
192 10 mongoose_acc:set(roster, subscription_lists, NewLists, Acc).
193
194 get_jid_info({Subscription, Groups}, _HostType, ToJID, JID) ->
195
:-(
ToUS = jid:to_lus(ToJID),
196
:-(
US1 = jid:to_lus(JID),
197
:-(
SRUsers = get_user_to_groups_map(ToUS, false),
198
:-(
case dict:find(US1, SRUsers) of
199 {ok, GroupNames} ->
200
:-(
NewGroups = case Groups of
201
:-(
[] -> GroupNames;
202
:-(
_ -> Groups
203 end,
204
:-(
{both, NewGroups};
205
:-(
error -> {Subscription, Groups}
206 end.
207
208 -spec in_subscription(Acc:: mongoose_acc:t(),
209 ToJID :: jid:jid(),
210 FromJID :: jid:jid(),
211 Type :: mod_roster:sub_presence(),
212 _Reason :: any()) ->
213 mongoose_acc:t() | {stop, mongoose_acc:t()}.
214 in_subscription(Acc, ToJID, FromJID, Type, _Reason) ->
215
:-(
case process_subscription(in, ToJID, FromJID, Type) of
216 stop ->
217
:-(
{stop, Acc};
218 {stop, false} ->
219
:-(
{stop, mongoose_acc:set(hook, result, false, Acc)};
220
:-(
_ -> Acc
221 end.
222
223 -spec out_subscription(Acc:: mongoose_acc:t(),
224 FromJID :: jid:jid(),
225 ToJID ::jid:jid(),
226 Type :: mod_roster:sub_presence()) ->
227 mongoose_acc:t() | {stop, mongoose_acc:t()}.
228 out_subscription(Acc, FromJID, ToJID, Type) ->
229
:-(
case process_subscription(out, FromJID, ToJID, Type) of
230 stop ->
231
:-(
{stop, Acc};
232 {stop, false} ->
233
:-(
{stop, Acc};
234
:-(
false -> Acc
235 end.
236
237 process_subscription(Direction, #jid{luser = LUser, lserver = LServer}, ToJID, _Type) ->
238
:-(
US = {LUser, LServer},
239
:-(
{U1, S1, _} = jid:to_lower(jid:to_bare(ToJID)),
240
:-(
US1 = {U1, S1},
241
:-(
DisplayedGroups = get_user_displayed_groups(US),
242
:-(
SRUsers = lists:usort(lists:flatmap(
243 fun (Group) ->
244
:-(
get_group_users(LServer, Group)
245 end,
246 DisplayedGroups)),
247
:-(
case lists:member(US1, SRUsers) of
248 true ->
249
:-(
case Direction of
250
:-(
in -> {stop, false};
251
:-(
out -> stop
252 end;
253
:-(
false -> false
254 end.
255
256
257 %%====================================================================
258 %% gen_server callbacks
259 %%====================================================================
260 init([Host, Opts]) ->
261 1 State = parse_options(Host, Opts),
262 1 process_flag(trap_exit, true),
263 1 cache_tab:new(shared_roster_ldap_user,
264 [{max_size, State#state.user_cache_size}, {lru, false},
265 {life_time, State#state.user_cache_validity}]),
266 1 cache_tab:new(shared_roster_ldap_group,
267 [{max_size, State#state.group_cache_size}, {lru, false},
268 {life_time, State#state.group_cache_validity}]),
269 1 ejabberd_hooks:add(roster_get, Host, ?MODULE,
270 get_user_roster, 70),
271 1 ejabberd_hooks:add(roster_in_subscription, Host, ?MODULE,
272 in_subscription, 30),
273 1 ejabberd_hooks:add(roster_out_subscription, Host, ?MODULE,
274 out_subscription, 30),
275 1 ejabberd_hooks:add(roster_get_subscription_lists, Host, ?MODULE,
276 get_subscription_lists, 70),
277 1 ejabberd_hooks:add(roster_get_jid_info, Host, ?MODULE,
278 get_jid_info, 70),
279 1 ejabberd_hooks:add(roster_process_item, Host, ?MODULE,
280 process_item, 50),
281 1 {ok, State}.
282
283 handle_call(get_state, _From, State) ->
284 31 {reply, {ok, State}, State};
285 handle_call(_Request, _From, State) ->
286
:-(
{reply, {error, badarg}, State}.
287
288
:-(
handle_cast(_Msg, State) -> {noreply, State}.
289
290
:-(
handle_info(_Info, State) -> {noreply, State}.
291
292 terminate(_Reason, State) ->
293 1 Host = State#state.host,
294 1 ejabberd_hooks:delete(roster_get, Host, ?MODULE,
295 get_user_roster, 70),
296 1 ejabberd_hooks:delete(roster_in_subscription, Host,
297 ?MODULE, in_subscription, 30),
298 1 ejabberd_hooks:delete(roster_out_subscription, Host,
299 ?MODULE, out_subscription, 30),
300 1 ejabberd_hooks:delete(roster_get_subscription_lists,
301 Host, ?MODULE, get_subscription_lists, 70),
302 1 ejabberd_hooks:delete(roster_get_jid_info, Host,
303 ?MODULE, get_jid_info, 70),
304 1 ejabberd_hooks:delete(roster_process_item, Host,
305 ?MODULE, process_item, 50).
306
307
:-(
code_change(_OldVsn, State, _Extra) -> {ok, State}.
308
309 %%--------------------------------------------------------------------
310 %%% Internal functions
311 %%--------------------------------------------------------------------
312 %% For a given user, map all his shared roster contacts to groups they are
313 %% members of. Skip the user himself iff SkipUS is true.
314 get_user_to_groups_map({_, Server} = US, SkipUS) ->
315 3 DisplayedGroups = get_user_displayed_groups(US),
316 %% Pass given FilterParseArgs to eldap_filter:parse, and if successful, run and
317 %% return the resulting filter, retrieving given AttributesList. Return the
318 %% result entries. On any error silently return an empty list of results.
319 %%
320 %% Eldap server ID and base DN for the query are both retrieved from the State
321 %% record.
322 3 lists:foldl(fun (Group, Dict1) ->
323 3 GroupName = get_group_name(Server, Group),
324 3 lists:foldl(fun (Contact, Dict) when SkipUS, Contact == US ->
325 3 Dict;
326 (Contact, Dict) ->
327 2 dict:append(Contact, GroupName, Dict)
328 end,
329 Dict1, get_group_users(Server, Group))
330 end,
331 dict:new(), DisplayedGroups).
332
333 eldap_search(State, FilterParseArgs, AttributesList) ->
334 18 case apply(eldap_filter, parse, FilterParseArgs) of
335 {ok, EldapFilter} ->
336 18 SearchOpts = search_opts(EldapFilter, AttributesList, State),
337 18 case eldap_pool:search(State#state.eldap_id, SearchOpts) of
338 #eldap_search_result{entries = Es} ->
339 %% A result with entries. Return their list.
340 18 Es;
341 _ ->
342 %% Something else. Pretend we got no results.
343
:-(
[]
344 end;
345 _->
346 %% Filter parsing failed. Pretend we got no results.
347
:-(
[]
348 end.
349
350 search_opts(EldapFilter, AttributesList, State) ->
351 18 [{base, State#state.base},
352 {filter, EldapFilter},
353 {timeout, ?LDAP_SEARCH_TIMEOUT},
354 {deref, State#state.deref},
355 {attributes, AttributesList}].
356
357 get_user_displayed_groups({User, Host}) ->
358 13 {ok, State} = eldap_utils:get_state(Host, ?MODULE),
359 13 GroupAttr = State#state.group_attr,
360 13 Entries = eldap_search(State,
361 [eldap_filter:do_sub(State#state.rfilter, [{<<"%u">>, User}])],
362 [GroupAttr]),
363 13 Reply = lists:flatmap(fun (#eldap_entry{attributes = Attrs}) ->
364 88 case eldap_utils:singleton_value(Attrs) of
365 23 {GroupAttr, Value} -> [eldap_utils:maybe_list2b(Value)];
366 65 _ -> []
367 end
368 end,
369 Entries),
370 13 lists:usort(Reply).
371
372 get_group_users(Host, Group) ->
373 13 {ok, State} = eldap_utils:get_state(Host, ?MODULE),
374 13 case cache_tab:dirty_lookup(shared_roster_ldap_group,
375 {Group, Host},
376 3 fun () -> search_group_info(State, Group) end)
377 of
378 {ok, #group_info{members = Members}}
379 when Members /= undefined ->
380 13 Members;
381
:-(
_ -> []
382 end.
383
384 get_group_name(Host, Group) ->
385 3 {ok, State} = eldap_utils:get_state(Host, ?MODULE),
386 3 case cache_tab:dirty_lookup(shared_roster_ldap_group,
387 {Group, Host},
388
:-(
fun () -> search_group_info(State, Group) end)
389 of
390 {ok, #group_info{desc = GroupName}}
391 when GroupName /= undefined ->
392 3 GroupName;
393
:-(
_ -> Group
394 end.
395
396 get_user_name(User, Host) ->
397 2 {ok, State} = eldap_utils:get_state(Host, ?MODULE),
398 2 case cache_tab:dirty_lookup(shared_roster_ldap_user,
399 {User, Host},
400 2 fun () -> search_user_name(State, User) end)
401 of
402 2 {ok, UserName} -> UserName;
403
:-(
error -> User
404 end.
405
406 search_group_info(State, Group) ->
407 3 Extractor = case State#state.uid_format_re of
408 <<"">> ->
409 3 fun (UID) ->
410 5 catch eldap_utils:get_user_part(
411 UID,
412 State#state.uid_format)
413 end;
414 _ ->
415
:-(
fun (UID) ->
416
:-(
catch get_user_part_re(
417 UID,
418 State#state.uid_format_re)
419 end
420 end,
421 3 AuthChecker = case State#state.auth_check of
422 3 true -> fun ejabberd_auth:does_user_exist/1;
423
:-(
_ -> fun (_U, _S) -> true end
424 end,
425 3 Host = State#state.host,
426 3 case eldap_search(State,
427 [eldap_filter:do_sub(State#state.gfilter,
428 [{<<"%g">>, Group}])],
429 [State#state.group_attr, State#state.group_desc,
430 State#state.uid]) of
431 [] ->
432
:-(
error;
433 LDAPEntries ->
434 3 {GroupDesc, MembersLists} = ldap_entries_to_group(LDAPEntries, Host, Group, State,
435 Extractor, AuthChecker),
436 3 {ok, #group_info{desc = GroupDesc, members = lists:usort(MembersLists)}}
437 end.
438
439 ldap_entries_to_group(LDAPEntries, Host, Group, State, Extractor, AuthChecker) ->
440 3 ldap_entries_to_group(LDAPEntries, Host, Group, [], State, Extractor, AuthChecker).
441
442 ldap_entries_to_group([#eldap_entry{ attributes = Attrs } | REntries], Host,
443 DescAcc, JIDsAcc, State, Extractor, AuthChecker) ->
444 5 UID = lists:keysearch(State#state.uid, 1, Attrs),
445 5 ListUID = State#state.uid,
446 5 case {eldap_utils:get_ldap_attr(State#state.group_attr, Attrs),
447 eldap_utils:get_ldap_attr(State#state.group_desc, Attrs), UID} of
448 {ID, Desc, {value, {GroupMemberAttr, MemberIn}}}
449 when ID /= <<"">>, GroupMemberAttr == ListUID ->
450 5 Member = case MemberIn of
451 5 [M] -> M;
452
:-(
_ -> MemberIn
453 end,
454 5 Extracted = Extractor(eldap_utils:maybe_list2b(Member)),
455 5 NewJIDsAcc = check_and_accumulate_member(Extracted, AuthChecker, Host, JIDsAcc),
456 5 ldap_entries_to_group(REntries, Host, Desc, NewJIDsAcc, State, Extractor, AuthChecker);
457 _ ->
458
:-(
ldap_entries_to_group(REntries, Host, DescAcc, JIDsAcc, State, Extractor, AuthChecker)
459 end;
460 ldap_entries_to_group([], _Host, DescAcc, JIDsAcc, _State, _Extractor, _AuthChecker) ->
461 3 {DescAcc, JIDsAcc}.
462
463 check_and_accumulate_member({ok, UID}, AuthChecker, Host, JIDsAcc) ->
464 5 PUID = jid:nodeprep(UID),
465 5 case PUID of
466 error ->
467
:-(
JIDsAcc;
468 _ ->
469 5 JID = jid:make(PUID, Host, <<>>),
470 5 case AuthChecker(JID) of
471 true ->
472 5 [{PUID, Host} | JIDsAcc];
473 _ ->
474
:-(
JIDsAcc
475 end
476 end;
477 check_and_accumulate_member(_, _AuthChecker, _Host, JIDsAcc) ->
478
:-(
JIDsAcc.
479
480 search_user_name(State, User) ->
481 2 case eldap_search(State,
482 [eldap_filter:do_sub(State#state.ufilter,
483 [{<<"%u">>, User}])],
484 [State#state.user_desc, State#state.user_uid])
485 of
486 [#eldap_entry{attributes = Attrs} | _] ->
487 2 case {eldap_utils:get_ldap_attr(State#state.user_uid, Attrs),
488 eldap_utils:get_ldap_attr(State#state.user_desc, Attrs)}
489 of
490 2 {UID, Desc} when UID /= <<"">> -> {ok, Desc};
491
:-(
_ -> error
492 end;
493
:-(
[] -> error
494 end.
495
496 %% Getting User ID part by regex pattern
497 get_user_part_re(String, Pattern) ->
498
:-(
case catch re:run(String, Pattern) of
499 {match, Captured} ->
500
:-(
{First, Len} = lists:nth(2, Captured),
501
:-(
Result = binary:part(String, First, Len),
502
:-(
{ok, Result};
503
:-(
_ -> {error, badmatch}
504 end.
505
506 parse_options(Host, Opts) ->
507 1 EldapID = eldap_utils:get_mod_opt(ldap_pool_tag, Opts,
508
:-(
fun(A) when is_atom(A) -> A end, default),
509 1 Base = eldap_utils:get_base(Opts),
510 1 DerefAliases = eldap_utils:get_deref_aliases(Opts),
511 1 GroupAttr = eldap_utils:get_mod_opt(ldap_groupattr, Opts,
512 fun iolist_to_binary/1,
513 <<"cn">>),
514 1 GroupDesc = eldap_utils:get_mod_opt(ldap_groupdesc, Opts,
515 fun iolist_to_binary/1,
516 GroupAttr),
517 1 UserDesc = eldap_utils:get_mod_opt(ldap_userdesc, Opts,
518 fun iolist_to_binary/1,
519 <<"cn">>),
520 1 UserUID = eldap_utils:get_mod_opt(ldap_useruid, Opts,
521 fun iolist_to_binary/1,
522 <<"cn">>),
523 1 UIDAttr = eldap_utils:get_mod_opt(ldap_memberattr, Opts,
524 fun iolist_to_binary/1,
525 <<"memberUid">>),
526 1 UIDAttrFormat = eldap_utils:get_mod_opt(ldap_memberattr_format, Opts,
527 fun iolist_to_binary/1,
528 <<"%u">>),
529 1 UIDAttrFormatRe = eldap_utils:get_mod_opt(ldap_memberattr_format_re, Opts,
530 fun(S) ->
531
:-(
Re = iolist_to_binary(S),
532
:-(
{ok, MP} = re:compile(Re),
533
:-(
MP
534 end, <<"">>),
535 1 AuthCheck = eldap_utils:get_mod_opt(ldap_auth_check, Opts,
536
:-(
fun(false) -> false;
537
:-(
(true) -> true
538 end, true),
539 1 UserCacheValidity = eldap_utils:get_mod_opt(
540 ldap_user_cache_validity, Opts,
541 1 fun(I) when is_integer(I), I>0 -> I end,
542 ?USER_CACHE_VALIDITY),
543 1 GroupCacheValidity = eldap_utils:get_mod_opt(
544 ldap_group_cache_validity, Opts,
545 1 fun(I) when is_integer(I), I>0 -> I end,
546 ?GROUP_CACHE_VALIDITY),
547 1 UserCacheSize = eldap_utils:get_mod_opt(
548 ldap_user_cache_size, Opts,
549
:-(
fun(I) when is_integer(I), I>0 -> I end,
550 ?CACHE_SIZE),
551 1 GroupCacheSize = eldap_utils:get_mod_opt(
552 ldap_group_cache_size, Opts,
553
:-(
fun(I) when is_integer(I), I>0 -> I end,
554 ?CACHE_SIZE),
555 1 ConfigFilter = eldap_utils:get_mod_opt(ldap_filter, Opts,
556 fun check_filter/1, <<"">>),
557 1 ConfigUserFilter = eldap_utils:get_mod_opt(ldap_ufilter, Opts,
558 fun check_filter/1, <<"">>),
559 1 ConfigGroupFilter = eldap_utils:get_mod_opt(ldap_gfilter, Opts,
560 fun check_filter/1, <<"">>),
561 1 RosterFilter = eldap_utils:get_mod_opt(ldap_rfilter, Opts,
562 fun check_filter/1, <<"">>),
563 1 SubFilter = <<"(&(", UIDAttr/binary, "=", UIDAttrFormat/binary,
564 ")(", GroupAttr/binary, "=%g))">>,
565 1 UserSubFilter = case ConfigUserFilter of
566 <<"">> ->
567 1 eldap_filter:do_sub(SubFilter, [{<<"%g">>, <<"*">>}]);
568
:-(
UString -> UString
569 end,
570 1 GroupSubFilter = case ConfigGroupFilter of
571 <<"">> ->
572 1 eldap_filter:do_sub(SubFilter, [{<<"%u">>, <<"*">>}]);
573
:-(
GString -> GString
574 end,
575 1 Filter = case ConfigFilter of
576
:-(
<<"">> -> SubFilter;
577 _ ->
578 1 <<"(&", SubFilter/binary, ConfigFilter/binary, ")">>
579 end,
580 1 UserFilter = case ConfigFilter of
581
:-(
<<"">> -> UserSubFilter;
582 _ ->
583 1 <<"(&", UserSubFilter/binary, ConfigFilter/binary, ")">>
584 end,
585 1 GroupFilter = case ConfigFilter of
586
:-(
<<"">> -> GroupSubFilter;
587 _ ->
588 1 <<"(&", GroupSubFilter/binary, ConfigFilter/binary, ")">>
589 end,
590 1 #state{host = Host,
591 eldap_id = {Host, EldapID},
592 base = Base,
593 deref = DerefAliases,
594 uid = UIDAttr,
595 group_attr = GroupAttr, group_desc = GroupDesc,
596 user_desc = UserDesc, user_uid = UserUID,
597 uid_format = UIDAttrFormat,
598 uid_format_re = UIDAttrFormatRe, filter = Filter,
599 ufilter = UserFilter, rfilter = RosterFilter,
600 gfilter = GroupFilter, auth_check = AuthCheck,
601 user_cache_size = UserCacheSize,
602 user_cache_validity = UserCacheValidity,
603 group_cache_size = GroupCacheSize,
604 group_cache_validity = GroupCacheValidity}.
605
606 check_filter(F) ->
607 2 NewF = iolist_to_binary(F),
608 2 {ok, _} = eldap_filter:parse(NewF),
609 2 NewF.
Line Hits Source