}
bool
-ldns_nsec_covers_rrset(const ldns_rr *nsec, ldns_rdf *name, ldns_rr_type type)
+ldns_nsec_bitmap_covers_type(const ldns_rdf *nsec_bitmap, ldns_rr_type type)
{
uint8_t *bitmap;
uint16_t i;
uint8_t window_block_nr;
- ldns_rdf *nsec_owner = ldns_rr_owner(nsec);
- ldns_rdf *nsec_next = ldns_rr_rdf(nsec, 0);
-
- if (ldns_dname_compare(nsec_owner, name) <= 0 &&
- ldns_dname_compare(name, nsec_next) > 0) {
-
- /* Check the bitmap if our type is there */
- bitmap = ldns_rdf_data(ldns_rr_rdf(nsec, 1));
- window_block_nr = (uint8_t) (type / 256);
- i = 0;
- while (i < ldns_rdf_size(ldns_rr_rdf(nsec, 1))) {
- if (bitmap[i] == window_block_nr) {
- /* this is the right window, check the bit */
- if ((uint8_t) (type / 8) < bitmap[i + 1] &&
- ldns_get_bit(&bitmap[i + 1 + (type / 8)], (size_t) (7 - (type % 8)))) {
- return true;
- } else {
- return false;
- }
+ /* Check the bitmap if our type is there */
+ bitmap = ldns_rdf_data(nsec_bitmap);
+ window_block_nr = (uint8_t) (type / 256);
+ i = 0;
+ while (i < ldns_rdf_size(nsec_bitmap)) {
+ if (bitmap[i] == window_block_nr) {
+ /* this is the right window, check the bit */
+ if ((uint8_t) (type / 8) < bitmap[i + 1] &&
+ ldns_get_bit(&bitmap[i + 1 + (type / 8)], (size_t) (7 - (type % 8)))) {
+ return true;
} else {
- /* this is the wrong window, go to the next */
- i++;
- i += bitmap[i];
+ return false;
}
+ } else {
+ /* this is the wrong window, go to the next */
+ i++;
+ i += bitmap[i];
}
}
+
return false;
}
+bool
+ldns_nsec_covers_name(const ldns_rr *nsec, ldns_rdf *name)
+{
+ ldns_rdf *nsec_owner = ldns_rr_owner(nsec);
+ ldns_rdf *nsec_next = ldns_rr_rdf(nsec, 0);
+
+ return (ldns_dname_compare(nsec_owner, name) <= 0 &&
+ ldns_dname_compare(name, nsec_next) > 0);
+}
+
/* sig may be null - if so look in the packet */
ldns_status
ldns_pkt_verify(ldns_pkt *p, ldns_rr_type t, ldns_rdf *o,
LDNS_SECTION_ANY_NOQUESTION
);
- for (sig_i = 0; sig_i < ldns_rr_list_rr_count(sigs); sig_i++) {
- cur_sig = ldns_rr_clone(ldns_rr_list_rr(sigs, sig_i));
-
- keys = ldns_pkt_rr_list_by_name_and_type(pkt,
- ldns_rr_rdf(cur_sig, 7),
- LDNS_RR_TYPE_DNSKEY,
- LDNS_SECTION_ANY_NOQUESTION
- );
-
- if (qdebug != -1) {
- printf(";; Data set: ");
- ldns_rdf_print(stdout, name);
-
- lt = ldns_lookup_by_id(ldns_rr_classes, c);
- if (lt) {
- printf("\t%s\t", lt->name);
- } else {
- printf("\tCLASS%d\t", c);
- }
-
- descriptor = ldns_rr_descript(type);
-
- if (descriptor->_name) {
- printf("%s\t", descriptor->_name);
- } else {
- /* exceptions for qtype */
- if (type == 251) {
- printf("IXFR ");
- } else if (type == 252) {
- printf("AXFR ");
- } else if (type == 253) {
- printf("MAILB ");
- } else if (type == 254) {
- printf("MAILA ");
- } else if (type == 255) {
- printf("ANY ");
- } else {
- printf("TYPE%d\t", type);
- }
- }
+ if (rrset) {
+ for (sig_i = 0; sig_i < ldns_rr_list_rr_count(sigs); sig_i++) {
+ cur_sig = ldns_rr_clone(ldns_rr_list_rr(sigs, sig_i));
- printf("\n");
- printf(";; Signed by: ");
- ldns_rdf_print(stdout, ldns_rr_rdf(cur_sig, 7));
- printf("\n");
- }
-
- if (!keys) {
- ldns_pkt_free(pkt);
- pkt = NULL;
- pkt = ldns_resolver_query(res,
- ldns_rr_rdf(cur_sig, 7),
- LDNS_RR_TYPE_DNSKEY, c, qflags);
- if (!pkt) {
- ldns_rr_list_deep_free(rrset);
- ldns_rr_list_deep_free(sigs);
- return LDNS_STATUS_NETWORK_ERR;
- }
-
keys = ldns_pkt_rr_list_by_name_and_type(pkt,
ldns_rr_rdf(cur_sig, 7),
LDNS_RR_TYPE_DNSKEY,
LDNS_SECTION_ANY_NOQUESTION
);
- }
- if(!keys) {
- mesg("No key for data found in that zone!");
- ldns_rr_list_deep_free(rrset);
- ldns_rr_list_deep_free(sigs);
- ldns_pkt_free(pkt);
- ldns_rr_free(cur_sig);
- return LDNS_STATUS_CRYPTO_NO_DNSKEY;
- } else {
- result = LDNS_STATUS_ERR;
- for (key_i = 0; key_i < ldns_rr_list_rr_count(keys); key_i++) {
- /* only check matching keys */
-
- if (ldns_calc_keytag(ldns_rr_list_rr(keys, key_i))
- ==
- ldns_rdf2native_int16(ldns_rr_rrsig_keytag(cur_sig))
- ) {
- result = ldns_verify_rrsig(rrset, cur_sig, ldns_rr_list_rr(keys, key_i));
+
+ if (qdebug != -1) {
+ printf(";; Data set: ");
+ ldns_rdf_print(stdout, name);
- if (result == LDNS_STATUS_OK) {
- for (tkey_i = 0; tkey_i < ldns_rr_list_rr_count(trusted_keys); tkey_i++) {
- if (ldns_rr_compare_ds(ldns_rr_list_rr(keys, key_i),
- ldns_rr_list_rr(trusted_keys, tkey_i)
- )) {
- mesg("Key is trusted");
- ldns_rr_list_deep_free(rrset);
- ldns_rr_list_deep_free(sigs);
- ldns_rr_list_deep_free(keys);
- ldns_pkt_free(pkt);
- ldns_rr_free(cur_sig);
- return LDNS_STATUS_OK;
- }
- }
- result = do_chase(res, ldns_rr_rdf(cur_sig, 7), LDNS_RR_TYPE_DS, c, trusted_keys, pkt, qflags);
- ldns_rr_list_deep_free(rrset);
- ldns_rr_list_deep_free(sigs);
- ldns_rr_list_deep_free(keys);
- ldns_pkt_free(pkt);
- ldns_rr_free(cur_sig);
- return result;
+ lt = ldns_lookup_by_id(ldns_rr_classes, c);
+ if (lt) {
+ printf("\t%s\t", lt->name);
+ } else {
+ printf("\tCLASS%d\t", c);
+ }
+
+ descriptor = ldns_rr_descript(type);
+
+ if (descriptor->_name) {
+ printf("%s\t", descriptor->_name);
+ } else {
+ /* exceptions for qtype */
+ if (type == 251) {
+ printf("IXFR ");
+ } else if (type == 252) {
+ printf("AXFR ");
+ } else if (type == 253) {
+ printf("MAILB ");
+ } else if (type == 254) {
+ printf("MAILA ");
+ } else if (type == 255) {
+ printf("ANY ");
+ } else {
+ printf("TYPE%d\t", type);
}
}
-/*
- else {
- result = LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY;
+
+ printf("\n");
+ printf(";; Signed by: ");
+ ldns_rdf_print(stdout, ldns_rr_rdf(cur_sig, 7));
+ printf("\n");
+ }
+
+ if (!keys) {
+ ldns_pkt_free(pkt);
+ pkt = NULL;
+ pkt = ldns_resolver_query(res,
+ ldns_rr_rdf(cur_sig, 7),
+ LDNS_RR_TYPE_DNSKEY, c, qflags);
+ if (!pkt) {
+ ldns_rr_list_deep_free(rrset);
+ ldns_rr_list_deep_free(sigs);
+ return LDNS_STATUS_NETWORK_ERR;
}
-*/
+
+ keys = ldns_pkt_rr_list_by_name_and_type(pkt,
+ ldns_rr_rdf(cur_sig, 7),
+ LDNS_RR_TYPE_DNSKEY,
+ LDNS_SECTION_ANY_NOQUESTION
+ );
}
- if (result != LDNS_STATUS_OK) {
+ if(!keys) {
+ mesg("No key for data found in that zone!");
ldns_rr_list_deep_free(rrset);
ldns_rr_list_deep_free(sigs);
- ldns_rr_list_deep_free(keys);
ldns_pkt_free(pkt);
ldns_rr_free(cur_sig);
- return result;
+ return LDNS_STATUS_CRYPTO_NO_DNSKEY;
+ } else {
+ result = LDNS_STATUS_ERR;
+ for (key_i = 0; key_i < ldns_rr_list_rr_count(keys); key_i++) {
+ /* only check matching keys */
+
+ if (ldns_calc_keytag(ldns_rr_list_rr(keys, key_i))
+ ==
+ ldns_rdf2native_int16(ldns_rr_rrsig_keytag(cur_sig))
+ ) {
+ result = ldns_verify_rrsig(rrset, cur_sig, ldns_rr_list_rr(keys, key_i));
+
+ if (result == LDNS_STATUS_OK) {
+ for (tkey_i = 0; tkey_i < ldns_rr_list_rr_count(trusted_keys); tkey_i++) {
+ if (ldns_rr_compare_ds(ldns_rr_list_rr(keys, key_i),
+ ldns_rr_list_rr(trusted_keys, tkey_i)
+ )) {
+ mesg("Key is trusted");
+ ldns_rr_list_deep_free(rrset);
+ ldns_rr_list_deep_free(sigs);
+ ldns_rr_list_deep_free(keys);
+ ldns_pkt_free(pkt);
+ ldns_rr_free(cur_sig);
+ return LDNS_STATUS_OK;
+ }
+ }
+ result = do_chase(res, ldns_rr_rdf(cur_sig, 7), LDNS_RR_TYPE_DS, c, trusted_keys, pkt, qflags);
+ ldns_rr_list_deep_free(rrset);
+ ldns_rr_list_deep_free(sigs);
+ ldns_rr_list_deep_free(keys);
+ ldns_pkt_free(pkt);
+ ldns_rr_free(cur_sig);
+ return result;
+ }
+ }
+ }
+ if (result != LDNS_STATUS_OK) {
+ ldns_rr_list_deep_free(rrset);
+ ldns_rr_list_deep_free(sigs);
+ ldns_rr_list_deep_free(keys);
+ ldns_pkt_free(pkt);
+ ldns_rr_free(cur_sig);
+ return result;
+ }
+ ldns_rr_list_deep_free(keys);
}
- ldns_rr_list_deep_free(keys);
+ ldns_rr_free(cur_sig);
}
- ldns_rr_free(cur_sig);
+ ldns_rr_list_deep_free(rrset);
}
- ldns_rr_list_deep_free(rrset);
- if (ldns_rr_list_rr_count(sigs) > 0) {
+ if (rrset && ldns_rr_list_rr_count(sigs) > 0) {
ldns_rr_list_deep_free(sigs);
ldns_pkt_free(pkt);
return LDNS_STATUS_CRYPTO_NO_TRUSTED_DNSKEY;
result = LDNS_STATUS_CRYPTO_NO_RRSIG;
for (nsec_i = 0; nsec_i < ldns_rr_list_rr_count(nsecs); nsec_i++) {
- if (ldns_nsec_covers_rrset(ldns_rr_list_rr(nsecs, nsec_i), name, type)) {
+ /* there are four options:
+ * - name equals ownername and is covered by the type bitmap
+ * - name equals ownername but is not covered by the type bitmap
+ * - name falls within nsec coverage but is not equal to the owner name
+ * - name falls outside of nsec coverage
+ */
+ if (ldns_dname_compare(ldns_rr_owner(ldns_rr_list_rr(nsecs, nsec_i)), name) == 0) {
+ if (ldns_nsec_bitmap_covers_type(ldns_rr_rdf(ldns_rr_list_rr(nsecs, nsec_i), 1), type)) {
+ /* Error, according to the nsec this rrset is signed */
+ result = LDNS_STATUS_CRYPTO_NO_RRSIG;
+ } else {
+ /* ok nsec denies existence, chase the nsec now */
+ result = do_chase(res, ldns_rr_owner(ldns_rr_list_rr(nsecs, nsec_i)), LDNS_RR_TYPE_NSEC, c, trusted_keys, pkt, qflags);
+ if (result == LDNS_STATUS_OK) {
+ ldns_pkt_free(pkt);
+ printf(";; Verifiably insecure.\n");
+ return result;
+ }
+ }
+ } else if (ldns_nsec_covers_name(ldns_rr_list_rr(nsecs, nsec_i), name)) {
/* Verifably insecure? chase the covering nsec */
result = do_chase(res, ldns_rr_owner(ldns_rr_list_rr(nsecs, nsec_i)), LDNS_RR_TYPE_NSEC, c, trusted_keys, pkt, qflags);
if (result == LDNS_STATUS_OK) {
ldns_pkt_free(pkt);
+ printf(";; Verifiably insecure.\n");
return result;
}
+ } else {
+ /* nsec has nothing to do with this data */
}
}
ldns_pkt_free(pkt);