summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/plop_httputil.erl44
1 files changed, 42 insertions, 2 deletions
diff --git a/src/plop_httputil.erl b/src/plop_httputil.erl
index 2d840aa..3b1c104 100644
--- a/src/plop_httputil.erl
+++ b/src/plop_httputil.erl
@@ -5,6 +5,7 @@
-module(plop_httputil).
-export([request/4]).
-include_lib("hackney/include/hackney_lib.hrl").
+-include_lib("public_key/include/public_key.hrl").
get_auth_header(Headers) ->
case hackney_headers:get_value("X-Catlfish-Auth", Headers) of
@@ -20,15 +21,54 @@ add_auth(Method, Path, Headers, Data) ->
lager:debug("sent auth header: ~p", [AuthHeader]),
[{"X-Catlfish-Auth", AuthHeader} | Headers].
+get_cert_hostname(Cert) ->
+ TBSCert = Cert#'OTPCertificate'.tbsCertificate,
+ Subject = TBSCert#'OTPTBSCertificate'.subject,
+ {rdnSequence, RDNs} = Subject,
+ CNs = lists:map(fun([#'AttributeTypeAndValue'{type=?'id-at-commonName', value=Value}]) ->
+ Value;
+ (_) ->
+ none
+ end, RDNs),
+ case [CN || CN <- CNs, CN /= none] of
+ [{utf8String, BinCN} | _] when is_binary(BinCN) ->
+ binary_to_list(BinCN);
+ [CN | _] ->
+ CN;
+ [] ->
+ ""
+ end.
+
+verify_fun(_,{bad_cert, _} = Reason, _) ->
+ {fail, Reason};
+verify_fun(_,{extension, _}, UserState) ->
+ {unknown, UserState};
+verify_fun(_, valid, UserState) ->
+ {valid, UserState};
+verify_fun(Cert, valid_peer, UserState) ->
+ CertHostname = get_cert_hostname(Cert),
+ case lists:keyfind(check_hostname, 1, UserState) of
+ {check_hostname, CertHostname} ->
+ {valid, UserState};
+ {check_hostname, ExpectedHostname} ->
+ lager:info("Expected hostname ~p but certificate has hostname ~p", [ExpectedHostname, CertHostname]),
+ {fail, "Hostname does not match"};
+ false ->
+ {valid, UserState}
+ end.
+
request(DebugTag, URL, Headers, RequestBody) ->
Starttime = os:timestamp(),
ParsedURL = hackney_url:parse_url(URL),
CACertFile = application:get_env(catlfish, https_cacertfile, none),
- #hackney_url{path = Path} = ParsedURL,
+ #hackney_url{path = Path, host = Host} = ParsedURL,
lager:debug("~s: sending http request to ~p",
[DebugTag, URL]),
case hackney:connect(ParsedURL,
- [{ssl_options, [{cacertfile, CACertFile}]}]) of
+ [{ssl_options, [{cacertfile, CACertFile},
+ {verify, verify_peer},
+ {verify_fun, {fun verify_fun/3, [{check_hostname, Host}]}}
+ ]}]) of
{ok, ConnRef} ->
lager:debug("~s: connected to ~p",
[DebugTag, URL]),