mirror of
https://github.com/processone/ejabberd.git
synced 2024-12-20 17:27:00 +01:00
Introduce option 'ca_file'
The option is supposed to be used as a fallback for certificates validation. For instance, the option will be used if 's2s_cafile' option is not set. The value should be a path to a file containing CA certificate(s) in PEM format, e.g.: ca_file: "/etc/ssl/certs/ca-bundle.pem"
This commit is contained in:
parent
242b3d3968
commit
783ebd1080
@ -28,7 +28,7 @@
|
||||
%% API
|
||||
-export([start_link/0, add_certfile/1, format_error/1, opt_type/1,
|
||||
get_certfile/1, try_certfile/1, route_registered/1,
|
||||
config_reloaded/0, certs_dir/0]).
|
||||
config_reloaded/0, certs_dir/0, ca_file/0]).
|
||||
%% gen_server callbacks
|
||||
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
|
||||
terminate/2, code_change/3]).
|
||||
@ -146,7 +146,11 @@ config_reloaded() ->
|
||||
gen_server:call(?MODULE, config_reloaded, 60000).
|
||||
|
||||
opt_type(ca_path) ->
|
||||
fun(Path) -> iolist_to_binary(Path) end;
|
||||
fun(Path) -> binary_to_list(Path) end;
|
||||
opt_type(ca_file) ->
|
||||
fun(Path) ->
|
||||
binary_to_list(misc:try_read_file(Path))
|
||||
end;
|
||||
opt_type(certfiles) ->
|
||||
fun(CertList) ->
|
||||
[binary_to_list(Path) || Path <- CertList]
|
||||
@ -157,7 +161,7 @@ opt_type(O) when O == c2s_certfile; O == s2s_certfile; O == domain_certfile ->
|
||||
misc:try_read_file(File)
|
||||
end;
|
||||
opt_type(_) ->
|
||||
[ca_path, certfiles, c2s_certfile, s2s_certfile, domain_certfile].
|
||||
[ca_path, ca_file, certfiles, c2s_certfile, s2s_certfile, domain_certfile].
|
||||
|
||||
%%%===================================================================
|
||||
%%% gen_server callbacks
|
||||
@ -175,7 +179,7 @@ init([]) ->
|
||||
erlang:function_exported(
|
||||
public_key, short_name_hash, 1)
|
||||
end,
|
||||
if Validate -> check_ca_dir();
|
||||
if Validate -> check_ca();
|
||||
true -> ok
|
||||
end,
|
||||
State = #state{validate = Validate, notify = Notify},
|
||||
@ -524,6 +528,10 @@ validate_path([Cert|_] = Certs) ->
|
||||
ca_dir() ->
|
||||
ejabberd_config:get_option(ca_path, "/etc/ssl/certs").
|
||||
|
||||
-spec ca_file() -> string() | undefined.
|
||||
ca_file() ->
|
||||
ejabberd_config:get_option(ca_file).
|
||||
|
||||
-spec certs_dir() -> string().
|
||||
certs_dir() ->
|
||||
MnesiaDir = mnesia:system_info(directory),
|
||||
@ -543,11 +551,12 @@ clean_dir(Dir) ->
|
||||
end
|
||||
end, Files).
|
||||
|
||||
-spec check_ca_dir() -> ok.
|
||||
check_ca_dir() ->
|
||||
-spec check_ca() -> ok.
|
||||
check_ca() ->
|
||||
CAFile = ca_file(),
|
||||
case wildcard(filename:join(ca_dir(), "*.0")) of
|
||||
[] ->
|
||||
Hint = "configuring 'ca_path' option might help",
|
||||
[] when CAFile == undefined ->
|
||||
Hint = "configuring 'ca_path' or 'ca_file' options might help",
|
||||
case file:list_dir(ca_dir()) of
|
||||
{error, Why} ->
|
||||
?WARNING_MSG("failed to read CA directory ~s: ~s; ~s",
|
||||
@ -563,10 +572,23 @@ check_ca_dir() ->
|
||||
|
||||
-spec find_local_issuer(cert()) -> {ok, cert()} | {error, {bad_cert, unknown_ca}}.
|
||||
find_local_issuer(Cert) ->
|
||||
case find_issuer_in_dir(Cert, ca_dir()) of
|
||||
{ok, IssuerCert} ->
|
||||
{ok, IssuerCert};
|
||||
{error, _} = Err ->
|
||||
case ca_file() of
|
||||
undefined -> Err;
|
||||
CAFile -> find_issuer_in_file(Cert, CAFile)
|
||||
end
|
||||
end.
|
||||
|
||||
-spec find_issuer_in_dir(cert(), file:filename_all())
|
||||
-> {ok, cert()} | {error, {bad_cert, unknown_ca}}.
|
||||
find_issuer_in_dir(Cert, CADir) ->
|
||||
{ok, {_, IssuerID}} = public_key:pkix_issuer_id(Cert, self),
|
||||
Hash = short_name_hash(IssuerID),
|
||||
filelib:fold_files(
|
||||
ca_dir(), Hash ++ "\\.[0-9]+", false,
|
||||
CADir, Hash ++ "\\.[0-9]+", false,
|
||||
fun(_, {ok, IssuerCert}) ->
|
||||
{ok, IssuerCert};
|
||||
(CertFile, Acc) ->
|
||||
@ -586,6 +608,29 @@ find_local_issuer(Cert) ->
|
||||
end
|
||||
end, {error, {bad_cert, unknown_ca}}).
|
||||
|
||||
-spec find_issuer_in_file(cert(), file:filename_all() | undefined)
|
||||
-> {ok, cert()} | {error, {bad_cert, unknown_ca}}.
|
||||
find_issuer_in_file(_Cert, undefined) ->
|
||||
{error, {bad_cert, unknown_ca}};
|
||||
find_issuer_in_file(Cert, CAFile) ->
|
||||
try
|
||||
{ok, Data} = file:read_file(CAFile),
|
||||
{ok, IssuerCerts, _} = pem_decode(Data),
|
||||
lists:foldl(
|
||||
fun(_, {ok, _} = Res) ->
|
||||
Res;
|
||||
(IssuerCert, Err) ->
|
||||
case public_key:pkix_is_issuer(Cert, IssuerCert) of
|
||||
true -> {ok, IssuerCert};
|
||||
false -> Err
|
||||
end
|
||||
end, {error, {bad_cert, unknown_ca}}, IssuerCerts)
|
||||
catch _:{badmatch, {error, Why}} ->
|
||||
?ERROR_MSG("failed to read CA certificates from \"~s\": ~s",
|
||||
[CAFile, format_error(Why)]),
|
||||
{error, {bad_cert, unknown_ca}}
|
||||
end.
|
||||
|
||||
-spec match_cert_keys([{path, [cert()]}], [priv_key()])
|
||||
-> {ok, [{cert(), priv_key()}]} | {error, {bad_cert, missing_priv_key}}.
|
||||
match_cert_keys(CertPaths, PrivKeys) ->
|
||||
|
@ -222,8 +222,7 @@ tls_options(LServer, DefaultOpts) ->
|
||||
DHFile -> lists:keystore(dhfile, 1, TLSOpts3,
|
||||
{dhfile, DHFile})
|
||||
end,
|
||||
TLSOpts5 = case ejabberd_config:get_option(
|
||||
{s2s_cafile, LServer}) of
|
||||
TLSOpts5 = case get_cafile(LServer) of
|
||||
undefined -> TLSOpts4;
|
||||
CAFile -> lists:keystore(cafile, 1, TLSOpts4,
|
||||
{cafile, CAFile})
|
||||
@ -267,7 +266,7 @@ queue_type(LServer) ->
|
||||
{s2s_queue_type, LServer},
|
||||
ejabberd_config:default_queue_type(LServer)).
|
||||
|
||||
-spec get_certfile(binary()) -> file:filename_all().
|
||||
-spec get_certfile(binary()) -> file:filename_all() | undefined.
|
||||
get_certfile(LServer) ->
|
||||
case ejabberd_pkix:get_certfile(LServer) of
|
||||
{ok, CertFile} ->
|
||||
@ -278,6 +277,15 @@ get_certfile(LServer) ->
|
||||
ejabberd_config:get_option({s2s_certfile, LServer}))
|
||||
end.
|
||||
|
||||
-spec get_cafile(binary()) -> file:filename_all() | undefined.
|
||||
get_cafile(LServer) ->
|
||||
case ejabberd_config:get_option({s2s_cafile, LServer}) of
|
||||
undefined ->
|
||||
ejabberd_pkix:ca_file();
|
||||
File ->
|
||||
File
|
||||
end.
|
||||
|
||||
%%====================================================================
|
||||
%% gen_server callbacks
|
||||
%%====================================================================
|
||||
|
Loading…
Reference in New Issue
Block a user