]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/resolve/test-dnssec.c
Merge pull request #2129 from poettering/dnssec3
[thirdparty/systemd.git] / src / resolve / test-dnssec.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2015 Lennart Poettering
7
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.
12
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.
17
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/>.
20 ***/
21
22 #include <arpa/inet.h>
23 #include <netinet/in.h>
24 #include <sys/socket.h>
25
26 #include "alloc-util.h"
27 #include "resolved-dns-dnssec.h"
28 #include "resolved-dns-rr.h"
29 #include "string-util.h"
30
31 static void test_dnssec_verify_rrset(void) {
32
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,
42 };
43
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,
54 };
55
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;
59 DnssecResult result;
60
61 a = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_A, "nAsA.gov");
62 assert_se(a);
63
64 a->a.in_addr.s_addr = inet_addr("52.0.14.116");
65
66 assert_se(dns_resource_record_to_string(a, &x) >= 0);
67 log_info("A: %s", x);
68
69 rrsig = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_RRSIG, "NaSa.GOV.");
70 assert_se(rrsig);
71
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);
84
85 assert_se(dns_resource_record_to_string(rrsig, &y) >= 0);
86 log_info("RRSIG: %s", y);
87
88 dnskey = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DNSKEY, "nASA.gOV");
89 assert_se(dnskey);
90
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);
97
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));
101
102 assert_se(dnssec_key_match_rrsig(a->key, rrsig) > 0);
103 assert_se(dnssec_rrsig_match_dnskey(rrsig, dnskey) > 0);
104
105 answer = dns_answer_new(1);
106 assert_se(answer);
107 assert_se(dns_answer_add(answer, a, 0) >= 0);
108
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);
112 }
113
114 static void test_dnssec_verify_dns_key(void) {
115
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,
119 };
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,
123 };
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,
142 };
143
144 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *dnskey = NULL, *ds1 = NULL, *ds2 = NULL;
145 _cleanup_free_ char *a = NULL, *b = NULL, *c = NULL;
146
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");
149 assert_se(ds1);
150
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);
157
158 assert_se(dns_resource_record_to_string(ds1, &a) >= 0);
159 log_info("DS1: %s", a);
160
161 ds2 = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DS, "NASA.GOV");
162 assert_se(ds2);
163
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);
170
171 assert_se(dns_resource_record_to_string(ds2, &b) >= 0);
172 log_info("DS2: %s", b);
173
174 dnskey = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DNSKEY, "nasa.GOV");
175 assert_se(dnskey);
176
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);
183
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));
187
188 assert_se(dnssec_verify_dnskey(dnskey, ds1) > 0);
189 assert_se(dnssec_verify_dnskey(dnskey, ds2) > 0);
190 }
191
192 static void test_dnssec_canonicalize_one(const char *original, const char *canonical, int r) {
193 char canonicalized[DNSSEC_CANONICAL_HOSTNAME_MAX];
194
195 assert_se(dnssec_canonicalize(original, canonicalized, sizeof(canonicalized)) == r);
196 if (r < 0)
197 return;
198
199 assert_se(streq(canonicalized, canonical));
200 }
201
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);
210 }
211
212 int main(int argc, char*argv[]) {
213
214 test_dnssec_canonicalize();
215 test_dnssec_verify_dns_key();
216 test_dnssec_verify_rrset();
217
218 return 0;
219 }