Beispiel #1
0
void
drill_pkt_print_footer(FILE *fd, ldns_resolver *r, ldns_pkt *p)
{
	ldns_rr_list *hostnames;

	if (verbosity < 5) {
		return;
	}

	hostnames = ldns_get_rr_list_name_by_addr(r, ldns_pkt_answerfrom(p), 0, 0);

	fprintf(fd, ";; Received %d bytes from %s#%d(",
			(int) ldns_pkt_size(p),
			ldns_rdf2str(ldns_pkt_answerfrom(p)),
			(int) ldns_resolver_port(r));
	/* if we can resolve this print it, other print the ip again */
	if (hostnames) {
		ldns_rdf_print(fd,
				ldns_rr_rdf(ldns_rr_list_rr(hostnames, 0), 0));
		ldns_rr_list_deep_free(hostnames);
	} else {
		fprintf(fd, "%s", ldns_rdf2str(ldns_pkt_answerfrom(p)));
	}
	fprintf(fd, ") in %u ms\n\n", (unsigned int)ldns_pkt_querytime(p));
}
Beispiel #2
0
void
drill_pkt_print(FILE *fd, ldns_resolver *r, ldns_pkt *p)
{
	ldns_rr_list *new_nss;
	ldns_rr_list *hostnames;

	if (verbosity < 5) {
		return;
	}

	hostnames = ldns_get_rr_list_name_by_addr(r, ldns_pkt_answerfrom(p), 0, 0);

	new_nss = ldns_pkt_rr_list_by_type(p,
			LDNS_RR_TYPE_NS, LDNS_SECTION_ANSWER);
	ldns_rr_list_print(fd, new_nss);

	/* new_nss can be empty.... */

	fprintf(fd, ";; Received %d bytes from %s#%d(",
			(int) ldns_pkt_size(p),
			ldns_rdf2str(ldns_pkt_answerfrom(p)),
			(int) ldns_resolver_port(r));
	/* if we can resolve this print it, other print the ip again */
	if (hostnames) {
		ldns_rdf_print(fd,
				ldns_rr_rdf(ldns_rr_list_rr(hostnames, 0), 0));
		ldns_rr_list_deep_free(hostnames);
	} else {
		fprintf(fd, "%s", ldns_rdf2str(ldns_pkt_answerfrom(p)));
	}
	fprintf(fd, ") in %u ms\n\n", (unsigned int)ldns_pkt_querytime(p));
}
Beispiel #3
0
ldns_pkt *
ldns_resolver_search(const ldns_resolver *r,const  ldns_rdf *name, ldns_rr_type type, 
                ldns_rr_class c, uint16_t flags)
{

	char *str_dname;
	ldns_rdf *new_name;
	ldns_rdf **search_list;
	size_t i;
	ldns_pkt *p;

	str_dname = ldns_rdf2str(name);

	if (ldns_dname_str_absolute(str_dname)) {
		/* query as-is */
		return ldns_resolver_query(r, name, type, c, flags);
	} else {
		search_list = ldns_resolver_searchlist(r);
		for (i = 0; i < ldns_resolver_searchlist_count(r); i++) {
			new_name = ldns_dname_cat_clone(name, search_list[i]);

			p = ldns_resolver_query(r, new_name, type, c, flags);
			ldns_rdf_free(new_name);
			if (p) {
				return p;
			}
		}
	}
	return NULL;
}
static DCPluginSyncFilterResult
apply_block_ips(DCPluginDNSPacket *dcp_packet, Blocking * const blocking,
                ldns_pkt * const packet)
{
    StrList      *scanned;
    ldns_rr_list *answers;
    ldns_rr      *answer;
    char         *answer_str;
    ldns_rr_type  type;
    size_t        answers_count;
    size_t        i;

    answers = ldns_pkt_answer(packet);
    answers_count = ldns_rr_list_rr_count(answers);
    for (i = (size_t) 0U; i < answers_count; i++) {
        answer = ldns_rr_list_rr(answers, i);
        type = ldns_rr_get_type(answer);
        if (type != LDNS_RR_TYPE_A && type != LDNS_RR_TYPE_AAAA) {
            continue;
        }
        if ((answer_str = ldns_rdf2str(ldns_rr_a_address(answer))) == NULL) {
            return DCP_SYNC_FILTER_RESULT_FATAL;
        }
        scanned = blocking->ips;
        do {
            if (strcasecmp(scanned->str, answer_str) == 0) {
                LDNS_RCODE_SET(dcplugin_get_wire_data(dcp_packet),
                               LDNS_RCODE_REFUSED);
                break;
            }
        } while ((scanned = scanned->next) != NULL);
        free(answer_str);
    }
    return DCP_SYNC_FILTER_RESULT_OK;
}
static DCPluginSyncFilterResult
apply_block_domains(DCPluginDNSPacket *dcp_packet, Blocking * const blocking,
                    ldns_pkt * const packet)
{
    StrList  *scanned;
    ldns_rr  *question;
    char     *owner_str;
    size_t    owner_str_len;

    scanned = blocking->domains;
    question = ldns_rr_list_rr(ldns_pkt_question(packet), 0U);
    if ((owner_str = ldns_rdf2str(ldns_rr_owner(question))) == NULL) {
        return DCP_SYNC_FILTER_RESULT_FATAL;
    }
    owner_str_len = strlen(owner_str);
    if (owner_str_len > (size_t) 1U && owner_str[--owner_str_len] == '.') {
        owner_str[owner_str_len] = 0;
    }
    do {
        if (wildcard_match(owner_str, scanned->str)) {
            LDNS_RCODE_SET(dcplugin_get_wire_data(dcp_packet),
                           LDNS_RCODE_REFUSED);
            break;
        }
    } while ((scanned = scanned->next) != NULL);
    free(owner_str);

    return DCP_SYNC_FILTER_RESULT_OK;
}
Beispiel #6
0
/** dump message to rrset reference */
static int
dump_msg_ref(SSL* ssl, struct ub_packed_rrset_key* k)
{
	ldns_rdf* rdf;
	ldns_status status;
	size_t pos;
	char* nm, *tp, *cl;

	pos = 0;
	status = ldns_wire2dname(&rdf, k->rk.dname, k->rk.dname_len, &pos);
	if(status != LDNS_STATUS_OK) {
		return ssl_printf(ssl, "BADREF\n");
	}
	nm = ldns_rdf2str(rdf);
	ldns_rdf_deep_free(rdf);
	tp = ldns_rr_type2str(ntohs(k->rk.type));
	cl = ldns_rr_class2str(ntohs(k->rk.rrset_class));
	if(!nm || !cl || !tp) {
		free(nm);
		free(tp);
		free(cl);
		return ssl_printf(ssl, "BADREF\n");
	}
	if(!ssl_printf(ssl, "%s %s %s %d\n", nm, cl, tp, (int)k->rk.flags)) {
		free(nm);
		free(tp);
		free(cl);
		return 0;
	}
	free(nm);
	free(tp);
	free(cl);

	return 1;
}
Beispiel #7
0
ldns_pkt *mp_ldns_resolver_query(const ldns_resolver *r, const ldns_rdf *name, ldns_rr_type t, ldns_rr_class c, uint16_t flags) {
    if (mp_verbose >= 3) {
        printf("--[ Query ]-------------------------------------------------\n");
        printf("Name:  %s\n", ldns_rdf2str(name));
        printf("Type:  %s\n", ldns_rr_type2str(t));
        printf("Class: %s\n", ldns_rr_class2str(c));
        printf("------------------------------------------------------------\n");
    }
    return ldns_resolver_query(r, name, t, c, flags);
}
Beispiel #8
0
getdns_return_t
getdns_convert_dns_name_to_fqdn(
    const struct getdns_bindata *dns_name_wire_fmt, char **fqdn_as_string)
{
    ldns_rdf *rdf = ldns_rdf_new(LDNS_RDF_TYPE_DNAME,
                                 dns_name_wire_fmt->size,
                                 (void *)dns_name_wire_fmt->data); /* unconst is safe here */
    if (!rdf) return GETDNS_RETURN_MEMORY_ERROR;
    *fqdn_as_string = ldns_rdf2str(rdf);
    ldns_rdf_free(rdf);
    return *fqdn_as_string ? GETDNS_RETURN_GOOD
           : GETDNS_RETURN_GENERIC_ERROR;
}
Beispiel #9
0
/**
 * Lookup zone by dname.
 *
 */
