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