25
1
mirror of https://github.com/processone/ejabberd.git synced 2024-11-22 16:20:52 +01:00

Support IDN hostnames in ACME requests

This commit is contained in:
Evgeny Khramtsov 2019-09-22 11:04:38 +03:00
parent d5e0ccb04a
commit a616cc04cb
2 changed files with 34 additions and 14 deletions

View File

@ -24,7 +24,8 @@
{fast_tls, ".*", {git, "https://github.com/processone/fast_tls", {tag, "1.1.2"}}}, {fast_tls, ".*", {git, "https://github.com/processone/fast_tls", {tag, "1.1.2"}}},
{stringprep, ".*", {git, "https://github.com/processone/stringprep", {tag, "1.0.17"}}}, {stringprep, ".*", {git, "https://github.com/processone/stringprep", {tag, "1.0.17"}}},
{fast_xml, ".*", {git, "https://github.com/processone/fast_xml", {tag, "1.1.37"}}}, {fast_xml, ".*", {git, "https://github.com/processone/fast_xml", {tag, "1.1.37"}}},
{xmpp, ".*", {git, "https://github.com/processone/xmpp", "e3181a5"}}, {idna, ".*", {git, "https://github.com/benoitc/erlang-idna", {tag, "6.0.0"}}},
{xmpp, ".*", {git, "https://github.com/processone/xmpp", "984b3c3"}},
{fast_yaml, ".*", {git, "https://github.com/processone/fast_yaml", {tag, "1.0.20"}}}, {fast_yaml, ".*", {git, "https://github.com/processone/fast_yaml", {tag, "1.0.20"}}},
{yconf, ".*", {git, "https://github.com/processone/yconf", {tag, "1.0.0"}}}, {yconf, ".*", {git, "https://github.com/processone/yconf", {tag, "1.0.0"}}},
{jiffy, ".*", {git, "https://github.com/davisp/jiffy", {tag, "0.14.8"}}}, {jiffy, ".*", {git, "https://github.com/davisp/jiffy", {tag, "0.14.8"}}},
@ -33,7 +34,7 @@
{jose, ".*", {git, "https://github.com/potatosalad/erlang-jose", {tag, "1.8.4"}}}, {jose, ".*", {git, "https://github.com/potatosalad/erlang-jose", {tag, "1.8.4"}}},
{eimp, ".*", {git, "https://github.com/processone/eimp", {tag, "1.0.12"}}}, {eimp, ".*", {git, "https://github.com/processone/eimp", {tag, "1.0.12"}}},
{mqtree, ".*", {git, "https://github.com/processone/mqtree", {tag, "1.0.4"}}}, {mqtree, ".*", {git, "https://github.com/processone/mqtree", {tag, "1.0.4"}}},
{acme, ".*", {git, "https://github.com/processone/acme.git", "b4c2899"}}, {acme, ".*", {git, "https://github.com/processone/acme.git", "b312547"}},
{if_var_true, stun, {stun, ".*", {git, "https://github.com/processone/stun", {tag, "1.0.29"}}}}, {if_var_true, stun, {stun, ".*", {git, "https://github.com/processone/stun", {tag, "1.0.29"}}}},
{if_var_true, sip, {esip, ".*", {git, "https://github.com/processone/esip", {tag, "1.0.30"}}}}, {if_var_true, sip, {esip, ".*", {git, "https://github.com/processone/esip", {tag, "1.0.30"}}}},
{if_var_true, mysql, {p1_mysql, ".*", {git, "https://github.com/processone/p1_mysql", {if_var_true, mysql, {p1_mysql, ".*", {git, "https://github.com/processone/p1_mysql",

View File

@ -46,7 +46,9 @@
-type cert() :: #'OTPCertificate'{}. -type cert() :: #'OTPCertificate'{}.
-type cert_type() :: ec | rsa. -type cert_type() :: ec | rsa.
-type io_error() :: file:posix(). -type io_error() :: file:posix().
-type issue_result() :: ok | acme:issue_return() | {error, {file, io_error()}}. -type issue_result() :: ok | acme:issue_return() |
{error, {file, io_error()} |
{idna_failed, binary()}}.
%%%=================================================================== %%%===================================================================
%%% API %%% API
@ -191,17 +193,22 @@ unregister_challenge(Ref) ->
%%%=================================================================== %%%===================================================================
-spec issue_request(state(), [binary(),...]) -> {issue_result(), state()}. -spec issue_request(state(), [binary(),...]) -> {issue_result(), state()}.
issue_request(State, Domains) -> issue_request(State, Domains) ->
case read_account_key() of case check_idna(Domains) of
{ok, AccKey} -> ok ->
Config = ejabberd_option:acme(), case read_account_key() of
DirURL = maps:get(ca_url, Config, default_directory_url()), {ok, AccKey} ->
Contact = maps:get(contact, Config, []), Config = ejabberd_option:acme(),
CertType = maps:get(cert_type, Config, rsa), DirURL = maps:get(ca_url, Config, default_directory_url()),
issue_request(State, DirURL, Domains, AccKey, CertType, Contact); Contact = maps:get(contact, Config, []),
{error, Reason} = Err -> CertType = maps:get(cert_type, Config, rsa),
?ERROR_MSG("Failed to request certificate for ~s: ~s", issue_request(State, DirURL, Domains, AccKey, CertType, Contact);
[misc:format_hosts_list(Domains), {error, Reason} = Err ->
format_error(Reason)]), ?ERROR_MSG("Failed to request certificate for ~s: ~s",
[misc:format_hosts_list(Domains),
format_error(Reason)]),
{Err, State}
end;
{error, _} = Err ->
{Err, State} {Err, State}
end. end.
@ -620,6 +627,16 @@ have_acme_listener() ->
false false
end, ejabberd_option:listen()). end, ejabberd_option:listen()).
-spec check_idna([binary()]) -> ok | {error, {idna_failed, binary()}}.
check_idna([Domain|Domains]) ->
try idna:to_ascii(binary_to_list(Domain)) of
_ -> check_idna(Domains)
catch _:_ ->
{error, {idna_failed, Domain}}
end;
check_idna([]) ->
ok.
-spec format_error(term()) -> string(). -spec format_error(term()) -> string().
format_error({file, Reason}) -> format_error({file, Reason}) ->
"I/O error: " ++ file:format_error(Reason); "I/O error: " ++ file:format_error(Reason);
@ -631,6 +648,8 @@ format_error(invalid_argument) ->
"Invalid argument"; "Invalid argument";
format_error(unexpected_certfile) -> format_error(unexpected_certfile) ->
"The certificate file was not obtained using ACME"; "The certificate file was not obtained using ACME";
format_error({idna_failed, Domain}) ->
"Not an IDN hostname: " ++ binary_to_list(Domain);
format_error({bad_cert, _, _} = Reason) -> format_error({bad_cert, _, _} = Reason) ->
"Malformed certificate file: " ++ pkix:format_error(Reason); "Malformed certificate file: " ++ pkix:format_error(Reason);
format_error(Reason) -> format_error(Reason) ->