./ct_report/coverage/extauth.COVER.html

1 %%%----------------------------------------------------------------------
2 %%% File : extauth.erl
3 %%% Author : Leif Johansson <leifj@it.su.se>
4 %%% Purpose : External authentication using a simple port-driver
5 %%% Created : 30 Jul 2004 by Leif Johansson <leifj@it.su.se>
6 %%%
7 %%%
8 %%% ejabberd, Copyright (C) 2002-2011 ProcessOne
9 %%%
10 %%% This program is free software; you can redistribute it and/or
11 %%% modify it under the terms of the GNU General Public License as
12 %%% published by the Free Software Foundation; either version 2 of the
13 %%% License, or (at your option) any later version.
14 %%%
15 %%% This program is distributed in the hope that it will be useful,
16 %%% but WITHOUT ANY WARRANTY; without even the implied warranty of
17 %%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 %%% General Public License for more details.
19 %%%
20 %%% You should have received a copy of the GNU General Public License
21 %%% along with this program; if not, write to the Free Software
22 %%% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 %%%
24 %%%----------------------------------------------------------------------
25
26 -module(extauth).
27 -author('leifj@it.su.se').
28
29 -export([start/2,
30 stop/1,
31 init/2,
32 check_password/4,
33 set_password/4,
34 try_register/4,
35 remove_user/3,
36 does_user_exist/3]).
37
38 -include("mongoose.hrl").
39
40 -define(INIT_TIMEOUT, 60000). % Timeout is in milliseconds: 60 seconds == 60000
41 -define(CALL_TIMEOUT, 10000). % Timeout is in milliseconds: 10 seconds == 10000
42
43
44 -spec start(mongooseim:host_type(), _) -> 'ok'.
45 start(HostType, ExtPrg) ->
46
:-(
lists:foreach(
47 fun(This) ->
48
:-(
start_instance(get_process_name(HostType, This), ExtPrg)
49 end,
50 lists:seq(0, get_instances(HostType) - 1)
51 ).
52
53
54 -spec start_instance(atom(), _) -> pid().
55 start_instance(ProcessName, ExtPrg) ->
56
:-(
spawn(?MODULE, init, [ProcessName, ExtPrg]).
57
58
59 -spec restart_instance(atom(), _) -> pid().
60 restart_instance(ProcessName, ExtPrg) ->
61
:-(
unregister(ProcessName),
62
:-(
start_instance(ProcessName, ExtPrg).
63
64
65 -spec init(atom(), string()) -> no_return().
66 init(ProcessName, ExtPrg) ->
67
:-(
register(ProcessName, self()),
68
:-(
process_flag(trap_exit, true),
69
:-(
Port = open_port({spawn, ExtPrg}, [{packet, 2}]),
70
:-(
loop(Port, ?INIT_TIMEOUT, ProcessName, ExtPrg).
71
72
73 -spec stop(atom() | binary()) -> 'ok'.
74 stop(HostType) ->
75
:-(
lists:foreach(
76 fun(This) ->
77
:-(
get_process_name(HostType, This) ! stop
78 end,
79 lists:seq(0, get_instances(HostType) - 1)
80 ).
81
82
83 -spec get_process_name(binary(), integer()) -> atom().
84 get_process_name(HostType, Integer) ->
85
:-(
gen_mod:get_module_proc(lists:append([erlang:binary_to_list(HostType),
86 integer_to_list(Integer)]), eauth).
87
88
89 -spec check_password(mongooseim:host_type(), jid:user(), jid:server(), binary()) -> boolean().
90 check_password(HostType, User, Server, Password) ->
91
:-(
call_port(HostType, [<<"auth">>, User, Server, Password]).
92
93
94 -spec does_user_exist(mongooseim:host_type(), jid:user(), jid:server()) -> boolean().
95 does_user_exist(HostType, User, Server) ->
96
:-(
call_port(HostType, [<<"isuser">>, User, Server]).
97
98
99 -spec set_password(mongooseim:host_type(), jid:user(), jid:server(), binary()) -> any().
100 set_password(HostType, User, Server, Password) ->
101
:-(
call_port(HostType, [<<"setpass">>, User, Server, Password]).
102
103
104 -spec try_register(mongooseim:host_type(), jid:user(), jid:server(), binary()) ->
105 ok | {error, not_allowed}.
106 try_register(HostType, User, Server, Password) ->
107
:-(
case call_port(HostType, [<<"tryregister">>, User, Server, Password]) of
108
:-(
true -> ok;
109
:-(
false -> {error, not_allowed}
110 end.
111
112
113 -spec remove_user(mongooseim:host_type(), jid:user(), jid:server()) -> any().
114 remove_user(HostType, User, Server) ->
115
:-(
call_port(HostType, [<<"removeuser">>, User, Server]).
116
117 -spec call_port(mongooseim:host_type(), [any(), ...]) -> any().
118 call_port(HostType, Msg) ->
119
:-(
ProcessName = get_process_name(HostType, random_instance(get_instances(HostType))),
120
:-(
ProcessName ! {call, self(), Msg},
121
:-(
receive
122 {eauth, Result} ->
123
:-(
Result
124 end.
125
126
127 -spec random_instance(pos_integer()) -> non_neg_integer().
128 random_instance(MaxNum) ->
129
:-(
rand:uniform(MaxNum) - 1.
130
131
132 -spec get_instances(mongooseim:host_type()) -> integer().
133 get_instances(HostType) ->
134
:-(
mongoose_config:get_opt([{auth, HostType}, external, instances]).
135
136
137 -spec loop(port(), integer(), atom(), any()) -> no_return().
138 loop(Port, Timeout, ProcessName, ExtPrg) ->
139
:-(
receive
140 {call, Caller, Msg} ->
141
:-(
port_command(Port, encode(Msg)),
142
:-(
receive
143 {Port, {data, Data}} ->
144
:-(
?LOG_DEBUG(#{what => extauth_result,
145 extauth_call => Msg, result => Data,
146
:-(
text => <<"extauth call received data response">>}),
147
:-(
Caller ! {eauth, decode(Data)},
148
:-(
loop(Port, ?CALL_TIMEOUT, ProcessName, ExtPrg);
149 {Port, Other} ->
150
:-(
?LOG_ERROR(#{what => extauth_unexpected_message,
151 extauth_call => Msg, unexpected_message => Other,
152
:-(
text => <<"extauth call received strange response">>}),
153
:-(
Caller ! {eauth, false},
154
:-(
loop(Port, ?CALL_TIMEOUT, ProcessName, ExtPrg)
155 after
156 Timeout ->
157
:-(
?LOG_ERROR(#{what => extauth_timeout, extauth_call => Msg,
158
:-(
text => <<"extauth call didn't receive response, restarting instance">>}),
159
:-(
Caller ! {eauth, false},
160
:-(
Pid = restart_instance(ProcessName, ExtPrg),
161
:-(
flush_buffer_and_forward_messages(Pid),
162
:-(
exit(port_terminated)
163 end;
164 stop ->
165
:-(
Port ! {self(), close},
166
:-(
receive
167 {Port, closed} ->
168
:-(
exit(normal)
169 end;
170 {'EXIT', Port, Reason} ->
171
:-(
?LOG_CRITICAL(#{what => extauth_crash,
172 text => <<"extauth script has exitted abruptly, restarting instance">>,
173
:-(
reason => Reason}),
174
:-(
Pid = restart_instance(ProcessName, ExtPrg),
175
:-(
flush_buffer_and_forward_messages(Pid),
176
:-(
exit(port_terminated)
177 end.
178
179
180 -spec flush_buffer_and_forward_messages(pid()) -> 'true'.
181 flush_buffer_and_forward_messages(Pid) ->
182
:-(
receive
183 Message ->
184
:-(
Pid ! Message,
185
:-(
flush_buffer_and_forward_messages(Pid)
186 after 0 ->
187
:-(
true
188 end.
189
190
191 -spec join([binary()], binary()) -> binary().
192 join(List, Sep) ->
193
:-(
lists:foldl(fun(A, <<"">>) -> A;
194
:-(
(A, Acc) -> <<Acc/bitstring, Sep/bitstring, A/bitstring>>
195 end, <<"">>, List).
196
197
198 -spec encode([binary()]) -> [byte()].
199 encode(L) ->
200
:-(
erlang:binary_to_list(join(L, <<":">>)).
201
202
203 -spec decode([0 | 1, ...]) -> boolean().
204
:-(
decode([0, 0]) -> false;
205
:-(
decode([0, 1]) -> true.
206
Line Hits Source