From: Jelte Jansen Date: Tue, 5 Feb 2008 13:41:38 +0000 (+0000) Subject: synced function defs in .h and .c files. No doxygen yet. X-Git-Tag: release-1.3.0~102 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ca0d7b145d9a699115c3c71e8def2b8a4099a12b;p=thirdparty%2Fldns.git synced function defs in .h and .c files. No doxygen yet. --- diff --git a/dnssec.c b/dnssec.c index cf24998b..f29dbf08 100644 --- a/dnssec.c +++ b/dnssec.c @@ -99,7 +99,9 @@ ldns_nsec_get_bitmap(ldns_rr *nsec) { int verbosity = 5; ldns_rdf * -ldns_dnssec_nsec3_closest_encloser(ldns_rdf *qname, ldns_rr_type qtype, ldns_rr_list *nsec3s) +ldns_dnssec_nsec3_closest_encloser(ldns_rdf *qname, + ldns_rr_type qtype, + ldns_rr_list *nsec3s) { /* remember parameters, they must match */ uint8_t algorithm; @@ -217,192 +219,6 @@ ldns_dnssec_nsec3_closest_encloser(ldns_rdf *qname, ldns_rr_type qtype, ldns_rr_ return result; } -ldns_status -ldns_dnssec_verify_denial_nsec3(ldns_rr *rr, - ldns_rr_list *nsecs, - ldns_rr_list *rrsigs, - ldns_pkt_rcode packet_rcode, - ldns_rr_type packet_qtype, - bool packet_nodata) -{ - ldns_rdf *closest_encloser; - ldns_rdf *wildcard; - bool wildcard_covered = false; - ldns_rdf *zone_name; - ldns_rdf *hashed_name; - size_t i; - - rrsigs = rrsigs; - - /* section 8.4 */ - if (packet_rcode == LDNS_RCODE_NXDOMAIN) { - closest_encloser = ldns_dnssec_nsec3_closest_encloser(ldns_rr_owner(rr), - ldns_rr_get_type(rr), - nsecs); - - printf("[XX} NSEC3 denial for: "); - ldns_rr_print(stdout, rr); - printf("[XX] closest encloser: "); - ldns_rdf_print(stdout, closest_encloser); - printf("\n"); - - wildcard = ldns_dname_new_frm_str("*"); - ldns_dname_cat(wildcard, closest_encloser); - - for (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) { - if (ldns_nsec_covers_name(ldns_rr_list_rr(nsecs, i), - wildcard)) { - printf("[XX] wildcard covered\n"); - wildcard_covered = true; - } - } - - if (!wildcard_covered) { - return LDNS_STATUS_DNSSEC_NSEC_WILDCARD_NOT_COVERED; - } - if (closest_encloser && wildcard_covered) { - return LDNS_STATUS_OK; - } - return LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED; - } else if (packet_nodata && packet_qtype != LDNS_RR_TYPE_DS) { - /* section 8.5 */ - hashed_name = ldns_nsec3_hash_name_frm_nsec3(ldns_rr_list_rr(nsecs, 0), - ldns_rr_owner(rr) - ); - zone_name = ldns_dname_left_chop(ldns_rr_owner(ldns_rr_list_rr(nsecs,0))); - ldns_dname_cat(hashed_name, zone_name); - printf("[XX] hashed name: "); - ldns_rdf_print(stdout, hashed_name); - printf("\n"); - for (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) { - if (ldns_dname_compare(hashed_name, ldns_rr_owner(ldns_rr_list_rr(nsecs, i))) == 0) { - if (!ldns_nsec_bitmap_covers_type(ldns_nsec3_bitmap(ldns_rr_list_rr(nsecs, i)), packet_qtype) && - !ldns_nsec_bitmap_covers_type(ldns_nsec3_bitmap(ldns_rr_list_rr(nsecs, i)), LDNS_RR_TYPE_CNAME)) { - printf("exact match!\n"); - return LDNS_STATUS_OK; - } - } - } - return LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED; - } else if (packet_nodata && packet_qtype == LDNS_RR_TYPE_DS) { - /* section 8.6 */ - /* note: up to XXX this is the same as for 8.5 */ - hashed_name = ldns_nsec3_hash_name_frm_nsec3(ldns_rr_list_rr(nsecs, 0), - ldns_rr_owner(rr) - ); - zone_name = ldns_dname_left_chop(ldns_rr_owner(ldns_rr_list_rr(nsecs,0))); - ldns_dname_cat(hashed_name, zone_name); - printf("[XX] hashed name: "); - ldns_rdf_print(stdout, hashed_name); - printf("\n"); - for (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) { - if (ldns_dname_compare(hashed_name, ldns_rr_owner(ldns_rr_list_rr(nsecs, i))) == 0) { - if (!ldns_nsec_bitmap_covers_type(ldns_nsec3_bitmap(ldns_rr_list_rr(nsecs, i)), LDNS_RR_TYPE_DS) && - !ldns_nsec_bitmap_covers_type(ldns_nsec3_bitmap(ldns_rr_list_rr(nsecs, i)), LDNS_RR_TYPE_CNAME)) { - printf("exact match!\n"); - return LDNS_STATUS_OK; - } - } - } - - /* XXX see note above */ - closest_encloser = ldns_dnssec_nsec3_closest_encloser(ldns_rr_owner(rr), - ldns_rr_get_type(rr), - nsecs); - - if (closest_encloser) { - printf("[XX] closest encloser: "); - ldns_rdf_print(stdout, closest_encloser); - printf("\n"); - exit(0); - } - return LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED; - - } - return LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED; -} - -ldns_status -ldns_dnssec_verify_denial(ldns_rr *rr, - ldns_rr_list *nsecs, - ldns_rr_list *rrsigs) -{ - ldns_rdf *rr_name; - ldns_rdf *wildcard_name; - ldns_rdf *chopped_dname; - ldns_rr *cur_nsec; - size_t i; - ldns_status result; - /* needed for wildcard check on exact match */ - ldns_rr *rrsig; - bool name_covered = false; - bool type_covered = false; - bool wildcard_covered = false; - bool wildcard_type_covered = false; - - wildcard_name = ldns_dname_new_frm_str("*"); - rr_name = ldns_rr_owner(rr); - chopped_dname = ldns_dname_left_chop(rr_name); - result = ldns_dname_cat(wildcard_name, chopped_dname); - if (result != LDNS_STATUS_OK) { - return result; - } - - ldns_rdf_deep_free(chopped_dname); - - for (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) { - cur_nsec = ldns_rr_list_rr(nsecs, i); - if (ldns_dname_compare(rr_name, ldns_rr_owner(cur_nsec)) == 0) { - /* see section 5.4 of RFC4035, if the label count of the NSEC's - RRSIG is equal, then it is proven that wildcard expansion - could not have been used to match the request */ - rrsig = ldns_dnssec_get_rrsig_for_name_and_type(ldns_rr_owner(cur_nsec), ldns_rr_get_type(cur_nsec), rrsigs); - if (rrsig && ldns_rdf2native_int8(ldns_rr_rrsig_labels(rrsig)) == ldns_dname_label_count(rr_name)) { - printf("[XX] wildcard covered from label count\n"); - wildcard_covered = true; - } - - if (ldns_nsec_bitmap_covers_type(ldns_nsec_get_bitmap(cur_nsec), ldns_rr_get_type(rr))) { - printf("[XX] type covered\n"); - type_covered = true; - } - } - printf("[XX] Name covered?\n"); - if (ldns_nsec_covers_name(cur_nsec, rr_name)) { - printf("[XX] yes!\n"); - name_covered = true; - } - - if (ldns_dname_compare(wildcard_name, ldns_rr_owner(cur_nsec)) == 0) { - printf("[XX] Wildcard type covered?\n"); - if (ldns_nsec_bitmap_covers_type(ldns_nsec_get_bitmap(cur_nsec), ldns_rr_get_type(rr))) { - printf("[XX] yes!\n"); - wildcard_type_covered = true; - } - } - - printf("[XX] Wildcard covered?\n"); - if (ldns_nsec_covers_name(cur_nsec, wildcard_name)) { - printf("[XX] yes!\n"); - wildcard_covered = true; - } - - } - - ldns_rdf_deep_free(wildcard_name); - - if (type_covered || !name_covered) { - return LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED; - } - - if (wildcard_type_covered || !wildcard_covered) { - return LDNS_STATUS_DNSSEC_NSEC_WILDCARD_NOT_COVERED; - } - - return LDNS_STATUS_OK; -} - - bool ldns_dnssec_pkt_has_rrsigs(const ldns_pkt *pkt) { @@ -533,6 +349,111 @@ uint16_t ldns_calc_keytag_raw(uint8_t* key, size_t keysize) } } +DSA * +ldns_key_buf2dsa(ldns_buffer *key) +{ + return ldns_key_buf2dsa_raw((unsigned char*)ldns_buffer_begin(key), + ldns_buffer_position(key)); +} + +DSA * +ldns_key_buf2dsa_raw(unsigned char* key, size_t len) +{ + uint8_t T; + uint16_t length; + uint16_t offset; + DSA *dsa; + BIGNUM *Q; BIGNUM *P; + BIGNUM *G; BIGNUM *Y; + + if(len == 0) + return NULL; + T = (uint8_t)key[0]; + length = (64 + T * 8); + offset = 1; + + if (T > 8) { + return NULL; + } + if(len < (size_t)1 + SHA_DIGEST_LENGTH + 3*length) + return NULL; + + Q = BN_bin2bn(key+offset, SHA_DIGEST_LENGTH, NULL); + offset += SHA_DIGEST_LENGTH; + + P = BN_bin2bn(key+offset, (int)length, NULL); + offset += length; + + G = BN_bin2bn(key+offset, (int)length, NULL); + offset += length; + + Y = BN_bin2bn(key+offset, (int)length, NULL); + offset += length; + + /* create the key and set its properties */ + dsa = DSA_new(); + dsa->p = P; + dsa->q = Q; + dsa->g = G; + dsa->pub_key = Y; + + return dsa; +} + +RSA * +ldns_key_buf2rsa(ldns_buffer *key) +{ + return ldns_key_buf2rsa_raw((unsigned char*)ldns_buffer_begin(key), + ldns_buffer_position(key)); +} + +RSA * +ldns_key_buf2rsa_raw(unsigned char* key, size_t len) +{ + uint16_t offset; + uint16_t exp; + uint16_t int16; + RSA *rsa; + BIGNUM *modulus; + BIGNUM *exponent; + + if (len == 0) + return NULL; + if (key[0] == 0) { + if(len < 3) + return NULL; + /* need some smart comment here XXX*/ + /* the exponent is too large so it's places + * futher...???? */ + memmove(&int16, key+1, 2); + exp = ntohs(int16); + offset = 3; + } else { + exp = key[0]; + offset = 1; + } + + /* key length at least one */ + if(len < (size_t)offset + exp + 1) + return NULL; + + /* Exponent */ + exponent = BN_new(); + (void) BN_bin2bn(key+offset, (int)exp, exponent); + offset += exp; + + /* Modulus */ + modulus = BN_new(); + /* length of the buffer must match the key length! */ + (void) BN_bin2bn(key+offset, (int)(len - offset), modulus); + + rsa = RSA_new(); + rsa->n = modulus; + rsa->e = exponent; + + return rsa; +} + ldns_rr * ldns_key_rr2ds(const ldns_rr *key, ldns_hash h) { @@ -1202,8 +1123,8 @@ ldns_nsec3_iterations(const ldns_rr *nsec3_rr) } -ldns_rdf -*ldns_nsec3_salt(const ldns_rr *nsec3_rr) +ldns_rdf * +ldns_nsec3_salt(const ldns_rr *nsec3_rr) { if (nsec3_rr && ldns_rr_get_type(nsec3_rr) == LDNS_RR_TYPE_NSEC3) { return ldns_rr_rdf(nsec3_rr, 3); @@ -1429,6 +1350,7 @@ ldns_pkt_verify(ldns_pkt *p, ldns_rr_type t, ldns_rdf *o, return ldns_verify(rrset, sigs, k, good_keys); } +#if 0 ldns_rr_list * ldns_zone_create_nsecs(const ldns_zone *zone, ldns_rr_list *orig_zone_rrs, ldns_rr_list *glue_rrs) { @@ -1506,6 +1428,7 @@ ldns_rr_list_strip_dnssec(ldns_rr_list *rr_list, ldns_rr_list *removed_rrs) return new_list; } +#endif ldns_status ldns_dnssec_chain_nsec3_list(ldns_rr_list *nsec3_rrs) @@ -1547,7 +1470,7 @@ ldns_dnssec_chain_nsec3_list(ldns_rr_list *nsec3_rrs) return status; } -static int +int qsort_rr_compare_nsec3(const void *a, const void *b) { const ldns_rr *rr1 = * (const ldns_rr **) a; @@ -1564,7 +1487,9 @@ qsort_rr_compare_nsec3(const void *a, const void *b) return ldns_rdf_compare(ldns_rr_owner(rr1), ldns_rr_owner(rr2)); } -void ldns_rr_list_sort_nsec3(ldns_rr_list *unsorted) { +void +ldns_rr_list_sort_nsec3(ldns_rr_list *unsorted) +{ qsort(unsorted->_rrs, ldns_rr_list_rr_count(unsorted), sizeof(ldns_rr *), diff --git a/dnssec_sign.c b/dnssec_sign.c index d1ccce3e..78b01367 100644 --- a/dnssec_sign.c +++ b/dnssec_sign.c @@ -431,6 +431,7 @@ ldns_dnssec_zone_create_nsecs(ldns_dnssec_zone *zone, ldns_rr_list_push_rr(new_rrs, nsec_rr); break; case LDNS_RR_TYPE_NSEC3: + /*TODO separate function*/ break; default: return LDNS_STATUS_ERR; @@ -443,7 +444,8 @@ ldns_dnssec_rrs * ldns_dnssec_remove_signatures(ldns_dnssec_rrs *signatures, ldns_key_list *key_list, int (*func)(ldns_rr *, void *), - void *arg) { + void *arg) +{ ldns_dnssec_rrs *base_rrs = signatures; ldns_dnssec_rrs *cur_rr = base_rrs; ldns_dnssec_rrs *prev_rr = NULL; @@ -529,7 +531,8 @@ ldns_dnssec_zone_create_rrsigs(ldns_dnssec_zone *zone, ldns_rr_list *new_rrs, ldns_key_list *key_list, int (*func)(ldns_rr *, void*), - void *arg) { + void *arg) +{ ldns_status result = LDNS_STATUS_OK; zone = zone; new_rrs = new_rrs; @@ -1170,7 +1173,6 @@ ldns_rr_list_print(stdout, signed_zone_rrs); ldns_rr_list_free(glue_rrs); return signed_zone; #endif - } #endif diff --git a/dnssec_verify.c b/dnssec_verify.c index 65672b9e..fc5d38fa 100644 --- a/dnssec_verify.c +++ b/dnssec_verify.c @@ -345,8 +345,8 @@ ldns_dnssec_build_data_chain(ldns_resolver *res, uint16_t qflags, const ldns_rr_ ldns_dnssec_trust_tree * ldns_dnssec_trust_tree_new() { - ldns_dnssec_trust_tree *new_tree = LDNS_XMALLOC(ldns_dnssec_trust_tree, 1); - + ldns_dnssec_trust_tree *new_tree = LDNS_XMALLOC(ldns_dnssec_trust_tree, + 1); new_tree->rr = NULL; new_tree->rrset = NULL; new_tree->parent_count = 0; @@ -366,27 +366,20 @@ ldns_dnssec_trust_tree_free(ldns_dnssec_trust_tree *tree) LDNS_FREE(tree); } -ldns_status -ldns_dnssec_trust_tree_add_parent(ldns_dnssec_trust_tree *tree, - const ldns_dnssec_trust_tree *parent, - const ldns_rr *signature, - const ldns_status parent_status) +size_t +ldns_dnssec_trust_tree_depth(ldns_dnssec_trust_tree *tree) { - if (tree && parent && tree->parent_count < LDNS_DNSSEC_TRUST_TREE_MAX_PARENTS) { - /* - printf("Add parent for: "); - ldns_rr_print(stdout, tree->rr); - printf("parent: "); - ldns_rr_print(stdout, parent->rr); - */ - tree->parents[tree->parent_count] = (ldns_dnssec_trust_tree *) parent; - tree->parent_status[tree->parent_count] = parent_status; - tree->parent_signature[tree->parent_count] = (ldns_rr *) signature; - tree->parent_count++; - return LDNS_STATUS_OK; - } else { - return LDNS_STATUS_ERR; + size_t result = 0; + size_t parent = 0; + size_t i; + + for (i = 0; i < tree->parent_count; i++) { + parent = ldns_dnssec_trust_tree_depth(tree->parents[i]); + if (parent > result) { + result = parent; + } } + return 1 + result; } /* TODO ldns_ */ @@ -405,24 +398,13 @@ print_tabs(FILE *out, size_t nr, uint8_t *map, size_t treedepth) } } -size_t -ldns_dnssec_trust_tree_depth(ldns_dnssec_trust_tree *tree) -{ - size_t result = 0; - size_t parent = 0; - size_t i; - - for (i = 0; i < tree->parent_count; i++) { - parent = ldns_dnssec_trust_tree_depth(tree->parents[i]); - if (parent > result) { - result = parent; - } - } - return 1 + result; -} - void -ldns_dnssec_trust_tree_print_sm(FILE *out, ldns_dnssec_trust_tree *tree, size_t tabs, bool extended, uint8_t *sibmap, size_t treedepth) +ldns_dnssec_trust_tree_print_sm(FILE *out, + ldns_dnssec_trust_tree *tree, + size_t tabs, + bool extended, + uint8_t *sibmap, + size_t treedepth) { size_t i; const ldns_rr_descriptor *descriptor; @@ -540,6 +522,115 @@ ldns_dnssec_trust_tree_print(FILE *out, ldns_dnssec_trust_tree *tree, size_t tab ldns_dnssec_trust_tree_print_sm(out, tree, tabs, extended, NULL, 0); } +ldns_status +ldns_dnssec_trust_tree_add_parent(ldns_dnssec_trust_tree *tree, + const ldns_dnssec_trust_tree *parent, + const ldns_rr *signature, + const ldns_status parent_status) +{ + if (tree && parent && tree->parent_count < LDNS_DNSSEC_TRUST_TREE_MAX_PARENTS) { + /* + printf("Add parent for: "); + ldns_rr_print(stdout, tree->rr); + printf("parent: "); + ldns_rr_print(stdout, parent->rr); + */ + tree->parents[tree->parent_count] = (ldns_dnssec_trust_tree *) parent; + tree->parent_status[tree->parent_count] = parent_status; + tree->parent_signature[tree->parent_count] = (ldns_rr *) signature; + tree->parent_count++; + return LDNS_STATUS_OK; + } else { + return LDNS_STATUS_ERR; + } +} + +/* if rr is null, take the first from the rrset */ +ldns_dnssec_trust_tree * +ldns_dnssec_derive_trust_tree(ldns_dnssec_data_chain *data_chain, ldns_rr *rr) +{ + ldns_rr_list *cur_rrset; + ldns_rr_list *cur_sigs; + ldns_rr *cur_rr = NULL; + ldns_rr *cur_sig_rr; + uint16_t cur_keytag; + size_t i, j; + + ldns_dnssec_trust_tree *new_tree = ldns_dnssec_trust_tree_new(); + + if (data_chain && data_chain->rrset) { + cur_rrset = data_chain->rrset; + + cur_sigs = data_chain->signatures; + + if (rr) { + cur_rr = rr; + } + + if (!cur_rr && ldns_rr_list_rr_count(cur_rrset) > 0) { + cur_rr = ldns_rr_list_rr(cur_rrset, 0); + } + + if (cur_rr) { + new_tree->rr = cur_rr; + new_tree->rrset = cur_rrset; + /* there are three possibilities: + 1 - 'normal' rrset, signed by a key + 2 - dnskey signed by other dnskey + 3 - dnskey proven by higher level DS + (data denied by nsec is a special case that can + occur in multiple places) + + */ + if (cur_sigs) { + for (i = 0; i < ldns_rr_list_rr_count(cur_sigs); i++) { + /* find the appropriate key in the parent list */ + cur_sig_rr = ldns_rr_list_rr(cur_sigs, i); + cur_keytag = ldns_rdf2native_int16(ldns_rr_rrsig_keytag(cur_sig_rr)); + + if (ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_NSEC) { + if (ldns_dname_compare(ldns_rr_owner(cur_sig_rr), + ldns_rr_owner(cur_rr))) + { + /* find first that does match */ + + for (j = 0; + j < ldns_rr_list_rr_count(cur_rrset) && + ldns_dname_compare(ldns_rr_owner(cur_sig_rr),ldns_rr_owner(cur_rr)) != 0; + j++) { + cur_rr = ldns_rr_list_rr(cur_rrset, j); + + } + if (ldns_dname_compare(ldns_rr_owner(cur_sig_rr), + ldns_rr_owner(cur_rr))) + { + break; + } + } + + } + /* option 1 */ + if (data_chain->parent) { + ldns_dnssec_derive_trust_tree_normal_rrset(new_tree, data_chain, cur_sig_rr); + } + + /* option 2 */ + ldns_dnssec_derive_trust_tree_dnskey_rrset(new_tree, data_chain, cur_rr, cur_sig_rr); + } + + ldns_dnssec_derive_trust_tree_ds_rrset(new_tree, data_chain, cur_rr); + } else { + /* no signatures? maybe it's nsec data */ + + /* just add every rr from parent as new parent */ + ldns_dnssec_derive_trust_tree_no_sig(new_tree, data_chain); + } + } + } + + return new_tree; +} + void ldns_dnssec_derive_trust_tree_normal_rrset(ldns_dnssec_trust_tree *new_tree, ldns_dnssec_data_chain *data_chain, @@ -676,15 +767,6 @@ ldns_dnssec_derive_trust_tree_ds_rrset(ldns_dnssec_trust_tree *new_tree, } } -void -breakme() -{ - // just to define a break point - int i,j; - i = 123; - j = i + 1; -} - void ldns_dnssec_derive_trust_tree_no_sig(ldns_dnssec_trust_tree *new_tree, ldns_dnssec_data_chain *data_chain) @@ -731,92 +813,6 @@ ldns_dnssec_derive_trust_tree_no_sig(ldns_dnssec_trust_tree *new_tree, } } -/* if rr is null, take the first from the rrset */ -ldns_dnssec_trust_tree * -ldns_dnssec_derive_trust_tree(ldns_dnssec_data_chain *data_chain, ldns_rr *rr) -{ - ldns_rr_list *cur_rrset; - ldns_rr_list *cur_sigs; - ldns_rr *cur_rr = NULL; - ldns_rr *cur_sig_rr; - uint16_t cur_keytag; - size_t i, j; - - ldns_dnssec_trust_tree *new_tree = ldns_dnssec_trust_tree_new(); - - if (data_chain && data_chain->rrset) { - cur_rrset = data_chain->rrset; - - cur_sigs = data_chain->signatures; - - if (rr) { - cur_rr = rr; - } - - if (!cur_rr && ldns_rr_list_rr_count(cur_rrset) > 0) { - cur_rr = ldns_rr_list_rr(cur_rrset, 0); - } - - if (cur_rr) { - new_tree->rr = cur_rr; - new_tree->rrset = cur_rrset; - /* there are three possibilities: - 1 - 'normal' rrset, signed by a key - 2 - dnskey signed by other dnskey - 3 - dnskey proven by higher level DS - (data denied by nsec is a special case that can - occur in multiple places) - - */ - if (cur_sigs) { - for (i = 0; i < ldns_rr_list_rr_count(cur_sigs); i++) { - /* find the appropriate key in the parent list */ - cur_sig_rr = ldns_rr_list_rr(cur_sigs, i); - cur_keytag = ldns_rdf2native_int16(ldns_rr_rrsig_keytag(cur_sig_rr)); - - if (ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_NSEC) { - if (ldns_dname_compare(ldns_rr_owner(cur_sig_rr), - ldns_rr_owner(cur_rr))) - { - /* find first that does match */ - - for (j = 0; - j < ldns_rr_list_rr_count(cur_rrset) && - ldns_dname_compare(ldns_rr_owner(cur_sig_rr),ldns_rr_owner(cur_rr)) != 0; - j++) { - cur_rr = ldns_rr_list_rr(cur_rrset, j); - - } - if (ldns_dname_compare(ldns_rr_owner(cur_sig_rr), - ldns_rr_owner(cur_rr))) - { - break; - } - } - - } - /* option 1 */ - if (data_chain->parent) { - ldns_dnssec_derive_trust_tree_normal_rrset(new_tree, data_chain, cur_sig_rr); - } - - /* option 2 */ - ldns_dnssec_derive_trust_tree_dnskey_rrset(new_tree, data_chain, cur_rr, cur_sig_rr); - } - - ldns_dnssec_derive_trust_tree_ds_rrset(new_tree, data_chain, cur_rr); - } else { - /* no signatures? maybe it's nsec data */ - - /* just add every rr from parent as new parent */ - ldns_dnssec_derive_trust_tree_no_sig(new_tree, data_chain); - } - } - } - - return new_tree; -} - /* * returns OK if there is a path from tree to key with only OK * the (first) error in between otherwise @@ -837,7 +833,8 @@ ldns_dnssec_trust_tree_contains_keys(ldns_dnssec_trust_tree *tree, ldns_rr_list printf("Trying key: "); ldns_rr_print(stdout, tree->rr); */ - equal = ldns_rr_compare_ds(tree->rr, ldns_rr_list_rr(trusted_keys, i)); + equal = ldns_rr_compare_ds(tree->rr, + ldns_rr_list_rr(trusted_keys, i)); if (equal) { result = LDNS_STATUS_OK; return result; @@ -905,7 +902,10 @@ ldns_verify(ldns_rr_list *rrset, ldns_rr_list *rrsig, const ldns_rr_list *keys, } ldns_rr_list * -ldns_fetch_valid_domain_keys(const ldns_resolver * res, const ldns_rdf * domain, const ldns_rr_list * keys, ldns_status *status) +ldns_fetch_valid_domain_keys(const ldns_resolver *res, + const ldns_rdf *domain, + const ldns_rr_list *keys, + ldns_status *status) { ldns_rr_list * trusted_keys = NULL; ldns_rr_list * ds_keys = NULL; @@ -943,7 +943,9 @@ ldns_fetch_valid_domain_keys(const ldns_resolver * res, const ldns_rdf * domain, } ldns_rr_list * -ldns_validate_domain_dnskey (const ldns_resolver * res, const ldns_rdf * domain, const ldns_rr_list * keys) +ldns_validate_domain_dnskey(const ldns_resolver * res, + const ldns_rdf * domain, + const ldns_rr_list * keys) { ldns_status status; ldns_pkt * keypkt; @@ -1013,7 +1015,9 @@ ldns_validate_domain_dnskey (const ldns_resolver * res, const ldns_rdf * domain, } ldns_rr_list * -ldns_validate_domain_ds (const ldns_resolver * res, const ldns_rdf * domain, const ldns_rr_list * keys) +ldns_validate_domain_ds(const ldns_resolver *res, + const ldns_rdf * domain, + const ldns_rr_list * keys) { ldns_status status; ldns_pkt * dspkt; @@ -1048,7 +1052,10 @@ ldns_validate_domain_ds (const ldns_resolver * res, const ldns_rdf * domain, con } ldns_status -ldns_verify_trusted(ldns_resolver * res, ldns_rr_list * rrset, ldns_rr_list * rrsigs, ldns_rr_list * validating_keys) +ldns_verify_trusted(ldns_resolver *res, + ldns_rr_list *rrset, + ldns_rr_list * rrsigs, + ldns_rr_list * validating_keys) { /* */ uint16_t sig_i; uint16_t key_i; @@ -1108,6 +1115,191 @@ ldns_verify_trusted(ldns_resolver * res, ldns_rr_list * rrset, ldns_rr_list * rr return result; } +ldns_status +ldns_dnssec_verify_denial(ldns_rr *rr, + ldns_rr_list *nsecs, + ldns_rr_list *rrsigs) +{ + ldns_rdf *rr_name; + ldns_rdf *wildcard_name; + ldns_rdf *chopped_dname; + ldns_rr *cur_nsec; + size_t i; + ldns_status result; + /* needed for wildcard check on exact match */ + ldns_rr *rrsig; + bool name_covered = false; + bool type_covered = false; + bool wildcard_covered = false; + bool wildcard_type_covered = false; + + wildcard_name = ldns_dname_new_frm_str("*"); + rr_name = ldns_rr_owner(rr); + chopped_dname = ldns_dname_left_chop(rr_name); + result = ldns_dname_cat(wildcard_name, chopped_dname); + if (result != LDNS_STATUS_OK) { + return result; + } + + ldns_rdf_deep_free(chopped_dname); + + for (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) { + cur_nsec = ldns_rr_list_rr(nsecs, i); + if (ldns_dname_compare(rr_name, ldns_rr_owner(cur_nsec)) == 0) { + /* see section 5.4 of RFC4035, if the label count of the NSEC's + RRSIG is equal, then it is proven that wildcard expansion + could not have been used to match the request */ + rrsig = ldns_dnssec_get_rrsig_for_name_and_type(ldns_rr_owner(cur_nsec), ldns_rr_get_type(cur_nsec), rrsigs); + if (rrsig && ldns_rdf2native_int8(ldns_rr_rrsig_labels(rrsig)) == ldns_dname_label_count(rr_name)) { + printf("[XX] wildcard covered from label count\n"); + wildcard_covered = true; + } + + if (ldns_nsec_bitmap_covers_type(ldns_nsec_get_bitmap(cur_nsec), ldns_rr_get_type(rr))) { + printf("[XX] type covered\n"); + type_covered = true; + } + } + printf("[XX] Name covered?\n"); + if (ldns_nsec_covers_name(cur_nsec, rr_name)) { + printf("[XX] yes!\n"); + name_covered = true; + } + + if (ldns_dname_compare(wildcard_name, ldns_rr_owner(cur_nsec)) == 0) { + printf("[XX] Wildcard type covered?\n"); + if (ldns_nsec_bitmap_covers_type(ldns_nsec_get_bitmap(cur_nsec), ldns_rr_get_type(rr))) { + printf("[XX] yes!\n"); + wildcard_type_covered = true; + } + } + + printf("[XX] Wildcard covered?\n"); + if (ldns_nsec_covers_name(cur_nsec, wildcard_name)) { + printf("[XX] yes!\n"); + wildcard_covered = true; + } + + } + + ldns_rdf_deep_free(wildcard_name); + + if (type_covered || !name_covered) { + return LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED; + } + + if (wildcard_type_covered || !wildcard_covered) { + return LDNS_STATUS_DNSSEC_NSEC_WILDCARD_NOT_COVERED; + } + + return LDNS_STATUS_OK; +} + +ldns_status +ldns_dnssec_verify_denial_nsec3(ldns_rr *rr, + ldns_rr_list *nsecs, + ldns_rr_list *rrsigs, + ldns_pkt_rcode packet_rcode, + ldns_rr_type packet_qtype, + bool packet_nodata) +{ + ldns_rdf *closest_encloser; + ldns_rdf *wildcard; + bool wildcard_covered = false; + ldns_rdf *zone_name; + ldns_rdf *hashed_name; + size_t i; + + rrsigs = rrsigs; + + /* section 8.4 */ + if (packet_rcode == LDNS_RCODE_NXDOMAIN) { + closest_encloser = ldns_dnssec_nsec3_closest_encloser(ldns_rr_owner(rr), + ldns_rr_get_type(rr), + nsecs); + + printf("[XX} NSEC3 denial for: "); + ldns_rr_print(stdout, rr); + printf("[XX] closest encloser: "); + ldns_rdf_print(stdout, closest_encloser); + printf("\n"); + + wildcard = ldns_dname_new_frm_str("*"); + ldns_dname_cat(wildcard, closest_encloser); + + for (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) { + if (ldns_nsec_covers_name(ldns_rr_list_rr(nsecs, i), + wildcard)) { + printf("[XX] wildcard covered\n"); + wildcard_covered = true; + } + } + + if (!wildcard_covered) { + return LDNS_STATUS_DNSSEC_NSEC_WILDCARD_NOT_COVERED; + } + if (closest_encloser && wildcard_covered) { + return LDNS_STATUS_OK; + } + return LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED; + } else if (packet_nodata && packet_qtype != LDNS_RR_TYPE_DS) { + /* section 8.5 */ + hashed_name = ldns_nsec3_hash_name_frm_nsec3(ldns_rr_list_rr(nsecs, 0), + ldns_rr_owner(rr) + ); + zone_name = ldns_dname_left_chop(ldns_rr_owner(ldns_rr_list_rr(nsecs,0))); + ldns_dname_cat(hashed_name, zone_name); + printf("[XX] hashed name: "); + ldns_rdf_print(stdout, hashed_name); + printf("\n"); + for (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) { + if (ldns_dname_compare(hashed_name, ldns_rr_owner(ldns_rr_list_rr(nsecs, i))) == 0) { + if (!ldns_nsec_bitmap_covers_type(ldns_nsec3_bitmap(ldns_rr_list_rr(nsecs, i)), packet_qtype) && + !ldns_nsec_bitmap_covers_type(ldns_nsec3_bitmap(ldns_rr_list_rr(nsecs, i)), LDNS_RR_TYPE_CNAME)) { + printf("exact match!\n"); + return LDNS_STATUS_OK; + } + } + } + return LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED; + } else if (packet_nodata && packet_qtype == LDNS_RR_TYPE_DS) { + /* section 8.6 */ + /* note: up to XXX this is the same as for 8.5 */ + hashed_name = ldns_nsec3_hash_name_frm_nsec3(ldns_rr_list_rr(nsecs, 0), + ldns_rr_owner(rr) + ); + zone_name = ldns_dname_left_chop(ldns_rr_owner(ldns_rr_list_rr(nsecs,0))); + ldns_dname_cat(hashed_name, zone_name); + printf("[XX] hashed name: "); + ldns_rdf_print(stdout, hashed_name); + printf("\n"); + for (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) { + if (ldns_dname_compare(hashed_name, ldns_rr_owner(ldns_rr_list_rr(nsecs, i))) == 0) { + if (!ldns_nsec_bitmap_covers_type(ldns_nsec3_bitmap(ldns_rr_list_rr(nsecs, i)), LDNS_RR_TYPE_DS) && + !ldns_nsec_bitmap_covers_type(ldns_nsec3_bitmap(ldns_rr_list_rr(nsecs, i)), LDNS_RR_TYPE_CNAME)) { + printf("exact match!\n"); + return LDNS_STATUS_OK; + } + } + } + + /* XXX see note above */ + closest_encloser = ldns_dnssec_nsec3_closest_encloser(ldns_rr_owner(rr), + ldns_rr_get_type(rr), + nsecs); + + if (closest_encloser) { + printf("[XX] closest encloser: "); + ldns_rdf_print(stdout, closest_encloser); + printf("\n"); + exit(0); + } + return LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED; + + } + return LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED; +} + ldns_status ldns_verify_rrsig_buffers(ldns_buffer *rawsig_buf, ldns_buffer *verify_buf, ldns_buffer *key_buf, uint8_t algo) @@ -1367,10 +1559,8 @@ ldns_verify_rrsig_keylist(ldns_rr_list *rrset, ldns_rr *rrsig, const ldns_rr_lis } ldns_status -ldns_convert_dsa_rrsig_rdata( - ldns_buffer *target_buffer, - ldns_rdf *sig_rdf - ) +ldns_convert_dsa_rrsig_rdata(ldns_buffer *target_buffer, + ldns_rdf *sig_rdf) { /* the EVP api wants the DER encoding of the signature... */ uint8_t t; @@ -1403,6 +1593,7 @@ ldns_convert_dsa_rrsig_rdata( return ldns_buffer_status(target_buffer); } +#if 0 void print_dates(time_t now, time_t inception) { @@ -1420,6 +1611,7 @@ print_dates(time_t now, time_t inception) LDNS_FREE(istr); return; } +#endif ldns_status ldns_verify_rrsig(ldns_rr_list *rrset, ldns_rr *rrsig, ldns_rr *key) @@ -1760,109 +1952,4 @@ ldns_verify_rrsig_rsamd5_raw(unsigned char* sig, size_t siglen, return result; } -DSA * -ldns_key_buf2dsa(ldns_buffer *key) -{ - return ldns_key_buf2dsa_raw((unsigned char*)ldns_buffer_begin(key), - ldns_buffer_position(key)); -} - -DSA * -ldns_key_buf2dsa_raw(unsigned char* key, size_t len) -{ - uint8_t T; - uint16_t length; - uint16_t offset; - DSA *dsa; - BIGNUM *Q; BIGNUM *P; - BIGNUM *G; BIGNUM *Y; - - if(len == 0) - return NULL; - T = (uint8_t)key[0]; - length = (64 + T * 8); - offset = 1; - - if (T > 8) { - return NULL; - } - if(len < (size_t)1 + SHA_DIGEST_LENGTH + 3*length) - return NULL; - - Q = BN_bin2bn(key+offset, SHA_DIGEST_LENGTH, NULL); - offset += SHA_DIGEST_LENGTH; - - P = BN_bin2bn(key+offset, (int)length, NULL); - offset += length; - - G = BN_bin2bn(key+offset, (int)length, NULL); - offset += length; - - Y = BN_bin2bn(key+offset, (int)length, NULL); - offset += length; - - /* create the key and set its properties */ - dsa = DSA_new(); - dsa->p = P; - dsa->q = Q; - dsa->g = G; - dsa->pub_key = Y; - - return dsa; -} - -RSA * -ldns_key_buf2rsa(ldns_buffer *key) -{ - return ldns_key_buf2rsa_raw((unsigned char*)ldns_buffer_begin(key), - ldns_buffer_position(key)); -} - -RSA * -ldns_key_buf2rsa_raw(unsigned char* key, size_t len) -{ - uint16_t offset; - uint16_t exp; - uint16_t int16; - RSA *rsa; - BIGNUM *modulus; - BIGNUM *exponent; - - if (len == 0) - return NULL; - if (key[0] == 0) { - if(len < 3) - return NULL; - /* need some smart comment here XXX*/ - /* the exponent is too large so it's places - * futher...???? */ - memmove(&int16, key+1, 2); - exp = ntohs(int16); - offset = 3; - } else { - exp = key[0]; - offset = 1; - } - - /* key length at least one */ - if(len < (size_t)offset + exp + 1) - return NULL; - - /* Exponent */ - exponent = BN_new(); - (void) BN_bin2bn(key+offset, (int)exp, exponent); - offset += exp; - - /* Modulus */ - modulus = BN_new(); - /* length of the buffer must match the key length! */ - (void) BN_bin2bn(key+offset, (int)(len - offset), modulus); - - rsa = RSA_new(); - rsa->n = modulus; - rsa->e = exponent; - - return rsa; -} - #endif diff --git a/ldns/dnssec.h b/ldns/dnssec.h index 7a66d704..7ccd6104 100644 --- a/ldns/dnssec.h +++ b/ldns/dnssec.h @@ -73,6 +73,31 @@ ldns_rdf *ldns_nsec_get_bitmap(ldns_rr *nsec); #define LDNS_NSEC3_MAX_ITERATIONS 65535 +/** + * Returns the dname of the closest (provable) encloser + */ +ldns_rdf * +ldns_dnssec_nsec3_closest_encloser(ldns_rdf *qname, + ldns_rr_type qtype, + ldns_rr_list *nsec3s); + +/** + * Checks whether the packet contains rrsigs + */ +bool +ldns_dnssec_pkt_has_rrsigs(const ldns_pkt *pkt); + +/** + * Returns a ldns_rr_list containing the signatures covering the given name + * and type + */ +ldns_rr_list *ldns_dnssec_pkt_get_rrsigs_for_name_and_type(const ldns_pkt *pkt, ldns_rdf *name, ldns_rr_type type); + +/** + * Returns a ldns_rr_list containing the signatures covering the given type + */ +ldns_rr_list *ldns_dnssec_pkt_get_rrsigs_for_type(const ldns_pkt *pkt, ldns_rr_type type); + /** * calculates a keytag of a key for use in DNSSEC. * @@ -81,10 +106,6 @@ ldns_rdf *ldns_nsec_get_bitmap(ldns_rr *nsec); */ uint16_t ldns_calc_keytag(const ldns_rr *key); -ldns_rr_list *ldns_dnssec_pkt_get_rrsigs_for_type(const ldns_pkt *pkt, ldns_rr_type type); - -ldns_rr_list *ldns_dnssec_pkt_get_rrsigs_for_name_and_type(const ldns_pkt *pkt, ldns_rdf *name, ldns_rr_type type); - /** * Calculates keytag of DNSSEC key, operates on wireformat rdata. * \param[in] key the key as uncompressed wireformat rdata. @@ -118,6 +139,7 @@ DSA *ldns_key_buf2dsa_raw(unsigned char* key, size_t len); * \return a RSA * structure with the key material */ RSA *ldns_key_buf2rsa(ldns_buffer *key); + /** * Like ldns_key_buf2rsa, but uses raw buffer. * \param[in] key the uncompressed wireformat of the key. @@ -136,6 +158,35 @@ RSA *ldns_key_buf2rsa_raw(unsigned char* key, size_t len); */ ldns_rr *ldns_key_rr2ds(const ldns_rr *key, ldns_hash h); +/** + * Create the type bitmap for an NSEC(3) record + */ +ldns_rdf * +ldns_dnssec_create_nsec_bitmap(ldns_rr_type rr_type_list[], + size_t size, + ldns_rr_type nsec_type); + +/** + * Creates NSEC + */ +ldns_rr * +ldns_dnssec_create_nsec(ldns_dnssec_name *from, + ldns_dnssec_name *to, + ldns_rr_type nsec_type); + +/** + * Creates NSEC3 + */ +ldns_rr * +ldns_dnssec_create_nsec3(ldns_dnssec_name *from, + ldns_dnssec_name *to, + ldns_rdf *zone_name, + uint8_t algorithm, + uint8_t flags, + uint16_t iterations, + uint8_t salt_length, + uint8_t *salt); + /** * Create a NSEC record * \param[in] cur_owner the current owner which should be taken as the starting point @@ -146,24 +197,45 @@ ldns_rr *ldns_key_rr2ds(const ldns_rr *key, ldns_hash h); ldns_rr * ldns_create_nsec(ldns_rdf *cur_owner, ldns_rdf *next_owner, ldns_rr_list *rrs); /** - * Checks coverage of NSEC RR type bitmap - * \param[in] nsec_bitmap The NSEC bitmap rdata field to check - * \param[in] type The type to check - * \return true if the NSEC RR covers the type + * Calculates the hashed name using the given parameters + * \param[in] *name The owner name to calculate the hash for + * \param[in] algorithm The hash algorithm to use + * \param[in] iterations The number of hash iterations to use + * \param[in] salt_length The length of the salt in bytes + * \param[in] salt The salt to use + * \return The hashed owner name rdf, without the domain name */ -bool ldns_nsec_bitmap_covers_type(const ldns_rdf *nsec_bitmap, ldns_rr_type type); +ldns_rdf *ldns_nsec3_hash_name(ldns_rdf *name, uint8_t algorithm, uint16_t iterations, uint8_t salt_length, uint8_t *salt); /** - * Checks coverage of NSEC(3) RR name span - * Remember that nsec and name must both be in canonical form (ie use - * \ref ldns_rr2canonical and \ref ldns_dname2canonical prior to calling this - * function) - * - * \param[in] nsec The NSEC RR to check - * \param[in] name The owner dname to check, if the nsec record is a NSEC3 record, this should be the hashed name - * \return true if the NSEC RR covers the owner name + * Sets all the NSEC3 options. The rr to set them in must be initialized with _new() and + * type LDNS_RR_TYPE_NSEC3 + * \param[in] *rr The RR to set the values in + * \param[in] algorithm The NSEC3 hash algorithm + * \param[in] flags The flags field + * \param[in] iterations The number of hash iterations + * \param[in] salt_length The length of the salt in bytes + * \param[in] salt The salt bytes */ -bool ldns_nsec_covers_name(const ldns_rr *nsec, const ldns_rdf *name); +void ldns_nsec3_add_param_rdfs(ldns_rr *rr, + uint8_t algorithm, + uint8_t flags, + uint16_t iterations, + uint8_t salt_length, + uint8_t *salt); + +/* this will NOT return the NSEC3 completed, you will have to run the + finalize function on the rrlist later! */ +ldns_rr * +ldns_create_nsec3(ldns_rdf *cur_owner, + ldns_rdf *cur_zone, + ldns_rr_list *rrs, + uint8_t algorithm, + uint8_t flags, + uint16_t iterations, + uint8_t salt_length, + uint8_t *salt, + bool emptynonterminal); /** * Returns the hash algorithm used in the given NSEC3 RR @@ -172,6 +244,19 @@ bool ldns_nsec_covers_name(const ldns_rr *nsec, const ldns_rdf *name); */ uint8_t ldns_nsec3_algorithm(const ldns_rr *nsec3_rr); +/** + * Returns flags field + */ +uint8_t +ldns_nsec3_flags(const ldns_rr *nsec3_rr); + +/** + * Returns true if the opt-out flag has been set in the given NSEC3 RR + * \param[in] *nsec3_rr The RR to read from + * \return true if the RR has type NSEC3 and the opt-out bit has been set, false otherwise + */ +bool ldns_nsec3_optout(const ldns_rr *nsec3_rr); + /** * Returns the number of hash iterations used in the given NSEC3 RR * \param[in] *nsec3_rr The RR to read from @@ -200,13 +285,6 @@ uint8_t ldns_nsec3_salt_length(const ldns_rr *nsec3_rr); */ uint8_t *ldns_nsec3_salt_data(const ldns_rr *nsec3_rr); -/** - * Returns true if the opt-out flag has been set in the given NSEC3 RR - * \param[in] *nsec3_rr The RR to read from - * \return true if the RR has type NSEC3 and the opt-out bit has been set, false otherwise - */ -bool ldns_nsec3_optout(const ldns_rr *nsec3_rr); - /** * Returns the first label of the next ownername in the NSEC3 chain (ie. without the domain) * \param[in] nsec3_rr The RR to read from @@ -214,19 +292,6 @@ bool ldns_nsec3_optout(const ldns_rr *nsec3_rr); */ ldns_rdf *ldns_nsec3_next_owner(const ldns_rr *nsec3_rr); -/** - * Sets all the NSEC3 options. The rr to set them in must be initialized with _new() and - * type LDNS_RR_TYPE_NSEC3 - * \param[in] *rr The RR to set the values in - * \param[in] algorithm The NSEC3 hash algorithm - * \param[in] flags The flags field - * \param[in] iterations The number of hash iterations - * \param[in] salt_length The length of the salt in bytes - * \param[in] salt The salt bytes - */ -void ldns_nsec3_add_param_rdfs(ldns_rr *rr, uint8_t algorithm, uint8_t flags, uint16_t iterations, uint8_t salt_length, uint8_t *salt); - - /** * Returns the bitmap specifying the covered types of the given NSEC3 RR * \param[in] *nsec3_rr The RR to read from @@ -243,16 +308,24 @@ ldns_rdf *ldns_nsec3_bitmap(const ldns_rr *nsec3_rr); ldns_rdf *ldns_nsec3_hash_name_frm_nsec3(const ldns_rr *nsec, ldns_rdf *name); /** - * Calculates the hashed name using the given parameters - * \param[in] *name The owner name to calculate the hash for - * \param[in] algorithm The hash algorithm to use - * \param[in] iterations The number of hash iterations to use - * \param[in] salt_length The length of the salt in bytes - * \param[in] salt The salt to use - * \return The hashed owner name rdf, without the domain name + * Checks coverage of NSEC RR type bitmap + * \param[in] nsec_bitmap The NSEC bitmap rdata field to check + * \param[in] type The type to check + * \return true if the NSEC RR covers the type */ -ldns_rdf *ldns_nsec3_hash_name(ldns_rdf *name, uint8_t algorithm, uint16_t iterations, uint8_t salt_length, uint8_t *salt); +bool ldns_nsec_bitmap_covers_type(const ldns_rdf *nsec_bitmap, ldns_rr_type type); +/** + * Checks coverage of NSEC(3) RR name span + * Remember that nsec and name must both be in canonical form (ie use + * \ref ldns_rr2canonical and \ref ldns_dname2canonical prior to calling this + * function) + * + * \param[in] nsec The NSEC RR to check + * \param[in] name The owner dname to check, if the nsec record is a NSEC3 record, this should be the hashed name + * \return true if the NSEC RR covers the owner name + */ +bool ldns_nsec_covers_name(const ldns_rr *nsec, const ldns_rdf *name); /** * verify a packet @@ -267,9 +340,35 @@ ldns_rdf *ldns_nsec3_hash_name(ldns_rdf *name, uint8_t algorithm, uint16_t itera */ ldns_status ldns_pkt_verify(ldns_pkt *p, ldns_rr_type t, ldns_rdf *o, ldns_rr_list *k, ldns_rr_list *s, ldns_rr_list *good_keys); -bool ldns_dnssec_pkt_has_rrsigs(const ldns_pkt *pkt); +/** + * chains nsec3 list + */ +ldns_status +ldns_dnssec_chain_nsec3_list(ldns_rr_list *nsec3_rrs); +/** + * compare for nsec3 sort + */ +int +qsort_rr_compare_nsec3(const void *a, const void *b); +/** + * sort nsec3 list + */ +void +ldns_rr_list_sort_nsec3(ldns_rr_list *unsorted); + +/** + * Adds NSEC3 records to the zone + */ +ldns_status +ldns_dnssec_zone_create_nsec3s(ldns_dnssec_zone *zone, + ldns_rr_list *new_rrs, + uint8_t algorithm, + uint8_t flags, + uint16_t iterations, + uint8_t salt_length, + uint8_t *salt); /** * Default callback function to always leave present signatures, and * add new ones @@ -303,78 +402,4 @@ int ldns_dnssec_default_delete_signatures(ldns_rr *sig, void *n); */ int ldns_dnssec_default_replace_signatures(ldns_rr *sig, void *n); -/** - * Tries to build an authentication chain from the given keys down to the queried domain. - * - * If we find a valid trust path, return the valid keys for the domain. - * - * \param[in] res the current resolver - * \param[in] domain the domain we want valid keys for - * \param[in] keys the current set of trusted keys - * \param[out] status pointer to the status variable where the result code will be stored - * \return the set of trusted keys for the domain, or NULL if no trust path could be built. - */ -ldns_rr_list * -ldns_fetch_valid_domain_keys(const ldns_resolver * res, const ldns_rdf * domain, const ldns_rr_list * keys, ldns_status *status); - -/** - * Validates the DNSKEY RRset for the given domain using the provided trusted keys. - * - * \param[in] res the current resolver - * \param[in] domain the domain we want valid keys for - * \param[in] keys the current set of trusted keys - * \return the set of trusted keys for the domain, or NULL if the RRSET could not be validated - */ -ldns_rr_list * -ldns_validate_domain_dnskey (const ldns_resolver * res, const ldns_rdf * domain, const ldns_rr_list * keys); - -/** - * Validates the DS RRset for the given domain using the provided trusted keys. - * - * \param[in] res the current resolver - * \param[in] domain the domain we want valid keys for - * \param[in] keys the current set of trusted keys - * \return the set of trusted keys for the domain, or NULL if the RRSET could not be validated - */ -ldns_rr_list * -ldns_validate_domain_ds (const ldns_resolver * res, const ldns_rdf * domain, const ldns_rr_list * keys); - -/** - * Verifies a list of signatures for one RRset using a valid trust path. - * - * \param[in] res the current resolver - * \param[in] rrset the rrset to verify - * \param[in] rrsigs a list of signatures to check - * \param[out] validating_keys if this is a (initialized) list, the keys from keys that validate one of the signatures are added to it - * \return status LDNS_STATUS_OK if there is at least one correct key - */ -ldns_status -ldns_verify_trusted(ldns_resolver * res, ldns_rr_list * rrset, ldns_rr_list * rrsigs, ldns_rr_list * validating_keys); - -ldns_rr * -ldns_dnssec_create_nsec(ldns_dnssec_name *from, - ldns_dnssec_name *to, - ldns_rr_type nsec_type); - -ldns_status -ldns_dnssec_zone_create_nsec3s(ldns_dnssec_zone *zone, - ldns_rr_list *new_rrs, - uint8_t algorithm, - uint8_t flags, - uint16_t iterations, - uint8_t salt_length, - uint8_t *salt); -ldns_status -ldns_dnssec_verify_denial_nsec3(ldns_rr *rr, - ldns_rr_list *nsecs, - ldns_rr_list *rrsigs, - ldns_pkt_rcode packet_rcode, - ldns_rr_type packet_qtype, - bool packet_nodata); - -ldns_status -ldns_dnssec_verify_denial(ldns_rr *rr, - ldns_rr_list *nsecs, - ldns_rr_list *rrsigs); - #endif /* LDNS_DNSSEC_H */ diff --git a/ldns/dnssec_sign.h b/ldns/dnssec_sign.h index 8fd87238..bf7725d0 100644 --- a/ldns/dnssec_sign.h +++ b/ldns/dnssec_sign.h @@ -32,21 +32,49 @@ ldns_rdf *ldns_sign_public_evp(ldns_buffer *to_sign, const EVP_MD *digest_type); /** - * Sign a buffer with the RSA key (hash with MD5) + * Sign a buffer with the RSA key (hash with SHA1) * \param[in] to_sign buffer with the data * \param[in] key the key to use * \return a ldns_rdf with the signed data */ -ldns_rdf *ldns_sign_public_rsamd5(ldns_buffer *to_sign, RSA *key); +ldns_rdf *ldns_sign_public_rsasha1(ldns_buffer *to_sign, RSA *key); + /** - * Sign a buffer with the RSA key (hash with SHA1) + * Sign a buffer with the RSA key (hash with MD5) * \param[in] to_sign buffer with the data * \param[in] key the key to use * \return a ldns_rdf with the signed data */ -ldns_rdf *ldns_sign_public_rsasha1(ldns_buffer *to_sign, RSA *key); +ldns_rdf *ldns_sign_public_rsamd5(ldns_buffer *to_sign, RSA *key); #endif /* HAVE_SSL */ +/** + * Adds NSEC RRs to the zone + */ +ldns_status +ldns_dnssec_zone_create_nsecs(ldns_dnssec_zone *zone, + ldns_rr_list *new_rrs, + ldns_rr_type nsec_type); + +/** + * remove signatures if callback function tells to + */ +ldns_dnssec_rrs * +ldns_dnssec_remove_signatures(ldns_dnssec_rrs *signatures, + ldns_key_list *key_list, + int (*func)(ldns_rr *, void *), + void *arg); + +/** + * Adds signatures to the zone + */ +ldns_status +ldns_dnssec_zone_create_rrsigs(ldns_dnssec_zone *zone, + ldns_rr_list *new_rrs, + ldns_key_list *key_list, + int (*func)(ldns_rr *, void*), + void *arg); + /** * signs the given zone with the given new zone * @@ -96,6 +124,7 @@ ldns_status ldns_dnssec_zone_sign_nsec3(ldns_dnssec_zone *zone, * \return signed zone */ ldns_zone *ldns_zone_sign(const ldns_zone *zone, ldns_key_list *key_list); + /** * Signs the zone with NSEC3, and returns a newly allocated signed zone * \param[in] zone the zone to sign diff --git a/ldns/dnssec_verify.h b/ldns/dnssec_verify.h index f88ec5de..9fe31f0a 100644 --- a/ldns/dnssec_verify.h +++ b/ldns/dnssec_verify.h @@ -48,6 +48,17 @@ void ldns_dnssec_data_chain_deep_free(ldns_dnssec_data_chain *chain); */ void ldns_dnssec_data_chain_print(FILE *out, const ldns_dnssec_data_chain *chain); +/** + * the data set will be cloned + * the pkt is optional, can contain the original packet + * (and hence the sigs and maybe the key) + */ +ldns_dnssec_data_chain *ldns_dnssec_build_data_chain(ldns_resolver *res, + const uint16_t qflags, + const ldns_rr_list *data_set, + const ldns_pkt *pkt, + ldns_rr *orig_rr); + #define LDNS_DNSSEC_TRUST_TREE_MAX_PARENTS 10 /** @@ -104,10 +115,11 @@ ldns_dnssec_trust_tree *ldns_dnssec_trust_tree_new(); */ void ldns_dnssec_trust_tree_free(ldns_dnssec_trust_tree *tree); - +/** + * returns the depth + */ size_t ldns_dnssec_trust_tree_depth(ldns_dnssec_trust_tree *tree); - /** * Prints the dnssec_trust_tree structure to the given file stream * Each line is prepended by 2*tabs spaces @@ -120,16 +132,6 @@ size_t ldns_dnssec_trust_tree_depth(ldns_dnssec_trust_tree *tree); */ void ldns_dnssec_trust_tree_print(FILE *out, ldns_dnssec_trust_tree *tree, size_t tabs, bool extended); -/** - * Generates a dnssec_trust_ttree for the given rr from the given data_chain - * Don't free the data_chain before you are done with this tree - * - * \param[in] *data_chain The chain to derive the trust tree from - * \param[in] *rr The RR this tree will be about - * \return ldns_dnssec_trust_tree * - */ -ldns_dnssec_trust_tree *ldns_dnssec_derive_trust_tree(ldns_dnssec_data_chain *data_chain, ldns_rr *rr); - /** * Adds a trust tree as a parent for the given trust tree * @@ -146,8 +148,50 @@ ldns_dnssec_trust_tree_add_parent(ldns_dnssec_trust_tree *tree, const ldns_status parent_status); /** - * Returns OK if there is a trusted path in the tree to one of the DNSKEY or DS RRs in the - * given list + * Generates a dnssec_trust_ttree for the given rr from the given data_chain + * Don't free the data_chain before you are done with this tree + * + * \param[in] *data_chain The chain to derive the trust tree from + * \param[in] *rr The RR this tree will be about + * \return ldns_dnssec_trust_tree * + */ +ldns_dnssec_trust_tree *ldns_dnssec_derive_trust_tree(ldns_dnssec_data_chain *data_chain, ldns_rr *rr); + +/** + * Sub function for derive_trust_tree + */ +void +ldns_dnssec_derive_trust_tree_normal_rrset(ldns_dnssec_trust_tree *new_tree, + ldns_dnssec_data_chain *data_chain, + ldns_rr *cur_sig_rr); + +/** + * Sub function for derive_trust_tree + */ +void +ldns_dnssec_derive_trust_tree_dnskey_rrset(ldns_dnssec_trust_tree *new_tree, + ldns_dnssec_data_chain *data_chain, + ldns_rr *cur_rr, + ldns_rr *cur_sig_rr); + +/** + * Sub function for derive_trust_tree + */ +void +ldns_dnssec_derive_trust_tree_ds_rrset(ldns_dnssec_trust_tree *new_tree, + ldns_dnssec_data_chain *data_chain, + ldns_rr *cur_rr); + +/** + * Sub function for derive_trust_tree + */ +void +ldns_dnssec_derive_trust_tree_no_sig(ldns_dnssec_trust_tree *new_tree, + ldns_dnssec_data_chain *data_chain); + +/** + * Returns OK if there is a trusted path in the tree to one of + * the DNSKEY or DS RRs in the given list * * \param *tree The trust tree so search * \param *keys A ldns_rr_list of DNSKEY and DS rrs to look for @@ -156,13 +200,6 @@ ldns_dnssec_trust_tree_add_parent(ldns_dnssec_trust_tree *tree, */ ldns_status ldns_dnssec_trust_tree_contains_keys(ldns_dnssec_trust_tree *tree, ldns_rr_list *keys); - -/** - * the data set will be cloned - * the pkt is optional, can contain the original packet (and hence the sigs and maybe the key) - */ -ldns_dnssec_data_chain *ldns_dnssec_build_data_chain(ldns_resolver *res, const uint16_t qflags, const ldns_rr_list *data_set, const ldns_pkt *pkt, ldns_rr *orig_rr); - /** * Verifies a list of signatures for one rrset. * @@ -174,6 +211,81 @@ ldns_dnssec_data_chain *ldns_dnssec_build_data_chain(ldns_resolver *res, const u */ ldns_status ldns_verify(ldns_rr_list *rrset, ldns_rr_list *rrsig, const ldns_rr_list *keys, ldns_rr_list *good_keys); +/** + * Tries to build an authentication chain from the given keys down to the queried domain. + * + * If we find a valid trust path, return the valid keys for the domain. + * + * \param[in] res the current resolver + * \param[in] domain the domain we want valid keys for + * \param[in] keys the current set of trusted keys + * \param[out] status pointer to the status variable where the result code will be stored + * \return the set of trusted keys for the domain, or NULL if no trust path could be built. + */ +ldns_rr_list * +ldns_fetch_valid_domain_keys(const ldns_resolver * res, + const ldns_rdf * domain, + const ldns_rr_list * keys, + ldns_status *status); + +/** + * Validates the DNSKEY RRset for the given domain using the provided trusted keys. + * + * \param[in] res the current resolver + * \param[in] domain the domain we want valid keys for + * \param[in] keys the current set of trusted keys + * \return the set of trusted keys for the domain, or NULL if the RRSET could not be validated + */ +ldns_rr_list * +ldns_validate_domain_dnskey (const ldns_resolver *res, + const ldns_rdf *domain, + const ldns_rr_list *keys); + +/** + * Validates the DS RRset for the given domain using the provided trusted keys. + * + * \param[in] res the current resolver + * \param[in] domain the domain we want valid keys for + * \param[in] keys the current set of trusted keys + * \return the set of trusted keys for the domain, or NULL if the RRSET could not be validated + */ +ldns_rr_list * +ldns_validate_domain_ds(const ldns_resolver *res, + const ldns_rdf * + domain, + const ldns_rr_list * keys); + +/** + * Verifies a list of signatures for one RRset using a valid trust path. + * + * \param[in] res the current resolver + * \param[in] rrset the rrset to verify + * \param[in] rrsigs a list of signatures to check + * \param[out] validating_keys if this is a (initialized) list, the keys from keys that validate one of the signatures are added to it + * \return status LDNS_STATUS_OK if there is at least one correct key + */ +ldns_status +ldns_verify_trusted(ldns_resolver *res, + ldns_rr_list *rrset, + ldns_rr_list *rrsigs, + ldns_rr_list *validating_keys); + +/** + * denial is not just a river in egypt + */ +ldns_status +ldns_dnssec_verify_denial(ldns_rr *rr, + ldns_rr_list *nsecs, + ldns_rr_list *rrsigs); + +ldns_status +ldns_dnssec_verify_denial_nsec3(ldns_rr *rr, + ldns_rr_list *nsecs, + ldns_rr_list *rrsigs, + ldns_pkt_rcode packet_rcode, + ldns_rr_type packet_qtype, + bool packet_nodata); + /** * Verifies the already processed data in the buffers * This function should probably not be used directly. @@ -210,6 +322,13 @@ ldns_status ldns_verify_rrsig_buffers_raw(unsigned char* sig, size_t siglen, */ ldns_status ldns_verify_rrsig_keylist(ldns_rr_list *rrset, ldns_rr *rrsig, const ldns_rr_list *keys, ldns_rr_list *good_keys); +/** + * convert dsa data + */ +ldns_status +ldns_convert_dsa_rrsig_rdata(ldns_buffer *target_buffer, + ldns_rdf *sig_rdf); + /** * verify an rrsig with 1 key * \param[in] rrset the rrset @@ -254,6 +373,7 @@ ldns_status ldns_verify_rrsig_evp_raw(unsigned char *sig, size_t siglen, * \param[in] key the key data */ ldns_status ldns_verify_rrsig_dsa(ldns_buffer *sig, ldns_buffer *rrset, ldns_buffer *key); + /** * verifies a buffer with signature data (RSASHA1) for a buffer with rrset data * with a buffer with key data. @@ -263,6 +383,7 @@ ldns_status ldns_verify_rrsig_dsa(ldns_buffer *sig, ldns_buffer *rrset, ldns_buf * \param[in] key the key data */ ldns_status ldns_verify_rrsig_rsasha1(ldns_buffer *sig, ldns_buffer *rrset, ldns_buffer *key); + /** * verifies a buffer with signature data (RSAMD5) for a buffer with rrset data * with a buffer with key data. @@ -272,6 +393,7 @@ ldns_status ldns_verify_rrsig_rsasha1(ldns_buffer *sig, ldns_buffer *rrset, ldns * \param[in] key the key data */ ldns_status ldns_verify_rrsig_rsamd5(ldns_buffer *sig, ldns_buffer *rrset, ldns_buffer *key); + /** * Like ldns_verify_rrsig_dsa, but uses raw signature and key data. * \param[in] sig raw uncompressed wireformat signature data @@ -282,6 +404,7 @@ ldns_status ldns_verify_rrsig_rsamd5(ldns_buffer *sig, ldns_buffer *rrset, ldns_ */ ldns_status ldns_verify_rrsig_dsa_raw(unsigned char* sig, size_t siglen, ldns_buffer* rrset, unsigned char* key, size_t keylen); + /** * Like ldns_verify_rrsig_rsasha1, but uses raw signature and key data. * \param[in] sig raw uncompressed wireformat signature data @@ -300,8 +423,10 @@ ldns_status ldns_verify_rrsig_rsasha1_raw(unsigned char* sig, size_t siglen, * \param[in] key raw uncompressed wireformat key data * \param[in] keylen length of key data */ + ldns_status ldns_verify_rrsig_rsasha256_raw(unsigned char* sig, size_t siglen, ldns_buffer* rrset, unsigned char* key, size_t keylen); + /** * Like ldns_verify_rrsig_rsasha512, but uses raw signature and key data. * \param[in] sig raw uncompressed wireformat signature data @@ -312,6 +437,7 @@ ldns_status ldns_verify_rrsig_rsasha256_raw(unsigned char* sig, size_t siglen, */ ldns_status ldns_verify_rrsig_rsasha512_raw(unsigned char* sig, size_t siglen, ldns_buffer* rrset, unsigned char* key, size_t keylen); + /** * Like ldns_verify_rrsig_rsamd5, but uses raw signature and key data. * \param[in] sig raw uncompressed wireformat signature data @@ -323,6 +449,5 @@ ldns_status ldns_verify_rrsig_rsasha512_raw(unsigned char* sig, size_t siglen, ldns_status ldns_verify_rrsig_rsamd5_raw(unsigned char* sig, size_t siglen, ldns_buffer* rrset, unsigned char* key, size_t keylen); - #endif