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
;
60 a
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_A
, "nAsA.gov");
63 a
->a
.in_addr
.s_addr
= inet_addr("52.0.14.116");
65 assert_se(dns_resource_record_to_string(a
, &x
) >= 0);
68 rrsig
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_RRSIG
, "NaSa.GOV.");
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
);
84 assert_se(dns_resource_record_to_string(rrsig
, &y
) >= 0);
85 log_info("RRSIG: %s", y
);
87 dnskey
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_DNSKEY
, "nASA.gOV");
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
);
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
));
101 assert_se(dnssec_key_match_rrsig(a
->key
, rrsig
) > 0);
102 assert_se(dnssec_rrsig_match_dnskey(rrsig
, dnskey
) > 0);
104 answer
= dns_answer_new(1);
106 assert_se(dns_answer_add(answer
, a
, 0) >= 0);
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
);
112 static void test_dnssec_verify_dns_key(void) {
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,
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,
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,
142 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*dnskey
= NULL
, *ds1
= NULL
, *ds2
= NULL
;
143 _cleanup_free_
char *a
= NULL
, *b
= NULL
, *c
= NULL
;
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");
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
);
156 assert_se(dns_resource_record_to_string(ds1
, &a
) >= 0);
157 log_info("DS1: %s", a
);
159 ds2
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_DS
, "NASA.GOV");
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
);
169 assert_se(dns_resource_record_to_string(ds2
, &b
) >= 0);
170 log_info("DS2: %s", b
);
172 dnskey
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_DNSKEY
, "nasa.GOV");
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
);
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
));
186 assert_se(dnssec_verify_dnskey(dnskey
, ds1
) > 0);
187 assert_se(dnssec_verify_dnskey(dnskey
, ds2
) > 0);
190 static void test_dnssec_canonicalize_one(const char *original
, const char *canonical
, int r
) {
191 char canonicalized
[DNSSEC_CANONICAL_HOSTNAME_MAX
];
193 assert_se(dnssec_canonicalize(original
, canonicalized
, sizeof(canonicalized
)) == r
);
197 assert_se(streq(canonicalized
, canonical
));
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
);
210 int main(int argc
, char*argv
[]) {
212 test_dnssec_canonicalize();
213 test_dnssec_verify_dns_key();
214 test_dnssec_verify_rrset();