]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/resolve/test-dnssec.c
Merge pull request #2076 from keszybz/downgrade-masked-unit-message
[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
60 a = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_A, "nAsA.gov");
61 assert_se(a);
62
63 a->a.in_addr.s_addr = inet_addr("52.0.14.116");
64
65 assert_se(dns_resource_record_to_string(a, &x) >= 0);
66 log_info("A: %s", x);
67
68 rrsig = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_RRSIG, "NaSa.GOV.");
69 assert_se(rrsig);
70
71 rrsig->rrsig.type_covered = DNS_TYPE_A;
72 rrsig->rrsig.algorithm = DNSSEC_ALGORITHM_RSASHA256;
73 rrsig->rrsig.labels = 2;
74 rrsig->rrsig.original_ttl = 600;
75 rrsig->rrsig.expiration = 0x5683135c;
76 rrsig->rrsig.inception = 0x565b7da8;
77 rrsig->rrsig.key_tag = 63876;
78 rrsig->rrsig.signer = strdup("Nasa.Gov.");
79 assert_se(rrsig->rrsig.signer);
80 rrsig->rrsig.signature_size = sizeof(signature_blob);
81 rrsig->rrsig.signature = memdup(signature_blob, rrsig->rrsig.signature_size);
82 assert_se(rrsig->rrsig.signature);
83
84 assert_se(dns_resource_record_to_string(rrsig, &y) >= 0);
85 log_info("RRSIG: %s", y);
86
87 dnskey = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DNSKEY, "nASA.gOV");
88 assert_se(dnskey);
89
90 dnskey->dnskey.flags = 256;
91 dnskey->dnskey.protocol = 3;
92 dnskey->dnskey.algorithm = DNSSEC_ALGORITHM_RSASHA256;
93 dnskey->dnskey.key_size = sizeof(dnskey_blob);
94 dnskey->dnskey.key = memdup(dnskey_blob, sizeof(dnskey_blob));
95 assert_se(dnskey->dnskey.key);
96
97 assert_se(dns_resource_record_to_string(dnskey, &z) >= 0);
98 log_info("DNSKEY: %s", z);
99 log_info("DNSKEY keytag: %u", dnssec_keytag(dnskey));
100
101 assert_se(dnssec_key_match_rrsig(a->key, rrsig) > 0);
102 assert_se(dnssec_rrsig_match_dnskey(rrsig, dnskey) > 0);
103
104 answer = dns_answer_new(1);
105 assert_se(answer);
106 assert_se(dns_answer_add(answer, a, 0) >= 0);
107
108 /* Validate the RR as it if was 2015-12-2 today */
109 assert_se(dnssec_verify_rrset(answer, a->key, rrsig, dnskey, 1449092754*USEC_PER_SEC) == DNSSEC_VERIFIED);
110 }
111
112 static void test_dnssec_verify_dns_key(void) {
113
114 static const uint8_t ds1_fprint[] = {
115 0x46, 0x8B, 0xC8, 0xDD, 0xC7, 0xE8, 0x27, 0x03, 0x40, 0xBB, 0x8A, 0x1F, 0x3B, 0x2E, 0x45, 0x9D,
116 0x80, 0x67, 0x14, 0x01,
117 };
118 static const uint8_t ds2_fprint[] = {
119 0x8A, 0xEE, 0x80, 0x47, 0x05, 0x5F, 0x83, 0xD1, 0x48, 0xBA, 0x8F, 0xF6, 0xDD, 0xA7, 0x60, 0xCE,
120 0x94, 0xF7, 0xC7, 0x5E, 0x52, 0x4C, 0xF2, 0xE9, 0x50, 0xB9, 0x2E, 0xCB, 0xEF, 0x96, 0xB9, 0x98,
121 };
122 static const uint8_t dnskey_blob[] = {
123 0x03, 0x01, 0x00, 0x01, 0xa8, 0x12, 0xda, 0x4f, 0xd2, 0x7d, 0x54, 0x14, 0x0e, 0xcc, 0x5b, 0x5e,
124 0x45, 0x9c, 0x96, 0x98, 0xc0, 0xc0, 0x85, 0x81, 0xb1, 0x47, 0x8c, 0x7d, 0xe8, 0x39, 0x50, 0xcc,
125 0xc5, 0xd0, 0xf2, 0x00, 0x81, 0x67, 0x79, 0xf6, 0xcc, 0x9d, 0xad, 0x6c, 0xbb, 0x7b, 0x6f, 0x48,
126 0x97, 0x15, 0x1c, 0xfd, 0x0b, 0xfe, 0xd3, 0xd7, 0x7d, 0x9f, 0x81, 0x26, 0xd3, 0xc5, 0x65, 0x49,
127 0xcf, 0x46, 0x62, 0xb0, 0x55, 0x6e, 0x47, 0xc7, 0x30, 0xef, 0x51, 0xfb, 0x3e, 0xc6, 0xef, 0xde,
128 0x27, 0x3f, 0xfa, 0x57, 0x2d, 0xa7, 0x1d, 0x80, 0x46, 0x9a, 0x5f, 0x14, 0xb3, 0xb0, 0x2c, 0xbe,
129 0x72, 0xca, 0xdf, 0xb2, 0xff, 0x36, 0x5b, 0x4f, 0xec, 0x58, 0x8e, 0x8d, 0x01, 0xe9, 0xa9, 0xdf,
130 0xb5, 0x60, 0xad, 0x52, 0x4d, 0xfc, 0xa9, 0x3e, 0x8d, 0x35, 0x95, 0xb3, 0x4e, 0x0f, 0xca, 0x45,
131 0x1b, 0xf7, 0xef, 0x3a, 0x88, 0x25, 0x08, 0xc7, 0x4e, 0x06, 0xc1, 0x62, 0x1a, 0xce, 0xd8, 0x77,
132 0xbd, 0x02, 0x65, 0xf8, 0x49, 0xfb, 0xce, 0xf6, 0xa8, 0x09, 0xfc, 0xde, 0xb2, 0x09, 0x9d, 0x39,
133 0xf8, 0x63, 0x9c, 0x32, 0x42, 0x7c, 0xa0, 0x30, 0x86, 0x72, 0x7a, 0x4a, 0xc6, 0xd4, 0xb3, 0x2d,
134 0x24, 0xef, 0x96, 0x3f, 0xc2, 0xda, 0xd3, 0xf2, 0x15, 0x6f, 0xda, 0x65, 0x4b, 0x81, 0x28, 0x68,
135 0xf4, 0xfe, 0x3e, 0x71, 0x4f, 0x50, 0x96, 0x72, 0x58, 0xa1, 0x89, 0xdd, 0x01, 0x61, 0x39, 0x39,
136 0xc6, 0x76, 0xa4, 0xda, 0x02, 0x70, 0x3d, 0xc0, 0xdc, 0x8d, 0x70, 0x72, 0x04, 0x90, 0x79, 0xd4,
137 0xec, 0x65, 0xcf, 0x49, 0x35, 0x25, 0x3a, 0x14, 0x1a, 0x45, 0x20, 0xeb, 0x31, 0xaf, 0x92, 0xba,
138 0x20, 0xd3, 0xcd, 0xa7, 0x13, 0x44, 0xdc, 0xcf, 0xf0, 0x27, 0x34, 0xb9, 0xe7, 0x24, 0x6f, 0x73,
139 0xe7, 0xea, 0x77, 0x03,
140 };
141
142 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *dnskey = NULL, *ds1 = NULL, *ds2 = NULL;
143 _cleanup_free_ char *a = NULL, *b = NULL, *c = NULL;
144
145 /* The two DS RRs in effect for nasa.gov on 2015-12-01. */
146 ds1 = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DS, "nasa.gov");
147 assert_se(ds1);
148
149 ds1->ds.key_tag = 47857;
150 ds1->ds.algorithm = DNSSEC_ALGORITHM_RSASHA256;
151 ds1->ds.digest_type = DNSSEC_DIGEST_SHA1;
152 ds1->ds.digest_size = sizeof(ds1_fprint);
153 ds1->ds.digest = memdup(ds1_fprint, ds1->ds.digest_size);
154 assert_se(ds1->ds.digest);
155
156 assert_se(dns_resource_record_to_string(ds1, &a) >= 0);
157 log_info("DS1: %s", a);
158
159 ds2 = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DS, "NASA.GOV");
160 assert_se(ds2);
161
162 ds2->ds.key_tag = 47857;
163 ds2->ds.algorithm = DNSSEC_ALGORITHM_RSASHA256;
164 ds2->ds.digest_type = DNSSEC_DIGEST_SHA256;
165 ds2->ds.digest_size = sizeof(ds2_fprint);
166 ds2->ds.digest = memdup(ds2_fprint, ds2->ds.digest_size);
167 assert_se(ds2->ds.digest);
168
169 assert_se(dns_resource_record_to_string(ds2, &b) >= 0);
170 log_info("DS2: %s", b);
171
172 dnskey = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DNSKEY, "nasa.GOV");
173 assert_se(dnskey);
174
175 dnskey->dnskey.flags = 257;
176 dnskey->dnskey.protocol = 3;
177 dnskey->dnskey.algorithm = DNSSEC_ALGORITHM_RSASHA256;
178 dnskey->dnskey.key_size = sizeof(dnskey_blob);
179 dnskey->dnskey.key = memdup(dnskey_blob, sizeof(dnskey_blob));
180 assert_se(dnskey->dnskey.key);
181
182 assert_se(dns_resource_record_to_string(dnskey, &c) >= 0);
183 log_info("DNSKEY: %s", c);
184 log_info("DNSKEY keytag: %u", dnssec_keytag(dnskey));
185
186 assert_se(dnssec_verify_dnskey(dnskey, ds1) > 0);
187 assert_se(dnssec_verify_dnskey(dnskey, ds2) > 0);
188 }
189
190 static void test_dnssec_canonicalize_one(const char *original, const char *canonical, int r) {
191 char canonicalized[DNSSEC_CANONICAL_HOSTNAME_MAX];
192
193 assert_se(dnssec_canonicalize(original, canonicalized, sizeof(canonicalized)) == r);
194 if (r < 0)
195 return;
196
197 assert_se(streq(canonicalized, canonical));
198 }
199
200 static void test_dnssec_canonicalize(void) {
201 test_dnssec_canonicalize_one("", ".", 1);
202 test_dnssec_canonicalize_one(".", ".", 1);
203 test_dnssec_canonicalize_one("foo", "foo.", 4);
204 test_dnssec_canonicalize_one("foo.", "foo.", 4);
205 test_dnssec_canonicalize_one("FOO.", "foo.", 4);
206 test_dnssec_canonicalize_one("FOO.bar.", "foo.bar.", 8);
207 test_dnssec_canonicalize_one("FOO..bar.", NULL, -EINVAL);
208 }
209
210 int main(int argc, char*argv[]) {
211
212 test_dnssec_canonicalize();
213 test_dnssec_verify_dns_key();
214 test_dnssec_verify_rrset();
215
216 return 0;
217 }