Skip to content

Commit

Permalink
inet_dns: support SIG(0) [WiP]
Browse files Browse the repository at this point in the history
  • Loading branch information
jimdigriz committed Oct 30, 2023
1 parent 80acc76 commit 476e6ab
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 0 deletions.
54 changes: 54 additions & 0 deletions lib/kernel/src/inet_dns.erl
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,10 @@
%% RFC 1996: A Mechanism for Prompt Notification of Zone Changes (DNS NOTIFY)
%% RFC 2136: Dynamic Updates in the Domain Name System (DNS UPDATE)
%% RFC 2181: Clarifications to the DNS Specification
%% RFC 2535: Domain Name System Security Extensions
%% RFC 2782: A DNS RR for specifying the location of services (DNS SRV)
%% RFC 2915: The Naming Authority Pointer (NAPTR) DNS Resource Rec
%% RFC 2931: DNS Request and Transaction Signatures ( SIG(0)s )
%% RFC 5936: DNS Zone Transfer Protocol (AXFR)
%% RFC 6488: DNS Certification Authority Authorization (CAA) Resource Record
%% RFC 6762: Multicast DNS
Expand All @@ -36,6 +38,7 @@
%% RFC 8945: Secret Key Transaction Authentication for DNS (TSIG)

-export([decode/1, encode/1]).
-export([decode_dnssec_algname/1, encode_dnssec_algname/1]).
-export([decode_algname/1, encode_algname/1]).

-import(lists, [reverse/1]).
Expand Down Expand Up @@ -255,6 +258,32 @@ decode_rr_section(Opcode, Bin, N, Buffer, RRs) ->
z = Z,
data = D,
do = DnssecOk};
?S_SIG ->
{DR,Name} = decode_name(D, Buffer),
{DR1,Sig} = ?MATCH_ELSE_DECODE_ERROR(
DR,
<<TypeCovered:16, Algorithm:8, Labels:8,
OriginalTTL:32, SigExp:32, SigInc:32,
KeyTag:16, R/binary>>,
{R, #dns_rr_sig{
domain = Name,
type = Type,
offset = byte_size(Buffer) - byte_size(Bin),
type_covered = TypeCovered,
algorithm = Algorithm,
labels = Labels,
original_ttl = OriginalTTL,
signature_expiration = SigExp,
signature_inception = SigInc,
key_tag = KeyTag}),
%% RFC 2535: 4.3. SIG(0) must be last
Sig#dns_rr_sig.type_covered == 0
andalso Rest =/= <<>>
andalso throw(?DECODE_ERROR),
{Signature,SignersName} = decode_name(DR1, Buffer),
Sig#dns_rr_sig{
signers_name = SignersName,
signature = Signature};
?S_TSIG ->
%% RFC 8945: 5.2. FORMERR if not last
%% RFC 8945: 5.2. FORMERR if more than one dns_rr_tsig
Expand Down Expand Up @@ -427,6 +456,8 @@ decode_type(Type) ->
?T_MINFO -> ?S_MINFO;
?T_MX -> ?S_MX;
?T_TXT -> ?S_TXT;
?T_SIG -> ?S_SIG;
?T_KEY -> ?S_KEY;
?T_AAAA -> ?S_AAAA;
?T_LOC -> ?S_LOC;
?T_SRV -> ?S_SRV;
Expand Down Expand Up @@ -470,6 +501,8 @@ encode_type(Type) ->
?S_MINFO -> ?T_MINFO;
?S_MX -> ?T_MX;
?S_TXT -> ?T_TXT;
?S_SIG -> ?T_SIG;
?S_KEY -> ?T_KEY;
?S_AAAA -> ?T_AAAA;
?S_LOC -> ?T_LOC;
?S_SRV -> ?T_SRV;
Expand Down Expand Up @@ -874,6 +907,15 @@ encode_data(Comp, _, ?S_CAA, Data)->
_ ->
{encode_txt(Data),Comp}
end;
encode_data(Comp, Pos, ?S_SIG, Data)->
{TypeCovered,Algorithm,Labels,OriginalTTL,SigExp,SigInc,KeyTag,
SignersName,Signature} = Data,
AlgorithmEncoded = encode_dnssec_algname(Algorithm),
{SignersNameEncoded,Comp1} = encode_name(Comp, Pos, SignersName),
DataB = <<TypeCovered:16, AlgorithmEncoded:8, Labels:8, OriginalTTL:32,
SigExp:32, SigInc:32, KeyTag:16,
SignersNameEncoded/binary, Signature/binary>>,
{DataB,Comp1};
encode_data(Comp, _, ?S_TSIG, Data)->
{AlgName,Now,Fudge,MAC,OriginalId,Error,OtherData} = Data,
%% Bypass name compression (RFC 8945, section 4.2)
Expand Down Expand Up @@ -1026,6 +1068,18 @@ encode_loc_size(X)
Base = (X + Multiplier - 1) div Multiplier,
<<Base:4, Exponent:4>>.