zone_type*
zonelist_lookup_zone_by_dname(zonelist_type* zonelist, ldns_rdf* dname,
                              ldns_rr_class klass)
{
    char* name = NULL;
    zone_type* result = NULL;
    if (zonelist && zonelist->zones && dname && klass) {
        name = ldns_rdf2str(dname);
        result = zonelist_lookup_zone_by_name(zonelist, name, klass);
        free((void*)name);
    }
    return result;
}
Beispiel #10
0
static ldns_status
ldns_tsig_mac_new(ldns_rdf **tsig_mac, uint8_t *pkt_wire, size_t pkt_wire_size,
		const char *key_data, ldns_rdf *key_name_rdf, ldns_rdf *fudge_rdf,
		ldns_rdf *algorithm_rdf, ldns_rdf *time_signed_rdf, ldns_rdf *error_rdf,
		ldns_rdf *other_data_rdf, ldns_rdf *orig_mac_rdf, int tsig_timers_only)
{
	ldns_status status;
	char *wireformat;
	int wiresize;
	unsigned char *mac_bytes = NULL;
	unsigned char *key_bytes = NULL;
	int key_size;
	const EVP_MD *digester;
	char *algorithm_name = NULL;
	unsigned int md_len = EVP_MAX_MD_SIZE;
	ldns_rdf *result = NULL;
	ldns_buffer *data_buffer = NULL;
	ldns_rdf *canonical_key_name_rdf = NULL;
	ldns_rdf *canonical_algorithm_rdf = NULL;
	
	if (key_name_rdf == NULL || algorithm_rdf == NULL) {
		return LDNS_STATUS_NULL;
	}
	canonical_key_name_rdf  = ldns_rdf_clone(key_name_rdf);
	if (canonical_key_name_rdf == NULL) {
		return LDNS_STATUS_MEM_ERR;
	}
	canonical_algorithm_rdf = ldns_rdf_clone(algorithm_rdf);
	if (canonical_algorithm_rdf == NULL) {
		ldns_rdf_deep_free(canonical_key_name_rdf);
		return LDNS_STATUS_MEM_ERR;
	}
	/*
	 * prepare the digestable information
	 */
	data_buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
	if (!data_buffer) {
		status = LDNS_STATUS_MEM_ERR;
		goto clean;
	}
	/* if orig_mac is not NULL, add it too */
	if (orig_mac_rdf) {
		(void) ldns_rdf2buffer_wire(data_buffer, orig_mac_rdf);
 	}
	ldns_buffer_write(data_buffer, pkt_wire, pkt_wire_size);
	if (!tsig_timers_only) {
		ldns_dname2canonical(canonical_key_name_rdf);
		(void)ldns_rdf2buffer_wire(data_buffer, 
				canonical_key_name_rdf);
		ldns_buffer_write_u16(data_buffer, LDNS_RR_CLASS_ANY);
		ldns_buffer_write_u32(data_buffer, 0);
		ldns_dname2canonical(canonical_algorithm_rdf);
		(void)ldns_rdf2buffer_wire(data_buffer, 
				canonical_algorithm_rdf);
	}
	(void)ldns_rdf2buffer_wire(data_buffer, time_signed_rdf);
	(void)ldns_rdf2buffer_wire(data_buffer, fudge_rdf);
	if (!tsig_timers_only) {
		(void)ldns_rdf2buffer_wire(data_buffer, error_rdf);
		(void)ldns_rdf2buffer_wire(data_buffer, other_data_rdf);
	}

	wireformat = (char *) data_buffer->_data;
	wiresize = (int) ldns_buffer_position(data_buffer);

	algorithm_name = ldns_rdf2str(algorithm_rdf);
	if(!algorithm_name) {
		status = LDNS_STATUS_MEM_ERR;
		goto clean;
	}

	/* prepare the key */
	key_bytes = LDNS_XMALLOC(unsigned char,
			ldns_b64_pton_calculate_size(strlen(key_data)));
	if(!key_bytes) {
		status = LDNS_STATUS_MEM_ERR;
		goto clean;
	}
	key_size = ldns_b64_pton(key_data, key_bytes,
	ldns_b64_pton_calculate_size(strlen(key_data)));
	if (key_size < 0) {
		status = LDNS_STATUS_INVALID_B64;
		goto clean;
	}
	/* hmac it */
	/* 2 spare bytes for the length */
	mac_bytes = LDNS_XMALLOC(unsigned char, md_len+2);
	if(!mac_bytes) {
		status = LDNS_STATUS_MEM_ERR;
		goto clean;
	}
	memset(mac_bytes, 0, md_len+2);

	digester = ldns_digest_function(algorithm_name);

	if (digester) {
		(void) HMAC(digester, key_bytes, key_size, (void *)wireformat,
		            (size_t) wiresize, mac_bytes + 2, &md_len);

		ldns_write_uint16(mac_bytes, md_len);
		result = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_INT16_DATA, md_len + 2,
				mac_bytes);
	} else {
		status = LDNS_STATUS_CRYPTO_UNKNOWN_ALGO;
		goto clean;
	}
	*tsig_mac = result;
	status = LDNS_STATUS_OK;
  clean:
	LDNS_FREE(mac_bytes);
	LDNS_FREE(key_bytes);
	LDNS_FREE(algorithm_name);
	ldns_buffer_free(data_buffer);
	ldns_rdf_deep_free(canonical_algorithm_rdf);
	ldns_rdf_deep_free(canonical_key_name_rdf);
	return status;
}
int
main(int argc, char *argv[])
{
	ldns_resolver *res;
	ldns_rdf *ns;
	ldns_rdf *domain;
	ldns_rr_list *l = NULL;

	ldns_rr_list *dns_root = NULL;
	const char *root_file = "/etc/named.root";

	ldns_status status;
	
	int i;

	char *domain_str;
	char *outputfile_str;
	ldns_buffer *outputfile_buffer;
	FILE *outputfile;
	ldns_rr *k;
	
	bool insecure = false;
	ldns_pkt *pkt;

	domain = NULL;
	res = NULL;

	if (argc < 2) {
		usage(stdout, argv[0]);
		exit(EXIT_FAILURE);
	} else {
		for (i = 1; i < argc; i++) {
			if (strncmp("-4", argv[i], 3) == 0) {
				if (address_family != 0) {
					fprintf(stderr, "Options -4 and -6 cannot be specified at the same time\n");
					exit(EXIT_FAILURE);
				}
				address_family = 1;
			} else if (strncmp("-6", argv[i], 3) == 0) {
				if (address_family != 0) {
					fprintf(stderr, "Options -4 and -6 cannot be specified at the same time\n");
					exit(EXIT_FAILURE);
				}
				address_family = 2;
			} else if (strncmp("-h", argv[i], 3) == 0) {
				usage(stdout, argv[0]);
				exit(EXIT_SUCCESS);
			} else if (strncmp("-i", argv[i], 2) == 0) {
				insecure = true;
			} else if (strncmp("-r", argv[i], 2) == 0) {
				if (strlen(argv[i]) > 2) {
					root_file = argv[i]+2;
				} else if (i+1 >= argc) {
					usage(stdout, argv[0]);
					exit(EXIT_FAILURE);
				} else {
					root_file = argv[i+1];
					i++;
				}
			} else if (strncmp("-s", argv[i], 3) == 0) {
				store_in_file = true;
			} else if (strncmp("-v", argv[i], 2) == 0) {
				if (strlen(argv[i]) > 2) {
					verbosity = atoi(argv[i]+2);
				} else if (i+1 > argc) {
					usage(stdout, argv[0]);
					exit(EXIT_FAILURE);
				} else {
					verbosity = atoi(argv[i+1]);
					i++;
				}
			} else {
				/* create a rdf from the command line arg */
				if (domain) {
					fprintf(stdout, "You can only specify one domain at a time\n");
					exit(EXIT_FAILURE);
				}

				domain = ldns_dname_new_frm_str(argv[i]);
			}

		}
		if (!domain) {
			usage(stdout, argv[0]);
			exit(EXIT_FAILURE);
		}
	}

	dns_root = read_root_hints(root_file);
	if (!dns_root) {
		fprintf(stderr, "cannot read the root hints file\n");
		exit(EXIT_FAILURE);
	}

	/* create a new resolver from /etc/resolv.conf */
	status = ldns_resolver_new_frm_file(&res, NULL);

	if (status != LDNS_STATUS_OK) {
		fprintf(stderr, "Warning: Unable to create stub resolver from /etc/resolv.conf:\n");
		fprintf(stderr, "%s\n", ldns_get_errorstr_by_id(status));
		fprintf(stderr, "defaulting to nameserver at 127.0.0.1 for separate nameserver name lookups\n");
		res = ldns_resolver_new();
		ns = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_A, "127.0.0.1");
		status = ldns_resolver_push_nameserver(res, ns);
		if (status != LDNS_STATUS_OK) {
			fprintf(stderr, "Unable to create stub resolver: %s\n", ldns_get_errorstr_by_id(status));
			exit(EXIT_FAILURE);
		}
		ldns_rdf_deep_free(ns);
	}

	ldns_resolver_set_ip6(res, address_family);

	if (insecure) {
		pkt = ldns_resolver_query(res, domain, LDNS_RR_TYPE_DNSKEY, LDNS_RR_CLASS_IN, LDNS_RD);
		if (pkt) {
		l = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_DNSKEY, LDNS_SECTION_ANY_NOQUESTION);
		}
	} else {
		l = retrieve_dnskeys(res, domain, LDNS_RR_TYPE_DNSKEY, LDNS_RR_CLASS_IN, dns_root);
	}
	
	/* separator for result data and verbosity data */
	if (verbosity > 0) {
		fprintf(stdout, "; ---------------------------\n");
		fprintf(stdout, "; Got the following keys:\n");
	}
	if (l) {
		if (store_in_file) {
			/* create filename:
			 * K<domain>.+<alg>.+<id>.key
			 */
			for (i = 0; (size_t) i < ldns_rr_list_rr_count(l); i++) {
				k = ldns_rr_list_rr(l, (size_t) i);
				
				outputfile_buffer = ldns_buffer_new(300);
				domain_str = ldns_rdf2str(ldns_rr_owner(k));
				ldns_buffer_printf(outputfile_buffer, "K%s+%03u+%05u.key", domain_str, ldns_rdf2native_int8(ldns_rr_rdf(k, 2)),
					(unsigned int) ldns_calc_keytag(k));
				outputfile_str = ldns_buffer_export(outputfile_buffer);
				
				if (verbosity >= 1) {
					fprintf(stdout, "Writing key to file %s\n", outputfile_str);
				}
				
				outputfile = fopen(outputfile_str, "w");
				if (!outputfile) {
					fprintf(stderr, "Error writing key to file %s: %s\n", outputfile_str, strerror(errno));
				} else {
					ldns_rr_print(outputfile, k);
					fclose(outputfile);
				}
				
				LDNS_FREE(domain_str);
				LDNS_FREE(outputfile_str);
				LDNS_FREE(outputfile_buffer);
			}
		} else {
			ldns_rr_list_print(stdout, l);
		}
	} else {
		fprintf(stderr, "no answer packet received, stub resolver config:\n");
		ldns_resolver_print(stderr, res);
	}
	printf("\n");

	ldns_rdf_deep_free(domain);
	ldns_resolver_deep_free(res);
	ldns_rr_list_deep_free(l);
	ldns_rr_list_deep_free(dns_root);
	return EXIT_SUCCESS;
}
Beispiel #12
0
/**
 * Process RR.
 *
 */
