Пример #1
0
/** setup qinfo and edns */
static int
setup_qinfo_edns(struct libworker* w, struct ctx_query* q, 
	struct query_info* qinfo, struct edns_data* edns)
{
	ldns_rdf* rdf;
	qinfo->qtype = (uint16_t)q->res->qtype;
	qinfo->qclass = (uint16_t)q->res->qclass;
	rdf = ldns_dname_new_frm_str(q->res->qname);
	if(!rdf) {
		return 0;
	}
#ifdef UNBOUND_ALLOC_LITE
	qinfo->qname = memdup(ldns_rdf_data(rdf), ldns_rdf_size(rdf));
	qinfo->qname_len = ldns_rdf_size(rdf);
	ldns_rdf_deep_free(rdf);
	rdf = 0;
#else
	qinfo->qname = ldns_rdf_data(rdf);
	qinfo->qname_len = ldns_rdf_size(rdf);
#endif
	edns->edns_present = 1;
	edns->ext_rcode = 0;
	edns->edns_version = 0;
	edns->bits = EDNS_DO;
	if(ldns_buffer_capacity(w->back->udp_buff) < 65535)
		edns->udp_size = (uint16_t)ldns_buffer_capacity(
			w->back->udp_buff);
	else	edns->udp_size = 65535;
	ldns_rdf_free(rdf);
	return 1;
}
Пример #2
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;
}
Пример #3
0
static int
l_rdf_free(lua_State *L)
{
	ldns_rdf *tofree = (ldns_rdf*)lua_touserdata(L, 1); /* pop from the stack */
	if (!tofree) {
		return 0;
	}
	ldns_rdf_free(tofree);
	return 0;
}
Пример #4
0
ldns_pkt *
ldns_resolver_query(const ldns_resolver *r, const ldns_rdf *name, ldns_rr_type type, 
		ldns_rr_class c, uint16_t flags)
{
	ldns_rdf *newname;
	ldns_pkt *pkt;
	ldns_status status;

	pkt = NULL;

	if (!ldns_resolver_defnames(r)) {
		status = ldns_resolver_send(&pkt, (ldns_resolver *)r, name, type, c, 
				flags);
		if (status == LDNS_STATUS_OK) {
			return pkt;
		} else {
			if (pkt) {
				ldns_pkt_free(pkt);
			}
			fprintf(stderr, "error: %s\n", ldns_get_errorstr_by_id(status));
			return NULL;
		}
	}

	if (!ldns_resolver_domain(r)) {
		/* _defnames is set, but the domain is not....?? */
		status = ldns_resolver_send(&pkt, (ldns_resolver *)r, name, type, c, 
				flags);
		if (status == LDNS_STATUS_OK) {
			return pkt;
		} else {
			if (pkt) {
				ldns_pkt_free(pkt);
			}
			return NULL;
		}
	}

	newname = ldns_dname_cat_clone((const ldns_rdf*)name, ldns_resolver_domain(r));
	if (!newname) {
		if (pkt) {
			ldns_pkt_free(pkt);
		}
		return NULL;
	}
	status = ldns_resolver_send(&pkt, (ldns_resolver *)r, newname, type, c, 
			flags);

	ldns_rdf_free(newname);

	return pkt;
}
Пример #5
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;
}
Пример #6
0
getdns_return_t
getdns_convert_fqdn_to_dns_name(
    const char *fqdn_as_string, struct getdns_bindata **dns_name_wire_fmt)
{
    ldns_rdf *rdf;
    if (ldns_str2rdf_dname(&rdf, fqdn_as_string) != LDNS_STATUS_OK)
        return GETDNS_RETURN_GENERIC_ERROR;;
    *dns_name_wire_fmt = malloc(sizeof(struct getdns_bindata));
    if (*dns_name_wire_fmt) {
        (*dns_name_wire_fmt)->size = ldns_rdf_size(rdf);
        (*dns_name_wire_fmt)->data = ldns_rdf_data(rdf);
    }
    ldns_rdf_free(rdf);
    return *dns_name_wire_fmt ? GETDNS_RETURN_GOOD
           : GETDNS_RETURN_MEMORY_ERROR;
}
Пример #7
0
/** parse ORIGIN */
static void 
get_origin(const char* name, int lineno, ldns_rdf** origin, char* parse)
{
	/* snip off rest of the text so as to make the parse work in ldns */
	char* end;
	char store;
	ldns_status status;

	ldns_rdf_free(*origin);
	*origin = NULL;

	end=parse;
	while(!isspace((int)*end) && !isendline(*end))
		end++;
	store = *end;
	*end = 0;
	verbose(3, "parsing '%s'\n", parse);
	status = ldns_str2rdf_dname(origin, parse);
	*end = store;
	if (status != LDNS_STATUS_OK)
		error("%s line %d:\n\t%s: %s", name, lineno,
		ldns_get_errorstr_by_id(status), parse);
}
Пример #8
0
void
check_cover(ldns_rr_list *list, ldns_rdf *qname)
{
	ldns_status status;
	size_t i;
	if(check_done(qname))
		return;
	for(i=0; i<ldns_rr_list_rr_count(list); ++i)
	{
		ldns_rr* nsec3 = ldns_rr_list_rr(list, i);
		if(ldns_rr_get_type(nsec3) != LDNS_RR_TYPE_NSEC3) {
			/* skip non nsec3 */
			continue;
		}
		ldns_rdf* hashed = ldns_nsec3_hash_name_frm_nsec3(
			nsec3, qname);
		status = ldns_dname_cat(hashed, ldns_dname_left_chop(
			ldns_rr_owner(nsec3)));
		if(status != LDNS_STATUS_OK)
			abort_ldns_error("ldns_dname_cat", status);

		if(ldns_dname_compare(hashed, ldns_rr_owner(nsec3)) == 0) {
			ldns_rdf_print(stdout, ldns_rr_owner(nsec3));
			printf(" proves ");
			ldns_rdf_print(stdout, qname);
			printf(" exists.\n");
		}
		else if(ldns_nsec_covers_name(nsec3, hashed)) {
			ldns_rdf_print(stdout, ldns_rr_owner(nsec3));
			printf(" proves ");
			ldns_rdf_print(stdout, qname);
			printf(" does not exist.\n");
		}
		ldns_rdf_free(hashed);
	}
}
Пример #9
0
ldns_status
ldns_pkt_tsig_sign_next(ldns_pkt *pkt, const char *key_name, const char *key_data,
	uint16_t fudge, const char *algorithm_name, ldns_rdf *query_mac, int tsig_timers_only)
{
	ldns_rr *tsig_rr;
	ldns_rdf *key_name_rdf = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, key_name);
	ldns_rdf *fudge_rdf = NULL;
	ldns_rdf *orig_id_rdf = NULL;
	ldns_rdf *algorithm_rdf;
	ldns_rdf *error_rdf = NULL;
	ldns_rdf *mac_rdf = NULL;
	ldns_rdf *other_data_rdf = NULL;

	ldns_status status = LDNS_STATUS_OK;

	uint8_t *pkt_wire = NULL;
	size_t pkt_wire_len;

	struct timeval tv_time_signed;
	uint8_t *time_signed = NULL;
	ldns_rdf *time_signed_rdf = NULL;

	algorithm_rdf = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, algorithm_name);
	if(!key_name_rdf || !algorithm_rdf) {
		status = LDNS_STATUS_MEM_ERR;
		goto clean;
	}

	/* eww don't have create tsigtime rdf yet :( */
	/* bleh :p */
	if (gettimeofday(&tv_time_signed, NULL) == 0) {
		time_signed = LDNS_XMALLOC(uint8_t, 6);
		if(!time_signed) {
			status = LDNS_STATUS_MEM_ERR;
			goto clean;
		}
		ldns_write_uint64_as_uint48(time_signed,
				(uint64_t)tv_time_signed.tv_sec);
	} else {
		status = LDNS_STATUS_INTERNAL_ERR;
		goto clean;
	}

	time_signed_rdf = ldns_rdf_new(LDNS_RDF_TYPE_TSIGTIME, 6, time_signed);
	if(!time_signed_rdf) {
		LDNS_FREE(time_signed);
		status = LDNS_STATUS_MEM_ERR;
		goto clean;
	}

	fudge_rdf = ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16, fudge);

	orig_id_rdf = ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16, ldns_pkt_id(pkt));

	error_rdf = ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16, 0);

	other_data_rdf = ldns_native2rdf_int16_data(0, NULL);

	if(!fudge_rdf || !orig_id_rdf || !error_rdf || !other_data_rdf) {
		status = LDNS_STATUS_MEM_ERR;
		goto clean;
	}

	if (ldns_pkt2wire(&pkt_wire, pkt, &pkt_wire_len) != LDNS_STATUS_OK) {
		status = LDNS_STATUS_ERR;
		goto clean;
	}

	status = ldns_tsig_mac_new(&mac_rdf, pkt_wire, pkt_wire_len,
			key_data, key_name_rdf, fudge_rdf, algorithm_rdf,
			time_signed_rdf, error_rdf, other_data_rdf, query_mac, tsig_timers_only);

	if (!mac_rdf) {
		goto clean;
	}

	LDNS_FREE(pkt_wire);

	/* Create the TSIG RR */
	tsig_rr = ldns_rr_new();
	if(!tsig_rr) {
		status = LDNS_STATUS_MEM_ERR;
		goto clean;
	}
	ldns_rr_set_owner(tsig_rr, key_name_rdf);
	ldns_rr_set_class(tsig_rr, LDNS_RR_CLASS_ANY);
	ldns_rr_set_type(tsig_rr, LDNS_RR_TYPE_TSIG);
	ldns_rr_set_ttl(tsig_rr, 0);

	ldns_rr_push_rdf(tsig_rr, algorithm_rdf);
	ldns_rr_push_rdf(tsig_rr, time_signed_rdf);
	ldns_rr_push_rdf(tsig_rr, fudge_rdf);
	ldns_rr_push_rdf(tsig_rr, mac_rdf);
	ldns_rr_push_rdf(tsig_rr, orig_id_rdf);
	ldns_rr_push_rdf(tsig_rr, error_rdf);
	ldns_rr_push_rdf(tsig_rr, other_data_rdf);

	ldns_pkt_set_tsig(pkt, tsig_rr);

	return status;

  clean:
	LDNS_FREE(pkt_wire);
	ldns_rdf_free(key_name_rdf);
	ldns_rdf_free(algorithm_rdf);
	ldns_rdf_free(time_signed_rdf);
	ldns_rdf_free(fudge_rdf);
	ldns_rdf_free(orig_id_rdf);
	ldns_rdf_free(error_rdf);
	ldns_rdf_free(other_data_rdf);
	return status;
}
Пример #10
0
/**
 * use this function to sign with a public/private key alg
 * return the created signatures
 */