decode_dnssec_algname(AlgName) ->
case AlgName of
?T_DNSSEC_ALGNUM_ECDSAP256SHA256 -> ?S_DNSSEC_ALGNUM_ECDSAP256SHA256;
_ -> AlgName % raw unknown algname
end.

encode_dnssec_algname(Alg) ->
case Alg of
?S_DNSSEC_ALGNUM_ECDSAP256SHA256 -> ?T_DNSSEC_ALGNUM_ECDSAP256SHA256;
Alg when is_integer(Alg) -> Alg % raw unknown algname
end.

decode_algname(AlgName) ->
case AlgName of
?T_TSIG_HMAC_MD5 -> ?S_TSIG_HMAC_MD5;
Expand Down
29 changes: 29 additions & 0 deletions lib/kernel/src/inet_dns.hrl
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@
-define(T_MINFO, 14). %% mailbox information
-define(T_MX, 15). %% mail routing information
-define(T_TXT, 16). %% text strings
-define(T_SIG, 24). %% signature
-define(T_KEY, 25). %% key
-define(T_AAAA, 28). %% ipv6 address
%% LOC (RFC 1876)
-define(T_LOC, 29). %% location information
Expand Down Expand Up @@ -114,6 +116,8 @@
-define(S_MINFO, minfo). %% mailbox information
-define(S_MX, mx). %% mail routing information
-define(S_TXT, txt). %% text strings
-define(S_SIG, sig). %% signature
-define(S_KEY, key). %% key
-define(S_AAAA, aaaa). %% ipv6 address
%% LOC (RFC 1876)
-define(S_LOC, loc). %% location information
Expand Down Expand Up @@ -149,6 +153,14 @@
-define(C_NONE, 254). %% for DDNS (RFC2136, section 2.4)
-define(C_ANY, 255). %% wildcard match

%%
%% Domain Name System Security (DNSSEC) Algorithm Numbers
%% https://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml
%%
-define(T_DNSSEC_ALGNUM_ECDSAP256SHA256, 13).
%
-define(S_DNSSEC_ALGNUM_ECDSAP256SHA256, ecdsap256sha256).

%%
%% TSIG Algorithms and Identifiers (RFC8945, section 6)
%%
Expand Down Expand Up @@ -239,6 +251,23 @@
do = false %% RFC6891(6.1.3 DO)
}).

-record(dns_rr_sig, %% SIG RR OPT (RFC2535), dns_rr{type=sig}
{
domain = "", %% should be the root domain
type = sig,
offset, %% position of RR in packet ( SIG(0) )
%% RFC2535(4.1 SIG RDATA Format)
type_covered,
algorithm,
labels,
original_ttl,
signature_expiration,
signature_inception,
key_tag,
signers_name,
signature
}).

-record(dns_rr_tsig, %% TSIG RR OPT (RFC8945), dns_rr{type=tsig}
{
domain = "", %% name of the key
Expand Down

0 comments on commit 476e6ab

Please sign in to comment.