summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKonstantinos Kallas <konstantinos.kallas@hotmail.com>2017-07-12 19:23:52 +0300
committerKonstantinos Kallas <konstantinos.kallas@hotmail.com>2017-07-12 19:23:52 +0300
commit77a96b0ec6c793ce0f5741d4683edd2ee9b3b877 (patch)
treeb62198406f8895562a3523d630f4486e9bb06723
parentChangle acme file permissions (diff)
Solve acme challenges using built in http server
-rw-r--r--ejabberd.yml.example4
-rw-r--r--src/acme_challenge.erl62
-rw-r--r--src/ejabberd_acme.erl13
-rw-r--r--src/ejabberd_acme_comm.erl6
4 files changed, 68 insertions, 17 deletions
diff --git a/ejabberd.yml.example b/ejabberd.yml.example
index 5e6f9b63..7a75c553 100644
--- a/ejabberd.yml.example
+++ b/ejabberd.yml.example
@@ -160,6 +160,7 @@ listen:
request_handlers:
"/websocket": ejabberd_http_ws
"/api": mod_http_api
+ "/.well-known": acme_challenge
## "/pub/archive": mod_http_fileserver
web_admin: true
http_bind: true
@@ -668,7 +669,8 @@ language: "en"
acme:
contact: "mailto:cert-admin-ejabberd@example.com"
http_dir: "/home/konstantinos/Desktop/Programming/test-server-for-acme/"
- cert_dir: "/usr/local/var/lib/ejabberd/"
+
+cert_dir: "/usr/local/var/lib/ejabberd/"
###. =======
###' MODULES
diff --git a/src/acme_challenge.erl b/src/acme_challenge.erl
index 433de814..2638e0dd 100644
--- a/src/acme_challenge.erl
+++ b/src/acme_challenge.erl
@@ -1,7 +1,9 @@
-module(acme_challenge).
--export ([ key_authorization/2,
- solve_challenge/3
+-export ([key_authorization/2,
+ solve_challenge/3,
+
+ process/2
]).
%% Challenge Types
%% ================
@@ -13,9 +15,19 @@
-include("ejabberd.hrl").
-include("logger.hrl").
-include("xmpp.hrl").
-
+-include("ejabberd_http.hrl").
-include("ejabberd_acme.hrl").
+%% TODO: Maybe validate request here??
+process(LocalPath, Request) ->
+ Result = ets_get_key_authorization(LocalPath),
+ ?INFO_MSG("Trying to serve: ~p at: ~p", [Request, LocalPath]),
+ ?INFO_MSG("Http Response: ~p", [Result]),
+ {200,
+ [{<<"Content-Type">>, <<"text/plain">>}],
+ Result}.
+
+
-spec key_authorization(bitstring(), jose_jwk:key()) -> bitstring().
key_authorization(Token, Key) ->
Thumbprint = jose_jwk:thumbprint(Key),
@@ -68,17 +80,49 @@ solve_challenge(ChallengeType, Challenges, Options) ->
{ok, url(), bitstring()} | {error, _}.
solve_challenge1(Chal = #challenge{type = <<"http-01">>, token=Tkn}, {Key, HttpDir}) ->
KeyAuthz = key_authorization(Tkn, Key),
+ %% save_key_authorization(Chal, Tkn, KeyAuthz, HttpDir);
+ ets_put_key_authorization(Tkn, KeyAuthz),
+ {ok, Chal#challenge.uri, KeyAuthz};
+solve_challenge1(Challenge, _Key) ->
+ ?INFO_MSG("Challenge: ~p~n", [Challenge]).
+
+
+save_key_authorization(Chal, Tkn, KeyAuthz, HttpDir) ->
FileLocation = HttpDir ++ "/.well-known/acme-challenge/" ++ bitstring_to_list(Tkn),
case file:write_file(FileLocation, KeyAuthz) of
ok ->
{ok, Chal#challenge.uri, KeyAuthz};
- {error, _} = Err ->
- ?ERROR_MSG("Error writing to file: ~s with reason: ~p~n", [FileLocation, Err]),
+ {error, Reason} = Err ->
+ ?ERROR_MSG("Error writing to file: ~s with reason: ~p~n", [FileLocation, Reason]),
Err
- end;
-%% TODO: Fill stub
-solve_challenge1(Challenge, _Key) ->
- ?INFO_MSG("Challenge: ~p~n", [Challenge]).
+ end.
+
+-spec ets_put_key_authorization(bitstring(), bitstring()) -> ok.
+ets_put_key_authorization(Tkn, KeyAuthz) ->
+ Tab = ets_get_acme_table(),
+ Key = [<<"acme-challenge">>, Tkn],
+ ets:insert(Tab, {Key, KeyAuthz}),
+ ok.
+
+-spec ets_get_key_authorization([bitstring()]) -> bitstring().
+ets_get_key_authorization(Key) ->
+ Tab = ets_get_acme_table(),
+ case ets:take(Tab, Key) of
+ [{Key, KeyAuthz}] ->
+ KeyAuthz;
+ _ ->
+ ?ERROR_MSG("Unable to serve key authorization in: ~p", [Key]),
+ <<"">>
+ end.
+
+-spec ets_get_acme_table() -> atom().
+ets_get_acme_table() ->
+ case ets:info(acme) of
+ undefined ->
+ ets:new(acme, [named_table, public]);
+ _ ->
+ acme
+ end.
%% Useful functions
diff --git a/src/ejabberd_acme.erl b/src/ejabberd_acme.erl
index 60bb31be..209ac46c 100644
--- a/src/ejabberd_acme.erl
+++ b/src/ejabberd_acme.erl
@@ -513,13 +513,12 @@ get_config_hosts() ->
end.
get_config_cert_dir() ->
- {ok, Acme} = get_config_acme(),
- case lists:keyfind(cert_dir, 1, Acme) of
- {cert_dir, CertDir} ->
- {ok, CertDir};
- false ->
- ?ERROR_MSG("No certificate directory has been specified", []),
- {error, configuration_cert_dir}
+ case ejabberd_config:get_option(cert_dir, undefined) of
+ undefined ->
+ ?ERROR_MSG("No cert_dir configuration has been specified", []),
+ throw({error, configuration});
+ CertDir ->
+ {ok, CertDir}
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
diff --git a/src/ejabberd_acme_comm.erl b/src/ejabberd_acme_comm.erl
index 804d4653..b66d5f61 100644
--- a/src/ejabberd_acme_comm.erl
+++ b/src/ejabberd_acme_comm.erl
@@ -32,6 +32,12 @@
-define(MAX_POLL_REQUESTS, 20).
-define(POLL_WAIT_TIME, 500). % 500 ms.
+%%%
+%%% This module contains functions that implement all necessary http
+%%% requests to the ACME Certificate Authority. Its purpose is to
+%%% facilitate the acme client implementation by separating the
+%%% handling/validating/parsing of all the needed http requests.
+%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%