ldns_rr_list *
ldns_sign_public(ldns_rr_list *rrset, ldns_key_list *keys)
{
	ldns_rr_list *signatures;
	ldns_rr_list *rrset_clone;
	ldns_rr *current_sig;
	ldns_rdf *b64rdf;
	ldns_key *current_key;
	size_t key_count;
	uint16_t i;
	ldns_buffer *sign_buf;
	ldns_rdf *new_owner;

	if (!rrset || ldns_rr_list_rr_count(rrset) < 1 || !keys) {
		return NULL;
	}
	
	new_owner = NULL;

	key_count = 0;
	signatures = ldns_rr_list_new();

	/* prepare a signature and add all the know data
	 * prepare the rrset. Sign this together.  */
	rrset_clone = ldns_rr_list_clone(rrset);
	if (!rrset_clone) {
		return NULL;
	}

	/* make it canonical */
	for(i = 0; i < ldns_rr_list_rr_count(rrset_clone); i++) {
		ldns_rr2canonical(ldns_rr_list_rr(rrset_clone, i));
	}
	/* sort */
	ldns_rr_list_sort(rrset_clone);
	
	for (key_count = 0;
		key_count < ldns_key_list_key_count(keys);
		key_count++) {
		if (!ldns_key_use(ldns_key_list_key(keys, key_count))) {
			continue;
		}
		sign_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN);
		if (!sign_buf) {
			ldns_rr_list_free(rrset_clone);
			ldns_rr_list_free(signatures);
			ldns_rdf_free(new_owner);
			return NULL;
		}
		b64rdf = NULL;

		current_key = ldns_key_list_key(keys, key_count);
		/* sign all RRs with keys that have ZSKbit, !SEPbit.
		   sign DNSKEY RRs with keys that have ZSKbit&SEPbit */
		if (
		    ldns_key_flags(current_key) & LDNS_KEY_ZONE_KEY &&
		    (!(ldns_key_flags(current_key) & LDNS_KEY_SEP_KEY)
			|| ldns_rr_get_type(ldns_rr_list_rr(rrset, 0))
		        == LDNS_RR_TYPE_DNSKEY)
		    ) {
			current_sig = ldns_create_empty_rrsig(rrset_clone,
			                                      current_key);

			/* right now, we have: a key, a semi-sig and an rrset. For
			 * which we can create the sig and base64 encode that and
			 * add that to the signature */

			if (ldns_rrsig2buffer_wire(sign_buf, current_sig)
			    != LDNS_STATUS_OK) {
				ldns_buffer_free(sign_buf);
				/* ERROR */
				ldns_rr_list_deep_free(rrset_clone);
				return NULL;
			}

			/* add the rrset in sign_buf */
			if (ldns_rr_list2buffer_wire(sign_buf, rrset_clone)
			    != LDNS_STATUS_OK) {
				ldns_buffer_free(sign_buf);
				ldns_rr_list_deep_free(rrset_clone);
				return NULL;
			}

			b64rdf = ldns_sign_public_buffer(sign_buf, current_key);

			if (!b64rdf) {
				/* signing went wrong */
				ldns_rr_list_deep_free(rrset_clone);
				return NULL;
			}

			ldns_rr_rrsig_set_sig(current_sig, b64rdf);

			/* push the signature to the signatures list */
			ldns_rr_list_push_rr(signatures, current_sig);
		}
		ldns_buffer_free(sign_buf); /* restart for the next key */
	}
	ldns_rr_list_deep_free(rrset_clone);

	return signatures;
}
Пример #11
0
/*
 * Parses data buffer to a query, finds the correct answer 
 * and calls the given function for every packet to send.
 */
