./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 %% Hook handlers
43 -export([get_user_roster/3, get_subscription_lists/3,
44 get_jid_info/3, process_item/3, in_subscription/3,
45 out_subscription/3]).
46
47 -ignore_xref([start_link/2]).
48
49 -include("jlib.hrl").
50 -include("mod_roster.hrl").
51 -include("mongoose_config_spec.hrl").
52 -include_lib("eldap/include/eldap.hrl").
53
54 -define(CACHE_SIZE, 1000).
55
56 -define(USER_CACHE_VALIDITY, 300).
57
58 -define(GROUP_CACHE_VALIDITY, 300).
59
60 -define(LDAP_SEARCH_TIMEOUT, 5).
61
62 %% re:mp() type (it is not exprted in the re module)
63 -type re_mp() :: {re_pattern, _, _, _, _}.
64
65 -record(state,
66 {host = <<>> :: binary(),
67 eldap_id :: eldap_utils:eldap_id(),
68 base = <<>> :: binary(),
69 uid = <<>> :: binary(),
70 deref = neverDerefAliases :: eldap_utils:deref(),
71 group_attr = <<>> :: binary(),
72 group_desc = <<>> :: binary(),
73 user_desc = <<>> :: binary(),
74 user_uid = <<>> :: binary(),
75 uid_format = <<>> :: binary(),
76 uid_format_re = <<>> :: binary() | re_mp(),
77 filter = <<>> :: binary(),
78 ufilter = <<>> :: binary(),
79 rfilter = <<>> :: binary(),
80 gfilter = <<>> :: binary(),
81 auth_check = true :: boolean(),
82 user_cache_size = ?CACHE_SIZE :: non_neg_integer(),
83 group_cache_size = ?CACHE_SIZE :: non_neg_integer(),
84 user_cache_validity = ?USER_CACHE_VALIDITY :: non_neg_integer(),
85 group_cache_validity = ?GROUP_CACHE_VALIDITY :: non_neg_integer()}).
86
87 -record(group_info, {desc, members}).
88
89 %%====================================================================
90 %% API
91 %%====================================================================
92 start_link(Host, Opts) ->
93
:-(
Proc = gen_mod:get_module_proc(Host, ?MODULE),
94
:-(
gen_server:start_link({local, Proc}, ?MODULE,
95 [Host, Opts], []).
96
97 start(Host, Opts) ->
98
:-(
Proc = gen_mod:get_module_proc(Host, ?MODULE),
99
:-(
ChildSpec = {Proc, {?MODULE, start_link, [Host, Opts]},
100 permanent, 1000, worker, [?MODULE]},
101
:-(
ejabberd_sup:start_child(ChildSpec).
102
103 stop(Host) ->
104
:-(
Proc = gen_mod:get_module_proc(Host, ?MODULE),
105
:-(
ejabberd_sup:stop_child(Proc).
106
107 -spec config_spec() -> mongoose_config_spec:config_section().
108 config_spec() ->
109 84 CommonLDAPSpec = mongoose_ldap_config:spec(),
110 84 Items = #{<<"groupattr">> => #option{type = binary},
111 <<"groupdesc">> => #option{type = binary},
112 <<"userdesc">> => #option{type = binary},
113 <<"useruid">> => #option{type = binary},
114 <<"memberattr">> => #option{type = binary},
115 <<"memberattr_format">> => #option{type = binary},
116 <<"memberattr_format_re">> => #option{type = binary},
117 <<"auth_check">> => #option{type = boolean},
118 <<"user_cache_validity">> => #option{type = integer,
119 validate = positive},
120 <<"group_cache_validity">> => #option{type = integer,
121 validate = positive},
122 <<"user_cache_size">> => #option{type = integer,
123 validate = positive},
124 <<"group_cache_size">> => #option{type = integer,
125 validate = positive},
126 <<"rfilter">> => #option{type = binary},
127 <<"gfilter">> => #option{type = binary},
128 <<"ufilter">> => #option{type = binary}
129 },
130 84 Defaults = #{<<"groupattr">> => <<"cn">>,
131 <<"userdesc">> => <<"cn">>,
132 <<"useruid">> => <<"cn">>,
133 <<"memberattr">> => <<"memberUid">>,
134 <<"memberattr_format">> => <<"%u">>,
135 <<"memberattr_format_re">> => <<>>,
136 <<"auth_check">> => true,
137 <<"user_cache_validity">> => ?USER_CACHE_VALIDITY,
138 <<"group_cache_validity">> => ?GROUP_CACHE_VALIDITY,
139 <<"user_cache_size">> => ?CACHE_SIZE,
140 <<"group_cache_size">> => ?CACHE_SIZE,
141 <<"rfilter">> => <<>>,
142 <<"gfilter">> => <<>>,
143 <<"ufilter">> => <<>>},
144 84 CommonLDAPSpec#section{items = maps:merge(CommonLDAPSpec#section.items, Items),
145 defaults = maps:merge(CommonLDAPSpec#section.defaults, Defaults),
146 process = fun process_ldap_options/1}.
147
148 process_ldap_options(Opts = #{groupattr := GroupAttr}) ->
149
:-(
GroupDesc = maps:get(groupdesc, Opts, GroupAttr),
150
:-(
Opts#{groupdesc => GroupDesc}.
151
152 %%--------------------------------------------------------------------
153 %% Hooks
154 %%--------------------------------------------------------------------
155 -spec get_user_roster(Acc, Params, Extra) -> {ok, Acc} when
156 Acc :: [mod_roster:roster()],
157 Params :: #{mongoose_acc := mongoose_acc:t(), jid := jid:jid()},
158 Extra :: gen_hook:extra().
159 get_user_roster(Items, #{jid := JID}, _) ->
160
:-(
US = jid:to_lus(JID),
161
:-(
SRUsers = get_user_to_groups_map(US, true),
162
:-(
{NewItems1, SRUsersRest} =
163 lists:mapfoldl(
164 fun (Item, SRUsers1) ->
165
:-(
Contact = Item#roster.jid,
166
:-(
US1 = jid:to_lus(Contact),
167
:-(
case dict:find(US1, SRUsers1) of
168 {ok, _GroupNames} ->
169
:-(
{Item#roster{subscription = both, ask = none},
170 dict:erase(US1, SRUsers1)};
171 error ->
172
:-(
{Item, SRUsers1}
173 end
174 end,
175 SRUsers, Items),
176
:-(
SRItems = [#roster{usj = {US, {U1, S1, <<>>}},
177 us = US, jid = {U1, S1, <<>>},
178 name = get_user_name(U1, S1), subscription = both,
179 ask = none, groups = GroupNames}
180
:-(
|| {{U1, S1}, GroupNames} <- dict:to_list(SRUsersRest)],
181
:-(
{ok, SRItems ++ NewItems1}.
182
183 %% This function in use to rewrite the roster entries when moving or renaming
184 %% them in the user contact list.
185 -spec process_item(Acc, Params, Extra) -> {ok, Acc} when
186 Acc :: mod_roster:roster(),
187 Params :: map(),
188 Extra :: gen_hook:extra().
189 process_item(RosterItem, _, _) ->
190
:-(
USFrom = RosterItem#roster.us,
191
:-(
{User, Server, _Resource} = RosterItem#roster.jid,
192
:-(
USTo = {User, Server},
193
:-(
Map = get_user_to_groups_map(USFrom, false),
194
:-(
NewRosterItem = case dict:find(USTo, Map) of
195
:-(
error -> RosterItem;
196
:-(
{ok, []} -> RosterItem;
197 {ok, GroupNames}
198 when RosterItem#roster.subscription == remove ->
199
:-(
RosterItem#roster{subscription = both, ask = none,
200 groups = GroupNames};
201
:-(
_ -> RosterItem#roster{subscription = both, ask = none}
202 end,
203
:-(
{ok, NewRosterItem}.
204
205 -spec get_subscription_lists(Acc, Params, Extra) -> {ok, Acc} when
206 Acc ::mongoose_acc:t(),
207 Params :: #{jid := jid:jid()},
208 Extra :: gen_hook:extra().
209 get_subscription_lists(Acc, #{jid := #jid{lserver = LServer} = JID}, _) ->
210
:-(
{F, T, P} = mongoose_acc:get(roster, subscription_lists, {[], [], []}, Acc),
211
:-(
US = jid:to_lus(JID),
212
:-(
DisplayedGroups = get_user_displayed_groups(US),
213
:-(
SRUsers = lists:usort(lists:flatmap(fun (Group) ->
214
:-(
get_group_users(LServer, Group)
215 end,
216 DisplayedGroups)),
217
:-(
SRJIDs = [{U1, S1, <<>>} || {U1, S1} <- SRUsers],
218
:-(
NewLists = {lists:usort(SRJIDs ++ F), lists:usort(SRJIDs ++ T), P},
219
:-(
{ok, mongoose_acc:set(roster, subscription_lists, NewLists, Acc)}.
220
221 -spec get_jid_info(Acc, Params, Extra) -> {ok, Acc} when
222 Acc :: {mod_roster:subscription_state(), [binary()]},
223 Params :: #{to := jid:jid(), remote := jid:jid() | jid:simple_jid()},
224 Extra :: gen_hook:extra().
225 get_jid_info({Subscription, Groups}, #{to := ToJID, remote := JID}, _) ->
226
:-(
ToUS = jid:to_lus(ToJID),
227
:-(
US1 = jid:to_lus(JID),
228
:-(
SRUsers = get_user_to_groups_map(ToUS, false),
229
:-(
NewAcc = case dict:find(US1, SRUsers) of
230 {ok, GroupNames} ->
231
:-(
NewGroups = case Groups of
232
:-(
[] -> GroupNames;
233
:-(
_ -> Groups
234 end,
235
:-(
{both, NewGroups};
236
:-(
error -> {Subscription, Groups}
237 end,
238
:-(
{ok, NewAcc}.
239
240 -spec in_subscription(Acc, Params, Extra) -> {ok | stop, Acc} when
241 Acc :: mongoose_acc:t(),
242 Params :: #{to := jid:jid(),
243 from := jid:jid(),
244 type := mod_roster:sub_presence()},
245 Extra :: gen_hook:extra().
246 in_subscription(Acc, #{to := ToJID, from := FromJID, type := Type}, _) ->
247
:-(
case process_subscription(in, ToJID, FromJID, Type) of
248 stop ->
249
:-(
{stop, Acc};
250 {stop, false} ->
251
:-(
{stop, mongoose_acc:set(hook, result, false, Acc)};
252
:-(
_ -> {ok, Acc}
253 end.
254
255 -spec out_subscription(Acc, Params, Extra) -> {ok | stop, Acc} when
256 Acc :: mongoose_acc:t(),
257 Params :: #{to := jid:jid(),
258 from := jid:jid(),
259 type := mod_roster:sub_presence()},
260 Extra :: gen_hook:extra().
261 out_subscription(Acc, #{to := ToJID, from := FromJID, type := Type}, _) ->
262
:-(
case process_subscription(out, FromJID, ToJID, Type) of
263 stop ->
264
:-(
{stop, Acc};
265 {stop, false} ->
266
:-(
{stop, Acc};
267
:-(
false -> {ok, Acc}
268 end.
269
270 process_subscription(Direction, #jid{luser = LUser, lserver = LServer}, ToJID, _Type) ->
271
:-(
US = {LUser, LServer},
272
:-(
{U1, S1, _} = jid:to_lower(jid:to_bare(ToJID)),
273
:-(
US1 = {U1, S1},
274
:-(
DisplayedGroups = get_user_displayed_groups(US),
275
:-(
SRUsers = lists:usort(lists:flatmap(
276 fun (Group) ->
277
:-(
get_group_users(LServer, Group)
278 end,
279 DisplayedGroups)),
280
:-(
case lists:member(US1, SRUsers) of
281 true ->
282
:-(
case Direction of
283
:-(
in -> {stop, false};
284
:-(
out -> stop
285 end;
286
:-(
false -> false
287 end.
288
289
290 %%====================================================================
291 %% gen_server callbacks
292 %%====================================================================
293 init([Host, Opts]) ->
294
:-(
State = parse_options(Host, Opts),
295
:-(
process_flag(trap_exit, true),
296
:-(
cache_tab:new(shared_roster_ldap_user,
297 [{max_size, State#state.user_cache_size}, {lru, false},
298 {life_time, State#state.user_cache_validity}]),
299
:-(
cache_tab:new(shared_roster_ldap_group,
300 [{max_size, State#state.group_cache_size}, {lru, false},
301 {life_time, State#state.group_cache_validity}]),
302
:-(
gen_hook:add_handlers(hooks(Host)),
303
:-(
{ok, State}.
304
305 handle_call(get_state, _From, State) ->
306
:-(
{reply, {ok, State}, State};
307 handle_call(_Request, _From, State) ->
308
:-(
{reply, {error, badarg}, State}.
309
310
:-(
handle_cast(_Msg, State) -> {noreply, State}.
311
312
:-(
handle_info(_Info, State) -> {noreply, State}.
313
314 terminate(_Reason, State) ->
315
:-(
Host = State#state.host,
316
:-(
gen_hook:delete_handlers(hooks(Host)).
317
318
:-(
code_change(_OldVsn, State, _Extra) -> {ok, State}.
319
320 -spec hooks(mongooseim:host_type()) -> gen_hook:hook_list().
321 hooks(HostType) ->
322
:-(
[
323 {roster_get, HostType, fun ?MODULE:get_user_roster/3, #{}, 70},
324 {roster_in_subscription, HostType, fun ?MODULE:in_subscription/3, #{}, 70},
325 {roster_out_subscription, HostType, fun ?MODULE:out_subscription/3, #{}, 70},
326 {roster_get_subscription_lists, HostType, fun ?MODULE:get_subscription_lists/3, #{}, 70},
327 {roster_get_jid_info, HostType, fun ?MODULE:get_jid_info/3, #{}, 70},
328 {roster_process_item, HostType, fun ?MODULE:process_item/3, #{}, 70}
329 ].
330
331 %%--------------------------------------------------------------------
332 %%% Internal functions
333 %%--------------------------------------------------------------------
334 %% For a given user, map all his shared roster contacts to groups they are
335 %% members of. Skip the user himself iff SkipUS is true.
336 get_user_to_groups_map({_, Server} = US, SkipUS) ->
337
:-(
DisplayedGroups = get_user_displayed_groups(US),
338 %% Pass given FilterParseArgs to eldap_filter:parse, and if successful, run and
339 %% return the resulting filter, retrieving given AttributesList. Return the
340 %% result entries. On any error silently return an empty list of results.
341 %%
342 %% Eldap server ID and base DN for the query are both retrieved from the State
343 %% record.
344
:-(
lists:foldl(fun (Group, Dict1) ->
345
:-(
GroupName = get_group_name(Server, Group),
346
:-(
lists:foldl(fun (Contact, Dict) when SkipUS, Contact == US ->
347
:-(
Dict;
348 (Contact, Dict) ->
349
:-(
dict:append(Contact, GroupName, Dict)
350 end,
351 Dict1, get_group_users(Server, Group))
352 end,
353 dict:new(), DisplayedGroups).
354
355 eldap_search(State, FilterParseArgs, AttributesList) ->
356
:-(
case apply(eldap_filter, parse, FilterParseArgs) of
357 {ok, EldapFilter} ->
358
:-(
SearchOpts = search_opts(EldapFilter, AttributesList, State),
359
:-(
case eldap_pool:search(State#state.eldap_id, SearchOpts) of
360 #eldap_search_result{entries = Es} ->
361 %% A result with entries. Return their list.
362
:-(
Es;
363 _ ->
364 %% Something else. Pretend we got no results.
365
:-(
[]
366 end;
367 _ ->
368 %% Filter parsing failed. Pretend we got no results.
369
:-(
[]
370 end.
371
372 search_opts(EldapFilter, AttributesList, State) ->
373
:-(
[{base, State#state.base},
374 {filter, EldapFilter},
375 {timeout, ?LDAP_SEARCH_TIMEOUT},
376 {deref, State#state.deref},
377 {attributes, AttributesList}].
378
379 get_user_displayed_groups({User, Host}) ->
380
:-(
{ok, State} = eldap_utils:get_state(Host, ?MODULE),
381
:-(
GroupAttr = State#state.group_attr,
382
:-(
Entries = eldap_search(State,
383 [eldap_filter:do_sub(State#state.rfilter, [{<<"%u">>, User}])],
384 [GroupAttr]),
385
:-(
Reply = lists:flatmap(fun (#eldap_entry{attributes = Attrs}) ->
386
:-(
case eldap_utils:singleton_value(Attrs) of
387
:-(
{GroupAttr, Value} -> [eldap_utils:maybe_list2b(Value)];
388
:-(
_ -> []
389 end
390 end,
391 Entries),
392
:-(
lists:usort(Reply).
393
394 get_group_users(Host, Group) ->
395
:-(
{ok, State} = eldap_utils:get_state(Host, ?MODULE),
396
:-(
case cache_tab:dirty_lookup(shared_roster_ldap_group,
397 {Group, Host},
398
:-(
fun() -> search_group_info(State, Group) end)
399 of
400 {ok, #group_info{members = Members}}
401 when Members /= undefined ->
402
:-(
Members;
403
:-(
_ -> []
404 end.
405
406 get_group_name(Host, Group) ->
407
:-(
{ok, State} = eldap_utils:get_state(Host, ?MODULE),
408
:-(
case cache_tab:dirty_lookup(shared_roster_ldap_group,
409 {Group, Host},
410
:-(
fun() -> search_group_info(State, Group) end)
411 of
412 {ok, #group_info{desc = GroupName}}
413 when GroupName /= undefined ->
414
:-(
GroupName;
415
:-(
_ -> Group
416 end.
417
418 get_user_name(User, Host) ->
419
:-(
{ok, State} = eldap_utils:get_state(Host, ?MODULE),
420
:-(
case cache_tab:dirty_lookup(shared_roster_ldap_user,
421 {User, Host},
422
:-(
fun() -> search_user_name(State, User) end)
423 of
424
:-(
{ok, UserName} -> UserName;
425
:-(
error -> User
426 end.
427
428 search_group_info(State, Group) ->
429
:-(
Extractor = case State#state.uid_format_re of
430 <<"">> ->
431
:-(
fun (UID) ->
432
:-(
catch eldap_utils:get_user_part(
433 UID,
434 State#state.uid_format)
435 end;
436 _ ->
437
:-(
fun (UID) ->
438
:-(
catch get_user_part_re(
439 UID,
440 State#state.uid_format_re)
441 end
442 end,
443
:-(
AuthChecker = case State#state.auth_check of
444
:-(
true -> fun ejabberd_auth:does_user_exist/1;
445
:-(
false -> fun(_JID) -> true end
446 end,
447
:-(
Host = State#state.host,
448
:-(
case eldap_search(State,
449 [eldap_filter:do_sub(State#state.gfilter,
450 [{<<"%g">>, Group}])],
451 [State#state.group_attr, State#state.group_desc,
452 State#state.uid]) of
453 [] ->
454
:-(
error;
455 LDAPEntries ->
456
:-(
{GroupDesc, MembersLists} = ldap_entries_to_group(LDAPEntries, Host, Group, State,
457 Extractor, AuthChecker),
458
:-(
{ok, #group_info{desc = GroupDesc, members = lists:usort(MembersLists)}}
459 end.
460
461 ldap_entries_to_group(LDAPEntries, Host, Group, State, Extractor, AuthChecker) ->
462
:-(
ldap_entries_to_group(LDAPEntries, Host, Group, [], State, Extractor, AuthChecker).
463
464 ldap_entries_to_group([#eldap_entry{ attributes = Attrs } | REntries], Host,
465 DescAcc, JIDsAcc, State, Extractor, AuthChecker) ->
466
:-(
UID = lists:keysearch(State#state.uid, 1, Attrs),
467
:-(
ListUID = State#state.uid,
468
:-(
case {eldap_utils:get_ldap_attr(State#state.group_attr, Attrs),
469 eldap_utils:get_ldap_attr(State#state.group_desc, Attrs), UID} of
470 {ID, Desc, {value, {GroupMemberAttr, MemberIn}}}
471 when ID /= <<"">>, GroupMemberAttr == ListUID ->
472
:-(
Member = case MemberIn of
473
:-(
[M] -> M;
474
:-(
_ -> MemberIn
475 end,
476
:-(
Extracted = Extractor(eldap_utils:maybe_list2b(Member)),
477
:-(
NewJIDsAcc = check_and_accumulate_member(Extracted, AuthChecker, Host, JIDsAcc),
478
:-(
ldap_entries_to_group(REntries, Host, Desc, NewJIDsAcc, State, Extractor, AuthChecker);
479 _ ->
480
:-(
ldap_entries_to_group(REntries, Host, DescAcc, JIDsAcc, State, Extractor, AuthChecker)
481 end;
482 ldap_entries_to_group([], _Host, DescAcc, JIDsAcc, _State, _Extractor, _AuthChecker) ->
483
:-(
{DescAcc, JIDsAcc}.
484
485 check_and_accumulate_member({ok, UID}, AuthChecker, Host, JIDsAcc) ->
486
:-(
PUID = jid:nodeprep(UID),
487
:-(
case PUID of
488 error ->
489
:-(
JIDsAcc;
490 _ ->
491
:-(
JID = jid:make_bare(PUID, Host),
492
:-(
case AuthChecker(JID) of
493 true ->
494
:-(
[{PUID, Host} | JIDsAcc];
495 _ ->
496
:-(
JIDsAcc
497 end
498 end;
499 check_and_accumulate_member(_, _AuthChecker, _Host, JIDsAcc) ->
500
:-(
JIDsAcc.
501
502 search_user_name(State, User) ->
503
:-(
case eldap_search(State,
504 [eldap_filter:do_sub(State#state.ufilter,
505 [{<<"%u">>, User}])],
506 [State#state.user_desc, State#state.user_uid])
507 of
508 [#eldap_entry{attributes = Attrs} | _] ->
509
:-(
case {eldap_utils:get_ldap_attr(State#state.user_uid, Attrs),
510 eldap_utils:get_ldap_attr(State#state.user_desc, Attrs)}
511 of
512
:-(
{UID, Desc} when UID /= <<"">> -> {ok, Desc};
513
:-(
_ -> error
514 end;
515
:-(
[] -> error
516 end.
517
518 %% Getting User ID part by regex pattern
519 get_user_part_re(String, Pattern) ->
520
:-(
case catch re:run(String, Pattern) of
521 {match, Captured} ->
522
:-(
{First, Len} = lists:nth(2, Captured),
523
:-(
Result = binary:part(String, First, Len),
524
:-(
{ok, Result};
525
:-(
_ -> {error, badmatch}
526 end.
527
528
529 parse_options(Host, #{base := Base, pool_tag := EldapID, deref := Deref, filter := FilterIn,
530 groupattr := GroupAttr, groupdesc := GroupDesc, userdesc := UserDesc,
531 useruid := UserUID, memberattr := UIDAttr, memberattr_format := UIDAttrFormat,
532 memberattr_format_re := UIDAttrFormatReIn, auth_check := AuthCheck,
533 user_cache_validity := UserCacheValidity, group_cache_validity := GroupCacheValidity,
534 user_cache_size := UserCacheSize, group_cache_size := GroupCacheSize,
535 ufilter := UFilterIn, gfilter := GFilterIn, rfilter := RFilterIn}) ->
536
:-(
DerefAliases = eldap_utils:deref_aliases(Deref),
537
:-(
ConfigFilter = check_filter(FilterIn),
538
:-(
ConfigUserFilter = check_filter(UFilterIn),
539
:-(
ConfigGroupFilter = check_filter(GFilterIn),
540
:-(
RosterFilter = check_filter(RFilterIn),
541
:-(
SubFilter = <<"(&(", UIDAttr/binary, "=", UIDAttrFormat/binary,
542 ")(", GroupAttr/binary, "=%g))">>,
543
:-(
UIDAttrFormatRe = case UIDAttrFormatReIn of
544
:-(
<<>> -> UIDAttrFormatReIn;
545 RE ->
546
:-(
{ok, MP} = re:compile(RE),
547
:-(
MP
548 end,
549
:-(
UserSubFilter = case ConfigUserFilter of
550 <<"">> ->
551
:-(
eldap_filter:do_sub(SubFilter, [{<<"%g">>, <<"*">>}]);
552
:-(
UString -> UString
553 end,
554
:-(
GroupSubFilter = case ConfigGroupFilter of
555 <<"">> ->
556
:-(
eldap_filter:do_sub(SubFilter, [{<<"%u">>, <<"*">>}]);
557
:-(
GString -> GString
558 end,
559
:-(
Filter = case ConfigFilter of
560
:-(
<<"">> -> SubFilter;
561 _ ->
562
:-(
<<"(&", SubFilter/binary, ConfigFilter/binary, ")">>
563 end,
564
:-(
UserFilter = case ConfigFilter of
565
:-(
<<"">> -> UserSubFilter;
566 _ ->
567
:-(
<<"(&", UserSubFilter/binary, ConfigFilter/binary, ")">>
568 end,
569
:-(
GroupFilter = case ConfigFilter of
570
:-(
<<"">> -> GroupSubFilter;
571 _ ->
572
:-(
<<"(&", GroupSubFilter/binary, ConfigFilter/binary, ")">>
573 end,
574
:-(
#state{host = Host,
575 eldap_id = {Host, EldapID},
576 base = Base,
577 deref = DerefAliases,
578 uid = UIDAttr,
579 group_attr = GroupAttr, group_desc = GroupDesc,
580 user_desc = UserDesc, user_uid = UserUID,
581 uid_format = UIDAttrFormat,
582 uid_format_re = UIDAttrFormatRe, filter = Filter,
583 ufilter = UserFilter, rfilter = RosterFilter,
584 gfilter = GroupFilter, auth_check = AuthCheck,
585 user_cache_size = UserCacheSize,
586 user_cache_validity = UserCacheValidity,
587 group_cache_size = GroupCacheSize,
588 group_cache_validity = GroupCacheValidity}.
589
590
:-(
check_filter(<<>>) -> <<>>;
591 check_filter(F) ->
592
:-(
{ok, _} = eldap_filter:parse(F),
593
:-(
F.
Line Hits Source