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_rrset2(void) {
33 static const uint8_t signature_blob
[] = {
34 0x48, 0x45, 0xc8, 0x8b, 0xc0, 0x14, 0x92, 0xf5, 0x15, 0xc6, 0x84, 0x9d, 0x2f, 0xe3, 0x32, 0x11,
35 0x7d, 0xf1, 0xe6, 0x87, 0xb9, 0x42, 0xd3, 0x8b, 0x9e, 0xaf, 0x92, 0x31, 0x0a, 0x53, 0xad, 0x8b,
36 0xa7, 0x5c, 0x83, 0x39, 0x8c, 0x28, 0xac, 0xce, 0x6e, 0x9c, 0x18, 0xe3, 0x31, 0x16, 0x6e, 0xca,
37 0x38, 0x31, 0xaf, 0xd9, 0x94, 0xf1, 0x84, 0xb1, 0xdf, 0x5a, 0xc2, 0x73, 0x22, 0xf6, 0xcb, 0xa2,
38 0xe7, 0x8c, 0x77, 0x0c, 0x74, 0x2f, 0xc2, 0x13, 0xb0, 0x93, 0x51, 0xa9, 0x4f, 0xae, 0x0a, 0xda,
39 0x45, 0xcc, 0xfd, 0x43, 0x99, 0x36, 0x9a, 0x0d, 0x21, 0xe0, 0xeb, 0x30, 0x65, 0xd4, 0xa0, 0x27,
40 0x37, 0x3b, 0xe4, 0xc1, 0xc5, 0xa1, 0x2a, 0xd1, 0x76, 0xc4, 0x7e, 0x64, 0x0e, 0x5a, 0xa6, 0x50,
41 0x24, 0xd5, 0x2c, 0xcc, 0x6d, 0xe5, 0x37, 0xea, 0xbd, 0x09, 0x34, 0xed, 0x24, 0x06, 0xa1, 0x22,
44 static const uint8_t dnskey_blob
[] = {
45 0x03, 0x01, 0x00, 0x01, 0xc3, 0x7f, 0x1d, 0xd1, 0x1c, 0x97, 0xb1, 0x13, 0x34, 0x3a, 0x9a, 0xea,
46 0xee, 0xd9, 0x5a, 0x11, 0x1b, 0x17, 0xc7, 0xe3, 0xd4, 0xda, 0x20, 0xbc, 0x5d, 0xba, 0x74, 0xe3,
47 0x37, 0x99, 0xec, 0x25, 0xce, 0x93, 0x7f, 0xbd, 0x22, 0x73, 0x7e, 0x14, 0x71, 0xe0, 0x60, 0x07,
48 0xd4, 0x39, 0x8b, 0x5e, 0xe9, 0xba, 0x25, 0xe8, 0x49, 0xe9, 0x34, 0xef, 0xfe, 0x04, 0x5c, 0xa5,
49 0x27, 0xcd, 0xa9, 0xda, 0x70, 0x05, 0x21, 0xab, 0x15, 0x82, 0x24, 0xc3, 0x94, 0xf5, 0xd7, 0xb7,
50 0xc4, 0x66, 0xcb, 0x32, 0x6e, 0x60, 0x2b, 0x55, 0x59, 0x28, 0x89, 0x8a, 0x72, 0xde, 0x88, 0x56,
51 0x27, 0x95, 0xd9, 0xac, 0x88, 0x4f, 0x65, 0x2b, 0x68, 0xfc, 0xe6, 0x41, 0xc1, 0x1b, 0xef, 0x4e,
52 0xd6, 0xc2, 0x0f, 0x64, 0x88, 0x95, 0x5e, 0xdd, 0x3a, 0x02, 0x07, 0x50, 0xa9, 0xda, 0xa4, 0x49,
53 0x74, 0x62, 0xfe, 0xd7,
56 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*nsec
= NULL
, *rrsig
= NULL
, *dnskey
= NULL
;
57 _cleanup_(dns_answer_unrefp
) DnsAnswer
*answer
= NULL
;
58 _cleanup_free_
char *x
= NULL
, *y
= NULL
, *z
= NULL
;
61 nsec
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_NSEC
, "nasa.gov");
64 nsec
->nsec
.next_domain_name
= strdup("3D-Printing.nasa.gov");
65 assert_se(nsec
->nsec
.next_domain_name
);
67 nsec
->nsec
.types
= bitmap_new();
68 assert_se(nsec
->nsec
.types
);
69 assert_se(bitmap_set(nsec
->nsec
.types
, DNS_TYPE_A
) >= 0);
70 assert_se(bitmap_set(nsec
->nsec
.types
, DNS_TYPE_NS
) >= 0);
71 assert_se(bitmap_set(nsec
->nsec
.types
, DNS_TYPE_SOA
) >= 0);
72 assert_se(bitmap_set(nsec
->nsec
.types
, DNS_TYPE_MX
) >= 0);
73 assert_se(bitmap_set(nsec
->nsec
.types
, DNS_TYPE_TXT
) >= 0);
74 assert_se(bitmap_set(nsec
->nsec
.types
, DNS_TYPE_RRSIG
) >= 0);
75 assert_se(bitmap_set(nsec
->nsec
.types
, DNS_TYPE_NSEC
) >= 0);
76 assert_se(bitmap_set(nsec
->nsec
.types
, DNS_TYPE_DNSKEY
) >= 0);
77 assert_se(bitmap_set(nsec
->nsec
.types
, 65534) >= 0);
79 assert_se(dns_resource_record_to_string(nsec
, &x
) >= 0);
80 log_info("NSEC: %s", x
);
82 rrsig
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_RRSIG
, "NaSa.GOV.");
85 rrsig
->rrsig
.type_covered
= DNS_TYPE_NSEC
;
86 rrsig
->rrsig
.algorithm
= DNSSEC_ALGORITHM_RSASHA256
;
87 rrsig
->rrsig
.labels
= 2;
88 rrsig
->rrsig
.original_ttl
= 300;
89 rrsig
->rrsig
.expiration
= 0x5689002f;
90 rrsig
->rrsig
.inception
= 0x56617230;
91 rrsig
->rrsig
.key_tag
= 30390;
92 rrsig
->rrsig
.signer
= strdup("Nasa.Gov.");
93 assert_se(rrsig
->rrsig
.signer
);
94 rrsig
->rrsig
.signature_size
= sizeof(signature_blob
);
95 rrsig
->rrsig
.signature
= memdup(signature_blob
, rrsig
->rrsig
.signature_size
);
96 assert_se(rrsig
->rrsig
.signature
);
98 assert_se(dns_resource_record_to_string(rrsig
, &y
) >= 0);
99 log_info("RRSIG: %s", y
);
101 dnskey
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_DNSKEY
, "nASA.gOV");
104 dnskey
->dnskey
.flags
= 256;
105 dnskey
->dnskey
.protocol
= 3;
106 dnskey
->dnskey
.algorithm
= DNSSEC_ALGORITHM_RSASHA256
;
107 dnskey
->dnskey
.key_size
= sizeof(dnskey_blob
);
108 dnskey
->dnskey
.key
= memdup(dnskey_blob
, sizeof(dnskey_blob
));
109 assert_se(dnskey
->dnskey
.key
);
111 assert_se(dns_resource_record_to_string(dnskey
, &z
) >= 0);
112 log_info("DNSKEY: %s", z
);
113 log_info("DNSKEY keytag: %u", dnssec_keytag(dnskey
));
115 assert_se(dnssec_key_match_rrsig(nsec
->key
, rrsig
) > 0);
116 assert_se(dnssec_rrsig_match_dnskey(rrsig
, dnskey
) > 0);
118 answer
= dns_answer_new(1);
120 assert_se(dns_answer_add(answer
, nsec
, 0) >= 0);
122 /* Validate the RR as it if was 2015-12-11 today */
123 assert_se(dnssec_verify_rrset(answer
, nsec
->key
, rrsig
, dnskey
, 1449849318*USEC_PER_SEC
, &result
) >= 0);
124 assert_se(result
== DNSSEC_VALIDATED
);
127 static void test_dnssec_verify_rrset(void) {
129 static const uint8_t signature_blob
[] = {
130 0x7f, 0x79, 0xdd, 0x5e, 0x89, 0x79, 0x18, 0xd0, 0x34, 0x86, 0x8c, 0x72, 0x77, 0x75, 0x48, 0x4d,
131 0xc3, 0x7d, 0x38, 0x04, 0xab, 0xcd, 0x9e, 0x4c, 0x82, 0xb0, 0x92, 0xca, 0xe9, 0x66, 0xe9, 0x6e,
132 0x47, 0xc7, 0x68, 0x8c, 0x94, 0xf6, 0x69, 0xcb, 0x75, 0x94, 0xe6, 0x30, 0xa6, 0xfb, 0x68, 0x64,
133 0x96, 0x1a, 0x84, 0xe1, 0xdc, 0x16, 0x4c, 0x83, 0x6c, 0x44, 0xf2, 0x74, 0x4d, 0x74, 0x79, 0x8f,
134 0xf3, 0xf4, 0x63, 0x0d, 0xef, 0x5a, 0xe7, 0xe2, 0xfd, 0xf2, 0x2b, 0x38, 0x7c, 0x28, 0x96, 0x9d,
135 0xb6, 0xcd, 0x5c, 0x3b, 0x57, 0xe2, 0x24, 0x78, 0x65, 0xd0, 0x9e, 0x77, 0x83, 0x09, 0x6c, 0xff,
136 0x3d, 0x52, 0x3f, 0x6e, 0xd1, 0xed, 0x2e, 0xf9, 0xee, 0x8e, 0xa6, 0xbe, 0x9a, 0xa8, 0x87, 0x76,
137 0xd8, 0x77, 0xcc, 0x96, 0xa0, 0x98, 0xa1, 0xd1, 0x68, 0x09, 0x43, 0xcf, 0x56, 0xd9, 0xd1, 0x66,
140 static const uint8_t dnskey_blob
[] = {
141 0x03, 0x01, 0x00, 0x01, 0x9b, 0x49, 0x9b, 0xc1, 0xf9, 0x9a, 0xe0, 0x4e, 0xcf, 0xcb, 0x14, 0x45,
142 0x2e, 0xc9, 0xf9, 0x74, 0xa7, 0x18, 0xb5, 0xf3, 0xde, 0x39, 0x49, 0xdf, 0x63, 0x33, 0x97, 0x52,
143 0xe0, 0x8e, 0xac, 0x50, 0x30, 0x8e, 0x09, 0xd5, 0x24, 0x3d, 0x26, 0xa4, 0x49, 0x37, 0x2b, 0xb0,
144 0x6b, 0x1b, 0xdf, 0xde, 0x85, 0x83, 0xcb, 0x22, 0x4e, 0x60, 0x0a, 0x91, 0x1a, 0x1f, 0xc5, 0x40,
145 0xb1, 0xc3, 0x15, 0xc1, 0x54, 0x77, 0x86, 0x65, 0x53, 0xec, 0x10, 0x90, 0x0c, 0x91, 0x00, 0x5e,
146 0x15, 0xdc, 0x08, 0x02, 0x4c, 0x8c, 0x0d, 0xc0, 0xac, 0x6e, 0xc4, 0x3e, 0x1b, 0x80, 0x19, 0xe4,
147 0xf7, 0x5f, 0x77, 0x51, 0x06, 0x87, 0x61, 0xde, 0xa2, 0x18, 0x0f, 0x40, 0x8b, 0x79, 0x72, 0xfa,
148 0x8d, 0x1a, 0x44, 0x47, 0x0d, 0x8e, 0x3a, 0x2d, 0xc7, 0x39, 0xbf, 0x56, 0x28, 0x97, 0xd9, 0x20,
149 0x4f, 0x00, 0x51, 0x3b,
152 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*a
= NULL
, *rrsig
= NULL
, *dnskey
= NULL
;
153 _cleanup_(dns_answer_unrefp
) DnsAnswer
*answer
= NULL
;
154 _cleanup_free_
char *x
= NULL
, *y
= NULL
, *z
= NULL
;
157 a
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_A
, "nAsA.gov");
160 a
->a
.in_addr
.s_addr
= inet_addr("52.0.14.116");
162 assert_se(dns_resource_record_to_string(a
, &x
) >= 0);
163 log_info("A: %s", x
);
165 rrsig
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_RRSIG
, "NaSa.GOV.");
168 rrsig
->rrsig
.type_covered
= DNS_TYPE_A
;
169 rrsig
->rrsig
.algorithm
= DNSSEC_ALGORITHM_RSASHA256
;
170 rrsig
->rrsig
.labels
= 2;
171 rrsig
->rrsig
.original_ttl
= 600;
172 rrsig
->rrsig
.expiration
= 0x5683135c;
173 rrsig
->rrsig
.inception
= 0x565b7da8;
174 rrsig
->rrsig
.key_tag
= 63876;
175 rrsig
->rrsig
.signer
= strdup("Nasa.Gov.");
176 assert_se(rrsig
->rrsig
.signer
);
177 rrsig
->rrsig
.signature_size
= sizeof(signature_blob
);
178 rrsig
->rrsig
.signature
= memdup(signature_blob
, rrsig
->rrsig
.signature_size
);
179 assert_se(rrsig
->rrsig
.signature
);
181 assert_se(dns_resource_record_to_string(rrsig
, &y
) >= 0);
182 log_info("RRSIG: %s", y
);
184 dnskey
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_DNSKEY
, "nASA.gOV");
187 dnskey
->dnskey
.flags
= 256;
188 dnskey
->dnskey
.protocol
= 3;
189 dnskey
->dnskey
.algorithm
= DNSSEC_ALGORITHM_RSASHA256
;
190 dnskey
->dnskey
.key_size
= sizeof(dnskey_blob
);
191 dnskey
->dnskey
.key
= memdup(dnskey_blob
, sizeof(dnskey_blob
));
192 assert_se(dnskey
->dnskey
.key
);
194 assert_se(dns_resource_record_to_string(dnskey
, &z
) >= 0);
195 log_info("DNSKEY: %s", z
);
196 log_info("DNSKEY keytag: %u", dnssec_keytag(dnskey
));
198 assert_se(dnssec_key_match_rrsig(a
->key
, rrsig
) > 0);
199 assert_se(dnssec_rrsig_match_dnskey(rrsig
, dnskey
) > 0);
201 answer
= dns_answer_new(1);
203 assert_se(dns_answer_add(answer
, a
, 0) >= 0);
205 /* Validate the RR as it if was 2015-12-2 today */
206 assert_se(dnssec_verify_rrset(answer
, a
->key
, rrsig
, dnskey
, 1449092754*USEC_PER_SEC
, &result
) >= 0);
207 assert_se(result
== DNSSEC_VALIDATED
);
210 static void test_dnssec_verify_dns_key(void) {
212 static const uint8_t ds1_fprint
[] = {
213 0x46, 0x8B, 0xC8, 0xDD, 0xC7, 0xE8, 0x27, 0x03, 0x40, 0xBB, 0x8A, 0x1F, 0x3B, 0x2E, 0x45, 0x9D,
214 0x80, 0x67, 0x14, 0x01,
216 static const uint8_t ds2_fprint
[] = {
217 0x8A, 0xEE, 0x80, 0x47, 0x05, 0x5F, 0x83, 0xD1, 0x48, 0xBA, 0x8F, 0xF6, 0xDD, 0xA7, 0x60, 0xCE,
218 0x94, 0xF7, 0xC7, 0x5E, 0x52, 0x4C, 0xF2, 0xE9, 0x50, 0xB9, 0x2E, 0xCB, 0xEF, 0x96, 0xB9, 0x98,
220 static const uint8_t dnskey_blob
[] = {
221 0x03, 0x01, 0x00, 0x01, 0xa8, 0x12, 0xda, 0x4f, 0xd2, 0x7d, 0x54, 0x14, 0x0e, 0xcc, 0x5b, 0x5e,
222 0x45, 0x9c, 0x96, 0x98, 0xc0, 0xc0, 0x85, 0x81, 0xb1, 0x47, 0x8c, 0x7d, 0xe8, 0x39, 0x50, 0xcc,
223 0xc5, 0xd0, 0xf2, 0x00, 0x81, 0x67, 0x79, 0xf6, 0xcc, 0x9d, 0xad, 0x6c, 0xbb, 0x7b, 0x6f, 0x48,
224 0x97, 0x15, 0x1c, 0xfd, 0x0b, 0xfe, 0xd3, 0xd7, 0x7d, 0x9f, 0x81, 0x26, 0xd3, 0xc5, 0x65, 0x49,
225 0xcf, 0x46, 0x62, 0xb0, 0x55, 0x6e, 0x47, 0xc7, 0x30, 0xef, 0x51, 0xfb, 0x3e, 0xc6, 0xef, 0xde,
226 0x27, 0x3f, 0xfa, 0x57, 0x2d, 0xa7, 0x1d, 0x80, 0x46, 0x9a, 0x5f, 0x14, 0xb3, 0xb0, 0x2c, 0xbe,
227 0x72, 0xca, 0xdf, 0xb2, 0xff, 0x36, 0x5b, 0x4f, 0xec, 0x58, 0x8e, 0x8d, 0x01, 0xe9, 0xa9, 0xdf,
228 0xb5, 0x60, 0xad, 0x52, 0x4d, 0xfc, 0xa9, 0x3e, 0x8d, 0x35, 0x95, 0xb3, 0x4e, 0x0f, 0xca, 0x45,
229 0x1b, 0xf7, 0xef, 0x3a, 0x88, 0x25, 0x08, 0xc7, 0x4e, 0x06, 0xc1, 0x62, 0x1a, 0xce, 0xd8, 0x77,
230 0xbd, 0x02, 0x65, 0xf8, 0x49, 0xfb, 0xce, 0xf6, 0xa8, 0x09, 0xfc, 0xde, 0xb2, 0x09, 0x9d, 0x39,
231 0xf8, 0x63, 0x9c, 0x32, 0x42, 0x7c, 0xa0, 0x30, 0x86, 0x72, 0x7a, 0x4a, 0xc6, 0xd4, 0xb3, 0x2d,
232 0x24, 0xef, 0x96, 0x3f, 0xc2, 0xda, 0xd3, 0xf2, 0x15, 0x6f, 0xda, 0x65, 0x4b, 0x81, 0x28, 0x68,
233 0xf4, 0xfe, 0x3e, 0x71, 0x4f, 0x50, 0x96, 0x72, 0x58, 0xa1, 0x89, 0xdd, 0x01, 0x61, 0x39, 0x39,
234 0xc6, 0x76, 0xa4, 0xda, 0x02, 0x70, 0x3d, 0xc0, 0xdc, 0x8d, 0x70, 0x72, 0x04, 0x90, 0x79, 0xd4,
235 0xec, 0x65, 0xcf, 0x49, 0x35, 0x25, 0x3a, 0x14, 0x1a, 0x45, 0x20, 0xeb, 0x31, 0xaf, 0x92, 0xba,
236 0x20, 0xd3, 0xcd, 0xa7, 0x13, 0x44, 0xdc, 0xcf, 0xf0, 0x27, 0x34, 0xb9, 0xe7, 0x24, 0x6f, 0x73,
237 0xe7, 0xea, 0x77, 0x03,
240 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*dnskey
= NULL
, *ds1
= NULL
, *ds2
= NULL
;
241 _cleanup_free_
char *a
= NULL
, *b
= NULL
, *c
= NULL
;
243 /* The two DS RRs in effect for nasa.gov on 2015-12-01. */
244 ds1
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_DS
, "nasa.gov");
247 ds1
->ds
.key_tag
= 47857;
248 ds1
->ds
.algorithm
= DNSSEC_ALGORITHM_RSASHA256
;
249 ds1
->ds
.digest_type
= DNSSEC_DIGEST_SHA1
;
250 ds1
->ds
.digest_size
= sizeof(ds1_fprint
);
251 ds1
->ds
.digest
= memdup(ds1_fprint
, ds1
->ds
.digest_size
);
252 assert_se(ds1
->ds
.digest
);
254 assert_se(dns_resource_record_to_string(ds1
, &a
) >= 0);
255 log_info("DS1: %s", a
);
257 ds2
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_DS
, "NASA.GOV");
260 ds2
->ds
.key_tag
= 47857;
261 ds2
->ds
.algorithm
= DNSSEC_ALGORITHM_RSASHA256
;
262 ds2
->ds
.digest_type
= DNSSEC_DIGEST_SHA256
;
263 ds2
->ds
.digest_size
= sizeof(ds2_fprint
);
264 ds2
->ds
.digest
= memdup(ds2_fprint
, ds2
->ds
.digest_size
);
265 assert_se(ds2
->ds
.digest
);
267 assert_se(dns_resource_record_to_string(ds2
, &b
) >= 0);
268 log_info("DS2: %s", b
);
270 dnskey
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_DNSKEY
, "nasa.GOV");
273 dnskey
->dnskey
.flags
= 257;
274 dnskey
->dnskey
.protocol
= 3;
275 dnskey
->dnskey
.algorithm
= DNSSEC_ALGORITHM_RSASHA256
;
276 dnskey
->dnskey
.key_size
= sizeof(dnskey_blob
);
277 dnskey
->dnskey
.key
= memdup(dnskey_blob
, sizeof(dnskey_blob
));
278 assert_se(dnskey
->dnskey
.key
);
280 assert_se(dns_resource_record_to_string(dnskey
, &c
) >= 0);
281 log_info("DNSKEY: %s", c
);
282 log_info("DNSKEY keytag: %u", dnssec_keytag(dnskey
));
284 assert_se(dnssec_verify_dnskey(dnskey
, ds1
) > 0);
285 assert_se(dnssec_verify_dnskey(dnskey
, ds2
) > 0);
288 static void test_dnssec_canonicalize_one(const char *original
, const char *canonical
, int r
) {
289 char canonicalized
[DNSSEC_CANONICAL_HOSTNAME_MAX
];
291 assert_se(dnssec_canonicalize(original
, canonicalized
, sizeof(canonicalized
)) == r
);
295 assert_se(streq(canonicalized
, canonical
));
298 static void test_dnssec_canonicalize(void) {
299 test_dnssec_canonicalize_one("", ".", 1);
300 test_dnssec_canonicalize_one(".", ".", 1);
301 test_dnssec_canonicalize_one("foo", "foo.", 4);
302 test_dnssec_canonicalize_one("foo.", "foo.", 4);
303 test_dnssec_canonicalize_one("FOO.", "foo.", 4);
304 test_dnssec_canonicalize_one("FOO.bar.", "foo.bar.", 8);
305 test_dnssec_canonicalize_one("FOO..bar.", NULL
, -EINVAL
);
308 int main(int argc
, char*argv
[]) {
310 test_dnssec_canonicalize();
311 test_dnssec_verify_dns_key();
312 test_dnssec_verify_rrset();
313 test_dnssec_verify_rrset2();