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