static ods_status
adapi_process_rr(zone_type* zone, ldns_rr* rr, int add, int backup)
{
    ods_status status = ODS_STATUS_OK;
    uint32_t tmp = 0;
    ods_log_assert(rr);
    ods_log_assert(zone);
    ods_log_assert(zone->name);
    ods_log_assert(zone->db);
    ods_log_assert(zone->signconf);
    /* We only support IN class */
    if (ldns_rr_get_class(rr) != LDNS_RR_CLASS_IN) {
        ods_log_warning("[%s] only class in is supported, changing class "
            "to in", adapi_str);
        ldns_rr_set_class(rr, LDNS_RR_CLASS_IN);
    }
    /* RR processing */
    if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) {
        if (ldns_dname_compare(ldns_rr_owner(rr), zone->apex)) {
            ods_log_error("[%s] unable to %s rr to zone: soa record has "
                "invalid owner name", adapi_str, add?"add":"delete");
            return ODS_STATUS_ERR;
        }
        status = adapi_process_soa(zone, rr, add, backup);
        if (status != ODS_STATUS_OK) {
            ods_log_error("[%s] unable to %s rr: failed to process soa "
                "record", adapi_str, add?"add":"delete");
            return status;
        }
    } else {
        if (ldns_dname_compare(ldns_rr_owner(rr), zone->apex) &&
            !ldns_dname_is_subdomain(ldns_rr_owner(rr), zone->apex)) {
            ods_log_warning("[%s] zone %s contains out-of-zone data, "
                "skipping", adapi_str, zone->name);
            return ODS_STATUS_UNCHANGED;
        } else if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_DNSKEY) {
            adapi_process_dnskey(zone, rr);
        } else if (util_is_dnssec_rr(rr) && !backup) {
            ods_log_warning("[%s] zone %s contains dnssec data (type=%u), "
                "skipping", adapi_str, zone->name,
                (unsigned) ldns_rr_get_type(rr));
            return ODS_STATUS_UNCHANGED;
        } else if (zone->signconf->max_zone_ttl) {
            /* Convert MaxZoneTTL */
            tmp = (uint32_t) duration2time(zone->signconf->max_zone_ttl);
        }
    }
    /* //MaxZoneTTL. Only set for RRtype != SOA && RRtype != DNSKEY */
    if (tmp && tmp < ldns_rr_ttl(rr)) {
        char* str = ldns_rdf2str(ldns_rr_owner(rr));
        if (str) {
            size_t i = 0;
            str[(strlen(str))-1] = '\0';
            /* replace tabs with white space */
            for (i=0; i < strlen(str); i++) {
                if (str[i] == '\t') {
                    str[i] = ' ';
                }
            }
            ods_log_debug("[%s] capping ttl %u to MaxZoneTTL %u for rrset "
                "<%s,%s>", adapi_str, ldns_rr_ttl(rr), tmp, str,
                rrset_type2str(ldns_rr_get_type(rr)));
        }
        ldns_rr_set_ttl(rr, tmp);
    }

    /* TODO: DNAME and CNAME checks */
    /* TODO: NS and DS checks */

    if (add) {
        return zone_add_rr(zone, rr, 1);
    } else {
        return zone_del_rr(zone, rr, 1);
    }
    /* not reached */
    return ODS_STATUS_ERR;
}
Beispiel #13
0
/** dump message entry */
static int
dump_msg(SSL* ssl, struct query_info* k, struct reply_info* d, 
	uint32_t now)
{
	size_t i;
	char* nm, *tp, *cl;
	ldns_rdf* rdf;
	ldns_status status;
	size_t pos;
	if(!k || !d) return 1;
	if(d->ttl < now) return 1; /* expired */
	
	pos = 0;
	status = ldns_wire2dname(&rdf, k->qname, k->qname_len, &pos);
	if(status != LDNS_STATUS_OK) {
		return 1; /* skip this entry */
	}
	nm = ldns_rdf2str(rdf);
	ldns_rdf_deep_free(rdf);
	tp = ldns_rr_type2str(k->qtype);
	cl = ldns_rr_class2str(k->qclass);
	if(!nm || !tp || !cl) {
		free(nm);
		free(tp);
		free(cl);
		return 1; /* skip this entry */
	}
	if(!rrset_array_lock(d->ref, d->rrset_count, now)) {
		/* rrsets have timed out or do not exist */
		free(nm);
		free(tp);
		free(cl);
		return 1; /* skip this entry */
	}
	
	/* meta line */
	if(!ssl_printf(ssl, "msg %s %s %s %d %d %u %d %u %u %u\n",
			nm, cl, tp,
			(int)d->flags, (int)d->qdcount, 
			(unsigned)(d->ttl-now), (int)d->security,
			(unsigned)d->an_numrrsets, 
			(unsigned)d->ns_numrrsets,
			(unsigned)d->ar_numrrsets)) {
		free(nm);
		free(tp);
		free(cl);
		rrset_array_unlock(d->ref, d->rrset_count);
		return 0;
	}
	free(nm);
	free(tp);
	free(cl);
	
	for(i=0; i<d->rrset_count; i++) {
		if(!dump_msg_ref(ssl, d->rrsets[i])) {
			rrset_array_unlock(d->ref, d->rrset_count);
			return 0;
		}
	}
	rrset_array_unlock(d->ref, d->rrset_count);

	return 1;
}
Beispiel #14
0
void massdns_handle_packet(ldns_pkt *packet, struct sockaddr_storage ns, void *ctx)
{
    if (!packet || ldns_pkt_qdcount(packet) != 1)
    {
        return;
    }
    struct timeval now;
    gettimeofday(&now, NULL);
    lookup_context_t *context = (lookup_context_t *) ctx;
    ldns_pkt_rcode response_code = ldns_pkt_get_rcode(packet);
    ldns_rr_list l = ldns_pkt_question(packet)[0];
    ldns_rr *question = ldns_rr_list_rr(&l, 0);
    ldns_rdf* owner = ldns_rr_owner(question);
    char* name = ldns_rdf2str(owner);
    size_t name_len = strlen(name);
    if(name_len > 0 && name[name_len - 1] == '.')
    {
        name[name_len - 1] = 0;
    }
    lookup_t *lookup = hashmapGet(context->map, name);
    free(name);
    if (lookup == NULL)
    {
        return;
    }
    if (response_code == LDNS_RCODE_NOERROR || response_code == LDNS_RCODE_NXDOMAIN ||
        lookup->tries == context->cmd_args.resolve_count)
    {
        switch (response_code)
        {
            case LDNS_RCODE_NOERROR:
                stats.noerr++;
                break;
            case LDNS_RCODE_FORMERR:
                stats.formerr++;
                break;
            case LDNS_RCODE_SERVFAIL:
                stats.servfail++;
                break;
            case LDNS_RCODE_NXDOMAIN:
                stats.nxdomain++;
                break;
            case LDNS_RCODE_NOTIMPL:
                stats.notimp++;
                break;
            case LDNS_RCODE_REFUSED:
                stats.refused++;
                break;
            default:
                stats.other++;
                break;
        }
        context->current_rate++;
        ldns_buffer *buf = ldns_buffer_new(LDNS_MAX_PACKETLEN);
        if(buf == NULL)
        {
            abort();
        }
        if(LDNS_STATUS_OK != output_packet(buf, packet, ns, context))
        {
            abort();
        }
        char* packetstr = ldns_buffer_export2str(buf);
        if(packetstr == NULL)
        {
            abort();
        }
        fprintf(stdout, "%s", packetstr);
        free(packetstr);
        if (timediff(&now, &context->next_update) <= 0)
        {
            print_stats(context);
        }
        ldns_buffer_free(buf);
        hashmapRemove(context->map, lookup->domain);
        free(lookup->domain);
        free(lookup);
    }
}
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;
}