diff --git a/ChangeLog b/ChangeLog index 945545cce..c3562c717 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2009-02-16 Badlop + * src/ejabberd_config.erl: Check certfiles are readable on server + start and listener start (EJAB-753) + * src/ejabberd_listener.erl: Likewise + * src/mod_privacy.erl: Privacy List: deny presence-out all + send presence to: presence is sent (EJAB-255) * src/ejabberd_c2s.erl: Likewise diff --git a/src/ejabberd_config.erl b/src/ejabberd_config.erl index dc54ee884..bfd505352 100644 --- a/src/ejabberd_config.erl +++ b/src/ejabberd_config.erl @@ -31,9 +31,11 @@ add_global_option/2, add_local_option/2, get_global_option/1, get_local_option/1]). -export([get_vh_by_auth_method/1]). +-export([is_file_readable/1]). -include("ejabberd.hrl"). -include("ejabberd_config.hrl"). +-include_lib("kernel/include/file.hrl"). %% @type macro() = {macro_key(), macro_value()} @@ -79,6 +81,7 @@ get_ejabberd_config_path() -> %% @doc Load the ejabberd configuration file. %% It also includes additional configuration files and replaces macros. +%% This function will crash if finds some error in the configuration file. %% @spec (File::string()) -> ok load_file(File) -> Terms = get_plain_terms_file(File), @@ -343,9 +346,21 @@ process_term(Term, State) -> {s2s_use_starttls, Port} -> add_option(s2s_use_starttls, Port, State); {s2s_certfile, CertFile} -> - add_option(s2s_certfile, CertFile, State); + case ejabberd_config:is_file_readable(CertFile) of + true -> add_option(s2s_certfile, CertFile, State); + false -> + ErrorText = "There is a problem in the configuration: " + "the specified file is not readable: ", + throw({error, ErrorText ++ CertFile}) + end; {domain_certfile, Domain, CertFile} -> - add_option({domain_certfile, Domain}, CertFile, State); + case ejabberd_config:is_file_readable(CertFile) of + true -> add_option({domain_certfile, Domain}, CertFile, State); + false -> + ErrorText = "There is a problem in the configuration: " + "the specified file is not readable: ", + throw({error, ErrorText ++ CertFile}) + end; {node_type, NodeType} -> add_option(node_type, NodeType, State); {cluster_nodes, Nodes} -> @@ -517,3 +532,16 @@ get_vh_by_auth_method(AuthMethod) -> mnesia:dirty_select(local_config, [{#local_config{key = {auth_method, '$1'}, value=AuthMethod},[],['$1']}]). + +%% @spec (Path::string()) -> true | false +is_file_readable(Path) -> + case file:read_file_info(Path) of + {ok, FileInfo} -> + case {FileInfo#file_info.type, FileInfo#file_info.access} of + {regular, read} -> true; + {regular, read_write} -> true; + _ -> false + end; + {error, _Reason} -> + false + end. diff --git a/src/ejabberd_listener.erl b/src/ejabberd_listener.erl index 5ca3bdeb0..df3e343d8 100644 --- a/src/ejabberd_listener.erl +++ b/src/ejabberd_listener.erl @@ -86,28 +86,15 @@ start(Port, Module, Opts) -> _ -> start_dependent(Port, Module, Opts) end. -%% -> {ok, Pid} | {error, ErrorMessage} +%% @spec(Port, Module, Opts) -> {ok, Pid} | {error, ErrorMessage} start_dependent(Port, Module, Opts) -> - case includes_deprecated_ssl_option(Opts) of - false -> - proc_lib:start_link(?MODULE, init, [Port, Module, Opts]); - true -> - SSLErr="There is a problem with your ejabberd configuration file: " - "the option 'ssl' for listening sockets is no longer available." - "To get SSL encryption use the option 'tls'.", - ?ERROR_MSG(SSLErr, []), - {error, SSLErr} - end. - -%% Parse the options of the socket, -%% and return if the deprecated option 'ssl' is included -%% @spec(Opts::[opt()]) -> true | false -includes_deprecated_ssl_option(Opts) -> - case lists:keysearch(ssl, 1, Opts) of - {value, {ssl, _SSLOpts}} -> - true; - _ -> - lists:member(ssl, Opts) + try check_listener_options(Opts) of + ok -> + proc_lib:start_link(?MODULE, init, [Port, Module, Opts]) + catch + throw:{error, Error} -> + ?ERROR_MSG(Error, []), + {error, Error} end. init(PortIP, Module, Opts1) -> @@ -331,3 +318,48 @@ is_frontend(_) -> false. %% where FrontMod = atom() | {frontend, atom()} strip_frontend({frontend, Module}) -> Module; strip_frontend(Module) when is_atom(Module) -> Module. + + +%%% +%%% Check options +%%% + +check_listener_options(Opts) -> + case includes_deprecated_ssl_option(Opts) of + false -> ok; + true -> + Error = "There is a problem with your ejabberd configuration file: " + "the option 'ssl' for listening sockets is no longer available." + " To get SSL encryption use the option 'tls'.", + throw({error, Error}) + end, + case certfile_readable(Opts) of + true -> ok; + {false, Path} -> + ErrorText = "There is a problem in the configuration: " + "the specified file is not readable: ", + throw({error, ErrorText ++ Path}) + end, + ok. + +%% Parse the options of the socket, +%% and return if the deprecated option 'ssl' is included +%% @spec (Opts) -> true | false +includes_deprecated_ssl_option(Opts) -> + case lists:keysearch(ssl, 1, Opts) of + {value, {ssl, _SSLOpts}} -> + true; + _ -> + lists:member(ssl, Opts) + end. + +%% @spec (Opts) -> true | {false, Path::string()} +certfile_readable(Opts) -> + case proplists:lookup(certfile, Opts) of + none -> true; + {certfile, Path} -> + case ejabberd_config:is_file_readable(Path) of + true -> true; + false -> {false, Path} + end + end.