diff options
author | Alexey Shchepin <alexey@process-one.net> | 2003-02-01 20:21:28 +0000 |
---|---|---|
committer | Alexey Shchepin <alexey@process-one.net> | 2003-02-01 20:21:28 +0000 |
commit | 6599d1ecc544d48a2a5597f1618b1376d1294d5a (patch) | |
tree | b654ef1df8e3174f40fe7af5efcf1390532ca769 | |
parent | *** empty log message *** (diff) |
*** empty log message ***
SVN Revision: 55
-rw-r--r-- | doc/guide.html | 102 | ||||
-rw-r--r-- | doc/guide.tex | 98 | ||||
-rw-r--r-- | src/Makefile | 5 | ||||
-rw-r--r-- | src/acl.erl | 121 | ||||
-rw-r--r-- | src/ejabberd.app | 54 | ||||
-rw-r--r-- | src/ejabberd.cfg | 11 | ||||
-rw-r--r-- | src/ejabberd.erl | 112 | ||||
-rw-r--r-- | src/ejabberd_app.erl | 79 | ||||
-rw-r--r-- | src/ejabberd_c2s.erl | 59 | ||||
-rw-r--r-- | src/ejabberd_config.erl | 70 | ||||
-rw-r--r-- | src/ejabberd_listener.erl | 8 | ||||
-rw-r--r-- | src/ejabberd_local.erl | 9 | ||||
-rw-r--r-- | src/ejabberd_router.erl | 6 | ||||
-rw-r--r-- | src/ejabberd_s2s.erl | 6 | ||||
-rw-r--r-- | src/ejabberd_s2s_in.erl | 4 | ||||
-rw-r--r-- | src/ejabberd_service.erl | 22 | ||||
-rw-r--r-- | src/ejabberd_sm.erl | 6 | ||||
-rw-r--r-- | src/ejabberd_sup.erl | 54 | ||||
-rw-r--r-- | src/mod_configure.erl | 51 | ||||
-rw-r--r-- | src/msgs/ru.msg | 33 |
20 files changed, 678 insertions, 232 deletions
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.<BR> <BR> +To override old values following lines can be added in config: +<PRE> +override_global. +override_local. +override_acls. +</PRE>With this lines old global or local options or ACLs will be removed before +adding new ones.<BR> +<BR> <!--TOC subsubsection Host Name--> <H4>3.1.1 Host Name</H4><!--SEC END --> @@ -109,42 +117,9 @@ used.<BR> serves. E. g. to use <TT>jabber.org</TT> domain add following line in config: <PRE> {host, "jabber.org"}. -</PRE><!--TOC subsubsection Listened Sockets--> - -<H4>3.1.2 Listened Sockets</H4><!--SEC END --> - -<A NAME="sec:configlistened"></A>Option <TT>listen</TT> defines list of listened sockets and what services -runned on them. Each element of list is a tuple with following elements: -<UL> -<LI> - Port number; - -<LI> Module that serves this port; - -<LI> Function in this module that starts connection (likely will be removed); - -<LI> Options to this module. -</UL>Currently three modules implemented: -<UL> -<LI> - <TT>ejabberd_c2s</TT>: serves C2S connections; - -<LI> <TT>ejabberd_s2s_in</TT>: serves incoming S2S connections; - -<LI> <TT>ejabberd_service</TT>: serves connections to Jabber services - (i. e. that use <TT>jabber:component:accept</TT> namespace). -</UL>For example, following configuration defines that C2S connections listened on -port 5222, S2S on port 5269 and that service <TT>conference.jabber.org</TT> -must be connected to port 8888 with password ``<TT>secret</TT>''.<BR> -<BR> -<PRE> -{listen, [{5222, ejabberd_c2s, start, []}, - {5269, ejabberd_s2s_in, start, []}, - {8888, ejabberd_service, start, ["conference.jabber.org", "secret"]} - ]}. </PRE><!--TOC subsubsection Access Rules--> -<H4>3.1.3 Access Rules</H4><!--SEC END --> +<H4>3.1.2 Access Rules</H4><!--SEC END --> <A NAME="sec:configaccess"></A>Access control in <TT>ejabberd</TT> 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 <TT>`['</TT> is a <TT>`!'</TT>, then any character not enclosed is matched. </DL> +</DL>Following ACLs pre-defined: +<DL COMPACT=compact> +<DT> +<TT>all</TT><DD> Matches all JIDs. + +<DT><TT>none</TT><DD> Matches none JIDs. </DL>Allowing or denying of different services is like this: <PRE> {access, <accessname>, [{allow, <aclname>}, @@ -229,6 +210,57 @@ Example: {access, configure, [{allow, admin}]}. {access, something, [{deny, badmans}, {allow, all}]}. +</PRE>Following access rules pre-defined: +<DL COMPACT=compact> +<DT> +<TT>all</TT><DD> Always return ``<TT>allow</TT>'' + +<DT><TT>none</TT><DD> Always return ``<TT>deny</TT>'' +</DL><!--TOC subsubsection Listened Sockets--> + +<H4>3.1.3 Listened Sockets</H4><!--SEC END --> + +<A NAME="sec:configlistened"></A>Option <TT>listen</TT> defines list of listened sockets and what services +runned on them. Each element of list is a tuple with following elements: +<UL> +<LI> + Port number; + +<LI> Module that serves this port; + +<LI> Function in this module that starts connection (likely will be removed); + +<LI> Options to this module. +</UL>Currently three modules implemented: +<DL COMPACT=compact> +<DT> +<TT>ejabberd_c2s</TT><DD> This module serves C2S connections.<BR> +<BR> + Following options defined: + <DL COMPACT=compact> +<DT> + <TT>{access, <access rule>}</TT><DD> This option defines access of users + to this C2S port. Default value is ``<TT>all</TT>''. + </DL> + +<DT><TT>ejabberd_s2s_in</TT><DD> This module serves incoming S2S connections. + +<DT><TT>ejabberd_service</TT><DD> This module serves connections to Jabber + services (i. e. that use <TT>jabber:component:accept</TT> namespace). +</DL>For example, following configuration defines that C2S connections listened on +port 5222 and denied for user ``<TT>bad</TT>'', S2S on port 5269 and that +service <TT>conference.jabber.org</TT> must be connected to port 8888 with +password ``<TT>secret</TT>''.<BR> +<BR> +<PRE> +{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"}]}]} + ]}. </PRE><!--TOC subsubsection Modules--> <H4>3.1.4 Modules</H4><!--SEC END --> @@ -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 <TT>~ejabberd/.erlang.cookie</TT> must be the same on all nodes). This is needed because all nodes exchange information about connected users, S2S -connection, registered services, etc...<BR> +connections, registered services, etc...<BR> <BR> Each <TT>ejabberd</TT> node run following modules: <UL> 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, <accessname>, [{allow, <aclname>}, @@ -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, <access rule>\}}] 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, []). - -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). + application:start(mnesia), + application:start(ejabberd). +stop() -> + application:stop(ejabberd). -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). +%-include("ejabberd.hrl"). -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 <alexey@sevcom.net> +%%% Purpose : +%%% Created : 31 Jan 2003 by Alexey Shchepin <alexey@sevcom.net> +%%% 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 <alexey@sevcom.net> +%%% Purpose : +%%% Created : 31 Jan 2003 by Alexey Shchepin <alexey@sevcom.net> +%%% 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 |