diff --git a/doc/guide.html b/doc/guide.html
index 48d0469c8..6d95e6e73 100644
--- a/doc/guide.html
+++ b/doc/guide.html
@@ -101,6 +101,14 @@ database, and in next time they will be APPENDED to existing values. E. g.
if this file will not contain ``host'' definition, then old value will be
used.
+To override old values following lines can be added in config:
+
+override_global.
+override_local.
+override_acls.
+
With this lines old global or local options or ACLs will be removed before
+adding new ones.
+
3.1.1 Host Name
@@ -109,42 +117,9 @@ used.
serves. E. g. to use jabber.org domain add following line in config:
{host, "jabber.org"}.
-
-
-3.1.2 Listened Sockets
-
-Option listen defines list of listened sockets and what services
-runned on them. Each element of list is a tuple with following elements:
-
--
- Port number;
-
-
- Module that serves this port;
-
-
- Function in this module that starts connection (likely will be removed);
-
-
- Options to this module.
-
Currently three modules implemented:
-
--
- ejabberd_c2s: serves C2S connections;
-
-
- ejabberd_s2s_in: serves incoming S2S connections;
-
-
- ejabberd_service: serves connections to Jabber services
- (i. e. that use jabber:component:accept namespace).
-
For example, following configuration defines that C2S connections listened on
-port 5222, S2S on port 5269 and that service conference.jabber.org
-must be connected to port 8888 with password ``secret''.
-
-
-{listen, [{5222, ejabberd_c2s, start, []},
- {5269, ejabberd_s2s_in, start, []},
- {8888, ejabberd_service, start, ["conference.jabber.org", "secret"]}
- ]}.
-3.1.3 Access Rules
+3.1.2 Access Rules
Access control in ejabberd is done via Access Control Lists (ACL). In
config file they looks like this:
@@ -213,6 +188,12 @@ config file they looks like this:
If the first character after `[' is a `!', then any
character not enclosed is matched.
+Following ACLs pre-defined:
+
+-
+all
- Matches all JIDs.
+
+
- none
- Matches none JIDs.
Allowing or denying of different services is like this:
{access, <accessname>, [{allow, <aclname>},
@@ -229,6 +210,57 @@ Example:
{access, configure, [{allow, admin}]}.
{access, something, [{deny, badmans},
{allow, all}]}.
+
Following access rules pre-defined:
+
+-
+all
- Always return ``allow''
+
+
- none
- Always return ``deny''
+
+
+3.1.3 Listened Sockets
+
+Option listen defines list of listened sockets and what services
+runned on them. Each element of list is a tuple with following elements:
+
+-
+ Port number;
+
+
- Module that serves this port;
+
+
- Function in this module that starts connection (likely will be removed);
+
+
- Options to this module.
+
Currently three modules implemented:
+
+-
+ejabberd_c2s
- This module serves C2S connections.
+
+ Following options defined:
+
+-
+ {access, <access rule>}
- This option defines access of users
+ to this C2S port. Default value is ``all''.
+
+
+ - ejabberd_s2s_in
- This module serves incoming S2S connections.
+
+
- ejabberd_service
- This module serves connections to Jabber
+ services (i. e. that use jabber:component:accept namespace).
+
For example, following configuration defines that C2S connections listened on
+port 5222 and denied for user ``bad'', S2S on port 5269 and that
+service conference.jabber.org must be connected to port 8888 with
+password ``secret''.
+
+
+{acl, blocked, {user, "bad"}}.
+{access, c2s, [{deny, blocked},
+ {allow, all}]}.
+{listen, [{5222, ejabberd_c2s, start, [{access, c2s}]},
+ {5269, ejabberd_s2s_in, start, []},
+ {8888, ejabberd_service, start,
+ [{host, "conference.jabber.org", [{password, "secret"}]}]}
+ ]}.
3.1.4 Modules
@@ -282,7 +314,7 @@ have access to connect to port 4369 of all another nodes, and must have same
magic cookie (see Erlang/OTP documentation, in short file
~ejabberd/.erlang.cookie must be the same on all nodes). This is
needed because all nodes exchange information about connected users, S2S
-connection, registered services, etc...
+connections, registered services, etc...
Each ejabberd node run following modules:
diff --git a/doc/guide.tex b/doc/guide.tex
index 47061fada..7f516a8e2 100644
--- a/doc/guide.tex
+++ b/doc/guide.tex
@@ -132,6 +132,15 @@ database, and in next time they will be APPENDED to existing values. E.\,g.\
if this file will not contain ``host'' definition, then old value will be
used.
+To override old values following lines can be added in config:
+\begin{verbatim}
+override_global.
+override_local.
+override_acls.
+\end{verbatim}
+With this lines old global or local options or ACLs will be removed before
+adding new ones.
+
\subsubsection{Host Name}
\label{sec:confighostname}
@@ -146,38 +155,6 @@ serves. E.\,g.\ to use \texttt{jabber.org} domain add following line in config:
-\subsubsection{Listened Sockets}
-\label{sec:configlistened}
-
-Option \texttt{listen} defines list of listened sockets and what services
-runned on them. Each element of list is a tuple with following elements:
-\begin{itemize}
-\item Port number;
-\item Module that serves this port;
-\item Function in this module that starts connection (likely will be removed);
-\item Options to this module.
-\end{itemize}
-
-Currently three modules implemented:
-\begin{itemize}
-\item \texttt{ejabberd\_c2s}: serves C2S connections;
-\item \texttt{ejabberd\_s2s\_in}: serves incoming S2S connections;
-\item \texttt{ejabberd\_service}: serves connections to \Jabber{} services
- (i.\,e.\ that use \texttt{jabber:component:accept} namespace).
-\end{itemize}
-
-For example, following configuration defines that C2S connections listened on
-port 5222, S2S on port 5269 and that service \texttt{conference.jabber.org}
-must be connected to port 8888 with password ``\texttt{secret}''.
-
-\begin{verbatim}
-{listen, [{5222, ejabberd_c2s, start, []},
- {5269, ejabberd_s2s_in, start, []},
- {8888, ejabberd_service, start, ["conference.jabber.org", "secret"]}
- ]}.
-\end{verbatim}
-
-
\subsubsection{Access Rules}
\label{sec:configaccess}
@@ -253,6 +230,12 @@ config file they looks like this:
\end{description}
\end{description}
+Following ACLs pre-defined:
+\begin{description}
+\item[\texttt{all}] Matches all JIDs.
+\item[\texttt{none}] Matches none JIDs.
+\end{description}
+
Allowing or denying of different services is like this:
\begin{verbatim}
{access, , [{allow, },
@@ -272,6 +255,57 @@ Example:
{allow, all}]}.
\end{verbatim}
+Following access rules pre-defined:
+\begin{description}
+\item[\texttt{all}] Always return ``\texttt{allow}''
+\item[\texttt{none}] Always return ``\texttt{deny}''
+\end{description}
+
+
+\subsubsection{Listened Sockets}
+\label{sec:configlistened}
+
+Option \texttt{listen} defines list of listened sockets and what services
+runned on them. Each element of list is a tuple with following elements:
+\begin{itemize}
+\item Port number;
+\item Module that serves this port;
+\item Function in this module that starts connection (likely will be removed);
+\item Options to this module.
+\end{itemize}
+
+Currently three modules implemented:
+\begin{description}
+\item[\texttt{ejabberd\_c2s}] This module serves C2S connections.
+
+ Following options defined:
+ \begin{description}
+ \item[\texttt{\{access, \}}] This option defines access of users
+ to this C2S port. Default value is ``\texttt{all}''.
+ \end{description}
+\item[\texttt{ejabberd\_s2s\_in}] This module serves incoming S2S connections.
+\item[\texttt{ejabberd\_service}] This module serves connections to \Jabber{}
+ services (i.\,e.\ that use \texttt{jabber:component:accept} namespace).
+\end{description}
+
+For example, following configuration defines that C2S connections listened on
+port 5222 and denied for user ``\texttt{bad}'', S2S on port 5269 and that
+service \texttt{conference.jabber.org} must be connected to port 8888 with
+password ``\texttt{secret}''.
+
+\begin{verbatim}
+{acl, blocked, {user, "bad"}}.
+{access, c2s, [{deny, blocked},
+ {allow, all}]}.
+{listen, [{5222, ejabberd_c2s, start, [{access, c2s}]},
+ {5269, ejabberd_s2s_in, start, []},
+ {8888, ejabberd_service, start,
+ [{host, "conference.jabber.org", [{password, "secret"}]}]}
+ ]}.
+\end{verbatim}
+
+
+
\subsubsection{Modules}
diff --git a/src/Makefile b/src/Makefile
index 8f3c17bce..fe7705f9d 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -3,9 +3,10 @@
include Makefile.inc
INCLUDES = -I/usr/lib/erlang/usr/include \
- -I$(EI_DIR)/include
+ -I$(EI_DIR)/include \
+ -I/usr/local/include
-LIBDIRS = -L$(EI_DIR)/lib
+LIBDIRS = -L$(EI_DIR)/lib -L/usr/local/lib
ERLSHLIBS = expat_erl.so
diff --git a/src/acl.erl b/src/acl.erl
index 10bd11fdb..67b928cd1 100644
--- a/src/acl.erl
+++ b/src/acl.erl
@@ -11,7 +11,9 @@
-vsn('$Revision$ ').
-export([start/0,
+ to_record/2,
add/2,
+ add_list/2,
match_rule/2,
% for debugging only
match_acl/2]).
@@ -28,6 +30,8 @@ start() ->
mnesia:add_table_copy(acl, node(), ram_copies),
ok.
+to_record(ACLName, ACLSpec) ->
+ #acl{aclname = ACLName, aclspec = ACLSpec}.
add(ACLName, ACLSpec) ->
F = fun() ->
@@ -35,12 +39,44 @@ add(ACLName, ACLSpec) ->
end,
mnesia:transaction(F).
+add_list(ACLs, Clear) ->
+ F = fun() ->
+ if
+ Clear ->
+ Ks = mnesia:all_keys(acl),
+ lists:foreach(fun(K) ->
+ mnesia:delete({acl, K})
+ end, Ks);
+ true ->
+ ok
+ end,
+ lists:foreach(fun(ACL) ->
+ case ACL of
+ #acl{} ->
+ mnesia:write(ACL)
+ end
+ end, ACLs)
+ end,
+ case mnesia:transaction(F) of
+ {atomic, _} ->
+ ok;
+ _ ->
+ false
+ end.
+
+
+
match_rule(Rule, JID) ->
- case ejabberd_config:get_global_option({access, Rule}) of
- undefined ->
- deny;
- ACLs ->
- match_acls(ACLs, JID)
+ case Rule of
+ all -> allow;
+ none -> deny;
+ _ ->
+ case ejabberd_config:get_global_option({access, Rule}) of
+ undefined ->
+ deny;
+ ACLs ->
+ match_acls(ACLs, JID)
+ end
end.
match_acls([], _) ->
@@ -54,41 +90,46 @@ match_acls([{Access, ACL} | ACLs], JID) ->
end.
match_acl(ACL, JID) ->
- {User, Server, Resource} = jlib:jid_tolower(JID),
- lists:any(fun(#acl{aclspec = Spec}) ->
- case Spec of
- all ->
- true;
- {user, U} ->
- (U == User) andalso (?MYNAME == Server);
- {user, U, S} ->
- (U == User) andalso (S == Server);
- {server, S} ->
- S == Server;
- {user_regexp, UR} ->
- (?MYNAME == Server) andalso
- is_regexp_match(User, UR);
- {user_regexp, UR, S} ->
- (S == Server) andalso
- is_regexp_match(User, UR);
- {server_regexp, SR} ->
- is_regexp_match(Server, SR);
- {node_regexp, UR, SR} ->
- is_regexp_match(Server, SR) andalso
- is_regexp_match(User, UR);
- {user_glob, UR} ->
- (?MYNAME == Server) andalso
- is_glob_match(User, UR);
- {user_glob, UR, S} ->
- (S == Server) andalso
- is_glob_match(User, UR);
- {server_glob, SR} ->
- is_glob_match(Server, SR);
- {node_glob, UR, SR} ->
- is_glob_match(Server, SR) andalso
- is_glob_match(User, UR)
- end
- end, ets:lookup(acl, ACL)).
+ case ACL of
+ all -> true;
+ none -> false;
+ _ ->
+ {User, Server, Resource} = jlib:jid_tolower(JID),
+ lists:any(fun(#acl{aclspec = Spec}) ->
+ case Spec of
+ all ->
+ true;
+ {user, U} ->
+ (U == User) andalso (?MYNAME == Server);
+ {user, U, S} ->
+ (U == User) andalso (S == Server);
+ {server, S} ->
+ S == Server;
+ {user_regexp, UR} ->
+ (?MYNAME == Server) andalso
+ is_regexp_match(User, UR);
+ {user_regexp, UR, S} ->
+ (S == Server) andalso
+ is_regexp_match(User, UR);
+ {server_regexp, SR} ->
+ is_regexp_match(Server, SR);
+ {node_regexp, UR, SR} ->
+ is_regexp_match(Server, SR) andalso
+ is_regexp_match(User, UR);
+ {user_glob, UR} ->
+ (?MYNAME == Server) andalso
+ is_glob_match(User, UR);
+ {user_glob, UR, S} ->
+ (S == Server) andalso
+ is_glob_match(User, UR);
+ {server_glob, SR} ->
+ is_glob_match(Server, SR);
+ {node_glob, UR, SR} ->
+ is_glob_match(Server, SR) andalso
+ is_glob_match(User, UR)
+ end
+ end, ets:lookup(acl, ACL))
+ end.
is_regexp_match(String, RegExp) ->
case regexp:first_match(String, RegExp) of
diff --git a/src/ejabberd.app b/src/ejabberd.app
new file mode 100644
index 000000000..a90fbaeb4
--- /dev/null
+++ b/src/ejabberd.app
@@ -0,0 +1,54 @@
+% $Id$
+
+{application, ejabberd,
+ [{description, "ejabberd"},
+ {vsn, "0.0.1-alpha"},
+ {modules, [acl,
+ ejabberd,
+ ejabberd_auth,
+ ejabberd_c2s,
+ ejabberd_config,
+ ejabberd_listener,
+ ejabberd_local,
+ ejabberd_router,
+ ejabberd_s2s,
+ ejabberd_s2s_in,
+ ejabberd_s2s_out,
+ ejabberd_service,
+ ejabberd_sm,
+ jlib,
+ mod_configure,
+ mod_disco,
+ mod_echo,
+ mod_offline,
+ mod_private,
+ mod_register,
+ mod_roster,
+ mod_stats,
+ mod_time,
+ mod_vcard,
+ mod_version,
+ randoms,
+ sha,
+ translate,
+ xml,
+ xml_stream
+ ]},
+ {registered, [ejabberd,
+ ejabberd_auth,
+ ejabberd_router,
+ ejabberd_sm,
+ ejabberd_s2s,
+ ejabberd_local,
+ ejabberd_mod_roster,
+ ejabberd_listeners
+ ]},
+ {applications, [kernel, stdlib, mnesia]},
+ {env, []},
+ {mod, {ejabberd_app, []}}]}.
+
+
+
+% Local Variables:
+% mode: erlang
+% End:
diff --git a/src/ejabberd.cfg b/src/ejabberd.cfg
index 00992fed2..8724fea6a 100644
--- a/src/ejabberd.cfg
+++ b/src/ejabberd.cfg
@@ -6,6 +6,9 @@
{acl, admin, {user, "aleksey", "jabber.ru"}}.
{acl, admin, {user, "ermine", "jabber.ru"}}.
+
+{acl, blocked, {user, "test2"}}.
+
{acl, jabberorg, {server, "jabber.org"}}.
{acl, aleksey, {user, "aleksey", "jabber.ru"}}.
@@ -18,11 +21,15 @@
{access, configure, [{allow, admin}]}.
+{access, c2s, [{deny, blocked},
+ {allow, all}]}.
+
{host, "e.localhost"}.
-{listen, [{5522, ejabberd_c2s, start, []},
+{listen, [{5522, ejabberd_c2s, start, [{access, c2s}]},
{5269, ejabberd_s2s_in, start, []},
- {8888, ejabberd_service, start, ["asd.e.localhost", "asdqwe"]}
+ {8888, ejabberd_service, start,
+ [{host, "asd.e.localhost", [{password, "asdqwe"}]}]}
]}.
% This value (5569) is only for debugging, must be 5269
diff --git a/src/ejabberd.erl b/src/ejabberd.erl
index 2f6d2feba..ef3b85c15 100644
--- a/src/ejabberd.erl
+++ b/src/ejabberd.erl
@@ -10,62 +10,70 @@
-author('alexey@sevcom.net').
-vsn('$Revision$ ').
--export([start/0, init/0]).
-
--include("ejabberd.hrl").
+-export([start/0, stop/0]).
start() ->
- spawn(?MODULE, init, []).
+ application:start(mnesia),
+ application:start(ejabberd).
-init() ->
- register(ejabberd, self()),
- % Profiling
- %eprof:start(),
- %eprof:profile([self()]),
- %erlang:system_flag(fullsweep_after, 0),
- error_logger:logfile({open, ?ERROR_LOG_PATH}),
- randoms:start(),
- ok = erl_ddll:load_driver(".", expat_erl),
- Port = open_port({spawn, expat_erl}, [binary]),
- db_init(),
- sha:start(),
- translate:start(),
- acl:start(),
- gen_mod:start(),
- ejabberd_config:start(),
- ejabberd_auth:start(),
- ejabberd_router:start(),
- ejabberd_sm:start(),
- ejabberd_s2s:start(),
- ejabberd_local:start(),
- ejabberd_listener:start(),
- load_modules(),
- loop(Port).
+stop() ->
+ application:stop(ejabberd).
-loop(Port) ->
- receive
- _ ->
- loop(Port)
- end.
+%-include("ejabberd.hrl").
-db_init() ->
- case mnesia:system_info(extra_db_nodes) of
- [] ->
- mnesia:create_schema([node()]);
- _ ->
- ok
- end,
- mnesia:start(),
- mnesia:wait_for_tables(mnesia:system_info(local_tables), infinity).
-
-load_modules() ->
- case ejabberd_config:get_local_option(modules) of
- undefined ->
- ok;
- Modules ->
- lists:foreach(fun({Module, Args}) ->
- gen_mod:start_module(Module, Args)
- end, Modules)
- end.
+%start() ->
+% spawn(?MODULE, init, []).
+%
+%init() ->
+% register(ejabberd, self()),
+% % Profiling
+% %eprof:start(),
+% %eprof:profile([self()]),
+% %erlang:system_flag(fullsweep_after, 0),
+% error_logger:logfile({open, ?ERROR_LOG_PATH}),
+% randoms:start(),
+% ok = erl_ddll:load_driver(".", expat_erl),
+% Port = open_port({spawn, expat_erl}, [binary]),
+% db_init(),
+% sha:start(),
+% translate:start(),
+% acl:start(),
+% gen_mod:start(),
+% ejabberd_config:start(),
+% ejabberd_auth:start(),
+% ejabberd_router:start(),
+% ejabberd_sm:start(),
+% ejabberd_s2s:start(),
+% ejabberd_local:start(),
+% ejabberd_listener:start(),
+% load_modules(),
+% loop(Port).
+%
+%
+%loop(Port) ->
+% receive
+% _ ->
+% loop(Port)
+% end.
+%
+%db_init() ->
+% case mnesia:system_info(extra_db_nodes) of
+% [] ->
+% mnesia:create_schema([node()]);
+% _ ->
+% ok
+% end,
+% mnesia:start(),
+% mnesia:wait_for_tables(mnesia:system_info(local_tables), infinity).
+%
+%load_modules() ->
+% case ejabberd_config:get_local_option(modules) of
+% undefined ->
+% ok;
+% Modules ->
+% lists:foreach(fun({Module, Args}) ->
+% gen_mod:start_module(Module, Args)
+% end, Modules)
+% end.
diff --git a/src/ejabberd_app.erl b/src/ejabberd_app.erl
new file mode 100644
index 000000000..67099f88e
--- /dev/null
+++ b/src/ejabberd_app.erl
@@ -0,0 +1,79 @@
+%%%----------------------------------------------------------------------
+%%% File : ejabberd_app.erl
+%%% Author : Alexey Shchepin
+%%% Purpose :
+%%% Created : 31 Jan 2003 by Alexey Shchepin
+%%% Id : $Id$
+%%%----------------------------------------------------------------------
+
+-module(ejabberd_app).
+-author('alexey@sevcom.net').
+-vsn('$Revision$ ').
+
+-behaviour(application).
+
+-export([start/2, stop/1, init/0]).
+
+-include("ejabberd.hrl").
+
+start(normal, Args) ->
+ randoms:start(),
+ db_init(),
+ sha:start(),
+ translate:start(),
+ acl:start(),
+ gen_mod:start(),
+ ejabberd_config:start(),
+ ejabberd_auth:start(),
+ Sup = ejabberd_sup:start_link(),
+ start(),
+ load_modules(),
+ Sup;
+start(_, _) ->
+ {error, badarg}.
+
+stop(StartArgs) ->
+ ok.
+
+start() ->
+ spawn(?MODULE, init, []).
+
+init() ->
+ register(ejabberd, self()),
+ % Profiling
+ %eprof:start(),
+ %eprof:profile([self()]),
+ %erlang:system_flag(fullsweep_after, 0),
+ error_logger:logfile({open, ?ERROR_LOG_PATH}),
+ ok = erl_ddll:load_driver(".", expat_erl),
+ Port = open_port({spawn, expat_erl}, [binary]),
+
+ loop(Port).
+
+
+loop(Port) ->
+ receive
+ _ ->
+ loop(Port)
+ end.
+
+db_init() ->
+ case mnesia:system_info(extra_db_nodes) of
+ [] ->
+ mnesia:create_schema([node()]);
+ _ ->
+ ok
+ end,
+ mnesia:start(),
+ mnesia:wait_for_tables(mnesia:system_info(local_tables), infinity).
+
+load_modules() ->
+ case ejabberd_config:get_local_option(modules) of
+ undefined ->
+ ok;
+ Modules ->
+ lists:foreach(fun({Module, Args}) ->
+ gen_mod:start_module(Module, Args)
+ end, Modules)
+ end.
+
diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl
index 8c66d3262..2fa3e1d2e 100644
--- a/src/ejabberd_c2s.erl
+++ b/src/ejabberd_c2s.erl
@@ -13,12 +13,9 @@
-behaviour(gen_fsm).
%% External exports
--export([start/1, receiver/2, sender/1, send_text/2, send_element/2]).
+-export([start/2, receiver/2, sender/1, send_text/2, send_element/2]).
%% gen_fsm callbacks
-%-export([init/1, state_name/2, state_name/3, handle_event/3,
-% handle_sync_event/4, handle_info/3, terminate/3]).
-%
-export([init/1, wait_for_stream/2, wait_for_auth/2, session_established/2,
handle_event/3,
handle_sync_event/4,
@@ -32,6 +29,7 @@
-define(SETS, gb_sets).
-record(state, {socket, sender, receiver, streamid,
+ access,
user = "", server = ?MYNAME, resource = "",
pres_t = ?SETS:new(),
pres_f = ?SETS:new(),
@@ -63,8 +61,8 @@
%%%----------------------------------------------------------------------
%%% API
%%%----------------------------------------------------------------------
-start(Socket) ->
- gen_fsm:start(ejabberd_c2s, [Socket], ?FSMOPTS).
+start(Socket, Opts) ->
+ gen_fsm:start(ejabberd_c2s, [Socket, Opts], ?FSMOPTS).
%%%----------------------------------------------------------------------
%%% Callback functions from gen_fsm
@@ -77,13 +75,20 @@ start(Socket) ->
%% ignore |
%% {stop, StopReason}
%%----------------------------------------------------------------------
-init([Socket]) ->
+init([Socket, Opts]) ->
SenderPid = spawn(?MODULE, sender, [Socket]),
ReceiverPid = spawn(?MODULE, receiver, [Socket, self()]),
- {ok, wait_for_stream, #state{socket = Socket,
+ Access = case lists:keysearch(access, 1, Opts) of
+ {value, {_, A}} ->
+ A;
+ _ ->
+ all
+ end,
+ {ok, wait_for_stream, #state{socket = Socket,
receiver = ReceiverPid,
- sender = SenderPid,
- streamid = new_id()}}.
+ sender = SenderPid,
+ streamid = new_id(),
+ access = Access}}.
%%----------------------------------------------------------------------
%% Func: StateName/2
@@ -118,20 +123,28 @@ wait_for_auth({xmlstreamelement, El}, StateData) ->
{next_state, wait_for_auth, StateData};
{auth, ID, {U, P, D, R}} ->
io:format("AUTH: ~p~n", [{U, P, D, R}]),
- case ejabberd_auth:check_password(U, P,
- StateData#state.streamid, D) of
- true ->
- ejabberd_sm:open_session(U, R),
- Res = jlib:make_result_iq_reply(El),
- send_element(StateData#state.sender, Res),
- {Fs, Ts} = mod_roster:get_subscription_lists(U),
- {next_state, session_established,
- StateData#state{user = U,
- resource = R,
- pres_f = ?SETS:from_list(Fs),
- pres_t = ?SETS:from_list(Ts)}};
+ case acl:match_rule(StateData#state.access, {U, ?MYNAME, R}) of
+ allow ->
+ case ejabberd_auth:check_password(
+ U, P, StateData#state.streamid, D) of
+ true ->
+ ejabberd_sm:open_session(U, R),
+ Res = jlib:make_result_iq_reply(El),
+ send_element(StateData#state.sender, Res),
+ {Fs, Ts} = mod_roster:get_subscription_lists(U),
+ {next_state, session_established,
+ StateData#state{user = U,
+ resource = R,
+ pres_f = ?SETS:from_list(Fs),
+ pres_t = ?SETS:from_list(Ts)}};
+ _ ->
+ Err = jlib:make_error_reply(
+ El, "401", "Unauthorized"),
+ send_element(StateData#state.sender, Err),
+ {next_state, wait_for_auth, StateData}
+ end;
_ ->
- Err = jlib:make_error_reply(El, "401", "Unauthorized"),
+ Err = jlib:make_error_reply(El, "405", "Not Allowed"),
send_element(StateData#state.sender, Err),
{next_state, wait_for_auth, StateData}
end;
diff --git a/src/ejabberd_config.erl b/src/ejabberd_config.erl
index 51a78592c..321c735cb 100644
--- a/src/ejabberd_config.erl
+++ b/src/ejabberd_config.erl
@@ -18,6 +18,10 @@
-record(config, {key, value}).
-record(local_config, {key, value}).
+-record(state, {opts = [],
+ override_local = false,
+ override_global = false,
+ override_acls = false}).
start() ->
%ets:new(ejabberd_config, [named_table, public]),
@@ -36,23 +40,32 @@ start() ->
load_file(File) ->
case file:consult(File) of
{ok, Terms} ->
- lists:foreach(fun process_term/1, Terms);
+ Res = lists:foldl(fun process_term/2, #state{}, Terms),
+ set_opts(Res);
{error, Reason} ->
?ERROR_MSG("~p", [Reason]),
exit(file:format_error(Reason))
end.
-process_term(Term) ->
+process_term(Term, State) ->
case Term of
+ override_global ->
+ #state{override_global = true};
+ override_local ->
+ #state{override_local = true};
+ override_acls ->
+ #state{override_acls = true};
{acl, ACLName, ACLData} ->
- acl:add(ACLName, ACLData);
+ #state{opts =
+ [acl:to_record(ACLName, ACLData) | State#state.opts]};
{access, RuleName, Rules} ->
- add_global_option({access, RuleName}, Rules);
+ #state{opts = [#config{key = {access, RuleName}, value = Rules} |
+ State#state.opts]};
{Opt, Val} ->
- add_option(Opt, Val)
+ add_option(Opt, Val, State)
end.
-add_option(Opt, Val) ->
+add_option(Opt, Val, State) ->
Table = case Opt of
host ->
config;
@@ -61,11 +74,51 @@ add_option(Opt, Val) ->
end,
case Table of
config ->
- add_global_option(Opt, Val);
+ #state{opts = [#config{key = Opt, value = Val} |
+ State#state.opts]};
local_config ->
- add_local_option(Opt, Val)
+ #state{opts = [#local_config{key = Opt, value = Val} |
+ State#state.opts]}
end.
+
+set_opts(State) ->
+ Opts = lists:reverse(State#state.opts),
+ mnesia:transaction(
+ fun() ->
+ if
+ State#state.override_global ->
+ Ksg = mnesia:all_keys(config),
+ lists:foreach(fun(K) ->
+ mnesia:delete({config, K})
+ end, Ksg);
+ true ->
+ ok
+ end,
+ if
+ State#state.override_local ->
+ Ksl = mnesia:all_keys(local_config),
+ lists:foreach(fun(K) ->
+ mnesia:delete({local_config, K})
+ end, Ksl);
+ true ->
+ ok
+ end,
+ if
+ State#state.override_acls ->
+ Ksa = mnesia:all_keys(acl),
+ lists:foreach(fun(K) ->
+ mnesia:delete({acl, K})
+ end, Ksa);
+ true ->
+ ok
+ end,
+ lists:foreach(fun(R) ->
+ mnesia:write(R)
+ end, Opts)
+ end).
+
+
add_global_option(Opt, Val) ->
mnesia:transaction(fun() ->
mnesia:write(#config{key = Opt,
@@ -96,4 +149,3 @@ get_local_option(Opt) ->
end.
-
diff --git a/src/ejabberd_listener.erl b/src/ejabberd_listener.erl
index 9e6957c47..3ed030c7b 100644
--- a/src/ejabberd_listener.erl
+++ b/src/ejabberd_listener.erl
@@ -10,9 +10,9 @@
-author('alexey@sevcom.net').
-vsn('$Revision$ ').
--export([start/0, init/1, start/4, init/4]).
+-export([start_link/0, init/1, start/4, init/4]).
-start() ->
+start_link() ->
supervisor:start_link({local, ejabberd_listeners}, ?MODULE, []).
@@ -23,9 +23,9 @@ init(_) ->
Ls ->
{ok, {{one_for_one, 10, 1},
lists:map(
- fun({Port, Module, Fun, Args}) ->
+ fun({Port, Module, Fun, Opts}) ->
{Port,
- {?MODULE, start, [Port, Module, Fun, Args]},
+ {?MODULE, start, [Port, Module, Fun, [Opts]]},
permanent,
brutal_kill,
worker,
diff --git a/src/ejabberd_local.erl b/src/ejabberd_local.erl
index e0415b0d2..b5a32c977 100644
--- a/src/ejabberd_local.erl
+++ b/src/ejabberd_local.erl
@@ -10,7 +10,7 @@
-author('alexey@sevcom.net').
-vsn('$Revision$ ').
--export([start/0, init/0]).
+-export([start_link/0, init/0]).
-export([register_iq_handler/3,
register_iq_handler/4,
@@ -21,9 +21,10 @@
-record(state, {mydomain, iqtable}).
-start() ->
- register(ejabberd_local, spawn(ejabberd_local, init, [])),
- ok.
+start_link() ->
+ register(ejabberd_local,
+ Pid = proc_lib:spawn_link(ejabberd_local, init, [])),
+ {ok, Pid}.
init() ->
MyDomain = ?MYNAME,
diff --git a/src/ejabberd_router.erl b/src/ejabberd_router.erl
index 171244c03..9de7e67f4 100644
--- a/src/ejabberd_router.erl
+++ b/src/ejabberd_router.erl
@@ -19,7 +19,7 @@
dirty_get_all_domains/0
]).
--export([start/0, init/0]).
+-export([start_link/0, init/0]).
-include("ejabberd.hrl").
@@ -27,8 +27,8 @@
-record(local_route, {domain, pid}).
-start() ->
- spawn(ejabberd_router, init, []).
+start_link() ->
+ {ok, proc_lib:spawn_link(ejabberd_router, init, [])}.
init() ->
register(ejabberd_router, self()),
diff --git a/src/ejabberd_s2s.erl b/src/ejabberd_s2s.erl
index fbe6092f0..0aa36784b 100644
--- a/src/ejabberd_s2s.erl
+++ b/src/ejabberd_s2s.erl
@@ -10,7 +10,7 @@
-author('alexey@sevcom.net').
-vsn('$Revision$ ').
--export([start/0, init/0,
+-export([start_link/0, init/0,
have_connection/1,
get_key/1,
try_register/1,
@@ -23,8 +23,8 @@
-record(local_s2s, {fromto, pid}).
-start() ->
- spawn(ejabberd_s2s, init, []).
+start_link() ->
+ {ok, proc_lib:spawn_link(ejabberd_s2s, init, [])}.
init() ->
register(ejabberd_s2s, self()),
diff --git a/src/ejabberd_s2s_in.erl b/src/ejabberd_s2s_in.erl
index fbc572d32..388030549 100644
--- a/src/ejabberd_s2s_in.erl
+++ b/src/ejabberd_s2s_in.erl
@@ -13,7 +13,7 @@
-behaviour(gen_fsm).
%% External exports
--export([start/1, receiver/2, send_text/2, send_element/2]).
+-export([start/2, receiver/2, send_text/2, send_element/2]).
%% gen_fsm callbacks
-export([init/1,
@@ -65,7 +65,7 @@
%%%----------------------------------------------------------------------
%%% API
%%%----------------------------------------------------------------------
-start(Socket) ->
+start(Socket, Opts) ->
gen_fsm:start(ejabberd_s2s_in, [Socket], ?FSMOPTS).
%%%----------------------------------------------------------------------
diff --git a/src/ejabberd_service.erl b/src/ejabberd_service.erl
index e67b0ca32..78e7a9c9a 100644
--- a/src/ejabberd_service.erl
+++ b/src/ejabberd_service.erl
@@ -13,7 +13,7 @@
-behaviour(gen_fsm).
%% External exports
--export([start/3, receiver/2, send_text/2, send_element/2]).
+-export([start/2, receiver/2, send_text/2, send_element/2]).
%% gen_fsm callbacks
-export([init/1,
@@ -63,8 +63,8 @@
%%%----------------------------------------------------------------------
%%% API
%%%----------------------------------------------------------------------
-start(Socket, Host, Password) ->
- gen_fsm:start(ejabberd_service, [Socket, Host, Password], ?FSMOPTS).
+start(Socket, Opts) ->
+ gen_fsm:start(ejabberd_service, [Socket, Opts], ?FSMOPTS).
%%%----------------------------------------------------------------------
%%% Callback functions from gen_fsm
@@ -77,7 +77,21 @@ start(Socket, Host, Password) ->
%% ignore |
%% {stop, StopReason}
%%----------------------------------------------------------------------
-init([Socket, Host, Password]) ->
+init([Socket, Opts]) ->
+ {Host, Password} =
+ case lists:keysearch(host, 1, Opts) of
+ {value, {_, H, HOpts}} ->
+ case lists:keysearch(password, 1, HOpts) of
+ {value, {_, P}} ->
+ {H, P};
+ _ ->
+ % TODO: generate error
+ false
+ end;
+ _ ->
+ % TODO: generate error
+ false
+ end,
ReceiverPid = spawn(?MODULE, receiver, [Socket, self()]),
{ok, wait_for_stream, #state{socket = Socket,
receiver = ReceiverPid,
diff --git a/src/ejabberd_sm.erl b/src/ejabberd_sm.erl
index 8860dcf5d..0f5efe839 100644
--- a/src/ejabberd_sm.erl
+++ b/src/ejabberd_sm.erl
@@ -10,7 +10,7 @@
-author('alexey@sevcom.net').
-vsn('$Revision$ ').
--export([start/0, init/0, open_session/2, close_session/2,
+-export([start_link/0, init/0, open_session/2, close_session/2,
get_user_resources/1,
set_presence/3,
unset_presence/2,
@@ -28,8 +28,8 @@
-record(local_session, {ur, pid}).
-record(presence, {ur, user, priority}).
-start() ->
- spawn(ejabberd_sm, init, []).
+start_link() ->
+ {ok, proc_lib:spawn_link(ejabberd_sm, init, [])}.
init() ->
register(ejabberd_sm, self()),
diff --git a/src/ejabberd_sup.erl b/src/ejabberd_sup.erl
new file mode 100644
index 000000000..584cb0b61
--- /dev/null
+++ b/src/ejabberd_sup.erl
@@ -0,0 +1,54 @@
+%%%----------------------------------------------------------------------
+%%% File : ejabberd_sup.erl
+%%% Author : Alexey Shchepin
+%%% Purpose :
+%%% Created : 31 Jan 2003 by Alexey Shchepin
+%%% Id : $Id$
+%%%----------------------------------------------------------------------
+
+-module(ejabberd_sup).
+-author('alexey@sevcom.net').
+-vsn('$Revision$ ').
+
+-behaviour(supervisor).
+
+-export([start_link/0, init/1]).
+
+start_link() ->
+ supervisor:start_link({local, ?MODULE}, ?MODULE, []).
+
+
+init([]) ->
+ Router = {ejabberd_router,
+ {ejabberd_router, start_link, []},
+ permanent,
+ brutal_kill,
+ worker,
+ [ejabberd_router]},
+ SM = {ejabberd_sm,
+ {ejabberd_sm, start_link, []},
+ permanent,
+ brutal_kill,
+ worker,
+ [ejabberd_sm]},
+ S2S = {ejabberd_s2s,
+ {ejabberd_s2s, start_link, []},
+ permanent,
+ brutal_kill,
+ worker,
+ [ejabberd_s2s]},
+ Local = {ejabberd_local,
+ {ejabberd_local, start_link, []},
+ permanent,
+ brutal_kill,
+ worker,
+ [ejabberd_local]},
+ Listener = {ejabberd_listener,
+ {ejabberd_listener, start_link, []},
+ permanent,
+ brutal_kill,
+ supervisor,
+ [ejabberd_listener]},
+ {ok, {{one_for_one, 10, 1}, [Router, SM, S2S, Local, Listener]}}.
+
+
diff --git a/src/mod_configure.erl b/src/mod_configure.erl
index fe89a2ded..6d0f1f2fc 100644
--- a/src/mod_configure.erl
+++ b/src/mod_configure.erl
@@ -244,7 +244,7 @@ get_form(["config", "acls"], Lang) ->
{xmlelement, "value", [], [{xmlcdata, S}]}
end,
string:tokens(
- lists:flatten(io_lib:format("~p",
+ lists:flatten(io_lib:format("~p.",
[ets:tab2list(acl)])),
"\n"))
%{xmlelement, "value", [], [{xmlcdata, ?MYNAME}]}
@@ -343,22 +343,19 @@ set_form(["running nodes", ENode, "modules", "start"], Lang, XData) ->
{ok, Tokens, _} ->
case erl_parse:parse_term(Tokens) of
{ok, Modules} ->
- case catch lists:foreach(
- fun({Module, Args}) ->
- gen_mod:start_module(
- Module, Args)
- end, Modules) of
- {'EXIT', Reason} ->
- {error,
- "500", "Internal Server Error"};
- _ ->
- {result, []}
- end;
+ lists:foreach(
+ fun({Module, Args}) ->
+ rpc:call(Node,
+ gen_mod,
+ start_module,
+ [Module, Args])
+ end, Modules),
+ {result, []};
_ ->
- {error, "500", "Internal Server Error"}
+ {error, "406", "Not Acceptable"}
end;
_ ->
- {error, "500", "Internal Server Error"}
+ {error, "406", "Not Acceptable"}
end;
_ ->
{error, "406", "Not Acceptable"}
@@ -379,6 +376,32 @@ set_form(["config", "hostname"], Lang, XData) ->
{error, "406", "Not Acceptable"}
end;
+set_form(["config", "acls"], Lang, XData) ->
+ case lists:keysearch("acls", 1, XData) of
+ {value, {_, Strings}} ->
+ String = lists:foldl(fun(S, Res) ->
+ Res ++ S ++ "\n"
+ end, "", Strings),
+ case erl_scan:string(String) of
+ {ok, Tokens, _} ->
+ case erl_parse:parse_term(Tokens) of
+ {ok, ACLs} ->
+ case acl:add_list(ACLs, true) of
+ ok ->
+ {result, []};
+ _ ->
+ {error, "406", "Not Acceptable"}
+ end;
+ _ ->
+ {error, "406", "Not Acceptable"}
+ end;
+ _ ->
+ {error, "406", "Not Acceptable"}
+ end;
+ _ ->
+ {error, "406", "Not Acceptable"}
+ end;
+
set_form(["config", "remusers"], Lang, XData) ->
lists:foreach(
fun({Var, Vals}) ->
diff --git a/src/msgs/ru.msg b/src/msgs/ru.msg
index 429a6cb78..9469549bb 100644
--- a/src/msgs/ru.msg
+++ b/src/msgs/ru.msg
@@ -1,11 +1,44 @@
% $Id$
+% mod_configure.erl
+{"DB Tables Configuration", "Конфигурация таблиц БД"}.
+{"Choose storage type of tables", "Выберите тип хранения таблиц"}.
+{"", ""}.
+{"", ""}.
+{"", ""}.
+{"", ""}.
+{"", ""}.
+{"", ""}.
+{"", ""}.
+{"", ""}.
+{"", ""}.
+{"", ""}.
+{"", ""}.
+{"", ""}.
+{"", ""}.
+{"", ""}.
+{"", ""}.
+{"", ""}.
+
% mod_disco.erl
+{"Configuration", "Конфигурация"}.
{"Online Users", "Подключённые пользователи"}.
{"All Users", "Все пользователи"}.
{"Outgoing S2S connections", "Исходящие S2S-соединения"}.
{"To ~s", "К ~s"}.
{"From ~s", "От ~s"}.
+{"Running Nodes", "Работающие узлы"}.
+{"Stopped Nodes", "Остановленные узлы"}.
+{"Host Name", "Имя хоста"}.
+{"ACLs", "ACLs"}.
+{"Access Rules", "Правила доступа"}.
+{"Remove Users", "Удаление пользователей"}.
+{"DB", "БД"}.
+{"Modules", "Модули"}.
+{"Start Modules", "Запуск модулей"}.
+{"Stop Modules", "Остановка модулей"}.
+
+
% mod_vcard.erl