summaryrefslogtreecommitdiff
path: root/src/dnssecport.erl
diff options
context:
space:
mode:
Diffstat (limited to 'src/dnssecport.erl')
-rw-r--r--src/dnssecport.erl92
1 files changed, 57 insertions, 35 deletions
diff --git a/src/dnssecport.erl b/src/dnssecport.erl
index e9c3345..39ce230 100644
--- a/src/dnssecport.erl
+++ b/src/dnssecport.erl
@@ -39,37 +39,22 @@ decode_response(Response) ->
<<Status:16/integer, RRSet/binary>> = Response,
{ok, Status, dns:decode_rrset(RRSet)}.
+-define(DNSSEC_VALIDATION_TIME_SKEW, 30).
handle_call(stop, _From, State) ->
lager:debug("dnssec stop request received"),
stop_port(State);
-handle_call({validate, Data}, _From, State) ->
- case State#state.port of
- undefined ->
- {reply, {error, noport}, State};
- Port when is_port(Port) ->
- Port ! {self(), {command, Data}},
- receive
- {Port, {data, Response}} ->
- case decode_response(list_to_binary(Response)) of
- {ok, 400, [DS | Chain]} ->
- RRSIG = hd(Chain),
- R = [dns:encode_rr(dns:canonicalize_dsrr(DS, RRSIG)),
- dns:encode_rrset(Chain)],
- {reply, {ok, R}, State};
- {ok, Error, _} ->
- lager:debug("DNSSEC validation failed with ~p",
- [Error]),
- {reply, {error, Error}, State}
- end;
- {Port, {exit_status, ExitStatus}} ->
- lager:error("dnssec port ~p exiting with status ~p",
- [Port, ExitStatus]),
- {stop, portexit, State#state{port = undefined}}
- after
- 3000 ->
- lager:error("dnssec port timeout"),
- {stop, timeout, State}
- end
+handle_call({validate, RRset}, _From, State) ->
+ case dns:validate(RRset) of
+ {valid, ValidationTime} ->
+ case State#state.port of
+ undefined ->
+ {reply, {error, noport}, State};
+ Port when is_port(Port) ->
+ portcommand(RRset, ValidationTime,
+ ?DNSSEC_VALIDATION_TIME_SKEW, State)
+ end;
+ {invalid, Reason} ->
+ {reply, {invalid, Reason}, State}
end.
handle_info(_Info, State) ->
@@ -86,6 +71,34 @@ terminate(Reason, _State) ->
ok.
%%%%%%%%%%%%%%%%%%%%
+-spec portcommand(binary(), integer(), integer(), #state{}) ->
+ {stop, portexit|timeout, #state{}} |
+ {reply, tuple(), #state{}}.
+portcommand(Data, ValidationTime, Skew, State) ->
+ Port = State#state.port,
+ Port ! {self(), {command,
+ <<ValidationTime:32/integer,
+ Skew:32/integer,
+ Data/binary>>}},
+ receive
+ {Port, {data, Response}} ->
+ case decode_response(list_to_binary(Response)) of
+ {ok, 400, RRset} ->
+ C14N_RRset = dns:canonicalize(RRset),
+ {reply, {valid, dns:encode_rrset(C14N_RRset)}, State};
+ {ok, Code, _} ->
+ {reply, {invalid, Code}, State}
+ end;
+ {Port, {exit_status, ExitStatus}} ->
+ lager:error("dnssec port ~p exiting with status ~p",
+ [Port, ExitStatus]),
+ {stop, portexit, State#state{port = undefined}}
+ after
+ 3000 ->
+ lager:error("dnssec port timeout"),
+ {stop, timeout, State}
+ end.
+
create_port(Program, Args) ->
open_port({spawn_executable, Program},
[{args, Args},
@@ -113,8 +126,8 @@ stop_port(State) ->
-define(REQ1_FILE, "test/testdata/dnssec/testrrsets/req-basic").
-define(REQ2_FILE, "test/testdata/dnssec/testrrsets/req-lowttl").
-start_test_port() ->
- create_port("priv/dnssecport", [?TA_FILE]).
+start_test_port(Args) ->
+ create_port("priv/dnssecport", Args).
stop_test_port(Port) ->
{stop, closed, _State} = stop_port(#state{port = Port}),
@@ -133,7 +146,7 @@ read_dec_enc_test_() ->
full_test_() ->
{setup,
fun() ->
- start_test_port() end,
+ start_test_port([?TA_FILE]) end,
fun(Port) ->
stop_test_port(Port) end,
fun(Port) ->
@@ -141,15 +154,24 @@ full_test_() ->
self(), #state{port = Port}),
R2 = handle_call({validate, read_submission_from_file(?REQ2_FILE)},
self(), #state{port = Port}),
- {reply, {ok, [DSBin | _ChainBin]}, _} = R2,
- {DS, <<>>} = dns:decode_rr(DSBin),
+ {reply, {valid, ChainBin}, _} = R2,
+ {DS, _} = dns:decode_rr(ChainBin),
[
- ?_assertMatch({reply, {ok, _}, _State}, R1),
- ?_assertMatch({reply, {ok, _}, _State}, R2),
+ ?_assertMatch({reply, {valid, _}, _State}, R1),
+ ?_assertMatch({reply, {valid, _}, _State}, R2),
?_assertMatch({rr, _Name, _Type, _Class, 3600, _RDATA}, DS)
] end
}.
+no_trust_anchors_test_() ->
+ {setup,
+ fun() -> start_test_port([]) end,
+ fun(Port) -> stop_test_port(Port) end,
+ fun(Port) ->
+ R = handle_call({validate, read_submission_from_file(?REQ1_FILE)},
+ self(), #state{port = Port}),
+ [?_assertMatch({reply, {invalid, 401}, _}, R)] end}.
+
%% start_test_port(TestType) ->
%% Port = create_port("priv/dnssecport", ["--testmode", atom_to_list(TestType)]),
%% ?debugFmt("Port: ~p", [Port]),