void
handle_query(uint8_t* inbuf, ssize_t inlen, struct entry* entries, int* count,
	enum transport_type transport, void (*sendfunc)(uint8_t*, size_t, void*),
	void* userdata, FILE* verbose_out)
{
	ldns_status status;
	ldns_pkt *query_pkt = NULL;
	ldns_pkt *answer_pkt = NULL;
	struct reply_packet *p;
	ldns_rr *query_rr = NULL;
	uint8_t *outbuf = NULL;
	size_t answer_size = 0;
	struct entry* entry = NULL;
	ldns_rdf *stop_command = ldns_dname_new_frm_str("server.stop.");

	status = ldns_wire2pkt(&query_pkt, inbuf, (size_t)inlen);
	if (status != LDNS_STATUS_OK) {
		verbose(1, "Got bad packet: %s\n", ldns_get_errorstr_by_id(status));
		ldns_rdf_free(stop_command);
		return;
	}
	
	query_rr = ldns_rr_list_rr(ldns_pkt_question(query_pkt), 0);
	verbose(1, "query %d: id %d: %s %d bytes: ", ++(*count), (int)ldns_pkt_id(query_pkt), 
		(transport==transport_tcp)?"TCP":"UDP", (int)inlen);
	if(verbose_out) ldns_rr_print(verbose_out, query_rr);
	if(verbose_out) ldns_pkt_print(verbose_out, query_pkt);

	if (ldns_rr_get_type(query_rr) == LDNS_RR_TYPE_TXT &&
	    ldns_rr_get_class(query_rr) == LDNS_RR_CLASS_CH &&
	    ldns_dname_compare(ldns_rr_owner(query_rr), stop_command) == 0) {
		exit(0);
        }
	
	/* fill up answer packet */
	entry = find_match(entries, query_pkt, transport);
	if(!entry || !entry->reply_list) {
		verbose(1, "no answer packet for this query, no reply.\n");
		ldns_pkt_free(query_pkt);
		ldns_rdf_free(stop_command);
		return;
	}
	for(p = entry->reply_list; p; p = p->next)
	{
		verbose(3, "Answer pkt:\n");
		if (p->reply_from_hex) {
			/* try to parse the hex packet, if it can be
			 * parsed, we can use adjust rules. if not,
			 * send packet literally */
			status = ldns_buffer2pkt_wire(&answer_pkt, p->reply_from_hex);
			if (status == LDNS_STATUS_OK) {
				adjust_packet(entry, answer_pkt, query_pkt);
				if(verbose_out) ldns_pkt_print(verbose_out, answer_pkt);
				status = ldns_pkt2wire(&outbuf, answer_pkt, &answer_size);
				verbose(2, "Answer packet size: %u bytes.\n", (unsigned int)answer_size);
				if (status != LDNS_STATUS_OK) {
					verbose(1, "Error creating answer: %s\n", ldns_get_errorstr_by_id(status));
					ldns_pkt_free(query_pkt);
					ldns_rdf_free(stop_command);
					return;
				}
				ldns_pkt_free(answer_pkt);
				answer_pkt = NULL;
			} else {
				verbose(3, "Could not parse hex data (%s), sending hex data directly.\n", ldns_get_errorstr_by_id(status));
				/* still try to adjust ID */
				answer_size = ldns_buffer_capacity(p->reply_from_hex);
				outbuf = LDNS_XMALLOC(uint8_t, answer_size);
				memcpy(outbuf, ldns_buffer_export(p->reply_from_hex), answer_size);
				if(entry->copy_id) {
					ldns_write_uint16(outbuf, 
						ldns_pkt_id(query_pkt));
				}
			}
		} else {
			answer_pkt = ldns_pkt_clone(p->reply);
			adjust_packet(entry, answer_pkt, query_pkt);
			if(verbose_out) ldns_pkt_print(verbose_out, answer_pkt);
			status = ldns_pkt2wire(&outbuf, answer_pkt, &answer_size);
			verbose(1, "Answer packet size: %u bytes.\n", (unsigned int)answer_size);
			if (status != LDNS_STATUS_OK) {
				verbose(1, "Error creating answer: %s\n", ldns_get_errorstr_by_id(status));
				ldns_pkt_free(query_pkt);
				ldns_rdf_free(stop_command);
				return;
			}
			ldns_pkt_free(answer_pkt);
			answer_pkt = NULL;
		}
		if(p->packet_sleep) {
			verbose(3, "sleeping for next packet %d secs\n", 
				p->packet_sleep);
#ifdef HAVE_SLEEP
			sleep(p->packet_sleep);
#else
			Sleep(p->packet_sleep * 1000);
#endif
			verbose(3, "wakeup for next packet "
				"(slept %d secs)\n", p->packet_sleep);
		}
		sendfunc(outbuf, answer_size, userdata);
		LDNS_FREE(outbuf);
		outbuf = NULL;
		answer_size = 0;
	}
	ldns_pkt_free(query_pkt);
	ldns_rdf_free(stop_command);
}