Fix IDNA support in ACME requests

This commit is contained in:
Evgeny Khramtsov 2019-09-22 12:44:31 +03:00
parent 30346a56de
commit 75fe6f44d2
2 changed files with 17 additions and 16 deletions

View File

@ -25,7 +25,7 @@
{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"}}},
{idna, ".*", {git, "https://github.com/benoitc/erlang-idna", {tag, "6.0.0"}}}, {idna, ".*", {git, "https://github.com/benoitc/erlang-idna", {tag, "6.0.0"}}},
{xmpp, ".*", {git, "https://github.com/processone/xmpp", "984b3c3"}}, {xmpp, ".*", {git, "https://github.com/processone/xmpp", "3e892bc"}},
{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"}}},
@ -34,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", "b312547"}}, {acme, ".*", {git, "https://github.com/processone/acme.git", "be6405c"}},
{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

@ -194,14 +194,14 @@ 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 check_idna(Domains) of case check_idna(Domains) of
ok -> {ok, AsciiDomains} ->
case read_account_key() of case read_account_key() of
{ok, AccKey} -> {ok, AccKey} ->
Config = ejabberd_option:acme(), Config = ejabberd_option:acme(),
DirURL = maps:get(ca_url, Config, default_directory_url()), DirURL = maps:get(ca_url, Config, default_directory_url()),
Contact = maps:get(contact, Config, []), Contact = maps:get(contact, Config, []),
CertType = maps:get(cert_type, Config, rsa), CertType = maps:get(cert_type, Config, rsa),
issue_request(State, DirURL, Domains, AccKey, CertType, Contact); issue_request(State, DirURL, Domains, AsciiDomains, AccKey, CertType, Contact);
{error, Reason} = Err -> {error, Reason} = Err ->
?ERROR_MSG("Failed to request certificate for ~s: ~s", ?ERROR_MSG("Failed to request certificate for ~s: ~s",
[misc:format_hosts_list(Domains), [misc:format_hosts_list(Domains),
@ -215,12 +215,12 @@ issue_request(State, Domains) ->
{Err, State} {Err, State}
end. end.
-spec issue_request(state(), binary(), [binary(),...], priv_key(), -spec issue_request(state(), binary(), [binary(),...], [string(), ...], priv_key(),
cert_type(), [binary()]) -> {issue_result(), state()}. cert_type(), [binary()]) -> {issue_result(), state()}.
issue_request(State, DirURL, Domains, AccKey, CertType, Contact) -> issue_request(State, DirURL, Domains, AsciiDomains, AccKey, CertType, Contact) ->
Ref = make_ref(), Ref = make_ref(),
ChallengeFun = fun(Auth) -> register_challenge(Auth, Ref) end, ChallengeFun = fun(Auth) -> register_challenge(Auth, Ref) end,
Ret = case acme:issue(DirURL, Domains, AccKey, Ret = case acme:issue(DirURL, AsciiDomains, AccKey,
[{cert_type, CertType}, [{cert_type, CertType},
{contact, Contact}, {contact, Contact},
{debug_fun, debug_fun()}, {debug_fun, debug_fun()},
@ -630,15 +630,16 @@ have_acme_listener() ->
false false
end, ejabberd_option:listen()). end, ejabberd_option:listen()).
-spec check_idna([binary()]) -> ok | {error, {idna_failed, binary()}}. -spec check_idna([binary()]) -> {ok, [string()]} | {error, {idna_failed, binary()}}.
check_idna([Domain|Domains]) -> check_idna(Domains) ->
try idna:to_ascii(binary_to_list(Domain)) of lists:foldl(
_ -> check_idna(Domains) fun(D, {ok, Ds}) ->
catch _:_ -> try {ok, [idna:utf8_to_ascii(D)|Ds]}
{error, {idna_failed, Domain}} catch _:_ -> {error, {idna_failed, D}}
end; end;
check_idna([]) -> (_, Err) ->
ok. Err
end, {ok, []}, Domains).
-spec format_error(term()) -> string(). -spec format_error(term()) -> string().
format_error({file, Reason}) -> format_error({file, Reason}) ->