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

Add support for solving http-01 challenge

This commit is contained in:
Konstantinos Kallas 2017-06-18 13:20:47 +03:00
parent 1d1250b056
commit dc4c00a78c
2 changed files with 57 additions and 7 deletions

View File

@ -16,7 +16,7 @@
-include("ejabberd_acme.hrl"). -include("ejabberd_acme.hrl").
-spec parse_challenge(string(), jose_jwk:key()) -> bitstring(). -spec key_authorization(string(), jose_jwk:key()) -> bitstring().
key_authorization(Token, Key) -> key_authorization(Token, Key) ->
Thumbprint = jose_jwk:thumbprint(Key), Thumbprint = jose_jwk:thumbprint(Key),
% ?INFO_MSG("Thumbprint: ~p~n", [Thumbprint]), % ?INFO_MSG("Thumbprint: ~p~n", [Thumbprint]),
@ -34,7 +34,7 @@ parse_challenge(Challenge0) ->
Res = #challenge{ Res = #challenge{
type = Type, type = Type,
status = list_to_atom(bitstring_to_list(Status)), status = list_to_atom(bitstring_to_list(Status)),
uri = Uri, uri = bitstring_to_list(Uri),
token = Token token = Token
}, },
{ok, Res} {ok, Res}
@ -73,6 +73,7 @@ solve_challenge1(Chal = #challenge{type = <<"http-01">>, token=Tkn}, {Key, HttpD
?ERROR_MSG("Error writing to file: ~s with reason: ~p~n", [FileLocation, Err]), ?ERROR_MSG("Error writing to file: ~s with reason: ~p~n", [FileLocation, Err]),
Err Err
end; end;
%% TODO: Fill stub
solve_challenge1(Challenge, _Key) -> solve_challenge1(Challenge, _Key) ->
?INFO_MSG("Challenge: ~p~n", [Challenge]). ?INFO_MSG("Challenge: ~p~n", [Challenge]).

View File

@ -11,6 +11,8 @@
, new_authz/4 , new_authz/4
, get_authz/1 , get_authz/1
, solve_challenge/4
, scenario/3 , scenario/3
, scenario0/2 , scenario0/2
]). ]).
@ -23,6 +25,7 @@
-include_lib("public_key/include/public_key.hrl"). -include_lib("public_key/include/public_key.hrl").
-define(REQUEST_TIMEOUT, 5000). % 5 seconds. -define(REQUEST_TIMEOUT, 5000). % 5 seconds.
-define(MAX_POLL_REQUESTS, 20).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -90,6 +93,11 @@ new_authz(Url, PrivateKey, Req, Nonce) ->
get_authz(Url) -> get_authz(Url) ->
prepare_get_request(Url, fun get_response/1). prepare_get_request(Url, fun get_response/1).
-spec solve_challenge(url(), jose_jwk:key(), proplist(), nonce()) ->
{ok, proplist(), nonce()} | {error, _}.
solve_challenge(Url, PrivateKey, Req, Nonce) ->
EJson = {[{<<"resource">>, <<"challenge">>}] ++ Req},
prepare_post_request(Url, PrivateKey, EJson, Nonce, fun get_response/1).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% %%
@ -164,6 +172,37 @@ get_challenges(Body) ->
{<<"challenges">>, Challenges} = proplists:lookup(<<"challenges">>, Body), {<<"challenges">>, Challenges} = proplists:lookup(<<"challenges">>, Body),
Challenges. Challenges.
-spec get_authz_until_valid(url()) ->
{ok, proplist(), nonce()} | {error, _}.
get_authz_until_valid(Url) ->
get_authz_until_valid(Url, ?MAX_POLL_REQUESTS).
-spec get_authz_until_valid(url(), non_neg_integer()) ->
{ok, proplist(), nonce()} | {error, _}.
get_authz_until_valid(Url, 0) ->
?ERROR_MSG("Maximum request limit waiting for validation reached", []),
{error, max_request_limit};
get_authz_until_valid(Url, N) ->
case get_authz(Url) of
{ok, Resp, Nonce} ->
case is_authz_valid(Resp) of
true ->
{ok, Resp, Nonce};
false ->
get_authz_until_valid(Url, N-1)
end;
{error, _} = Err ->
Err
end.
-spec is_authz_valid(proplist()) -> boolean().
is_authz_valid(Authz) ->
case proplists:lookup(<<"status">>, Authz) of
{<<"status">>, <<"valid">>} ->
true;
none ->
false
end.
%% TODO: Fix the duplicated code at the below 4 functions %% TODO: Fix the duplicated code at the below 4 functions
@ -370,12 +409,22 @@ new_user_scenario(CAUrl, HttpDir) ->
{ok, Authz2, Nonce5} = get_authz(AuthzUrl), {ok, Authz2, Nonce5} = get_authz(AuthzUrl),
Challenges = get_challenges(Authz2), Challenges = get_challenges(Authz2),
?INFO_MSG("Challenges: ~p~n", [Challenges]), % ?INFO_MSG("Challenges: ~p~n", [Challenges]),
{ok, ChallengeUrl, KeyAuthz} = acme_challenge:solve_challenge(<<"http-01">>, Challenges, {PrivateKey, HttpDir}), {ok, ChallengeUrl, KeyAuthz} = acme_challenge:solve_challenge(<<"http-01">>, Challenges, {PrivateKey, HttpDir}),
?INFO_MSG("File for http-01 challenge written correctly", []), ?INFO_MSG("File for http-01 challenge written correctly", []),
{Account2, Authz2, PrivateKey}. Req3 =
[ {<<"type">>, <<"http-01">>}
, {<<"keyAuthorization">>, KeyAuthz}
],
{ok, SolvedChallenge, Nonce6} = solve_challenge(ChallengeUrl, PrivateKey, Req3, Nonce5),
?INFO_MSG("SolvedChallenge: ~p~n", [SolvedChallenge]),
timer:sleep(2000),
{ok, Authz3, Nonce7} = get_authz_until_valid(AuthzUrl),
{Account2, Authz2, Authz3, PrivateKey}.
generate_key() -> generate_key() ->