From 318168515843e1a7ec1ebb278a73116e8618d9d7 Mon Sep 17 00:00:00 2001 From: Badlop Date: Fri, 30 Jul 2010 20:34:01 +0200 Subject: [PATCH] Support parallel extauth script (thanks to Jesse Thompson)(EJAB-1280) --- doc/guide.html | 29 +++++++++++++++++++++++++++-- doc/guide.tex | 8 +++++++- src/extauth.erl | 35 ++++++++++++++++++++++++++++++----- 3 files changed, 64 insertions(+), 8 deletions(-) diff --git a/doc/guide.html b/doc/guide.html index 318f43640..528e8cf90 100644 --- a/doc/guide.html +++ b/doc/guide.html @@ -1078,7 +1078,9 @@ There are also several example authenti

{extauth_program, PathToScript}
Indicate in this option the full path to the external authentication script. -The script must be executable by ejabberd.
{extauth_cache, false|CacheTimeInteger}
+The script must be executable by ejabberd.
{extauth_instances, Integer}
+Indicate how many instances of the script to run simultaneously to serve authentication in the virtual host. +The default value is the minimum number: 1.
{extauth_cache, false|CacheTimeInteger}
The value false disables the caching feature, this is the default. The integer 0 (zero) enables caching for statistics, but doesn’t use that cached information to authenticate users. If another integer value is set, caching is enabled both for statistics and for authentication: @@ -1087,10 +1089,12 @@ the authentication information since the user last disconnected, to verify again the user authentication without querying again the extauth script. Note: caching should not be enabled in a host if internal auth is also enabled. If caching is enabled, mod_last must be enabled also in that vhost. -

This example sets external authentication, the extauth script, and enables caching for 10 minutes: +

This example sets external authentication, the extauth script, enables caching for 10 minutes, +and starts three instances of the script for each virtual host defined in ejabberd:

{auth_method, external}.
 {extauth_program, "/etc/ejabberd/JabberAuth.class.php"}.
 {extauth_cache, 600}.
+{extauth_instances, 3}. 
 

SASL Anonymous and Anonymous Login

The value anonymous will enable the internal authentication method.

The anonymous authentication method can be configured with the following @@ -3067,6 +3071,13 @@ the database connection (see the subsections of 3.2).

{iqdisc, Discipline}
This specifies the processing discipline for Roster Management (jabber:iq:roster) IQ queries (see section 3.3.2). +
access
+This option can be configured to specify rules to restrict roster management. +If a rule returns ‘deny’ on the requested user name, +that user cannot modify his personal roster: +not add/remove/modify contacts, +or subscribe/unsubscribe presence. +By default there aren’t restrictions.
{versioning, false|true}
Enables Roster Versioning. This option is disabled by default. @@ -3085,6 +3096,20 @@ Important: if you use mod_shared_roster, you must disable this option. {mod_roster, [{versioning, true}, {store_current_id, true}]}, ... ]}. +

With this example configuration only admins can manage their rosters; +everybody else cannot modify the roster: +

{acl, admin, {user, "bob", "example.org"}}.
+{acl, admin, {user, "sarah", "example.org"}}.
+
+{access, roster, [{allow, admin},
+                  {deny, all}]}.
+
+{modules,
+ [
+  ...
+  {mod_roster, [{access, roster}]},
+  ...
+ ]}.
 

3.3.20  mod_service_log

This module adds support for logging end user packets via a XMPP message diff --git a/doc/guide.tex b/doc/guide.tex index 2f573aa4f..c307bd1e3 100644 --- a/doc/guide.tex +++ b/doc/guide.tex @@ -1254,6 +1254,10 @@ These are the specific options: Indicate in this option the full path to the external authentication script. The script must be executable by ejabberd. + \titem{\{extauth\_instances, Integer\}} + Indicate how many instances of the script to run simultaneously to serve authentication in the virtual host. + The default value is the minimum number: 1. + \titem{\{extauth\_cache, false|CacheTimeInteger\}} The value \term{false} disables the caching feature, this is the default. The integer \term{0} (zero) enables caching for statistics, but doesn't use that cached information to authenticate users. @@ -1265,11 +1269,13 @@ These are the specific options: If caching is enabled, \term{mod\_last} must be enabled also in that vhost. \end{description} -This example sets external authentication, the extauth script, and enables caching for 10 minutes: +This example sets external authentication, the extauth script, enables caching for 10 minutes, +and starts three instances of the script for each virtual host defined in ejabberd: \begin{verbatim} {auth_method, external}. {extauth_program, "/etc/ejabberd/JabberAuth.class.php"}. {extauth_cache, 600}. +{extauth_instances, 3}. \end{verbatim} \makesubsubsection{saslanonymous}{SASL Anonymous and Anonymous Login} diff --git a/src/extauth.erl b/src/extauth.erl index e382241cb..2d0fae2bb 100644 --- a/src/extauth.erl +++ b/src/extauth.erl @@ -43,16 +43,29 @@ -define(CALL_TIMEOUT, 10000). % Timeout is in milliseconds: 10 seconds == 10000 start(Host, ExtPrg) -> - spawn(?MODULE, init, [Host, ExtPrg]). + lists:foreach( + fun(This) -> + spawn(?MODULE, init, [get_process_name(Host, This), ExtPrg]) + end, + lists:seq(0, get_instances(Host)-1) + ). -init(Host, ExtPrg) -> - register(gen_mod:get_module_proc(Host, eauth), self()), +init(ProcessName, ExtPrg) -> + register(ProcessName, self()), process_flag(trap_exit,true), Port = open_port({spawn, ExtPrg}, [{packet,2}]), loop(Port, ?INIT_TIMEOUT). stop(Host) -> - gen_mod:get_module_proc(Host, eauth) ! stop. + lists:foreach( + fun(This) -> + get_process_name(Host, This) ! stop + end, + lists:seq(0, get_instances(Host)-1) + ). + +get_process_name(Host, Integer) -> + gen_mod:get_module_proc(lists:append([Host, integer_to_list(Integer)]), eauth). check_password(User, Server, Password) -> call_port(Server, ["auth", User, Server, Password]). @@ -77,12 +90,24 @@ remove_user(User, Server, Password) -> call_port(Server, Msg) -> LServer = exmpp_stringprep:nameprep(Server), - gen_mod:get_module_proc(LServer, eauth) ! {call, self(), Msg}, + ProcessName = get_process_name(LServer, random_instance(get_instances(LServer))), + ProcessName ! {call, self(), Msg}, receive {eauth,Result} -> Result end. +random_instance(MaxNum) -> + {A1,A2,A3} = now(), + random:seed(A1, A2, A3), + random:uniform(MaxNum) - 1. + +get_instances(Server) -> + case ejabberd_config:get_local_option({extauth_instances, Server}) of + Num when is_integer(Num) -> Num; + _ -> 1 + end. + loop(Port, Timeout) -> receive {call, Caller, Msg} ->