diff options
Diffstat (limited to 'src/dnssecport.erl')
-rw-r--r-- | src/dnssecport.erl | 92 |
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]), |