Exemple #1
0
ldns_status
ldns_dnssec_zone_mark_glue(ldns_dnssec_zone *zone)
{
	ldns_rbnode_t *cur_node;
	ldns_dnssec_name *cur_name;
	ldns_rdf *cur_owner, *cur_parent;

	cur_node = ldns_rbtree_first(zone->names);
	while (cur_node != LDNS_RBTREE_NULL) {
		cur_name = (ldns_dnssec_name *) cur_node->data;
		cur_node = ldns_rbtree_next(cur_node);
		if (ldns_dnssec_name_has_only_a(cur_name)) {
			/* assume glue XXX check for zone cur */
			cur_owner = ldns_rdf_clone(ldns_rr_owner(
					      cur_name->rrsets->rrs->rr));
			while (ldns_dname_label_count(cur_owner) >
				  ldns_dname_label_count(zone->soa->name)) {
				if (ldns_dnssec_zone_find_rrset(zone,
										  cur_owner,
										  LDNS_RR_TYPE_NS)) {
					/*
					fprintf(stderr, "[XX] Marking as glue: ");
					ldns_rdf_print(stderr, cur_name->name);
					fprintf(stderr, "\n");
					*/
					cur_name->is_glue = true;
				}
				cur_parent = ldns_dname_left_chop(cur_owner);
				ldns_rdf_deep_free(cur_owner);
				cur_owner = cur_parent;
			}
			ldns_rdf_deep_free(cur_owner);
		}
	}
	return LDNS_STATUS_OK;
}
Exemple #2
0
void
covertests(ldns_rr_list *list, ldns_rdf *qname)
{
	size_t i;
	ldns_rdf *smaller = qname;
	ldns_rdf *wcard = ldns_dname_new_frm_str("*");
	for(i=0; i<ldns_dname_label_count(qname)+1; ++i)
	{
		check_cover(list, smaller);
		ldns_rdf* wcardchild = ldns_dname_cat_clone(wcard, smaller);
		check_cover(list, wcardchild);
		smaller = ldns_dname_left_chop(smaller);
	}
	/* check covers by weird names */
	if(0) {
		check_cover(list, ldns_dname_new_frm_str("x.bar.example."));
		check_cover(list, ldns_dname_new_frm_str("bar.example."));
	}
}
Exemple #3
0
ldns_rr *
ldns_create_empty_rrsig(ldns_rr_list *rrset,
                        ldns_key *current_key)
{
	uint32_t orig_ttl;
	time_t now;
	ldns_rr *current_sig;
	uint8_t label_count;

	label_count = ldns_dname_label_count(ldns_rr_owner(ldns_rr_list_rr(rrset,
	                                                   0)));
	
	current_sig = ldns_rr_new_frm_type(LDNS_RR_TYPE_RRSIG);
	
	/* set the type on the new signature */
	orig_ttl = ldns_rr_ttl(ldns_rr_list_rr(rrset, 0));

	ldns_rr_set_ttl(current_sig, orig_ttl);
	ldns_rr_set_owner(current_sig, 
			  ldns_rdf_clone(
			       ldns_rr_owner(
				    ldns_rr_list_rr(rrset,
						    0))));

	/* fill in what we know of the signature */
	
	/* set the orig_ttl */
	(void)ldns_rr_rrsig_set_origttl(
		   current_sig, 
		   ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32,
					 orig_ttl));
	/* the signers name */
	(void)ldns_rr_rrsig_set_signame(
			current_sig, 
			ldns_rdf_clone(ldns_key_pubkey_owner(current_key)));
	/* label count - get it from the first rr in the rr_list */
	(void)ldns_rr_rrsig_set_labels(
			current_sig, 
			ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8,
			                     label_count));
	/* inception, expiration */
	now = time(NULL);
	if (ldns_key_inception(current_key) != 0) {
		(void)ldns_rr_rrsig_set_inception(
				current_sig,
				ldns_native2rdf_int32(
				    LDNS_RDF_TYPE_TIME, 
				    ldns_key_inception(current_key)));
	} else {
		(void)ldns_rr_rrsig_set_inception(
				current_sig,
				ldns_native2rdf_int32(LDNS_RDF_TYPE_TIME, now));
	}
	if (ldns_key_expiration(current_key) != 0) {
		(void)ldns_rr_rrsig_set_expiration(
				current_sig,
				ldns_native2rdf_int32(
				    LDNS_RDF_TYPE_TIME, 
				    ldns_key_expiration(current_key)));
	} else {
		(void)ldns_rr_rrsig_set_expiration(
			     current_sig,
				ldns_native2rdf_int32(
				    LDNS_RDF_TYPE_TIME, 
				    now + LDNS_DEFAULT_EXP_TIME));
	}

	(void)ldns_rr_rrsig_set_keytag(
		   current_sig,
		   ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16, 
		                         ldns_key_keytag(current_key)));

	(void)ldns_rr_rrsig_set_algorithm(
			current_sig,
			ldns_native2rdf_int8(
			    LDNS_RDF_TYPE_ALG, 
			    ldns_key_algorithm(current_key)));

	(void)ldns_rr_rrsig_set_typecovered(
			current_sig,
			ldns_native2rdf_int16(
			    LDNS_RDF_TYPE_TYPE,
			    ldns_rr_get_type(ldns_rr_list_rr(rrset,
			                                     0))));
	return current_sig;
}
Exemple #4
0
ldns_status
ldns_dnssec_zone_add_empty_nonterminals(ldns_dnssec_zone *zone)
{
	ldns_dnssec_name *new_name;
	ldns_rdf *cur_name;
	ldns_rdf *next_name;
	ldns_rbnode_t *cur_node, *next_node, *new_node;

	/* for the detection */
	uint16_t i, cur_label_count, next_label_count;
	uint16_t soa_label_count = 0;
	ldns_rdf *l1, *l2;
	int lpos;

	if (!zone) {
		return LDNS_STATUS_ERR;
	}
	if (zone->soa && zone->soa->name) {
		soa_label_count = ldns_dname_label_count(zone->soa->name);
	}
	
	cur_node = ldns_rbtree_first(zone->names);
	while (cur_node != LDNS_RBTREE_NULL) {
		next_node = ldns_rbtree_next(cur_node);
		
		/* skip glue */
		while (next_node != LDNS_RBTREE_NULL && 
		       next_node->data &&
		       ((ldns_dnssec_name *)next_node->data)->is_glue
		) {
			next_node = ldns_rbtree_next(next_node);
		}

		if (next_node == LDNS_RBTREE_NULL) {
			next_node = ldns_rbtree_first(zone->names);
		}
		if (! cur_node->data || ! next_node->data) {
			return LDNS_STATUS_ERR;
		}
		cur_name = ((ldns_dnssec_name *)cur_node->data)->name;
		next_name = ((ldns_dnssec_name *)next_node->data)->name;
		cur_label_count = ldns_dname_label_count(cur_name);
		next_label_count = ldns_dname_label_count(next_name);

		/* Since the names are in canonical order, we can
		 * recognize empty non-terminals by their labels;
		 * every label after the first one on the next owner
		 * name is a non-terminal if it either does not exist
		 * in the current name or is different from the same
		 * label in the current name (counting from the end)
		 */
		for (i = 1; i < next_label_count - soa_label_count; i++) {
			lpos = (int)cur_label_count - (int)next_label_count + (int)i;
			if (lpos >= 0) {
				l1 = ldns_dname_clone_from(cur_name, (uint8_t)lpos);
			} else {
				l1 = NULL;
			}
			l2 = ldns_dname_clone_from(next_name, i);

			if (!l1 || ldns_dname_compare(l1, l2) != 0) {
				/* We have an empty nonterminal, add it to the
				 * tree
				 */
				new_name = ldns_dnssec_name_new();
				if (!new_name) {
					return LDNS_STATUS_MEM_ERR;
				}
				new_name->name = ldns_dname_clone_from(next_name,
				                                       i);
				if (!new_name->name) {
					ldns_dnssec_name_free(new_name);
					return LDNS_STATUS_MEM_ERR;
				}
				new_name->name_alloced = true;
				new_node = LDNS_MALLOC(ldns_rbnode_t);
				if (!new_node) {
					ldns_dnssec_name_free(new_name);
					return LDNS_STATUS_MEM_ERR;
				}
				new_node->key = new_name->name;
				new_node->data = new_name;
				(void)ldns_rbtree_insert(zone->names, new_node);
				ldns_dnssec_name_make_hashed_name(
						zone, new_name, NULL);
			}
			ldns_rdf_deep_free(l1);
			ldns_rdf_deep_free(l2);
		}
		
		/* we might have inserted a new node after
		 * the current one so we can't just use next()
		 */
		if (next_node != ldns_rbtree_first(zone->names)) {
			cur_node = next_node;
		} else {
			cur_node = LDNS_RBTREE_NULL;
		}
	}
	return LDNS_STATUS_OK;
}
Exemple #5
0
/* this is NOT the hash, but the original name! */
ldns_rdf *
ldns_nsec3_closest_encloser(ldns_rdf *qname, ldns_rr_type qtype, ldns_rr_list *nsec3s)
{
	/* remember parameters, they must match */
	uint8_t algorithm;
	uint32_t iterations;
	uint8_t salt_length;
	uint8_t *salt;

	ldns_rdf *sname, *hashed_sname, *tmp;
	ldns_rr *ce;
	bool flag;
	
	bool exact_match_found;
	bool in_range_found;
	
	ldns_status status;
	ldns_rdf *zone_name;
	
	size_t nsec_i;
	ldns_rr *nsec;
	ldns_rdf *result = NULL;
	
	if (!qname || !nsec3s || ldns_rr_list_rr_count(nsec3s) < 1) {
		return NULL;
	}

	if (verbosity >= 4) {
		printf(";; finding closest encloser for type %d ", qtype);
		ldns_rdf_print(stdout, qname);
		printf("\n");
	}

	nsec = ldns_rr_list_rr(nsec3s, 0);
	algorithm = ldns_nsec3_algorithm(nsec);
	salt_length = ldns_nsec3_salt_length(nsec);
	salt = ldns_nsec3_salt_data(nsec);
	iterations = ldns_nsec3_iterations(nsec);

	sname = ldns_rdf_clone(qname);

	ce = NULL;
	flag = false;
	
	zone_name = ldns_dname_left_chop(ldns_rr_owner(nsec));

	/* algorithm from nsec3-07 8.3 */
	while (ldns_dname_label_count(sname) > 0) {
		exact_match_found = false;
		in_range_found = false;
		
		if (verbosity >= 3) {
			printf(";; ");
			ldns_rdf_print(stdout, sname);
			printf(" hashes to: ");
		}
		hashed_sname = ldns_nsec3_hash_name(sname, algorithm, iterations, salt_length, salt);

		status = ldns_dname_cat(hashed_sname, zone_name);

		if (verbosity >= 3) {
			ldns_rdf_print(stdout, hashed_sname);
			printf("\n");
		}

		for (nsec_i = 0; nsec_i < ldns_rr_list_rr_count(nsec3s); nsec_i++) {
			nsec = ldns_rr_list_rr(nsec3s, nsec_i);
			
			/* check values of iterations etc! */
			
			/* exact match? */
			if (ldns_dname_compare(ldns_rr_owner(nsec), hashed_sname) == 0) {
				if (verbosity >= 4) {
					printf(";; exact match found\n");
				}
			 	exact_match_found = true;
			} else if (ldns_nsec_covers_name(nsec, hashed_sname)) {
				if (verbosity >= 4) {
					printf(";; in range of an nsec\n");
				}
				in_range_found = true;
			}
			
		}
		if (!exact_match_found && in_range_found) {
			flag = true;
		} else if (exact_match_found && flag) {
			result = ldns_rdf_clone(sname);
		} else if (exact_match_found && !flag) {
			// error!
			if (verbosity >= 4) {
				printf(";; the closest encloser is the same name (ie. this is an exact match, ie there is no closest encloser)\n");
			}
			ldns_rdf_deep_free(hashed_sname);
			goto done;
		} else {
			flag = false;
		}
		
		ldns_rdf_deep_free(hashed_sname);
		tmp = sname;
		sname = ldns_dname_left_chop(sname);
		ldns_rdf_deep_free(tmp);
	}

	done:
	LDNS_FREE(salt);
	ldns_rdf_deep_free(zone_name);
	ldns_rdf_deep_free(sname);

	if (!result) {
		if (verbosity >= 4) {
			printf(";; no closest encloser found\n");
		}
	}
	
	/* todo checks from end of 6.2. here or in caller? */
	return result;
}
int main(int argc, char **argv) {
    /* Local Vars */
    int             i;
    int             soa_valid = 0;
    int             ns_valid = 0;
    ldns_rdf        *rd_domain;
    ldns_rdf        *rd_trace;
    ldns_rdf        *rd_cdomain;
    ldns_pkt        *pkt;
    ldns_resolver   *res;
    ldns_rr         *rr;
    ldns_rr_list    *rrl;
    ldns_rr_list    *rrl_domain_soa;
    ldns_rr_list    *rrl_domain_soa_rrsig;
    ldns_rr_list    *rrl_domain_ns;
    ldns_rr_list    *rrl_domain_ns_rrsig;
    ldns_rr_list    *rrl_valid_keys;
    ldns_status	    status;

    /* Set signal handling and alarm */
    if (signal(SIGALRM, timeout_alarm_handler) == SIG_ERR)
        critical("Setup SIGALRM trap failed!");

    /* Process check arguments */
    if (process_arguments(argc, argv) != OK)
        unknown("Parsing arguments failed!");

    /* Start plugin timeout */
    alarm(mp_timeout);

    rd_domain = ldns_dname_new_frm_str(domainname);
    if (!rd_domain)
        unknown("Illegal domain name");

    rd_trace = ldns_dname_new_frm_str(domaintrace);
    if (!rd_trace)
        unknown("Illegal trace domain name");

    /* Check domain is subdomain from trace start */
    if (!ldns_dname_is_subdomain(rd_domain, rd_trace)) {
        ldns_rr_list_deep_free(trusted_keys);
        ldns_rdf_deep_free(rd_domain);
        ldns_rdf_deep_free(rd_trace);
        unknown("'%s' is not a subdomain of '%s'.", domainname,
                                                    domaintrace);
    }

    /* Add trusted keys for trace domain to rrl_valid_keys. */
    rrl_valid_keys = ldns_rr_list_new();
    for(i = 0; i < ldns_rr_list_rr_count(trusted_keys); i++) {
        rr = ldns_rr_list_rr(trusted_keys, i);
        if (ldns_dname_compare(ldns_rr_owner(rr),rd_trace) == 0)
            ldns_rr_list_push_rr(rrl_valid_keys, ldns_rr_clone(rr));
    }
    ldns_rr_list_deep_free(trusted_keys);

    if (ldns_rr_list_rr_count(rrl_valid_keys) == 0) {
        ldns_rdf_deep_free(rd_domain);
        ldns_rdf_deep_free(rd_trace);
        ldns_rr_list_deep_free(rrl_valid_keys);
        critical("No trusted key for trace start '%s'", domaintrace?domaintrace:".");
    }

    if (mp_verbose >= 2) {
        printf("--[ Trusted keys used ]-------------------------------------\n");
        ldns_rr_list_sort(rrl_valid_keys);
        ldns_rr_list_print(stdout, rrl_valid_keys);
        printf("------------------------------------------------------------\n");
    }

    /* create a new resolver with dns_server or server from /etc/resolv.conf */
    res = createResolver(hostname);
    if (!res) {
        ldns_rdf_deep_free(rd_domain);
        ldns_rdf_deep_free(rd_trace);
        ldns_rr_list_deep_free(rrl_valid_keys);
        unknown("Creating resolver failed.");
    }
    resolverEnableDnssec(res);
    ldns_resolver_set_dnssec_anchors(res, rrl_valid_keys);

    /* check domain exists */
    pkt = mp_ldns_resolver_query(res, rd_domain, LDNS_RR_TYPE_SOA,
                              LDNS_RR_CLASS_IN, LDNS_RD);

    if (pkt == NULL || ldns_pkt_get_rcode(pkt) != LDNS_RCODE_NOERROR) {
        ldns_rdf_deep_free(rd_domain);
        ldns_rdf_deep_free(rd_trace);
        ldns_resolver_deep_free(res);
        if (pkt && ldns_pkt_get_rcode(pkt) == LDNS_RCODE_NXDOMAIN) {
            ldns_pkt_free(pkt);
            critical("Domain '%s' don't exist.", domainname);
        }
        ldns_pkt_free(pkt);
        critical("Unable to get SOA for %s.", domainname);
    }

    rrl_domain_soa = ldns_pkt_rr_list_by_name_and_type(pkt, rd_domain,
                                                       LDNS_RR_TYPE_SOA,
                                                       LDNS_SECTION_ANSWER);

    if (rrl_domain_soa == NULL || ldns_rr_list_rr_count(rrl_domain_soa) == 0) {
        ldns_rdf_deep_free(rd_domain);
        ldns_rdf_deep_free(rd_trace);
        ldns_resolver_deep_free(res);
        ldns_pkt_free(pkt);
        critical("Domain '%s' not found.", domainname);
    }

    rrl_domain_soa_rrsig = ldns_dnssec_pkt_get_rrsigs_for_name_and_type(pkt,
                                rd_domain, LDNS_RR_TYPE_SOA);

    if (rrl_domain_soa_rrsig == NULL ||
        ldns_rr_list_rr_count(rrl_domain_soa_rrsig) == 0) {
        free(domaintrace);
        ldns_rdf_deep_free(rd_domain);
        ldns_rdf_deep_free(rd_trace);
        ldns_resolver_deep_free(res);
        ldns_pkt_free(pkt);
        ldns_rr_list_deep_free(rrl_domain_soa);
        critical("Domain '%s' not signed.", domainname);
    }

    ldns_pkt_free(pkt);
    pkt = ldns_resolver_query(res, rd_domain, LDNS_RR_TYPE_NS,
            LDNS_RR_CLASS_IN, LDNS_RD);

    rrl_domain_ns = ldns_pkt_rr_list_by_name_and_type(pkt, rd_domain,
                                                      LDNS_RR_TYPE_NS,
                                                      LDNS_SECTION_ANSWER);
    rrl_domain_ns_rrsig = ldns_dnssec_pkt_get_rrsigs_for_name_and_type(pkt,
                                                      rd_domain,
                                                      LDNS_RR_TYPE_NS);

    ldns_pkt_free(pkt);

    if (mp_verbose >= 2) {
        printf("--[ Checked Domain ]----------------------------------------\n");
        ldns_rr_list_print(stdout, rrl_domain_soa);
        printf("------------------------------------------------------------\n");
        ldns_rr_list_print(stdout, rrl_domain_soa_rrsig);
        printf("------------------------------------------------------------\n");
        ldns_rr_list_print(stdout, rrl_domain_ns);
        printf("------------------------------------------------------------\n");
        ldns_rr_list_print(stdout, rrl_domain_ns_rrsig);
        printf("------------------------------------------------------------\n");
    }


    /* create a new resolver with dns_server or server from /etc/resolv.conf */
    ldns_resolver_free(res);
    res = createResolver(resolver);
    if (!res) {
        ldns_rdf_deep_free(rd_domain);
        ldns_rdf_deep_free(rd_trace);
        ldns_rr_list_deep_free(rrl_valid_keys);
        unknown("Creating resolver failed.");
    }
    resolverEnableDnssec(res);
    ldns_resolver_set_dnssec_anchors(res, rrl_valid_keys);

    /* Fetch valid keys from top down */
    i = ldns_dname_label_count(rd_domain) - ldns_dname_label_count(rd_trace);
    for (; i>=0; i--) {
        rd_cdomain = ldns_dname_clone_from(rd_domain, i);
        if (mp_verbose) {
            char *str = ldns_rdf2str(rd_cdomain);
            printf("Trace: %s\n", str);
            free(str);
        }
        rrl = ldns_fetch_valid_domain_keys(res, rd_cdomain, rrl_valid_keys, &status);

        if (mp_verbose >= 2) {
            printf("--[ Valid Keys ]----------------------------------------\n");
            ldns_rr_list_sort(rrl);
            ldns_rr_list_print(stdout, rrl);
            printf("------------------------------------------------------------\n");
        }


        ldns_rr_list_cat(rrl_valid_keys, rrl);
        ldns_rr_list_free(rrl);

        ldns_rdf_deep_free(rd_cdomain);
    }

    ldns_rdf_deep_free(rd_trace);
    ldns_rdf_deep_free(rd_domain);

    /* Validate SOA */
    for(i = 0; i < ldns_rr_list_rr_count(rrl_domain_soa_rrsig); i++) {
        rr = ldns_rr_list_rr(rrl_domain_soa_rrsig, i);
        status = ldns_verify_rrsig_keylist(rrl_domain_soa, rr, rrl_valid_keys, NULL);
        if (status == LDNS_STATUS_OK)
            soa_valid++;
        else if (mp_verbose > 0)
            fprintf(stderr, "ldns_verify_rrsig_keylist SOA failed: %s\n",
                    ldns_get_errorstr_by_id(status));
    }

    ldns_rr_list_deep_free(rrl_domain_soa);
    ldns_rr_list_deep_free(rrl_domain_soa_rrsig);

    if (soa_valid == 0) {
        critical("No valid Signatur for SOA of '%s'", domainname);
        free(domainname);
        free(domaintrace);
        ldns_resolver_deep_free(res);
        ldns_rr_list_deep_free(rrl_domain_ns);
        ldns_rr_list_deep_free(rrl_domain_ns_rrsig);
        return checkState;
    }

    /* Validate NS */
    for(i = 0; i < ldns_rr_list_rr_count(rrl_domain_ns_rrsig); i++) {
        rr = ldns_rr_list_rr(rrl_domain_ns_rrsig, i);

        status = ldns_verify_rrsig_keylist(rrl_domain_ns, rr, rrl_valid_keys, NULL);
        if (status == LDNS_STATUS_OK)
            ns_valid++;
        else if (mp_verbose > 0)
            fprintf(stderr, "ldns_verify_rrsig_keylist NS failed: %s\n",
                    ldns_get_errorstr_by_id(status));
    }

    ldns_rr_list_deep_free(rrl_domain_ns);
    ldns_rr_list_deep_free(rrl_domain_ns_rrsig);
    ldns_resolver_deep_free(res);

    if (ns_valid == 0) {
        critical("No valid Signatur for NS of '%s'", domainname);
        free(domainname);
        free(domaintrace);
        return checkState;
    }

    ok("Trust for '%s' successfull traces from '%s'", domainname,
        domaintrace);
    free(domainname);
    free(domaintrace);
    return checkState;
}