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