diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index 92f2a3bdc..ac48444cb 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -904,10 +904,10 @@ transform_listen_option(Opt, Opts) -> (resource_conflict) -> fun((resource_conflict()) -> resource_conflict()); (disable_sasl_mechanisms) -> fun((binary() | [binary()]) -> [binary()]); (atom()) -> [atom()]. -opt_type(c2s_certfile) -> fun iolist_to_binary/1; -opt_type(c2s_ciphers) -> fun iolist_to_binary/1; -opt_type(c2s_dhfile) -> fun iolist_to_binary/1; -opt_type(c2s_cafile) -> fun iolist_to_binary/1; +opt_type(c2s_certfile) -> fun misc:try_read_file/1; +opt_type(c2s_ciphers) -> fun misc:try_read_file/1; +opt_type(c2s_dhfile) -> fun misc:try_read_file/1; +opt_type(c2s_cafile) -> fun misc:try_read_file/1; opt_type(c2s_protocol_options) -> fun (Options) -> str:join(Options, <<"|">>) end; opt_type(c2s_tls_compression) -> diff --git a/src/ejabberd_config.erl b/src/ejabberd_config.erl index 75f64ecb5..1dc30b1c5 100644 --- a/src/ejabberd_config.erl +++ b/src/ejabberd_config.erl @@ -1417,7 +1417,7 @@ opt_type(cache_life_time) -> (unlimited) -> infinity end; opt_type(domain_certfile) -> - fun iolist_to_binary/1; + fun misc:try_read_file/1; opt_type(shared_key) -> fun iolist_to_binary/1; opt_type(node_start) -> diff --git a/src/ejabberd_http.erl b/src/ejabberd_http.erl index 06da10c9c..e19fbac44 100644 --- a/src/ejabberd_http.erl +++ b/src/ejabberd_http.erl @@ -926,11 +926,11 @@ opt_type(_) -> [trusted_proxies]. listen_opt_type(tls) -> fun(B) when is_boolean(B) -> B end; listen_opt_type(certfile) -> - fun iolist_to_binary/1; + fun misc:try_read_file/1; listen_opt_type(ciphers) -> - fun iolist_to_binary/1; + fun misc:try_read_file/1; listen_opt_type(dhfile) -> - fun iolist_to_binary/1; + fun misc:try_read_file/1; listen_opt_type(protocol_options) -> fun(Options) -> str:join(Options, <<"|">>) end; listen_opt_type(tls_compression) -> diff --git a/src/ejabberd_listener.erl b/src/ejabberd_listener.erl index 653ad931a..6dd8e706d 100644 --- a/src/ejabberd_listener.erl +++ b/src/ejabberd_listener.erl @@ -90,14 +90,7 @@ start(Port, Module, Opts) -> %% @spec(Port, Module, Opts) -> {ok, Pid} | {error, ErrorMessage} start_dependent(Port, Module, 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. + proc_lib:start_link(?MODULE, init, [Port, Module, Opts]). init(PortIP, Module, RawOpts) -> {Port, IPT, IPS, IPV, Proto, OptsClean} = parse_listener_portip(PortIP, RawOpts), @@ -456,48 +449,6 @@ config_reloaded() -> %%% %%% 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} -> - PathS = binary_to_list(Path), - case ejabberd_config:is_file_readable(PathS) of - true -> true; - false -> {false, PathS} - end - end. - get_proto(Opts) -> case proplists:get_value(proto, Opts) of undefined -> diff --git a/src/ejabberd_s2s.erl b/src/ejabberd_s2s.erl index a447dcd67..9e9a94754 100644 --- a/src/ejabberd_s2s.erl +++ b/src/ejabberd_s2s.erl @@ -709,10 +709,10 @@ opt_type(route_subdomains) -> end; opt_type(s2s_access) -> fun acl:access_rules_validator/1; -opt_type(s2s_certfile) -> fun iolist_to_binary/1; -opt_type(s2s_ciphers) -> fun iolist_to_binary/1; -opt_type(s2s_dhfile) -> fun iolist_to_binary/1; -opt_type(s2s_cafile) -> fun iolist_to_binary/1; +opt_type(s2s_certfile) -> fun misc:try_read_file/1; +opt_type(s2s_ciphers) -> fun misc:try_read_file/1; +opt_type(s2s_dhfile) -> fun misc:try_read_file/1; +opt_type(s2s_cafile) -> fun misc:try_read_file/1; opt_type(s2s_protocol_options) -> fun (Options) -> str:join(Options, <<"|">>) end; opt_type(s2s_tls_compression) -> diff --git a/src/ejabberd_service.erl b/src/ejabberd_service.erl index 9829d6b6c..fff0eca5b 100644 --- a/src/ejabberd_service.erl +++ b/src/ejabberd_service.erl @@ -276,10 +276,10 @@ transform_listen_option(Opt, Opts) -> (atom()) -> [atom()]. listen_opt_type(access) -> fun acl:access_rules_validator/1; listen_opt_type(shaper_rule) -> fun acl:shaper_rules_validator/1; -listen_opt_type(certfile) -> fun iolist_to_binary/1; -listen_opt_type(ciphers) -> fun iolist_to_binary/1; -listen_opt_type(dhfile) -> fun iolist_to_binary/1; -listen_opt_type(cafile) -> fun iolist_to_binary/1; +listen_opt_type(certfile) -> fun misc:try_read_file/1; +listen_opt_type(ciphers) -> fun misc:try_read_file/1; +listen_opt_type(dhfile) -> fun misc:try_read_file/1; +listen_opt_type(cafile) -> fun misc:try_read_file/1; listen_opt_type(protocol_options) -> fun(Options) -> str:join(Options, <<"|">>) end; listen_opt_type(tls_compression) -> fun(B) when is_boolean(B) -> B end; diff --git a/src/ejabberd_sip.erl b/src/ejabberd_sip.erl index 5ee81cfa1..ee1f33c83 100644 --- a/src/ejabberd_sip.erl +++ b/src/ejabberd_sip.erl @@ -47,7 +47,7 @@ socket_type() -> raw. listen_opt_type(certfile) -> - fun iolist_to_binary/1; + fun misc:try_read_file/1; listen_opt_type(tls) -> fun(B) when is_boolean(B) -> B end; listen_opt_type(_) -> diff --git a/src/ejabberd_sql.erl b/src/ejabberd_sql.erl index dc6292ce4..7d607781c 100644 --- a/src/ejabberd_sql.erl +++ b/src/ejabberd_sql.erl @@ -1104,8 +1104,8 @@ opt_type(sql_server) -> fun iolist_to_binary/1; opt_type(sql_username) -> fun iolist_to_binary/1; opt_type(sql_ssl) -> fun(B) when is_boolean(B) -> B end; opt_type(sql_ssl_verify) -> fun(B) when is_boolean(B) -> B end; -opt_type(sql_ssl_certfile) -> fun iolist_to_binary/1; -opt_type(sql_ssl_cafile) -> fun iolist_to_binary/1; +opt_type(sql_ssl_certfile) -> fun misc:try_read_file/1; +opt_type(sql_ssl_cafile) -> fun misc:try_read_file/1; opt_type(sql_query_timeout) -> fun (I) when is_integer(I), I > 0 -> I end; opt_type(sql_connect_timeout) -> diff --git a/src/ejabberd_stun.erl b/src/ejabberd_stun.erl index 47a6b89de..7557df598 100644 --- a/src/ejabberd_stun.erl +++ b/src/ejabberd_stun.erl @@ -114,7 +114,7 @@ listen_opt_type(auth_realm) -> listen_opt_type(tls) -> fun(B) when is_boolean(B) -> B end; listen_opt_type(certfile) -> - fun iolist_to_binary/1; + fun misc:try_read_file/1; listen_opt_type(turn_min_port) -> fun(P) when is_integer(P), P > 0, P =< 65535 -> P end; listen_opt_type(turn_max_port) -> diff --git a/src/eldap_utils.erl b/src/eldap_utils.erl index 3704d2ce5..1dcdf0b48 100644 --- a/src/eldap_utils.erl +++ b/src/eldap_utils.erl @@ -367,7 +367,7 @@ opt_type(ldap_rootdn) -> fun iolist_to_binary/1; opt_type(ldap_servers) -> fun (L) -> [iolist_to_binary(H) || H <- L] end; opt_type(ldap_tls_cacertfile) -> - fun(S) -> binary_to_list(iolist_to_binary(S)) end; + fun(S) -> binary_to_list(misc:try_read_file(S)) end; opt_type(ldap_tls_depth) -> fun (I) when is_integer(I), I >= 0 -> I end; opt_type(ldap_tls_verify) -> diff --git a/src/misc.erl b/src/misc.erl index dae95c6d5..b8bbe0e48 100644 --- a/src/misc.erl +++ b/src/misc.erl @@ -33,7 +33,11 @@ hex_to_bin/1, hex_to_base64/1, expand_keyword/3, atom_to_binary/1, binary_to_atom/1, tuple_to_binary/1, l2i/1, i2l/1, i2l/2, expr_to_term/1, term_to_expr/1, - encode_pid/1, decode_pid/2, compile_exprs/2, join_atoms/2]). + encode_pid/1, decode_pid/2, compile_exprs/2, join_atoms/2, + try_read_file/1]). + +-include("logger.hrl"). +-include_lib("kernel/include/file.hrl"). %%%=================================================================== %%% API @@ -241,6 +245,30 @@ compile_exprs(Mod, Exprs) -> join_atoms(Atoms, Sep) -> str:join([io_lib:format("~p", [A]) || A <- Atoms], Sep). +%% @doc Checks if the file is readable and converts its name to binary. +%% Fails with `badarg` otherwise. The function is intended for usage +%% in configuration validators only. +-spec try_read_file(file:filename_all()) -> binary(). +try_read_file(Path) -> + Res = case file:read_file_info(Path) of + {ok, #file_info{type = Type, access = Access}} -> + case {Type, Access} of + {regular, read} -> ok; + {regular, read_write} -> ok; + {regular, _} -> {error, file:format_error(eaccess)}; + _ -> {error, "not a regular file"} + end; + {error, Why} -> + {error, file:format_error(Why)} + end, + case Res of + ok -> + iolist_to_binary(Path); + {error, Reason} -> + ?ERROR_MSG("Failed to read ~s: ~s", [Path, Reason]), + erlang:error(badarg) + end. + %%%=================================================================== %%% Internal functions %%%=================================================================== diff --git a/src/mod_muc_log.erl b/src/mod_muc_log.erl index 45ee645fc..9bf983422 100644 --- a/src/mod_muc_log.erl +++ b/src/mod_muc_log.erl @@ -1170,7 +1170,7 @@ has_no_permanent_store_hint(Packet) -> mod_opt_type(access_log) -> fun acl:access_rules_validator/1; -mod_opt_type(cssfile) -> fun iolist_to_binary/1; +mod_opt_type(cssfile) -> fun misc:try_read_file/1; mod_opt_type(dirname) -> fun (room_jid) -> room_jid; (room_name) -> room_name diff --git a/src/mod_shared_roster_ldap.erl b/src/mod_shared_roster_ldap.erl index bc7694fe4..24bd3233c 100644 --- a/src/mod_shared_roster_ldap.erl +++ b/src/mod_shared_roster_ldap.erl @@ -603,9 +603,9 @@ mod_opt_type(ldap_rootdn) -> fun iolist_to_binary/1; mod_opt_type(ldap_servers) -> fun (L) -> [iolist_to_binary(H) || H <- L] end; mod_opt_type(ldap_tls_cacertfile) -> - fun iolist_to_binary/1; + fun misc:try_read_file/1; mod_opt_type(ldap_tls_certfile) -> - fun iolist_to_binary/1; + fun misc:try_read_file/1; mod_opt_type(ldap_tls_depth) -> fun (I) when is_integer(I), I >= 0 -> I end; mod_opt_type(ldap_tls_verify) -> diff --git a/src/mod_vcard_ldap.erl b/src/mod_vcard_ldap.erl index 967a2c4cf..fe11d0962 100644 --- a/src/mod_vcard_ldap.erl +++ b/src/mod_vcard_ldap.erl @@ -467,9 +467,9 @@ mod_opt_type(ldap_rootdn) -> fun iolist_to_binary/1; mod_opt_type(ldap_servers) -> fun (L) -> [iolist_to_binary(H) || H <- L] end; mod_opt_type(ldap_tls_cacertfile) -> - fun iolist_to_binary/1; + fun misc:try_read_file/1; mod_opt_type(ldap_tls_certfile) -> - fun iolist_to_binary/1; + fun misc:try_read_file/1; mod_opt_type(ldap_tls_depth) -> fun (I) when is_integer(I), I >= 0 -> I end; mod_opt_type(ldap_tls_verify) ->