1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2015 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 #include <arpa/inet.h>
23 #include <netinet/in.h>
24 #include <sys/socket.h>
26 #include "alloc-util.h"
27 #include "resolved-dns-dnssec.h"
28 #include "resolved-dns-rr.h"
29 #include "string-util.h"
31 static void test_dnssec_verify_rrset(void) {
33 static const uint8_t signature_blob
[] = {
34 0x7f, 0x79, 0xdd, 0x5e, 0x89, 0x79, 0x18, 0xd0, 0x34, 0x86, 0x8c, 0x72, 0x77, 0x75, 0x48, 0x4d,
35 0xc3, 0x7d, 0x38, 0x04, 0xab, 0xcd, 0x9e, 0x4c, 0x82, 0xb0, 0x92, 0xca, 0xe9, 0x66, 0xe9, 0x6e,
36 0x47, 0xc7, 0x68, 0x8c, 0x94, 0xf6, 0x69, 0xcb, 0x75, 0x94, 0xe6, 0x30, 0xa6, 0xfb, 0x68, 0x64,
37 0x96, 0x1a, 0x84, 0xe1, 0xdc, 0x16, 0x4c, 0x83, 0x6c, 0x44, 0xf2, 0x74, 0x4d, 0x74, 0x79, 0x8f,
38 0xf3, 0xf4, 0x63, 0x0d, 0xef, 0x5a, 0xe7, 0xe2, 0xfd, 0xf2, 0x2b, 0x38, 0x7c, 0x28, 0x96, 0x9d,
39 0xb6, 0xcd, 0x5c, 0x3b, 0x57, 0xe2, 0x24, 0x78, 0x65, 0xd0, 0x9e, 0x77, 0x83, 0x09, 0x6c, 0xff,
40 0x3d, 0x52, 0x3f, 0x6e, 0xd1, 0xed, 0x2e, 0xf9, 0xee, 0x8e, 0xa6, 0xbe, 0x9a, 0xa8, 0x87, 0x76,
41 0xd8, 0x77, 0xcc, 0x96, 0xa0, 0x98, 0xa1, 0xd1, 0x68, 0x09, 0x43, 0xcf, 0x56, 0xd9, 0xd1, 0x66,
44 static const uint8_t dnskey_blob
[] = {
45 0x03, 0x01, 0x00, 0x01, 0x9b, 0x49, 0x9b, 0xc1, 0xf9, 0x9a, 0xe0, 0x4e, 0xcf, 0xcb, 0x14, 0x45,
46 0x2e, 0xc9, 0xf9, 0x74, 0xa7, 0x18, 0xb5, 0xf3, 0xde, 0x39, 0x49, 0xdf, 0x63, 0x33, 0x97, 0x52,
47 0xe0, 0x8e, 0xac, 0x50, 0x30, 0x8e, 0x09, 0xd5, 0x24, 0x3d, 0x26, 0xa4, 0x49, 0x37, 0x2b, 0xb0,
48 0x6b, 0x1b, 0xdf, 0xde, 0x85, 0x83, 0xcb, 0x22, 0x4e, 0x60, 0x0a, 0x91, 0x1a, 0x1f, 0xc5, 0x40,
49 0xb1, 0xc3, 0x15, 0xc1, 0x54, 0x77, 0x86, 0x65, 0x53, 0xec, 0x10, 0x90, 0x0c, 0x91, 0x00, 0x5e,
50 0x15, 0xdc, 0x08, 0x02, 0x4c, 0x8c, 0x0d, 0xc0, 0xac, 0x6e, 0xc4, 0x3e, 0x1b, 0x80, 0x19, 0xe4,
51 0xf7, 0x5f, 0x77, 0x51, 0x06, 0x87, 0x61, 0xde, 0xa2, 0x18, 0x0f, 0x40, 0x8b, 0x79, 0x72, 0xfa,
52 0x8d, 0x1a, 0x44, 0x47, 0x0d, 0x8e, 0x3a, 0x2d, 0xc7, 0x39, 0xbf, 0x56, 0x28, 0x97, 0xd9, 0x20,
53 0x4f, 0x00, 0x51, 0x3b,
56 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*a
= NULL
, *rrsig
= NULL
, *dnskey
= NULL
;
57 _cleanup_(dns_answer_unrefp
) DnsAnswer
*answer
= NULL
;
58 _cleanup_free_
char *x
= NULL
, *y
= NULL
, *z
= NULL
;
61 a
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_A
, "nAsA.gov");
64 a
->a
.in_addr
.s_addr
= inet_addr("52.0.14.116");
66 assert_se(dns_resource_record_to_string(a
, &x
) >= 0);
69 rrsig
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_RRSIG
, "NaSa.GOV.");
72 rrsig
->rrsig
.type_covered
= DNS_TYPE_A
;
73 rrsig
->rrsig
.algorithm
= DNSSEC_ALGORITHM_RSASHA256
;
74 rrsig
->rrsig
.labels
= 2;
75 rrsig
->rrsig
.original_ttl
= 600;
76 rrsig
->rrsig
.expiration
= 0x5683135c;
77 rrsig
->rrsig
.inception
= 0x565b7da8;
78 rrsig
->rrsig
.key_tag
= 63876;
79 rrsig
->rrsig
.signer
= strdup("Nasa.Gov.");
80 assert_se(rrsig
->rrsig
.signer
);
81 rrsig
->rrsig
.signature_size
= sizeof(signature_blob
);
82 rrsig
->rrsig
.signature
= memdup(signature_blob
, rrsig
->rrsig
.signature_size
);
83 assert_se(rrsig
->rrsig
.signature
);
85 assert_se(dns_resource_record_to_string(rrsig
, &y
) >= 0);
86 log_info("RRSIG: %s", y
);
88 dnskey
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_DNSKEY
, "nASA.gOV");
91 dnskey
->dnskey
.flags
= 256;
92 dnskey
->dnskey
.protocol
= 3;
93 dnskey
->dnskey
.algorithm
= DNSSEC_ALGORITHM_RSASHA256
;
94 dnskey
->dnskey
.key_size
= sizeof(dnskey_blob
);
95 dnskey
->dnskey
.key
= memdup(dnskey_blob
, sizeof(dnskey_blob
));
96 assert_se(dnskey
->dnskey
.key
);
98 assert_se(dns_resource_record_to_string(dnskey
, &z
) >= 0);
99 log_info("DNSKEY: %s", z
);
100 log_info("DNSKEY keytag: %u", dnssec_keytag(dnskey
));
102 assert_se(dnssec_key_match_rrsig(a
->key
, rrsig
) > 0);
103 assert_se(dnssec_rrsig_match_dnskey(rrsig
, dnskey
) > 0);
105 answer
= dns_answer_new(1);
107 assert_se(dns_answer_add(answer
, a
, 0) >= 0);
109 /* Validate the RR as it if was 2015-12-2 today */
110 assert_se(dnssec_verify_rrset(answer
, a
->key
, rrsig
, dnskey
, 1449092754*USEC_PER_SEC
, &result
) >= 0);
111 assert_se(result
== DNSSEC_VALIDATED
);
114 static void test_dnssec_verify_dns_key(void) {
116 static const uint8_t ds1_fprint
[] = {
117 0x46, 0x8B, 0xC8, 0xDD, 0xC7, 0xE8, 0x27, 0x03, 0x40, 0xBB, 0x8A, 0x1F, 0x3B, 0x2E, 0x45, 0x9D,
118 0x80, 0x67, 0x14, 0x01,
120 static const uint8_t ds2_fprint
[] = {
121 0x8A, 0xEE, 0x80, 0x47, 0x05, 0x5F, 0x83, 0xD1, 0x48, 0xBA, 0x8F, 0xF6, 0xDD, 0xA7, 0x60, 0xCE,
122 0x94, 0xF7, 0xC7, 0x5E, 0x52, 0x4C, 0xF2, 0xE9, 0x50, 0xB9, 0x2E, 0xCB, 0xEF, 0x96, 0xB9, 0x98,
124 static const uint8_t dnskey_blob
[] = {
125 0x03, 0x01, 0x00, 0x01, 0xa8, 0x12, 0xda, 0x4f, 0xd2, 0x7d, 0x54, 0x14, 0x0e, 0xcc, 0x5b, 0x5e,
126 0x45, 0x9c, 0x96, 0x98, 0xc0, 0xc0, 0x85, 0x81, 0xb1, 0x47, 0x8c, 0x7d, 0xe8, 0x39, 0x50, 0xcc,
127 0xc5, 0xd0, 0xf2, 0x00, 0x81, 0x67, 0x79, 0xf6, 0xcc, 0x9d, 0xad, 0x6c, 0xbb, 0x7b, 0x6f, 0x48,
128 0x97, 0x15, 0x1c, 0xfd, 0x0b, 0xfe, 0xd3, 0xd7, 0x7d, 0x9f, 0x81, 0x26, 0xd3, 0xc5, 0x65, 0x49,
129 0xcf, 0x46, 0x62, 0xb0, 0x55, 0x6e, 0x47, 0xc7, 0x30, 0xef, 0x51, 0xfb, 0x3e, 0xc6, 0xef, 0xde,
130 0x27, 0x3f, 0xfa, 0x57, 0x2d, 0xa7, 0x1d, 0x80, 0x46, 0x9a, 0x5f, 0x14, 0xb3, 0xb0, 0x2c, 0xbe,
131 0x72, 0xca, 0xdf, 0xb2, 0xff, 0x36, 0x5b, 0x4f, 0xec, 0x58, 0x8e, 0x8d, 0x01, 0xe9, 0xa9, 0xdf,
132 0xb5, 0x60, 0xad, 0x52, 0x4d, 0xfc, 0xa9, 0x3e, 0x8d, 0x35, 0x95, 0xb3, 0x4e, 0x0f, 0xca, 0x45,
133 0x1b, 0xf7, 0xef, 0x3a, 0x88, 0x25, 0x08, 0xc7, 0x4e, 0x06, 0xc1, 0x62, 0x1a, 0xce, 0xd8, 0x77,
134 0xbd, 0x02, 0x65, 0xf8, 0x49, 0xfb, 0xce, 0xf6, 0xa8, 0x09, 0xfc, 0xde, 0xb2, 0x09, 0x9d, 0x39,
135 0xf8, 0x63, 0x9c, 0x32, 0x42, 0x7c, 0xa0, 0x30, 0x86, 0x72, 0x7a, 0x4a, 0xc6, 0xd4, 0xb3, 0x2d,
136 0x24, 0xef, 0x96, 0x3f, 0xc2, 0xda, 0xd3, 0xf2, 0x15, 0x6f, 0xda, 0x65, 0x4b, 0x81, 0x28, 0x68,
137 0xf4, 0xfe, 0x3e, 0x71, 0x4f, 0x50, 0x96, 0x72, 0x58, 0xa1, 0x89, 0xdd, 0x01, 0x61, 0x39, 0x39,
138 0xc6, 0x76, 0xa4, 0xda, 0x02, 0x70, 0x3d, 0xc0, 0xdc, 0x8d, 0x70, 0x72, 0x04, 0x90, 0x79, 0xd4,
139 0xec, 0x65, 0xcf, 0x49, 0x35, 0x25, 0x3a, 0x14, 0x1a, 0x45, 0x20, 0xeb, 0x31, 0xaf, 0x92, 0xba,
140 0x20, 0xd3, 0xcd, 0xa7, 0x13, 0x44, 0xdc, 0xcf, 0xf0, 0x27, 0x34, 0xb9, 0xe7, 0x24, 0x6f, 0x73,
141 0xe7, 0xea, 0x77, 0x03,
144 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*dnskey
= NULL
, *ds1
= NULL
, *ds2
= NULL
;
145 _cleanup_free_
char *a
= NULL
, *b
= NULL
, *c
= NULL
;
147 /* The two DS RRs in effect for nasa.gov on 2015-12-01. */
148 ds1
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_DS
, "nasa.gov");
151 ds1
->ds
.key_tag
= 47857;
152 ds1
->ds
.algorithm
= DNSSEC_ALGORITHM_RSASHA256
;
153 ds1
->ds
.digest_type
= DNSSEC_DIGEST_SHA1
;
154 ds1
->ds
.digest_size
= sizeof(ds1_fprint
);
155 ds1
->ds
.digest
= memdup(ds1_fprint
, ds1
->ds
.digest_size
);
156 assert_se(ds1
->ds
.digest
);
158 assert_se(dns_resource_record_to_string(ds1
, &a
) >= 0);
159 log_info("DS1: %s", a
);
161 ds2
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_DS
, "NASA.GOV");
164 ds2
->ds
.key_tag
= 47857;
165 ds2
->ds
.algorithm
= DNSSEC_ALGORITHM_RSASHA256
;
166 ds2
->ds
.digest_type
= DNSSEC_DIGEST_SHA256
;
167 ds2
->ds
.digest_size
= sizeof(ds2_fprint
);
168 ds2
->ds
.digest
= memdup(ds2_fprint
, ds2
->ds
.digest_size
);
169 assert_se(ds2
->ds
.digest
);
171 assert_se(dns_resource_record_to_string(ds2
, &b
) >= 0);
172 log_info("DS2: %s", b
);
174 dnskey
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_DNSKEY
, "nasa.GOV");
177 dnskey
->dnskey
.flags
= 257;
178 dnskey
->dnskey
.protocol
= 3;
179 dnskey
->dnskey
.algorithm
= DNSSEC_ALGORITHM_RSASHA256
;
180 dnskey
->dnskey
.key_size
= sizeof(dnskey_blob
);
181 dnskey
->dnskey
.key
= memdup(dnskey_blob
, sizeof(dnskey_blob
));
182 assert_se(dnskey
->dnskey
.key
);
184 assert_se(dns_resource_record_to_string(dnskey
, &c
) >= 0);
185 log_info("DNSKEY: %s", c
);
186 log_info("DNSKEY keytag: %u", dnssec_keytag(dnskey
));
188 assert_se(dnssec_verify_dnskey(dnskey
, ds1
) > 0);
189 assert_se(dnssec_verify_dnskey(dnskey
, ds2
) > 0);
192 static void test_dnssec_canonicalize_one(const char *original
, const char *canonical
, int r
) {
193 char canonicalized
[DNSSEC_CANONICAL_HOSTNAME_MAX
];
195 assert_se(dnssec_canonicalize(original
, canonicalized
, sizeof(canonicalized
)) == r
);
199 assert_se(streq(canonicalized
, canonical
));
202 static void test_dnssec_canonicalize(void) {
203 test_dnssec_canonicalize_one("", ".", 1);
204 test_dnssec_canonicalize_one(".", ".", 1);
205 test_dnssec_canonicalize_one("foo", "foo.", 4);
206 test_dnssec_canonicalize_one("foo.", "foo.", 4);
207 test_dnssec_canonicalize_one("FOO.", "foo.", 4);
208 test_dnssec_canonicalize_one("FOO.bar.", "foo.bar.", 8);
209 test_dnssec_canonicalize_one("FOO..bar.", NULL
, -EINVAL
);
212 int main(int argc
, char*argv
[]) {
214 test_dnssec_canonicalize();
215 test_dnssec_verify_dns_key();
216 test_dnssec_verify_rrset();