Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/ldns/drill/dnssec.c
39478 views
1
/*
2
* dnssec.c
3
* Some DNSSEC helper function are defined here
4
* and tracing is done
5
* (c) 2005 NLnet Labs
6
*
7
* See the file LICENSE for the license
8
*
9
*/
10
11
#include "drill.h"
12
#include <ldns/ldns.h>
13
14
/* get rr_type from a server from a server */
15
ldns_rr_list *
16
get_rr(ldns_resolver *res, ldns_rdf *zname, ldns_rr_type t, ldns_rr_class c)
17
{
18
/* query, retrieve, extract and return */
19
ldns_pkt *p;
20
ldns_rr_list *found;
21
22
p = ldns_pkt_new();
23
found = NULL;
24
25
if (ldns_resolver_send(&p, res, zname, t, c, 0) == LDNS_STATUS_OK) {
26
found = ldns_pkt_rr_list_by_type(p, t, LDNS_SECTION_ANY_NOQUESTION);
27
}
28
ldns_pkt_free(p);
29
return found;
30
}
31
32
void
33
drill_pkt_print(FILE *fd, ldns_resolver *r, ldns_pkt *p)
34
{
35
ldns_rr_list *new_nss;
36
ldns_rr_list *hostnames;
37
char *answerfrom_str;
38
39
if (verbosity < 5) {
40
return;
41
}
42
43
hostnames = ldns_get_rr_list_name_by_addr(r, ldns_pkt_answerfrom(p), 0, 0);
44
45
new_nss = ldns_pkt_rr_list_by_type(p,
46
LDNS_RR_TYPE_NS, LDNS_SECTION_ANSWER);
47
ldns_rr_list_print(fd, new_nss);
48
ldns_rr_list_deep_free(new_nss);
49
50
fprintf(fd, ";; Received %d bytes from %s#%d(",
51
(int) ldns_pkt_size(p),
52
ldns_rdf2str(ldns_pkt_answerfrom(p)),
53
(int) ldns_resolver_port(r));
54
/* if we can resolve this print it, other print the ip again */
55
if (hostnames) {
56
ldns_rdf_print(fd,
57
ldns_rr_rdf(ldns_rr_list_rr(hostnames, 0), 0));
58
ldns_rr_list_deep_free(hostnames);
59
} else {
60
answerfrom_str = ldns_rdf2str(ldns_pkt_answerfrom(p));
61
if (answerfrom_str) {
62
fprintf(fd, "%s", answerfrom_str);
63
LDNS_FREE(answerfrom_str);
64
}
65
}
66
fprintf(fd, ") in %u ms\n\n", (unsigned int)ldns_pkt_querytime(p));
67
}
68
69
void
70
drill_pkt_print_footer(FILE *fd, ldns_resolver *r, ldns_pkt *p)
71
{
72
ldns_rr_list *hostnames;
73
char *answerfrom_str;
74
75
if (verbosity < 5) {
76
return;
77
}
78
79
hostnames = ldns_get_rr_list_name_by_addr(r, ldns_pkt_answerfrom(p), 0, 0);
80
81
fprintf(fd, ";; Received %d bytes from %s#%d(",
82
(int) ldns_pkt_size(p),
83
ldns_rdf2str(ldns_pkt_answerfrom(p)),
84
(int) ldns_resolver_port(r));
85
/* if we can resolve this print it, other print the ip again */
86
if (hostnames) {
87
ldns_rdf_print(fd,
88
ldns_rr_rdf(ldns_rr_list_rr(hostnames, 0), 0));
89
ldns_rr_list_deep_free(hostnames);
90
} else {
91
answerfrom_str = ldns_rdf2str(ldns_pkt_answerfrom(p));
92
if (answerfrom_str) {
93
fprintf(fd, "%s", answerfrom_str);
94
LDNS_FREE(answerfrom_str);
95
}
96
}
97
fprintf(fd, ") in %u ms\n\n", (unsigned int)ldns_pkt_querytime(p));
98
}
99
/*
100
* generic function to get some RRset from a nameserver
101
* and possible some signatures too (that would be the day...)
102
*/
103
ldns_pkt_type
104
get_dnssec_rr(ldns_pkt *p, ldns_rdf *name, ldns_rr_type t,
105
ldns_rr_list **rrlist, ldns_rr_list **sig)
106
{
107
ldns_pkt_type pt = LDNS_PACKET_UNKNOWN;
108
ldns_rr_list *sigs = NULL;
109
size_t i;
110
111
if (!p) {
112
if (rrlist) {
113
*rrlist = NULL;
114
}
115
return LDNS_PACKET_UNKNOWN;
116
}
117
118
pt = ldns_pkt_reply_type(p);
119
if (name) {
120
if (rrlist) {
121
*rrlist = ldns_pkt_rr_list_by_name_and_type(p, name, t,
122
LDNS_SECTION_ANSWER);
123
if (!*rrlist) {
124
*rrlist = ldns_pkt_rr_list_by_name_and_type(
125
p, name, t,
126
LDNS_SECTION_AUTHORITY);
127
}
128
}
129
if (sig) {
130
sigs = ldns_pkt_rr_list_by_name_and_type(p, name,
131
LDNS_RR_TYPE_RRSIG,
132
LDNS_SECTION_ANSWER);
133
if (!sigs) {
134
sigs = ldns_pkt_rr_list_by_name_and_type(
135
p, name, LDNS_RR_TYPE_RRSIG,
136
LDNS_SECTION_AUTHORITY);
137
}
138
}
139
} else {
140
/* A DS-referral - get the DS records if they are there */
141
if (rrlist) {
142
*rrlist = ldns_pkt_rr_list_by_type(
143
p, t, LDNS_SECTION_AUTHORITY);
144
}
145
if (sig) {
146
sigs = ldns_pkt_rr_list_by_type(p,
147
LDNS_RR_TYPE_RRSIG,
148
LDNS_SECTION_AUTHORITY);
149
}
150
}
151
if (sig) {
152
*sig = ldns_rr_list_new();
153
for (i = 0; i < ldns_rr_list_rr_count(sigs); i++) {
154
/* only add the sigs that cover this type */
155
if (t == ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(
156
ldns_rr_list_rr(sigs, i)))) {
157
158
ldns_rr_list_push_rr(*sig,
159
ldns_rr_clone(
160
ldns_rr_list_rr(
161
sigs, i)));
162
}
163
}
164
}
165
ldns_rr_list_deep_free(sigs);
166
167
if (pt == LDNS_PACKET_NXDOMAIN || pt == LDNS_PACKET_NODATA) {
168
return pt;
169
} else {
170
return LDNS_PACKET_ANSWER;
171
}
172
}
173
174
175
ldns_status
176
ldns_verify_denial(ldns_pkt *pkt, ldns_rdf *name, ldns_rr_type type, ldns_rr_list **nsec_rrs, ldns_rr_list **nsec_rr_sigs)
177
{
178
#ifdef HAVE_SSL
179
uint16_t nsec_i;
180
181
ldns_rr_list *nsecs;
182
ldns_status result;
183
const ldns_rr_descriptor *descriptor;
184
185
if (!pkt) {
186
descriptor = ldns_rr_descript(type);
187
188
printf("NETWORk ERROR! Cannot verify denial for: ");
189
ldns_rdf_print(stdout, name);
190
printf(" type ");
191
if (descriptor && descriptor->_name)
192
printf("%s", descriptor->_name);
193
else
194
printf("TYPE%u", type);
195
return LDNS_STATUS_CRYPTO_NO_RRSIG;
196
}
197
if (verbosity >= 5) {
198
printf("VERIFY DENIAL FROM:\n");
199
ldns_pkt_print(stdout, pkt);
200
}
201
202
result = LDNS_STATUS_CRYPTO_NO_RRSIG;
203
/* Try to see if there are NSECS in the packet */
204
nsecs = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_NSEC, LDNS_SECTION_ANY_NOQUESTION);
205
if (nsecs) {
206
for (nsec_i = 0; nsec_i < ldns_rr_list_rr_count(nsecs); nsec_i++) {
207
/* there are four options:
208
* - name equals ownername and is covered by the type bitmap
209
* - name equals ownername but is not covered by the type bitmap
210
* - name falls within nsec coverage but is not equal to the owner name
211
* - name falls outside of nsec coverage
212
*/
213
if (ldns_dname_compare(ldns_rr_owner(ldns_rr_list_rr(nsecs, nsec_i)), name) == 0) {
214
/*
215
printf("CHECKING NSEC:\n");
216
ldns_rr_print(stdout, ldns_rr_list_rr(nsecs, nsec_i));
217
printf("DAWASEM\n");
218
*/
219
if (ldns_nsec_bitmap_covers_type(
220
ldns_nsec_get_bitmap(ldns_rr_list_rr(nsecs,
221
nsec_i)),
222
type)) {
223
/* Error, according to the nsec this rrset is signed */
224
result = LDNS_STATUS_CRYPTO_NO_RRSIG;
225
} else {
226
/* ok nsec denies existence */
227
if (verbosity >= 3) {
228
printf(";; Existence of data set with this type denied by NSEC\n");
229
}
230
/*printf(";; Verifiably insecure.\n");*/
231
if (nsec_rrs && nsec_rr_sigs) {
232
(void) get_dnssec_rr(pkt, ldns_rr_owner(ldns_rr_list_rr(nsecs, nsec_i)), LDNS_RR_TYPE_NSEC, nsec_rrs, nsec_rr_sigs);
233
}
234
ldns_rr_list_deep_free(nsecs);
235
return LDNS_STATUS_OK;
236
}
237
} else if (ldns_nsec_covers_name(ldns_rr_list_rr(nsecs, nsec_i), name)) {
238
if (verbosity >= 3) {
239
printf(";; Existence of data set with this name denied by NSEC\n");
240
}
241
if (nsec_rrs && nsec_rr_sigs) {
242
(void) get_dnssec_rr(pkt, ldns_rr_owner(ldns_rr_list_rr(nsecs, nsec_i)), LDNS_RR_TYPE_NSEC, nsec_rrs, nsec_rr_sigs);
243
}
244
ldns_rr_list_deep_free(nsecs);
245
return LDNS_STATUS_OK;
246
} else {
247
/* nsec has nothing to do with this data */
248
}
249
}
250
ldns_rr_list_deep_free(nsecs);
251
} else if( (nsecs = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_NSEC3, LDNS_SECTION_ANY_NOQUESTION)) ) {
252
ldns_rr_list* sigs = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_RRSIG, LDNS_SECTION_ANY_NOQUESTION);
253
ldns_rr* q = ldns_rr_new();
254
ldns_rr* match = NULL;
255
256
if(!sigs) {
257
if (q) {
258
ldns_rr_free(q);
259
}
260
ldns_rr_list_deep_free(nsecs);
261
return LDNS_STATUS_MEM_ERR;
262
}
263
if(!q) {
264
ldns_rr_list_deep_free(nsecs);
265
ldns_rr_list_deep_free(sigs);
266
return LDNS_STATUS_MEM_ERR;
267
}
268
ldns_rr_set_question(q, 1);
269
ldns_rr_set_ttl(q, 0);
270
ldns_rr_set_owner(q, ldns_rdf_clone(name));
271
if(!ldns_rr_owner(q)) {
272
ldns_rr_free(q);
273
ldns_rr_list_deep_free(sigs);
274
ldns_rr_list_deep_free(nsecs);
275
return LDNS_STATUS_MEM_ERR;
276
}
277
ldns_rr_set_type(q, type);
278
279
/* result = ldns_dnssec_verify_denial_nsec3(q, nsecs, sigs, ldns_pkt_get_rcode(pkt), type, ldns_pkt_ancount(pkt) == 0); */
280
result = ldns_dnssec_verify_denial_nsec3_match(q, nsecs, sigs, ldns_pkt_get_rcode(pkt), type, ldns_pkt_ancount(pkt) == 0, &match);
281
if (result == LDNS_STATUS_OK && match && nsec_rrs && nsec_rr_sigs) {
282
(void) get_dnssec_rr(pkt, ldns_rr_owner(match), LDNS_RR_TYPE_NSEC3, nsec_rrs, nsec_rr_sigs);
283
}
284
ldns_rr_free(q);
285
ldns_rr_list_deep_free(nsecs);
286
ldns_rr_list_deep_free(sigs);
287
}
288
return result;
289
#else
290
(void)pkt;
291
(void)name;
292
(void)type;
293
(void)nsec_rrs;
294
(void)nsec_rr_sigs;
295
return LDNS_STATUS_ERR;
296
#endif /* HAVE_SSL */
297
}
298
299
/* NSEC3 draft -07 */
300
/*return hash name match*/
301
ldns_rr *
302
ldns_nsec3_exact_match(ldns_rdf *qname, ldns_rr_type qtype, ldns_rr_list *nsec3s) {
303
uint8_t algorithm;
304
uint32_t iterations;
305
uint8_t salt_length;
306
uint8_t *salt;
307
308
ldns_rdf *sname = NULL, *hashed_sname = NULL;
309
310
size_t nsec_i;
311
ldns_rr *nsec;
312
ldns_rr *result = NULL;
313
314
const ldns_rr_descriptor *descriptor;
315
316
ldns_rdf *zone_name = NULL;
317
318
if (verbosity >= 4) {
319
printf(";; finding exact match for ");
320
descriptor = ldns_rr_descript(qtype);
321
if (descriptor && descriptor->_name) {
322
printf("%s ", descriptor->_name);
323
} else {
324
printf("TYPE%d ", qtype);
325
}
326
ldns_rdf_print(stdout, qname);
327
printf("\n");
328
}
329
330
if (!qname || !nsec3s || ldns_rr_list_rr_count(nsec3s) < 1) {
331
if (verbosity >= 4) {
332
printf("no qname, nsec3s or list empty\n");
333
}
334
return NULL;
335
}
336
337
nsec = ldns_rr_list_rr(nsec3s, 0);
338
algorithm = ldns_nsec3_algorithm(nsec);
339
salt_length = ldns_nsec3_salt_length(nsec);
340
salt = ldns_nsec3_salt_data(nsec);
341
iterations = ldns_nsec3_iterations(nsec);
342
if (salt == NULL) {
343
goto done;
344
}
345
346
sname = ldns_rdf_clone(qname);
347
if (sname == NULL) {
348
goto done;
349
}
350
if (verbosity >= 4) {
351
printf(";; owner name hashes to: ");
352
}
353
hashed_sname = ldns_nsec3_hash_name(sname, algorithm, iterations, salt_length, salt);
354
if (hashed_sname == NULL) {
355
goto done;
356
}
357
zone_name = ldns_dname_left_chop(ldns_rr_owner(nsec));
358
if (zone_name == NULL) {
359
goto done;
360
}
361
if (ldns_dname_cat(hashed_sname, zone_name) != LDNS_STATUS_OK) {
362
goto done;
363
};
364
365
if (verbosity >= 4) {
366
ldns_rdf_print(stdout, hashed_sname);
367
printf("\n");
368
}
369
370
for (nsec_i = 0; nsec_i < ldns_rr_list_rr_count(nsec3s); nsec_i++) {
371
nsec = ldns_rr_list_rr(nsec3s, nsec_i);
372
373
/* check values of iterations etc! */
374
375
/* exact match? */
376
if (ldns_dname_compare(ldns_rr_owner(nsec), hashed_sname) == 0) {
377
result = nsec;
378
goto done;
379
}
380
381
}
382
383
done:
384
ldns_rdf_deep_free(zone_name);
385
ldns_rdf_deep_free(sname);
386
ldns_rdf_deep_free(hashed_sname);
387
LDNS_FREE(salt);
388
389
if (verbosity >= 4) {
390
if (result) {
391
printf(";; Found.\n");
392
} else {
393
printf(";; Not foud.\n");
394
}
395
}
396
return result;
397
}
398
399
/*return the owner name of the closest encloser for name from the list of rrs */
400
/* this is NOT the hash, but the original name! */
401
ldns_rdf *
402
ldns_nsec3_closest_encloser(ldns_rdf *qname, ldns_rr_type qtype, ldns_rr_list *nsec3s)
403
{
404
/* remember parameters, they must match */
405
uint8_t algorithm;
406
uint32_t iterations;
407
uint8_t salt_length;
408
uint8_t *salt;
409
410
ldns_rdf *sname = NULL, *hashed_sname = NULL, *tmp;
411
bool flag;
412
413
bool exact_match_found;
414
bool in_range_found;
415
416
ldns_rdf *zone_name = NULL;
417
418
size_t nsec_i;
419
ldns_rr *nsec;
420
ldns_rdf *result = NULL;
421
422
if (!qname || !nsec3s || ldns_rr_list_rr_count(nsec3s) < 1) {
423
return NULL;
424
}
425
426
if (verbosity >= 4) {
427
printf(";; finding closest encloser for type %d ", qtype);
428
ldns_rdf_print(stdout, qname);
429
printf("\n");
430
}
431
432
nsec = ldns_rr_list_rr(nsec3s, 0);
433
algorithm = ldns_nsec3_algorithm(nsec);
434
salt_length = ldns_nsec3_salt_length(nsec);
435
salt = ldns_nsec3_salt_data(nsec);
436
iterations = ldns_nsec3_iterations(nsec);
437
if (salt == NULL) {
438
goto done;
439
}
440
441
sname = ldns_rdf_clone(qname);
442
if (sname == NULL) {
443
goto done;
444
}
445
446
flag = false;
447
448
zone_name = ldns_dname_left_chop(ldns_rr_owner(nsec));
449
if (zone_name == NULL) {
450
goto done;
451
}
452
453
/* algorithm from nsec3-07 8.3 */
454
while (ldns_dname_label_count(sname) > 0) {
455
exact_match_found = false;
456
in_range_found = false;
457
458
if (verbosity >= 3) {
459
printf(";; ");
460
ldns_rdf_print(stdout, sname);
461
printf(" hashes to: ");
462
}
463
hashed_sname = ldns_nsec3_hash_name(sname, algorithm, iterations, salt_length, salt);
464
if (hashed_sname == NULL) {
465
goto done;
466
}
467
468
if (ldns_dname_cat(hashed_sname, zone_name) != LDNS_STATUS_OK){
469
ldns_rdf_deep_free(hashed_sname);
470
goto done;
471
}
472
473
if (verbosity >= 3) {
474
ldns_rdf_print(stdout, hashed_sname);
475
printf("\n");
476
}
477
478
for (nsec_i = 0; nsec_i < ldns_rr_list_rr_count(nsec3s); nsec_i++) {
479
nsec = ldns_rr_list_rr(nsec3s, nsec_i);
480
481
/* check values of iterations etc! */
482
483
/* exact match? */
484
if (ldns_dname_compare(ldns_rr_owner(nsec), hashed_sname) == 0) {
485
if (verbosity >= 4) {
486
printf(";; exact match found\n");
487
}
488
exact_match_found = true;
489
} else if (ldns_nsec_covers_name(nsec, hashed_sname)) {
490
if (verbosity >= 4) {
491
printf(";; in range of an nsec\n");
492
}
493
in_range_found = true;
494
}
495
496
}
497
if (!exact_match_found && in_range_found) {
498
flag = true;
499
} else if (exact_match_found && flag) {
500
result = ldns_rdf_clone(sname);
501
} else if (exact_match_found && !flag) {
502
// error!
503
if (verbosity >= 4) {
504
printf(";; the closest encloser is the same name (ie. this is an exact match, ie there is no closest encloser)\n");
505
}
506
ldns_rdf_deep_free(hashed_sname);
507
goto done;
508
} else {
509
flag = false;
510
}
511
512
ldns_rdf_deep_free(hashed_sname);
513
tmp = sname;
514
sname = ldns_dname_left_chop(sname);
515
ldns_rdf_deep_free(tmp);
516
if (sname == NULL) {
517
goto done;
518
}
519
}
520
521
done:
522
LDNS_FREE(salt);
523
ldns_rdf_deep_free(zone_name);
524
ldns_rdf_deep_free(sname);
525
526
if (!result) {
527
if (verbosity >= 4) {
528
printf(";; no closest encloser found\n");
529
}
530
}
531
532
/* todo checks from end of 6.2. here or in caller? */
533
return result;
534
}
535
536