コード例 #1
0
/*
 * Puts resource record data on 'db'.
 */
isc_result_t
bdb_putrdata(DB *db, dns_name_t *name, dns_ttl_t ttl, dns_rdata_t *rdata)
{
	static DBT key, data;
	isc_buffer_t keybuf, databuf;
	char nametext[DNS_NAME_MAXTEXT];
	char rdatatext[MAX_RDATATEXT];

	isc_buffer_init(&keybuf, nametext, DNS_NAME_MAXTEXT);

	dns_name_totext(name, ISC_TRUE, &keybuf);

	key.data = isc_buffer_base(&keybuf);
	key.size = isc_buffer_usedlength(&keybuf);

	isc_buffer_init(&databuf, rdatatext, MAX_RDATATEXT);

	dns_ttl_totext(ttl, ISC_FALSE, &databuf);
	*(char *)isc_buffer_used(&databuf) = ' ';
	isc_buffer_add(&databuf, 1);

	dns_rdatatype_totext(rdata->type, &databuf);	/* XXX private data */
	*(char *)isc_buffer_used(&databuf) = ' ';
	isc_buffer_add(&databuf, 1);

	dns_rdata_totext(rdata, NULL, &databuf);

	data.data = isc_buffer_base(&databuf);
	data.size = isc_buffer_usedlength(&databuf);

	REQUIRE(db->put(db, NULL, &key, &data, 0) == 0);

	return ISC_R_SUCCESS;
}
コード例 #2
0
ファイル: nslookup.c プロジェクト: krichter722/bind9
static void
printrdata(dns_rdata_t *rdata) {
	isc_result_t result;
	isc_buffer_t *b = NULL;
	unsigned int size = 1024;
	isc_boolean_t done = ISC_FALSE;

	if (rdata->type < N_KNOWN_RRTYPES)
		printf("%s", rtypetext[rdata->type]);
	else
		printf("rdata_%d = ", rdata->type);

	while (!done) {
		result = isc_buffer_allocate(mctx, &b, size);
		if (result != ISC_R_SUCCESS)
			check_result(result, "isc_buffer_allocate");
		result = dns_rdata_totext(rdata, NULL, b);
		if (result == ISC_R_SUCCESS) {
			printf("%.*s\n", (int)isc_buffer_usedlength(b),
			       (char *)isc_buffer_base(b));
			done = ISC_TRUE;
		} else if (result != ISC_R_NOSPACE)
			check_result(result, "dns_rdata_totext");
		isc_buffer_free(&b);
		size *= 2;
	}
}
コード例 #3
0
ファイル: fwd.c プロジェクト: pspacek/bind-dyndb-ldap
/**
 * Generate list of all values as bracketed list.
 * This string might be fed into cfg parser.
 *
 * Caller has to deallocate resulting output buffer.
 */
isc_result_t
fwd_print_bracketed_values_buf(isc_mem_t *mctx, ldap_valuelist_t *values,
			      isc_buffer_t **string) {
	isc_result_t result;
	ldap_value_t *value;
	const char prefix[] = "{ ";
	const char suffix[] = "}";
	isc_buffer_t tmp_buf; /* hack: only the base buffer is allocated */

	REQUIRE(string != NULL && *string == NULL);

	isc_buffer_initnull(&tmp_buf);
	tmp_buf.mctx = mctx;

	buffer_append_str(&tmp_buf, prefix, 2);
	for (value = HEAD(*values);
	     value != NULL && value->value != NULL;
	     value = NEXT(value, link)) {
		buffer_append_str(&tmp_buf, value->value, strlen(value->value));
		buffer_append_str(&tmp_buf, "; ", 2);
	}
	buffer_append_str(&tmp_buf, suffix, 2);

	/* create and copy string from tmp to output buffer */
	CHECK(isc_buffer_allocate(mctx, string, tmp_buf.used));
	isc_buffer_putmem(*string, isc_buffer_base(&tmp_buf), tmp_buf.used);

cleanup:
	if (tmp_buf.base != NULL)
		isc_mem_put(mctx, tmp_buf.base, tmp_buf.length);
	return result;
}
コード例 #4
0
ファイル: tkey.c プロジェクト: chris-wood/bind-prime
static void
dumpmessage(dns_message_t *msg) {
	isc_buffer_t outbuf;
	unsigned char *output;
	int len = TEMP_BUFFER_SZ;
	isc_result_t result;

	for (;;) {
		output = isc_mem_get(msg->mctx, len);
		if (output == NULL)
			return;

		isc_buffer_init(&outbuf, output, len);
		result = dns_message_totext(msg, &dns_master_style_debug,
					    0, &outbuf);
		if (result == ISC_R_NOSPACE) {
			isc_mem_put(msg->mctx, output, len);
			len *= 2;
			continue;
		}

		if (result == ISC_R_SUCCESS)
			tkey_log("%.*s",
				 (int)isc_buffer_usedlength(&outbuf),
				 (char *)isc_buffer_base(&outbuf));
		else
			tkey_log("Warning: dns_message_totext: %s",
				 dns_result_totext(result));
		break;
	}

	if (output != NULL)
		isc_mem_put(msg->mctx, output, len);
}
コード例 #5
0
ファイル: keygen.c プロジェクト: crossbuild/bind
/*%
 * Write a key file to 'keyfile'.  If 'user' is non-NULL,
 * make that user the owner of the file.  The key will have
 * the name 'keyname' and the secret in the buffer 'secret'.
 */
void
write_key_file(const char *keyfile, const char *user,
	       const char *keyname, isc_buffer_t *secret,
	       dns_secalg_t alg) {
	isc_result_t result;
	const char *algname = alg_totext(alg);
	FILE *fd = NULL;

	DO("create keyfile", isc_file_safecreate(keyfile, &fd));

	if (user != NULL) {
		if (set_user(fd, user) == -1)
			fatal("unable to set file owner\n");
	}

	fprintf(fd, "key \"%s\" {\n\talgorithm %s;\n"
		"\tsecret \"%.*s\";\n};\n",
		keyname, algname,
		(int)isc_buffer_usedlength(secret),
		(char *)isc_buffer_base(secret));
	fflush(fd);
	if (ferror(fd))
		fatal("write to %s failed\n", keyfile);
	if (fclose(fd))
		fatal("fclose(%s) failed\n", keyfile);
	fprintf(stderr, "wrote key file \"%s\"\n", keyfile);
}
コード例 #6
0
ファイル: dnstap-read.c プロジェクト: each/bind9-collab
static void
print_hex(dns_dtdata_t *dt) {
	isc_buffer_t *b = NULL;
	isc_result_t result;
	size_t textlen;

	if (dt->msg == NULL) {
		return;
	}

	textlen = (dt->msgdata.length * 2) + 1;
	isc_buffer_allocate(mctx, &b, textlen);
	if (b == NULL) {
		fatal("out of memory");
	}

	result = isc_hex_totext(&dt->msgdata, 0, "", b);
	CHECKM(result, "isc_hex_totext");

	printf("%.*s\n", (int) isc_buffer_usedlength(b),
	       (char *) isc_buffer_base(b));

 cleanup:
	if (b != NULL)
		isc_buffer_free(&b);
}
コード例 #7
0
ファイル: keytable.c プロジェクト: eljefedelrodeodeljefe/BIND
isc_result_t
dns_keytable_dump(dns_keytable_t *keytable, FILE *fp) {
	isc_result_t result;
	isc_buffer_t *text = NULL;

	REQUIRE(VALID_KEYTABLE(keytable));
	REQUIRE(fp != NULL);

	result = isc_buffer_allocate(keytable->mctx, &text, 4096);
	if (result != ISC_R_SUCCESS)
		return (result);

	result = dns_keytable_totext(keytable, &text);

	if (isc_buffer_usedlength(text) != 0) {
		(void) putstr(&text, "\n");
	} else if (result == ISC_R_SUCCESS)
		(void) putstr(&text, "none");
	else {
		(void) putstr(&text, "could not dump key table: ");
		(void) putstr(&text, isc_result_totext(result));
	}

	fprintf(fp, "%.*s", (int) isc_buffer_usedlength(text),
		(char *) isc_buffer_base(text));

	isc_buffer_free(&text);
	return (result);
}
コード例 #8
0
ファイル: keycreate.c プロジェクト: w796933/bind99damp
static void
recvquery(isc_task_t *task, isc_event_t *event) {
	dns_requestevent_t *reqev = (dns_requestevent_t *)event;
	isc_result_t result;
	dns_message_t *query, *response;
	char keyname[256];
	isc_buffer_t keynamebuf;
	int type;

	UNUSED(task);

	REQUIRE(reqev != NULL);

	if (reqev->result != ISC_R_SUCCESS) {
		fprintf(stderr, "I:request event result: %s\n",
			isc_result_totext(reqev->result));
		exit(-1);
	}

	query = reqev->ev_arg;

	response = NULL;
	result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &response);
	CHECK("dns_message_create", result);

	result = dns_request_getresponse(reqev->request, response,
					 DNS_MESSAGEPARSE_PRESERVEORDER);
	CHECK("dns_request_getresponse", result);

	if (response->rcode != dns_rcode_noerror) {
		result = ISC_RESULTCLASS_DNSRCODE + response->rcode;
		fprintf(stderr, "I:response rcode: %s\n",
			isc_result_totext(result));
			exit(-1);
	}

	result = dns_tkey_processdhresponse(query, response, ourkey, &nonce,
					    &tsigkey, ring);
	CHECK("dns_tkey_processdhresponse", result);

	/*
	 * Yes, this is a hack.
	 */
	isc_buffer_init(&keynamebuf, keyname, sizeof(keyname));
	result = dst_key_buildfilename(tsigkey->key, 0, "", &keynamebuf);
	CHECK("dst_key_buildfilename", result);
	printf("%.*s\n", (int)isc_buffer_usedlength(&keynamebuf),
	       (char *)isc_buffer_base(&keynamebuf));
	type = DST_TYPE_PRIVATE | DST_TYPE_PUBLIC | DST_TYPE_KEY;
	result = dst_key_tofile(tsigkey->key, type, "");
	CHECK("dst_key_tofile", result);

	dns_message_destroy(&query);
	dns_message_destroy(&response);
	dns_request_destroy(&reqev->request);
	isc_event_free(&event);
	isc_app_shutdown();
	return;
}
コード例 #9
0
ファイル: rndc.c プロジェクト: chris-wood/bind-prime
static void
rndc_recvdone(isc_task_t *task, isc_event_t *event) {
	isccc_sexpr_t *response = NULL;
	isccc_sexpr_t *data;
	isccc_region_t source;
	char *errormsg = NULL;
	char *textmsg = NULL;
	isc_result_t result;

	recvs--;

	if (ccmsg.result == ISC_R_EOF)
		fatal("connection to remote host closed\n"
		      "This may indicate that\n"
		      "* the remote server is using an older version of"
		      " the command protocol,\n"
		      "* this host is not authorized to connect,\n"
		      "* the clocks are not synchronized, or\n"
		      "* the key is invalid.");

	if (ccmsg.result != ISC_R_SUCCESS)
		fatal("recv failed: %s", isc_result_totext(ccmsg.result));

	source.rstart = isc_buffer_base(&ccmsg.buffer);
	source.rend = isc_buffer_used(&ccmsg.buffer);

	DO("parse message",
	   isccc_cc_fromwire(&source, &response, algorithm, &secret));

	data = isccc_alist_lookup(response, "_data");
	if (data == NULL)
		fatal("no data section in response");
	result = isccc_cc_lookupstring(data, "err", &errormsg);
	if (result == ISC_R_SUCCESS) {
		failed = ISC_TRUE;
		fprintf(stderr, "%s: '%s' failed: %s\n",
			progname, command, errormsg);
	}
	else if (result != ISC_R_NOTFOUND)
		fprintf(stderr, "%s: parsing response failed: %s\n",
			progname, isc_result_totext(result));

	result = isccc_cc_lookupstring(data, "text", &textmsg);
	if (result == ISC_R_SUCCESS) {
		if ((!quiet || failed) && strlen(textmsg) != 0U)
			fprintf(failed ? stderr : stdout, "%s\n", textmsg);
	} else if (result != ISC_R_NOTFOUND)
		fprintf(stderr, "%s: parsing response failed: %s\n",
			progname, isc_result_totext(result));

	isc_event_free(&event);
	isccc_sexpr_free(&response);
	if (sends == 0 && recvs == 0) {
		isc_socket_detach(&sock);
		isc_task_shutdown(task);
		RUNTIME_CHECK(isc_app_shutdown() == ISC_R_SUCCESS);
	}
}
コード例 #10
0
ファイル: pipequeries.c プロジェクト: pspacek/dyndb-work
static void
recvresponse(isc_task_t *task, isc_event_t *event) {
	dns_requestevent_t *reqev = (dns_requestevent_t *)event;
	isc_result_t result;
	dns_message_t *query, *response;
	isc_buffer_t outbuf;
	char output[1024];

	UNUSED(task);

	REQUIRE(reqev != NULL);

	if (reqev->result != ISC_R_SUCCESS) {
		fprintf(stderr, "I:request event result: %s\n",
			isc_result_totext(reqev->result));
		exit(-1);
	}

	query = reqev->ev_arg;

	response = NULL;
	result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &response);
	CHECK("dns_message_create", result);

	result = dns_request_getresponse(reqev->request, response,
					 DNS_MESSAGEPARSE_PRESERVEORDER);
	CHECK("dns_request_getresponse", result);

	if (response->rcode != dns_rcode_noerror) {
		result = ISC_RESULTCLASS_DNSRCODE + response->rcode;
		fprintf(stderr, "I:response rcode: %s\n",
			isc_result_totext(result));
			exit(-1);
	}
	if (response->counts[DNS_SECTION_ANSWER] != 1U) {
		fprintf(stderr, "I:response answer count (%u!=1)\n",
			response->counts[DNS_SECTION_ANSWER]);
	}

	isc_buffer_init(&outbuf, output, sizeof(output));
	result = dns_message_sectiontotext(response, DNS_SECTION_ANSWER,
					   &dns_master_style_simple,
					   DNS_MESSAGETEXTFLAG_NOCOMMENTS,
					   &outbuf);
	CHECK("dns_message_sectiontotext", result);
	printf("%.*s", (int)isc_buffer_usedlength(&outbuf),
	       (char *)isc_buffer_base(&outbuf));
	fflush(stdout);

	dns_message_destroy(&query);
	dns_message_destroy(&response);
	dns_request_destroy(&reqev->request);
	isc_event_free(&event);

	if (--onfly == 0)
		isc_app_shutdown();
	return;
}
コード例 #11
0
ファイル: gsstest.c プロジェクト: VargMon/netbsd-cvs-mirror
static void
recvresponse(isc_task_t *task, isc_event_t *event) {
	dns_requestevent_t *reqev = (dns_requestevent_t *)event;
	isc_result_t result, result2;
	dns_message_t *query = NULL, *response = NULL;
	isc_buffer_t outtoken;
	isc_buffer_t outbuf;
	char output[10 * 1024];

	unsigned char array[DNS_NAME_MAXTEXT + 1];
	isc_buffer_init(&outtoken, array, sizeof(array));

	UNUSED(task);

	REQUIRE(reqev != NULL);

	query = reqev->ev_arg;

	if (reqev->result != ISC_R_SUCCESS) {
		fprintf(stderr, "I:request event result: %s\n",
			isc_result_totext(reqev->result));
		goto end;
	}

	response = NULL;
	result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &response);
	CHECK("dns_message_create", result);

	printf("\nReceived Response:\n");

	result2 = dns_request_getresponse(reqev->request, response,
					 DNS_MESSAGEPARSE_PRESERVEORDER);
	isc_buffer_init(&outbuf, output, sizeof(output));
	result = dns_message_totext(response, &dns_master_style_debug, 0,
				    &outbuf);
	CHECK("dns_message_totext", result);
	printf("%.*s\n", (int)isc_buffer_usedlength(&outbuf),
	       (char *)isc_buffer_base(&outbuf));

	CHECK("dns_request_getresponse", result2);

	if (response != NULL)
		dns_message_destroy(&response);

 end:
	if (query != NULL)
		dns_message_destroy(&query);

	if (reqev->request != NULL)
		dns_request_destroy(&reqev->request);

	isc_event_free(&event);

	event = isc_event_allocate(mctx, (void *)1, 1, console, NULL,
				   sizeof(*event));
	isc_task_send(task, &event);
	return;
}
コード例 #12
0
ファイル: nslookup.c プロジェクト: krichter722/bind9
static void
printa(dns_rdata_t *rdata) {
	isc_result_t result;
	char text[sizeof("255.255.255.255")];
	isc_buffer_t b;

	isc_buffer_init(&b, text, sizeof(text));
	result = dns_rdata_totext(rdata, NULL, &b);
	check_result(result, "dns_rdata_totext");
	printf("Address: %.*s\n", (int)isc_buffer_usedlength(&b),
	       (char *)isc_buffer_base(&b));
}
コード例 #13
0
ファイル: tkey.c プロジェクト: coapp-packages/bind
static void
_dns_tkey_dumpmessage(dns_message_t *msg) {
	isc_buffer_t outbuf;
	unsigned char output[4096];
	isc_result_t result;

	isc_buffer_init(&outbuf, output, sizeof(output));
	result = dns_message_totext(msg, &dns_master_style_debug, 0,
				    &outbuf);
	/* XXXMLG ignore result */
	fprintf(stderr, "%.*s\n", (int)isc_buffer_usedlength(&outbuf),
		(char *)isc_buffer_base(&outbuf));
}
コード例 #14
0
ファイル: tkey.c プロジェクト: 274914765/C
static void _dns_tkey_dumpmessage (dns_message_t * msg)
{
    isc_buffer_t outbuf;

    unsigned char output[4096];

    isc_result_t result;

    isc_buffer_init (&outbuf, output, sizeof (output));
    result = dns_message_totext (msg, &dns_master_style_debug, 0, &outbuf);
    if (result != ISC_R_SUCCESS)
        fprintf (stderr, "Warning: dns_message_totext returned: %s\n", dns_result_totext (result));
    fprintf (stderr, "%.*s\n", (int) isc_buffer_usedlength (&outbuf), (char *) isc_buffer_base (&outbuf));
}
コード例 #15
0
ファイル: xfrout.c プロジェクト: ystk/debian-bind9
static void
log_rr(dns_name_t *name, dns_rdata_t *rdata, isc_uint32_t ttl) {
	isc_result_t result;
	isc_buffer_t buf;
	char mem[2000];
	dns_rdatalist_t rdl;
	dns_rdataset_t rds;
	dns_rdata_t rd = DNS_RDATA_INIT;

	rdl.type = rdata->type;
	rdl.rdclass = rdata->rdclass;
	rdl.ttl = ttl;
	if (rdata->type == dns_rdatatype_sig ||
	    rdata->type == dns_rdatatype_rrsig)
		rdl.covers = dns_rdata_covers(rdata);
	else
		rdl.covers = dns_rdatatype_none;
	ISC_LIST_INIT(rdl.rdata);
	ISC_LINK_INIT(&rdl, link);
	dns_rdataset_init(&rds);
	dns_rdata_init(&rd);
	dns_rdata_clone(rdata, &rd);
	ISC_LIST_APPEND(rdl.rdata, &rd, link);
	RUNTIME_CHECK(dns_rdatalist_tordataset(&rdl, &rds) == ISC_R_SUCCESS);

	isc_buffer_init(&buf, mem, sizeof(mem));
	result = dns_rdataset_totext(&rds, name,
				     ISC_FALSE, ISC_FALSE, &buf);

	/*
	 * We could use xfrout_log(), but that would produce
	 * very long lines with a repetitive prefix.
	 */
	if (result == ISC_R_SUCCESS) {
		/*
		 * Get rid of final newline.
		 */
		INSIST(buf.used >= 1 &&
		       ((char *) buf.base)[buf.used - 1] == '\n');
		buf.used--;

		isc_log_write(XFROUT_RR_LOGARGS, "%.*s",
			      (int)isc_buffer_usedlength(&buf),
			      (char *)isc_buffer_base(&buf));
	} else {
		isc_log_write(XFROUT_RR_LOGARGS, "<RR too large to print>");
	}
}
コード例 #16
0
ファイル: dnstap-read.c プロジェクト: each/bind9-collab
static void
print_dtdata(dns_dtdata_t *dt) {
	isc_result_t result;
	isc_buffer_t *b = NULL;

	isc_buffer_allocate(mctx, &b, 2048);
	if (b == NULL)
		fatal("out of memory");

	CHECKM(dns_dt_datatotext(dt, &b), "dns_dt_datatotext");
	printf("%.*s\n", (int) isc_buffer_usedlength(b),
	       (char *) isc_buffer_base(b));

 cleanup:
	if (b != NULL)
		isc_buffer_free(&b);
}
コード例 #17
0
ファイル: dnstap-read.c プロジェクト: each/bind9-collab
static void
print_packet(dns_dtdata_t *dt, const dns_master_style_t *style) {
	isc_buffer_t *b = NULL;
	isc_result_t result;

	if (dt->msg != NULL) {
		size_t textlen = 2048;

		isc_buffer_allocate(mctx, &b, textlen);
		if (b == NULL)
			fatal("out of memory");

		for (;;) {
			isc_buffer_reserve(&b, textlen);
			if (b == NULL)
				fatal("out of memory");

			result = dns_message_totext(dt->msg, style, 0, b);
			if (result == ISC_R_NOSPACE) {
				textlen *= 2;
				continue;
			} else if (result == ISC_R_SUCCESS) {
				printf("%.*s",
				       (int) isc_buffer_usedlength(b),
				       (char *) isc_buffer_base(b));
				isc_buffer_free(&b);
			} else {
				isc_buffer_free(&b);
				CHECKM(result, "dns_message_totext");
			}
			break;
		}
	}

 cleanup:
	if (b != NULL)
		isc_buffer_free(&b);
}
コード例 #18
0
static void
recvdone(isc_task_t *task, isc_event_t *event) {
	isc_socketevent_t *sevent = (isc_socketevent_t *)event;
	isc_buffer_t source;
	isc_result_t result;
	dns_message_t *response;

	REQUIRE(sevent != NULL);
	REQUIRE(sevent->ev_type == ISC_SOCKEVENT_RECVDONE);
	REQUIRE(task == task1);

	printf("recvdone\n");
	if (sevent->result != ISC_R_SUCCESS) {
		printf("failed\n");
		exit(-1);
	}

	isc_buffer_init(&source, sevent->region.base, sevent->region.length);
	isc_buffer_add(&source, sevent->n);

	response = NULL;
	result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &response);
	CHECK("dns_message_create", result);
	result = dns_message_parse(response, &source, 0);
	CHECK("dns_message_parse", result);

	isc_buffer_init(&outbuf, output, sizeof(output));
	result = dns_message_totext(response, style, 0, &outbuf);
	CHECK("dns_message_totext", result);
	printf("%.*s\n", (int)isc_buffer_usedlength(&outbuf),
	       (char *)isc_buffer_base(&outbuf));

	dns_message_destroy(&response);
	isc_event_free(&event);

	isc_app_shutdown();
}
コード例 #19
0
/*%
 * Write an rndc.key file to 'keyfile'.  If 'user' is non-NULL,
 * make that user the owner of the file.  The key will have
 * the name 'keyname' and the secret in the buffer 'secret'.
 */
static void
write_key_file(const char *keyfile, const char *user,
	       const char *keyname, isc_buffer_t *secret )
{
	FILE *fd;

	fd = safe_create(keyfile);
	if (fd == NULL)
		fatal( "unable to create \"%s\"\n", keyfile);
	if (user != NULL) {
		if (set_user(fd, user) == -1)
			fatal("unable to set file owner\n");
	}
	fprintf(fd, "key \"%s\" {\n\talgorithm hmac-md5;\n"
		"\tsecret \"%.*s\";\n};\n", keyname,
		(int)isc_buffer_usedlength(secret),
		(char *)isc_buffer_base(secret));
	fflush(fd);
	if (ferror(fd))
		fatal("write to %s failed\n", keyfile);
	if (fclose(fd))
		fatal("fclose(%s) failed\n", keyfile);
	fprintf(stderr, "wrote key file \"%s\"\n", keyfile);
}
コード例 #20
0
ファイル: lwresd.c プロジェクト: gosudream/netbsd-src
/*
 * Convert a resolv.conf file into a config structure.
 */
isc_result_t
ns_lwresd_parseeresolvconf(isc_mem_t *mctx, cfg_parser_t *pctx,
			   cfg_obj_t **configp)
{
	char text[4096];
	char str[16];
	isc_buffer_t b;
	lwres_context_t *lwctx = NULL;
	lwres_conf_t *lwc = NULL;
	isc_sockaddr_t sa;
	isc_netaddr_t na;
	int i;
	isc_result_t result;
	lwres_result_t lwresult;

	lwctx = NULL;
	lwresult = lwres_context_create(&lwctx, mctx, ns__lwresd_memalloc,
					ns__lwresd_memfree,
					LWRES_CONTEXT_SERVERMODE);
	if (lwresult != LWRES_R_SUCCESS) {
		result = ISC_R_NOMEMORY;
		goto cleanup;
	}

	lwresult = lwres_conf_parse(lwctx, lwresd_g_resolvconffile);
	if (lwresult != LWRES_R_SUCCESS) {
		result = DNS_R_SYNTAX;
		goto cleanup;
	}

	lwc = lwres_conf_get(lwctx);
	INSIST(lwc != NULL);

	isc_buffer_init(&b, text, sizeof(text));

	CHECK(buffer_putstr(&b, "options {\n"));

	/*
	 * Build the list of forwarders.
	 */
	if (lwc->nsnext > 0) {
		CHECK(buffer_putstr(&b, "\tforwarders {\n"));

		for (i = 0; i < lwc->nsnext; i++) {
			CHECK(lwaddr_sockaddr_fromlwresaddr(
							&sa,
							&lwc->nameservers[i],
							ns_g_port));
			isc_netaddr_fromsockaddr(&na, &sa);
			CHECK(buffer_putstr(&b, "\t\t"));
			CHECK(isc_netaddr_totext(&na, &b));
			CHECK(buffer_putstr(&b, ";\n"));
		}
		CHECK(buffer_putstr(&b, "\t};\n"));
	}

	/*
	 * Build the sortlist
	 */
	if (lwc->sortlistnxt > 0) {
		CHECK(buffer_putstr(&b, "\tsortlist {\n"));
		CHECK(buffer_putstr(&b, "\t\t{\n"));
		CHECK(buffer_putstr(&b, "\t\t\tany;\n"));
		CHECK(buffer_putstr(&b, "\t\t\t{\n"));
		for (i = 0; i < lwc->sortlistnxt; i++) {
			lwres_addr_t *lwaddr = &lwc->sortlist[i].addr;
			lwres_addr_t *lwmask = &lwc->sortlist[i].mask;
			unsigned int mask;

			CHECK(lwaddr_sockaddr_fromlwresaddr(&sa, lwmask, 0));
			isc_netaddr_fromsockaddr(&na, &sa);
			result = isc_netaddr_masktoprefixlen(&na, &mask);
			if (result != ISC_R_SUCCESS) {
				char addrtext[ISC_NETADDR_FORMATSIZE];
				isc_netaddr_format(&na, addrtext,
						   sizeof(addrtext));
				isc_log_write(ns_g_lctx,
					      NS_LOGCATEGORY_GENERAL,
					      NS_LOGMODULE_LWRESD,
					      ISC_LOG_ERROR,
					      "processing sortlist: '%s' is "
					      "not a valid netmask",
					      addrtext);
				goto cleanup;
			}

			CHECK(lwaddr_sockaddr_fromlwresaddr(&sa, lwaddr, 0));
			isc_netaddr_fromsockaddr(&na, &sa);

			CHECK(buffer_putstr(&b, "\t\t\t\t"));
			CHECK(isc_netaddr_totext(&na, &b));
			snprintf(str, sizeof(str), "%u", mask);
			CHECK(buffer_putstr(&b, "/"));
			CHECK(buffer_putstr(&b, str));
			CHECK(buffer_putstr(&b, ";\n"));
		}
		CHECK(buffer_putstr(&b, "\t\t\t};\n"));
		CHECK(buffer_putstr(&b, "\t\t};\n"));
		CHECK(buffer_putstr(&b, "\t};\n"));
	}

	CHECK(buffer_putstr(&b, "};\n\n"));

	CHECK(buffer_putstr(&b, "lwres {\n"));

	/*
	 * Build the search path
	 */
	if (lwc->searchnxt > 0) {
		if (lwc->searchnxt > 0) {
			CHECK(buffer_putstr(&b, "\tsearch {\n"));
			for (i = 0; i < lwc->searchnxt; i++) {
				CHECK(buffer_putstr(&b, "\t\t\""));
				CHECK(buffer_putstr(&b, lwc->search[i]));
				CHECK(buffer_putstr(&b, "\";\n"));
			}
			CHECK(buffer_putstr(&b, "\t};\n"));
		}
	}

	/*
	 * Build the ndots line
	 */
	if (lwc->ndots != 1) {
		CHECK(buffer_putstr(&b, "\tndots "));
		snprintf(str, sizeof(str), "%u", lwc->ndots);
		CHECK(buffer_putstr(&b, str));
		CHECK(buffer_putstr(&b, ";\n"));
	}

	/*
	 * Build the listen-on line
	 */
	if (lwc->lwnext > 0) {
		CHECK(buffer_putstr(&b, "\tlisten-on {\n"));

		for (i = 0; i < lwc->lwnext; i++) {
			CHECK(lwaddr_sockaddr_fromlwresaddr(&sa,
							    &lwc->lwservers[i],
							    0));
			isc_netaddr_fromsockaddr(&na, &sa);
			CHECK(buffer_putstr(&b, "\t\t"));
			CHECK(isc_netaddr_totext(&na, &b));
			CHECK(buffer_putstr(&b, ";\n"));
		}
		CHECK(buffer_putstr(&b, "\t};\n"));
	}

	CHECK(buffer_putstr(&b, "};\n"));

#if 0
	printf("%.*s\n",
	       (int)isc_buffer_usedlength(&b),
	       (char *)isc_buffer_base(&b));
#endif

	lwres_conf_clear(lwctx);
	lwres_context_destroy(&lwctx);

	return (cfg_parse_buffer(pctx, &b, &cfg_type_namedconf, configp));

 cleanup:

	if (lwctx != NULL) {
		lwres_conf_clear(lwctx);
		lwres_context_destroy(&lwctx);
	}

	return (result);
}
コード例 #21
0
ファイル: controlconf.c プロジェクト: krichter722/bind9
static isc_result_t
get_rndckey(isc_mem_t *mctx, controlkeylist_t *keyids) {
	isc_result_t result;
	cfg_parser_t *pctx = NULL;
	cfg_obj_t *config = NULL;
	const cfg_obj_t *key = NULL;
	const cfg_obj_t *algobj = NULL;
	const cfg_obj_t *secretobj = NULL;
	const char *algstr = NULL;
	const char *secretstr = NULL;
	controlkey_t *keyid = NULL;
	char secret[1024];
	unsigned int algtype;
	isc_buffer_t b;

	isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
		      NS_LOGMODULE_CONTROL, ISC_LOG_INFO,
		      "configuring command channel from '%s'",
		      ns_g_keyfile);
	if (! isc_file_exists(ns_g_keyfile))
		return (ISC_R_FILENOTFOUND);

	CHECK(cfg_parser_create(mctx, ns_g_lctx, &pctx));
	CHECK(cfg_parse_file(pctx, ns_g_keyfile, &cfg_type_rndckey, &config));
	CHECK(cfg_map_get(config, "key", &key));

	keyid = isc_mem_get(mctx, sizeof(*keyid));
	if (keyid == NULL)
		CHECK(ISC_R_NOMEMORY);
	keyid->keyname = isc_mem_strdup(mctx,
					cfg_obj_asstring(cfg_map_getname(key)));
	keyid->secret.base = NULL;
	keyid->secret.length = 0;
	keyid->algorithm = DST_ALG_UNKNOWN;
	ISC_LINK_INIT(keyid, link);
	if (keyid->keyname == NULL)
		CHECK(ISC_R_NOMEMORY);

	CHECK(bind9_check_key(key, ns_g_lctx));

	(void)cfg_map_get(key, "algorithm", &algobj);
	(void)cfg_map_get(key, "secret", &secretobj);
	INSIST(algobj != NULL && secretobj != NULL);

	algstr = cfg_obj_asstring(algobj);
	secretstr = cfg_obj_asstring(secretobj);

	if (ns_config_getkeyalgorithm2(algstr, NULL,
				       &algtype, NULL) != ISC_R_SUCCESS) {
		cfg_obj_log(key, ns_g_lctx,
			    ISC_LOG_WARNING,
			    "unsupported algorithm '%s' in "
			    "key '%s' for use with command "
			    "channel",
			    algstr, keyid->keyname);
		goto cleanup;
	}

	keyid->algorithm = algtype;
	isc_buffer_init(&b, secret, sizeof(secret));
	result = isc_base64_decodestring(secretstr, &b);

	if (result != ISC_R_SUCCESS) {
		cfg_obj_log(key, ns_g_lctx, ISC_LOG_WARNING,
			    "secret for key '%s' on command channel: %s",
			    keyid->keyname, isc_result_totext(result));
		goto cleanup;
	}

	keyid->secret.length = isc_buffer_usedlength(&b);
	keyid->secret.base = isc_mem_get(mctx,
					 keyid->secret.length);
	if (keyid->secret.base == NULL) {
		cfg_obj_log(key, ns_g_lctx, ISC_LOG_WARNING,
			   "couldn't register key '%s': "
			   "out of memory", keyid->keyname);
		CHECK(ISC_R_NOMEMORY);
	}
	memmove(keyid->secret.base, isc_buffer_base(&b),
		keyid->secret.length);
	ISC_LIST_APPEND(*keyids, keyid, link);
	keyid = NULL;
	result = ISC_R_SUCCESS;

  cleanup:
	if (keyid != NULL)
		free_controlkey(keyid, mctx);
	if (config != NULL)
		cfg_obj_destroy(pctx, &config);
	if (pctx != NULL)
		cfg_parser_destroy(&pctx);
	return (result);
}
コード例 #22
0
ファイル: controlconf.c プロジェクト: krichter722/bind9
static void
register_keys(const cfg_obj_t *control, const cfg_obj_t *keylist,
	      controlkeylist_t *keyids, isc_mem_t *mctx, const char *socktext)
{
	controlkey_t *keyid, *next;
	const cfg_obj_t *keydef;
	char secret[1024];
	isc_buffer_t b;
	isc_result_t result;

	/*
	 * Find the keys corresponding to the keyids used by this listener.
	 */
	for (keyid = ISC_LIST_HEAD(*keyids); keyid != NULL; keyid = next) {
		next = ISC_LIST_NEXT(keyid, link);

		result = cfgkeylist_find(keylist, keyid->keyname, &keydef);
		if (result != ISC_R_SUCCESS) {
			cfg_obj_log(control, ns_g_lctx, ISC_LOG_WARNING,
				    "couldn't find key '%s' for use with "
				    "command channel %s",
				    keyid->keyname, socktext);
			ISC_LIST_UNLINK(*keyids, keyid, link);
			free_controlkey(keyid, mctx);
		} else {
			const cfg_obj_t *algobj = NULL;
			const cfg_obj_t *secretobj = NULL;
			const char *algstr = NULL;
			const char *secretstr = NULL;
			unsigned int algtype;

			(void)cfg_map_get(keydef, "algorithm", &algobj);
			(void)cfg_map_get(keydef, "secret", &secretobj);
			INSIST(algobj != NULL && secretobj != NULL);

			algstr = cfg_obj_asstring(algobj);
			secretstr = cfg_obj_asstring(secretobj);

			if (ns_config_getkeyalgorithm2(algstr, NULL,
					&algtype, NULL) != ISC_R_SUCCESS)
			{
				cfg_obj_log(control, ns_g_lctx,
					    ISC_LOG_WARNING,
					    "unsupported algorithm '%s' in "
					    "key '%s' for use with command "
					    "channel %s",
					    algstr, keyid->keyname, socktext);
				ISC_LIST_UNLINK(*keyids, keyid, link);
				free_controlkey(keyid, mctx);
				continue;
			}

			keyid->algorithm = algtype;
			isc_buffer_init(&b, secret, sizeof(secret));
			result = isc_base64_decodestring(secretstr, &b);

			if (result != ISC_R_SUCCESS) {
				cfg_obj_log(keydef, ns_g_lctx, ISC_LOG_WARNING,
					    "secret for key '%s' on "
					    "command channel %s: %s",
					    keyid->keyname, socktext,
					    isc_result_totext(result));
				ISC_LIST_UNLINK(*keyids, keyid, link);
				free_controlkey(keyid, mctx);
				continue;
			}

			keyid->secret.length = isc_buffer_usedlength(&b);
			keyid->secret.base = isc_mem_get(mctx,
							 keyid->secret.length);
			if (keyid->secret.base == NULL) {
				cfg_obj_log(keydef, ns_g_lctx, ISC_LOG_WARNING,
					   "couldn't register key '%s': "
					   "out of memory", keyid->keyname);
				ISC_LIST_UNLINK(*keyids, keyid, link);
				free_controlkey(keyid, mctx);
				break;
			}
			memmove(keyid->secret.base, isc_buffer_base(&b),
				keyid->secret.length);
		}
	}
}
コード例 #23
0
ファイル: controlconf.c プロジェクト: krichter722/bind9
static void
control_recvmessage(isc_task_t *task, isc_event_t *event) {
	controlconnection_t *conn;
	controllistener_t *listener;
	controlkey_t *key;
	isccc_sexpr_t *request = NULL;
	isccc_sexpr_t *response = NULL;
	isc_uint32_t algorithm;
	isccc_region_t secret;
	isc_stdtime_t now;
	isc_buffer_t b;
	isc_region_t r;
	isc_buffer_t *text;
	isc_result_t result;
	isc_result_t eresult;
	isccc_sexpr_t *_ctrl;
	isccc_time_t sent;
	isccc_time_t exp;
	isc_uint32_t nonce;
	isccc_sexpr_t *data;

	REQUIRE(event->ev_type == ISCCC_EVENT_CCMSG);

	conn = event->ev_arg;
	listener = conn->listener;
	algorithm = DST_ALG_UNKNOWN;
	secret.rstart = NULL;
	text = NULL;

	/* Is the server shutting down? */
	if (listener->controls->shuttingdown)
		goto cleanup;

	if (conn->ccmsg.result != ISC_R_SUCCESS) {
		if (conn->ccmsg.result != ISC_R_CANCELED &&
		    conn->ccmsg.result != ISC_R_EOF)
			log_invalid(&conn->ccmsg, conn->ccmsg.result);
		goto cleanup;
	}

	request = NULL;

	for (key = ISC_LIST_HEAD(listener->keys);
	     key != NULL;
	     key = ISC_LIST_NEXT(key, link))
	{
		isccc_region_t ccregion;

		ccregion.rstart = isc_buffer_base(&conn->ccmsg.buffer);
		ccregion.rend = isc_buffer_used(&conn->ccmsg.buffer);
		secret.rstart = isc_mem_get(listener->mctx, key->secret.length);
		if (secret.rstart == NULL)
			goto cleanup;
		memmove(secret.rstart, key->secret.base, key->secret.length);
		secret.rend = secret.rstart + key->secret.length;
		algorithm = key->algorithm;
		result = isccc_cc_fromwire(&ccregion, &request,
					   algorithm, &secret);
		if (result == ISC_R_SUCCESS)
			break;
		isc_mem_put(listener->mctx, secret.rstart, REGION_SIZE(secret));
		if (result != ISCCC_R_BADAUTH) {
			log_invalid(&conn->ccmsg, result);
			goto cleanup;
		}
	}

	if (key == NULL) {
		log_invalid(&conn->ccmsg, ISCCC_R_BADAUTH);
		goto cleanup;
	}

	/* We shouldn't be getting a reply. */
	if (isccc_cc_isreply(request)) {
		log_invalid(&conn->ccmsg, ISC_R_FAILURE);
		goto cleanup_request;
	}

	isc_stdtime_get(&now);

	/*
	 * Limit exposure to replay attacks.
	 */
	_ctrl = isccc_alist_lookup(request, "_ctrl");
	if (_ctrl == NULL) {
		log_invalid(&conn->ccmsg, ISC_R_FAILURE);
		goto cleanup_request;
	}

	if (isccc_cc_lookupuint32(_ctrl, "_tim", &sent) == ISC_R_SUCCESS) {
		if ((sent + CLOCKSKEW) < now || (sent - CLOCKSKEW) > now) {
			log_invalid(&conn->ccmsg, ISCCC_R_CLOCKSKEW);
			goto cleanup_request;
		}
	} else {
		log_invalid(&conn->ccmsg, ISC_R_FAILURE);
		goto cleanup_request;
	}

	/*
	 * Expire messages that are too old.
	 */
	if (isccc_cc_lookupuint32(_ctrl, "_exp", &exp) == ISC_R_SUCCESS &&
	    now > exp) {
		log_invalid(&conn->ccmsg, ISCCC_R_EXPIRED);
		goto cleanup_request;
	}

	/*
	 * Duplicate suppression (required for UDP).
	 */
	isccc_cc_cleansymtab(listener->controls->symtab, now);
	result = isccc_cc_checkdup(listener->controls->symtab, request, now);
	if (result != ISC_R_SUCCESS) {
		if (result == ISC_R_EXISTS)
			result = ISCCC_R_DUPLICATE;
		log_invalid(&conn->ccmsg, result);
		goto cleanup_request;
	}

	if (conn->nonce != 0 &&
	    (isccc_cc_lookupuint32(_ctrl, "_nonce", &nonce) != ISC_R_SUCCESS ||
	     conn->nonce != nonce)) {
		log_invalid(&conn->ccmsg, ISCCC_R_BADAUTH);
		goto cleanup_request;
	}

	result = isc_buffer_allocate(listener->mctx, &text, 2 * 2048);
	if (result != ISC_R_SUCCESS)
		goto cleanup_request;

	/*
	 * Establish nonce.
	 */
	if (conn->nonce == 0) {
		while (conn->nonce == 0)
			isc_random_get(&conn->nonce);
		eresult = ISC_R_SUCCESS;
	} else
		eresult = ns_control_docommand(request, &text);

	result = isccc_cc_createresponse(request, now, now + 60, &response);
	if (result != ISC_R_SUCCESS)
		goto cleanup_request;

	data = isccc_alist_lookup(response, "_data");
	if (data != NULL) {
		if (isccc_cc_defineuint32(data, "result", eresult) == NULL)
			goto cleanup_response;
	}

	if (eresult != ISC_R_SUCCESS) {
		if (data != NULL) {
			const char *estr = isc_result_totext(eresult);
			if (isccc_cc_definestring(data, "err", estr) == NULL)
				goto cleanup_response;
		}
	}

	if (isc_buffer_usedlength(text) > 0) {
		if (data != NULL) {
			char *str = (char *)isc_buffer_base(text);
			if (isccc_cc_definestring(data, "text", str) == NULL)
				goto cleanup_response;
		}
	}

	_ctrl = isccc_alist_lookup(response, "_ctrl");
	if (_ctrl == NULL ||
	    isccc_cc_defineuint32(_ctrl, "_nonce", conn->nonce) == NULL)
		goto cleanup_response;

	if (conn->buffer == NULL) {
		result = isc_buffer_allocate(listener->mctx,
					     &conn->buffer, 2 * 2048);
		if (result != ISC_R_SUCCESS)
			goto cleanup_response;
	}

	isc_buffer_clear(conn->buffer);
	/* Skip the length field (4 bytes) */
	isc_buffer_add(conn->buffer, 4);

	result = isccc_cc_towire(response, &conn->buffer, algorithm, &secret);
	if (result != ISC_R_SUCCESS)
		goto cleanup_response;

	isc_buffer_init(&b, conn->buffer->base, 4);
	isc_buffer_putuint32(&b, conn->buffer->used - 4);

	r.base = conn->buffer->base;
	r.length = conn->buffer->used;

	result = isc_socket_send(conn->sock, &r, task, control_senddone, conn);
	if (result != ISC_R_SUCCESS)
		goto cleanup_response;
	conn->sending = ISC_TRUE;

	isc_mem_put(listener->mctx, secret.rstart, REGION_SIZE(secret));
	isccc_sexpr_free(&request);
	isccc_sexpr_free(&response);
	isc_buffer_free(&text);
	return;

 cleanup_response:
	isccc_sexpr_free(&response);

 cleanup_request:
	isccc_sexpr_free(&request);
	isc_mem_put(listener->mctx, secret.rstart, REGION_SIZE(secret));
	if (text != NULL)
		isc_buffer_free(&text);

 cleanup:
	isc_socket_detach(&conn->sock);
	isccc_ccmsg_invalidate(&conn->ccmsg);
	conn->ccmsg_valid = ISC_FALSE;
	maybe_free_connection(conn);
	maybe_free_listener(listener);
}
コード例 #24
0
static void
rndc_recvnonce(isc_task_t *task, isc_event_t *event) {
	isccc_sexpr_t *response = NULL;
	isccc_sexpr_t *_ctrl;
	isccc_region_t source;
	isc_result_t result;
	isc_uint32_t nonce;
	isccc_sexpr_t *request = NULL;
	isccc_time_t now;
	isc_region_t r;
	isccc_sexpr_t *data;
	isccc_region_t message;
	isc_uint32_t len;
	isc_buffer_t b;

	recvs--;

	if (ccmsg.result == ISC_R_EOF)
		fatal("connection to remote host closed\n"
		      "This may indicate that the remote server is using "
		      "an older version of \n"
		      "the command protocol, this host is not authorized "
		      "to connect,\nor the key is invalid.");

	if (ccmsg.result != ISC_R_SUCCESS)
		fatal("recv failed: %s", isc_result_totext(ccmsg.result));

	source.rstart = isc_buffer_base(&ccmsg.buffer);
	source.rend = isc_buffer_used(&ccmsg.buffer);

	DO("parse message", isccc_cc_fromwire(&source, &response, &secret));

	_ctrl = isccc_alist_lookup(response, "_ctrl");
	if (_ctrl == NULL)
		fatal("_ctrl section missing");
	nonce = 0;
	if (isccc_cc_lookupuint32(_ctrl, "_nonce", &nonce) != ISC_R_SUCCESS)
		nonce = 0;

	isc_stdtime_get(&now);

	DO("create message", isccc_cc_createmessage(1, NULL, NULL, ++serial,
						    now, now + 60, &request));
	data = isccc_alist_lookup(request, "_data");
	if (data == NULL)
		fatal("_data section missing");
	if (isccc_cc_definestring(data, "type", args) == NULL)
		fatal("out of memory");
	if (nonce != 0) {
		_ctrl = isccc_alist_lookup(request, "_ctrl");
		if (_ctrl == NULL)
			fatal("_ctrl section missing");
		if (isccc_cc_defineuint32(_ctrl, "_nonce", nonce) == NULL)
			fatal("out of memory");
	}
	message.rstart = databuf + 4;
	message.rend = databuf + sizeof(databuf);
	DO("render message", isccc_cc_towire(request, &message, &secret));
	len = sizeof(databuf) - REGION_SIZE(message);
	isc_buffer_init(&b, databuf, 4);
	isc_buffer_putuint32(&b, len - 4);
	r.length = len;
	r.base = databuf;

	isccc_ccmsg_cancelread(&ccmsg);
	DO("schedule recv", isccc_ccmsg_readmessage(&ccmsg, task,
						    rndc_recvdone, NULL));
	recvs++;
	DO("send message", isc_socket_send(sock, &r, task, rndc_senddone,
					   NULL));
	sends++;

	isc_event_free(&event);
	isccc_sexpr_free(&response);
	return;
}
コード例 #25
0
ファイル: dig.c プロジェクト: Gradwell/bind9
/*
 * Callback from dighost.c to print the reply from a server
 */
isc_result_t
printmessage(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers) {
	isc_result_t result;
	dns_messagetextflag_t flags;
	isc_buffer_t *buf = NULL;
	unsigned int len = OUTPUTBUF;
	dns_master_style_t *style = NULL;
	unsigned int styleflags = 0;

	styleflags |= DNS_STYLEFLAG_REL_OWNER;
	if (query->lookup->comments)
		styleflags |= DNS_STYLEFLAG_COMMENT;
	if (rrcomments)
		styleflags |= DNS_STYLEFLAG_RRCOMMENT;
	if (nottl)
		styleflags |= DNS_STYLEFLAG_NO_TTL;
	if (noclass)
		styleflags |= DNS_STYLEFLAG_NO_CLASS;
	if (multiline) {
		styleflags |= DNS_STYLEFLAG_OMIT_OWNER;
		styleflags |= DNS_STYLEFLAG_OMIT_CLASS;
		styleflags |= DNS_STYLEFLAG_REL_DATA;
		styleflags |= DNS_STYLEFLAG_OMIT_TTL;
		styleflags |= DNS_STYLEFLAG_TTL;
		styleflags |= DNS_STYLEFLAG_MULTILINE;
		styleflags |= DNS_STYLEFLAG_RRCOMMENT;
	}
	if (multiline || (nottl && noclass))
		result = dns_master_stylecreate2(&style, styleflags,
						 24, 24, 24, 32, 80, 8,
						 splitwidth, mctx);
	else if (nottl || noclass)
		result = dns_master_stylecreate2(&style, styleflags,
						 24, 24, 32, 40, 80, 8,
						 splitwidth, mctx);
	else
		result = dns_master_stylecreate2(&style, styleflags,
						 24, 32, 40, 48, 80, 8,
						 splitwidth, mctx);
	check_result(result, "dns_master_stylecreate");

	if (query->lookup->cmdline[0] != 0) {
		if (!short_form)
			fputs(query->lookup->cmdline, stdout);
		query->lookup->cmdline[0]=0;
	}
	debug("printmessage(%s %s %s)", headers ? "headers" : "noheaders",
	      query->lookup->comments ? "comments" : "nocomments",
	      short_form ? "short_form" : "long_form");

	flags = 0;
	if (!headers) {
		flags |= DNS_MESSAGETEXTFLAG_NOHEADERS;
		flags |= DNS_MESSAGETEXTFLAG_NOCOMMENTS;
	}
	if (onesoa && query->lookup->rdtype == dns_rdatatype_axfr)
		flags |= (query->msg_count == 0) ? DNS_MESSAGETEXTFLAG_ONESOA :
						   DNS_MESSAGETEXTFLAG_OMITSOA;
	if (!query->lookup->comments)
		flags |= DNS_MESSAGETEXTFLAG_NOCOMMENTS;

	result = isc_buffer_allocate(mctx, &buf, len);
	check_result(result, "isc_buffer_allocate");

	if (query->lookup->comments && !short_form) {
		if (query->lookup->cmdline[0] != 0)
			printf("; %s\n", query->lookup->cmdline);
		if (msg == query->lookup->sendmsg)
			printf(";; Sending:\n");
		else
			printf(";; Got answer:\n");

		if (headers) {
			printf(";; ->>HEADER<<- opcode: %s, status: %s, "
			       "id: %u\n",
			       opcodetext[msg->opcode],
			       rcode_totext(msg->rcode),
			       msg->id);
			printf(";; flags:");
			if ((msg->flags & DNS_MESSAGEFLAG_QR) != 0)
				printf(" qr");
			if ((msg->flags & DNS_MESSAGEFLAG_AA) != 0)
				printf(" aa");
			if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0)
				printf(" tc");
			if ((msg->flags & DNS_MESSAGEFLAG_RD) != 0)
				printf(" rd");
			if ((msg->flags & DNS_MESSAGEFLAG_RA) != 0)
				printf(" ra");
			if ((msg->flags & DNS_MESSAGEFLAG_AD) != 0)
				printf(" ad");
			if ((msg->flags & DNS_MESSAGEFLAG_CD) != 0)
				printf(" cd");
			if ((msg->flags & 0x0040U) != 0)
				printf("; MBZ: 0x4");

			printf("; QUERY: %u, ANSWER: %u, "
			       "AUTHORITY: %u, ADDITIONAL: %u\n",
			       msg->counts[DNS_SECTION_QUESTION],
			       msg->counts[DNS_SECTION_ANSWER],
			       msg->counts[DNS_SECTION_AUTHORITY],
			       msg->counts[DNS_SECTION_ADDITIONAL]);

			if (msg != query->lookup->sendmsg &&
			    (msg->flags & DNS_MESSAGEFLAG_RD) != 0 &&
			    (msg->flags & DNS_MESSAGEFLAG_RA) == 0)
				printf(";; WARNING: recursion requested "
				       "but not available\n");
		}
		if (msg != query->lookup->sendmsg &&
		    query->lookup->edns != -1 && msg->opt == NULL &&
		    (msg->rcode == dns_rcode_formerr ||
		     msg->rcode == dns_rcode_notimp))
			printf("\n;; WARNING: EDNS query returned status "
			       "%s - retry with '+noedns'\n",
			       rcode_totext(msg->rcode));
		if (msg != query->lookup->sendmsg && extrabytes != 0U)
			printf(";; WARNING: Messages has %u extra byte%s at "
			       "end\n", extrabytes, extrabytes != 0 ? "s" : "");
	}

repopulate_buffer:

	if (query->lookup->comments && headers && !short_form) {
		result = dns_message_pseudosectiontotext(msg,
			 DNS_PSEUDOSECTION_OPT,
			 style, flags, buf);
		if (result == ISC_R_NOSPACE) {
buftoosmall:
			len += OUTPUTBUF;
			isc_buffer_free(&buf);
			result = isc_buffer_allocate(mctx, &buf, len);
			if (result == ISC_R_SUCCESS)
				goto repopulate_buffer;
			else
				goto cleanup;
		}
		check_result(result,
		     "dns_message_pseudosectiontotext");
	}

	if (query->lookup->section_question && headers) {
		if (!short_form) {
			result = dns_message_sectiontotext(msg,
						       DNS_SECTION_QUESTION,
						       style, flags, buf);
			if (result == ISC_R_NOSPACE)
				goto buftoosmall;
			check_result(result, "dns_message_sectiontotext");
		}
	}
	if (query->lookup->section_answer) {
		if (!short_form) {
			result = dns_message_sectiontotext(msg,
						       DNS_SECTION_ANSWER,
						       style, flags, buf);
			if (result == ISC_R_NOSPACE)
				goto buftoosmall;
			check_result(result, "dns_message_sectiontotext");
		} else {
			result = short_answer(msg, flags, buf, query);
			if (result == ISC_R_NOSPACE)
				goto buftoosmall;
			check_result(result, "short_answer");
		}
	}
	if (query->lookup->section_authority) {
		if (!short_form) {
			result = dns_message_sectiontotext(msg,
						       DNS_SECTION_AUTHORITY,
						       style, flags, buf);
			if (result == ISC_R_NOSPACE)
				goto buftoosmall;
			check_result(result, "dns_message_sectiontotext");
		}
	}
	if (query->lookup->section_additional) {
		if (!short_form) {
			result = dns_message_sectiontotext(msg,
						      DNS_SECTION_ADDITIONAL,
						      style, flags, buf);
			if (result == ISC_R_NOSPACE)
				goto buftoosmall;
			check_result(result, "dns_message_sectiontotext");
			/*
			 * Only print the signature on the first record.
			 */
			if (headers) {
				result = dns_message_pseudosectiontotext(
						   msg,
						   DNS_PSEUDOSECTION_TSIG,
						   style, flags, buf);
				if (result == ISC_R_NOSPACE)
					goto buftoosmall;
				check_result(result,
					  "dns_message_pseudosectiontotext");
				result = dns_message_pseudosectiontotext(
						   msg,
						   DNS_PSEUDOSECTION_SIG0,
						   style, flags, buf);
				if (result == ISC_R_NOSPACE)
					goto buftoosmall;
				check_result(result,
					   "dns_message_pseudosectiontotext");
			}
		}
	}

	if (headers && query->lookup->comments && !short_form)
		printf("\n");

	printf("%.*s", (int)isc_buffer_usedlength(buf),
	       (char *)isc_buffer_base(buf));
	isc_buffer_free(&buf);

cleanup:
	if (style != NULL)
		dns_master_styledestroy(&style, mctx);
	return (result);
}
コード例 #26
0
static void
buildquery(void) {
	isc_result_t result;
	dns_rdataset_t *question = NULL;
	dns_name_t *qname = NULL;
	isc_region_t r, inr;
	dns_message_t *query;
	char nametext[] = "host.example";
	isc_buffer_t namesrc, namedst;
	unsigned char namedata[256];
	isc_sockaddr_t sa;
	dns_compress_t cctx;

	query = NULL;
	result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &query);
	CHECK("dns_message_create", result);
	result = dns_message_setsig0key(query, key);
	CHECK("dns_message_setsig0key", result);

	result = dns_message_gettemprdataset(query, &question);
	CHECK("dns_message_gettemprdataset", result);
	dns_rdataset_init(question);
	dns_rdataset_makequestion(question, dns_rdataclass_in,
				  dns_rdatatype_a);
	result = dns_message_gettempname(query, &qname);
	CHECK("dns_message_gettempname", result);
	isc_buffer_init(&namesrc, nametext, strlen(nametext));
	isc_buffer_add(&namesrc, strlen(nametext));
	isc_buffer_init(&namedst, namedata, sizeof(namedata));
	dns_name_init(qname, NULL);
	result = dns_name_fromtext(qname, &namesrc, dns_rootname, ISC_FALSE,
				   &namedst);
	CHECK("dns_name_fromtext", result);
	ISC_LIST_APPEND(qname->list, question, link);
	dns_message_addname(query, qname, DNS_SECTION_QUESTION);

	isc_buffer_init(&qbuffer, qdata, sizeof(qdata));

	result = dns_compress_init(&cctx, -1, mctx);
	CHECK("dns_compress_init", result);
	result = dns_message_renderbegin(query, &cctx, &qbuffer);
	CHECK("dns_message_renderbegin", result);
	result = dns_message_rendersection(query, DNS_SECTION_QUESTION, 0);
	CHECK("dns_message_rendersection(question)", result);
	result = dns_message_rendersection(query, DNS_SECTION_ANSWER, 0);
	CHECK("dns_message_rendersection(answer)", result);
	result = dns_message_rendersection(query, DNS_SECTION_AUTHORITY, 0);
	CHECK("dns_message_rendersection(auth)", result);
	result = dns_message_rendersection(query, DNS_SECTION_ADDITIONAL, 0);
	CHECK("dns_message_rendersection(add)", result);
	result = dns_message_renderend(query);
	CHECK("dns_message_renderend", result);
	dns_compress_invalidate(&cctx);

	isc_buffer_init(&outbuf, output, sizeof(output));
	result = dns_message_totext(query, style, 0, &outbuf);
	CHECK("dns_message_totext", result);
	printf("%.*s\n", (int)isc_buffer_usedlength(&outbuf),
	       (char *)isc_buffer_base(&outbuf));

	isc_buffer_usedregion(&qbuffer, &r);
	isc_sockaddr_any(&sa);
	result = isc_socket_bind(s, &sa);
	CHECK("isc_socket_bind", result);
	result = isc_socket_sendto(s, &r, task1, senddone, NULL, &address,
				   NULL);
	CHECK("isc_socket_sendto", result);

	inr.base = rdata;
	inr.length = sizeof(rdata);
	result = isc_socket_recv(s, &inr, 1, task1, recvdone, NULL);
	CHECK("isc_socket_recv", result);
	dns_message_destroy(&query);
}
コード例 #27
0
ファイル: keycreate.c プロジェクト: w796933/bind99damp
static void
sendquery(isc_task_t *task, isc_event_t *event) {
	struct in_addr inaddr;
	isc_sockaddr_t address;
	isc_region_t r;
	isc_result_t result;
	dns_fixedname_t keyname;
	dns_fixedname_t ownername;
	isc_buffer_t namestr, keybuf;
	unsigned char keydata[9];
	dns_message_t *query;
	dns_request_t *request;
	static char keystr[] = "0123456789ab";

	isc_event_free(&event);

	result = ISC_R_FAILURE;
	if (inet_pton(AF_INET, "10.53.0.1", &inaddr) != 1)
		CHECK("inet_pton", result);
	isc_sockaddr_fromin(&address, &inaddr, PORT);

	dns_fixedname_init(&keyname);
	isc_buffer_init(&namestr, "tkeytest.", 9);
	isc_buffer_add(&namestr, 9);
	result = dns_name_fromtext(dns_fixedname_name(&keyname), &namestr,
				   NULL, 0, NULL);
	CHECK("dns_name_fromtext", result);

	dns_fixedname_init(&ownername);
	isc_buffer_init(&namestr, ownername_str, strlen(ownername_str));
	isc_buffer_add(&namestr, strlen(ownername_str));
	result = dns_name_fromtext(dns_fixedname_name(&ownername), &namestr,
				   NULL, 0, NULL);
	CHECK("dns_name_fromtext", result);

	isc_buffer_init(&keybuf, keydata, 9);
	result = isc_base64_decodestring(keystr, &keybuf);
	CHECK("isc_base64_decodestring", result);

	isc_buffer_usedregion(&keybuf, &r);

	initialkey = NULL;
	result = dns_tsigkey_create(dns_fixedname_name(&keyname),
				    DNS_TSIG_HMACMD5_NAME,
				    isc_buffer_base(&keybuf),
				    isc_buffer_usedlength(&keybuf),
				    ISC_FALSE, NULL, 0, 0, mctx, ring,
				    &initialkey);
	CHECK("dns_tsigkey_create", result);

	query = NULL;
	result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &query);
	CHECK("dns_message_create", result);

	result = dns_tkey_builddhquery(query, ourkey,
				       dns_fixedname_name(&ownername),
				       DNS_TSIG_HMACMD5_NAME, &nonce, 3600);
	CHECK("dns_tkey_builddhquery", result);

	request = NULL;
	result = dns_request_create(requestmgr, query, &address,
				    0, initialkey, TIMEOUT, task,
				    recvquery, query, &request);
	CHECK("dns_request_create", result);
}
コード例 #28
0
int
main(int argc, char **argv) {
	isc_boolean_t show_final_mem = ISC_FALSE;
	isc_buffer_t key_txtbuffer;
	char key_txtsecret[256];
	isc_mem_t *mctx = NULL;
	isc_result_t result = ISC_R_SUCCESS;
	const char *keyname = NULL;
	const char *randomfile = NULL;
	const char *serveraddr = NULL;
	dns_secalg_t alg = DST_ALG_HMACMD5;
	const char *algname = alg_totext(alg);
	char *p;
	int ch;
	int port;
	int keysize;
	struct in_addr addr4_dummy;
	struct in6_addr addr6_dummy;
	char *chrootdir = NULL;
	char *user = NULL;
	isc_boolean_t keyonly = ISC_FALSE;
	int len;

	keydef = keyfile = RNDC_KEYFILE;

	result = isc_file_progname(*argv, program, sizeof(program));
	if (result != ISC_R_SUCCESS)
		memmove(program, "rndc-confgen", 13);
	progname = program;

	keyname = DEFAULT_KEYNAME;
	keysize = DEFAULT_KEYLENGTH;
	serveraddr = DEFAULT_SERVER;
	port = DEFAULT_PORT;

	isc_commandline_errprint = ISC_FALSE;

	while ((ch = isc_commandline_parse(argc, argv,
					   "ab:c:hk:Mmp:r:s:t:u:Vy")) != -1) {
		switch (ch) {
		case 'a':
			keyonly = ISC_TRUE;
			break;
		case 'b':
			keysize = strtol(isc_commandline_argument, &p, 10);
			if (*p != '\0' || keysize < 0)
				fatal("-b requires a non-negative number");
			break;
		case 'c':
			keyfile = isc_commandline_argument;
			break;
		case 'h':
			usage(0);
		case 'k':
		case 'y':	/* Compatible with rndc -y. */
			keyname = isc_commandline_argument;
			break;
		case 'M':
			isc_mem_debugging = ISC_MEM_DEBUGTRACE;
			break;

		case 'm':
			show_final_mem = ISC_TRUE;
			break;
		case 'p':
			port = strtol(isc_commandline_argument, &p, 10);
			if (*p != '\0' || port < 0 || port > 65535)
				fatal("port '%s' out of range",
				      isc_commandline_argument);
			break;
		case 'r':
			randomfile = isc_commandline_argument;
			break;
		case 's':
			serveraddr = isc_commandline_argument;
			if (inet_pton(AF_INET, serveraddr, &addr4_dummy) != 1 &&
			    inet_pton(AF_INET6, serveraddr, &addr6_dummy) != 1)
				fatal("-s should be an IPv4 or IPv6 address");
			break;
		case 't':
			chrootdir = isc_commandline_argument;
			break;
		case 'u':
			user = isc_commandline_argument;
			break;
		case 'V':
			verbose = ISC_TRUE;
			break;
		case '?':
			if (isc_commandline_option != '?') {
				fprintf(stderr, "%s: invalid argument -%c\n",
					program, isc_commandline_option);
				usage(1);
			} else
				usage(0);
			break;
		default:
			fprintf(stderr, "%s: unhandled option -%c\n",
				program, isc_commandline_option);
			exit(1);
		}
	}

	argc -= isc_commandline_index;
	argv += isc_commandline_index;
	POST(argv);

	if (argc > 0)
		usage(1);

	DO("create memory context", isc_mem_create(0, 0, &mctx));
	isc_buffer_init(&key_txtbuffer, &key_txtsecret, sizeof(key_txtsecret));

	generate_key(mctx, randomfile, alg, keysize, &key_txtbuffer);

	if (keyonly) {
		write_key_file(keyfile, chrootdir == NULL ? user : NULL,
			       keyname, &key_txtbuffer, alg);

		if (chrootdir != NULL) {
			char *buf;
			len = strlen(chrootdir) + strlen(keyfile) + 2;
			buf = isc_mem_get(mctx, len);
			if (buf == NULL)
				fatal("isc_mem_get(%d) failed\n", len);
			snprintf(buf, len, "%s%s%s", chrootdir,
				 (*keyfile != '/') ? "/" : "", keyfile);

			write_key_file(buf, user, keyname, &key_txtbuffer, alg);
			isc_mem_put(mctx, buf, len);
		}
	} else {
		printf("\
# Start of rndc.conf\n\
key \"%s\" {\n\
	algorithm %s;\n\
	secret \"%.*s\";\n\
};\n\
\n\
options {\n\
	default-key \"%s\";\n\
	default-server %s;\n\
	default-port %d;\n\
};\n\
# End of rndc.conf\n\
\n\
# Use with the following in named.conf, adjusting the allow list as needed:\n\
# key \"%s\" {\n\
# 	algorithm %s;\n\
# 	secret \"%.*s\";\n\
# };\n\
# \n\
# controls {\n\
# 	inet %s port %d\n\
# 		allow { %s; } keys { \"%s\"; };\n\
# };\n\
# End of named.conf\n",
		       keyname, algname,
		       (int)isc_buffer_usedlength(&key_txtbuffer),
		       (char *)isc_buffer_base(&key_txtbuffer),
		       keyname, serveraddr, port,
		       keyname, algname,
		       (int)isc_buffer_usedlength(&key_txtbuffer),
		       (char *)isc_buffer_base(&key_txtbuffer),
		       serveraddr, port, serveraddr, keyname);
	}

	if (show_final_mem)
		isc_mem_stats(mctx, stderr);

	isc_mem_destroy(&mctx);

	return (0);
}
コード例 #29
0
ファイル: tkey.c プロジェクト: chris-wood/bind-prime
static isc_result_t
process_gsstkey(dns_name_t *name, dns_rdata_tkey_t *tkeyin,
		dns_tkeyctx_t *tctx, dns_rdata_tkey_t *tkeyout,
		dns_tsig_keyring_t *ring)
{
	isc_result_t result = ISC_R_SUCCESS;
	dst_key_t *dstkey = NULL;
	dns_tsigkey_t *tsigkey = NULL;
	dns_fixedname_t principal;
	isc_stdtime_t now;
	isc_region_t intoken;
	isc_buffer_t *outtoken = NULL;
	gss_ctx_id_t gss_ctx = NULL;

	/*
	 * You have to define either a gss credential (principal) to
	 * accept with tkey-gssapi-credential, or you have to
	 * configure a specific keytab (with tkey-gssapi-keytab) in
	 * order to use gsstkey
	 */
	if (tctx->gsscred == NULL && tctx->gssapi_keytab == NULL) {
		tkey_log("process_gsstkey(): no tkey-gssapi-credential "
			 "or tkey-gssapi-keytab configured");
		return (ISC_R_NOPERM);
	}

	if (!dns_name_equal(&tkeyin->algorithm, DNS_TSIG_GSSAPI_NAME) &&
	    !dns_name_equal(&tkeyin->algorithm, DNS_TSIG_GSSAPIMS_NAME)) {
		tkeyout->error = dns_tsigerror_badalg;
		tkey_log("process_gsstkey(): dns_tsigerror_badalg");	/* XXXSRA */
		return (ISC_R_SUCCESS);
	}

	/*
	 * XXXDCL need to check for key expiry per 4.1.1
	 * XXXDCL need a way to check fully established, perhaps w/key_flags
	 */

	intoken.base = tkeyin->key;
	intoken.length = tkeyin->keylen;

	result = dns_tsigkey_find(&tsigkey, name, &tkeyin->algorithm, ring);
	if (result == ISC_R_SUCCESS)
		gss_ctx = dst_key_getgssctx(tsigkey->key);

	dns_fixedname_init(&principal);

	/*
	 * Note that tctx->gsscred may be NULL if tctx->gssapi_keytab is set
	 */
	result = dst_gssapi_acceptctx(tctx->gsscred, tctx->gssapi_keytab,
				      &intoken,
				      &outtoken, &gss_ctx,
				      dns_fixedname_name(&principal),
				      tctx->mctx);
	if (result == DNS_R_INVALIDTKEY) {
		if (tsigkey != NULL)
			dns_tsigkey_detach(&tsigkey);
		tkeyout->error = dns_tsigerror_badkey;
		tkey_log("process_gsstkey(): dns_tsigerror_badkey");    /* XXXSRA */
		return (ISC_R_SUCCESS);
	}
	if (result != DNS_R_CONTINUE && result != ISC_R_SUCCESS)
		goto failure;
	/*
	 * XXXDCL Section 4.1.3: Limit GSS_S_CONTINUE_NEEDED to 10 times.
	 */

	isc_stdtime_get(&now);

	if (tsigkey == NULL) {
#ifdef GSSAPI
		OM_uint32 gret, minor, lifetime;
#endif
		isc_uint32_t expire;

		RETERR(dst_key_fromgssapi(name, gss_ctx, ring->mctx,
					  &dstkey, &intoken));
		/*
		 * Limit keys to 1 hour or the context's lifetime whichever
		 * is smaller.
		 */
		expire = now + 3600;
#ifdef GSSAPI
		gret = gss_context_time(&minor, gss_ctx, &lifetime);
		if (gret == GSS_S_COMPLETE && now + lifetime < expire)
			expire = now + lifetime;
#endif
		RETERR(dns_tsigkey_createfromkey(name, &tkeyin->algorithm,
						 dstkey, ISC_TRUE,
						 dns_fixedname_name(&principal),
						 now, expire, ring->mctx, ring,
						 NULL));
		dst_key_free(&dstkey);
		tkeyout->inception = now;
		tkeyout->expire = expire;
	} else {
		tkeyout->inception = tsigkey->inception;
		tkeyout->expire = tsigkey->expire;
		dns_tsigkey_detach(&tsigkey);
	}

	if (outtoken) {
		tkeyout->key = isc_mem_get(tkeyout->mctx,
					   isc_buffer_usedlength(outtoken));
		if (tkeyout->key == NULL) {
			result = ISC_R_NOMEMORY;
			goto failure;
		}
		tkeyout->keylen = isc_buffer_usedlength(outtoken);
		memmove(tkeyout->key, isc_buffer_base(outtoken),
		       isc_buffer_usedlength(outtoken));
		isc_buffer_free(&outtoken);
	} else {
		tkeyout->key = isc_mem_get(tkeyout->mctx, tkeyin->keylen);
		if (tkeyout->key == NULL) {
			result = ISC_R_NOMEMORY;
			goto failure;
		}
		tkeyout->keylen = tkeyin->keylen;
		memmove(tkeyout->key, tkeyin->key, tkeyin->keylen);
	}

	tkeyout->error = dns_rcode_noerror;

	tkey_log("process_gsstkey(): dns_tsigerror_noerror");   /* XXXSRA */

	return (ISC_R_SUCCESS);

failure:
	if (tsigkey != NULL)
		dns_tsigkey_detach(&tsigkey);

	if (dstkey != NULL)
		dst_key_free(&dstkey);

	if (outtoken != NULL)
		isc_buffer_free(&outtoken);

	tkey_log("process_gsstkey(): %s",
		isc_result_totext(result));	/* XXXSRA */

	return (result);
}
コード例 #30
0
ファイル: tkey.c プロジェクト: chris-wood/bind-prime
static isc_result_t
process_dhtkey(dns_message_t *msg, dns_name_t *signer, dns_name_t *name,
	       dns_rdata_tkey_t *tkeyin, dns_tkeyctx_t *tctx,
	       dns_rdata_tkey_t *tkeyout,
	       dns_tsig_keyring_t *ring, dns_namelist_t *namelist)
{
	isc_result_t result = ISC_R_SUCCESS;
	dns_name_t *keyname, ourname;
	dns_rdataset_t *keyset = NULL;
	dns_rdata_t keyrdata = DNS_RDATA_INIT, ourkeyrdata = DNS_RDATA_INIT;
	isc_boolean_t found_key = ISC_FALSE, found_incompatible = ISC_FALSE;
	dst_key_t *pubkey = NULL;
	isc_buffer_t ourkeybuf, *shared = NULL;
	isc_region_t r, r2, ourkeyr;
	unsigned char keydata[DST_KEY_MAXSIZE];
	unsigned int sharedsize;
	isc_buffer_t secret;
	unsigned char *randomdata = NULL, secretdata[256];
	dns_ttl_t ttl = 0;

	if (tctx->dhkey == NULL) {
		tkey_log("process_dhtkey: tkey-dhkey not defined");
		tkeyout->error = dns_tsigerror_badalg;
		return (DNS_R_REFUSED);
	}

	if (!dns_name_equal(&tkeyin->algorithm, DNS_TSIG_HMACMD5_NAME)) {
		tkey_log("process_dhtkey: algorithms other than "
			 "hmac-md5 are not supported");
		tkeyout->error = dns_tsigerror_badalg;
		return (ISC_R_SUCCESS);
	}

	/*
	 * Look for a DH KEY record that will work with ours.
	 */
	for (result = dns_message_firstname(msg, DNS_SECTION_ADDITIONAL);
	     result == ISC_R_SUCCESS && !found_key;
	     result = dns_message_nextname(msg, DNS_SECTION_ADDITIONAL)) {
		keyname = NULL;
		dns_message_currentname(msg, DNS_SECTION_ADDITIONAL, &keyname);
		keyset = NULL;
		result = dns_message_findtype(keyname, dns_rdatatype_key, 0,
					      &keyset);
		if (result != ISC_R_SUCCESS)
			continue;

		for (result = dns_rdataset_first(keyset);
		     result == ISC_R_SUCCESS && !found_key;
		     result = dns_rdataset_next(keyset)) {
			dns_rdataset_current(keyset, &keyrdata);
			pubkey = NULL;
			result = dns_dnssec_keyfromrdata(keyname, &keyrdata,
							 msg->mctx, &pubkey);
			if (result != ISC_R_SUCCESS) {
				dns_rdata_reset(&keyrdata);
				continue;
			}
			if (dst_key_alg(pubkey) == DNS_KEYALG_DH) {
				if (dst_key_paramcompare(pubkey, tctx->dhkey))
				{
					found_key = ISC_TRUE;
					ttl = keyset->ttl;
					break;
				} else
					found_incompatible = ISC_TRUE;
			}
			dst_key_free(&pubkey);
			dns_rdata_reset(&keyrdata);
		}
	}

	if (!found_key) {
		if (found_incompatible) {
			tkey_log("process_dhtkey: found an incompatible key");
			tkeyout->error = dns_tsigerror_badkey;
			return (ISC_R_SUCCESS);
		} else {
			tkey_log("process_dhtkey: failed to find a key");
			return (DNS_R_FORMERR);
		}
	}

	RETERR(add_rdata_to_list(msg, keyname, &keyrdata, ttl, namelist));

	isc_buffer_init(&ourkeybuf, keydata, sizeof(keydata));
	RETERR(dst_key_todns(tctx->dhkey, &ourkeybuf));
	isc_buffer_usedregion(&ourkeybuf, &ourkeyr);
	dns_rdata_fromregion(&ourkeyrdata, dns_rdataclass_any,
			     dns_rdatatype_key, &ourkeyr);

	dns_name_init(&ourname, NULL);
	dns_name_clone(dst_key_name(tctx->dhkey), &ourname);

	/*
	 * XXXBEW The TTL should be obtained from the database, if it exists.
	 */
	RETERR(add_rdata_to_list(msg, &ourname, &ourkeyrdata, 0, namelist));

	RETERR(dst_key_secretsize(tctx->dhkey, &sharedsize));
	RETERR(isc_buffer_allocate(msg->mctx, &shared, sharedsize));

	result = dst_key_computesecret(pubkey, tctx->dhkey, shared);
	if (result != ISC_R_SUCCESS) {
		tkey_log("process_dhtkey: failed to compute shared secret: %s",
			 isc_result_totext(result));
		goto failure;
	}
	dst_key_free(&pubkey);

	isc_buffer_init(&secret, secretdata, sizeof(secretdata));

	randomdata = isc_mem_get(tkeyout->mctx, TKEY_RANDOM_AMOUNT);
	if (randomdata == NULL)
		goto failure;

	result = dst__entropy_getdata(randomdata, TKEY_RANDOM_AMOUNT,
				      ISC_FALSE);
	if (result != ISC_R_SUCCESS) {
		tkey_log("process_dhtkey: failed to obtain entropy: %s",
			 isc_result_totext(result));
		goto failure;
	}

	r.base = randomdata;
	r.length = TKEY_RANDOM_AMOUNT;
	r2.base = tkeyin->key;
	r2.length = tkeyin->keylen;
	RETERR(compute_secret(shared, &r2, &r, &secret));
	isc_buffer_free(&shared);

	RETERR(dns_tsigkey_create(name, &tkeyin->algorithm,
				  isc_buffer_base(&secret),
				  isc_buffer_usedlength(&secret),
				  ISC_TRUE, signer, tkeyin->inception,
				  tkeyin->expire, ring->mctx, ring, NULL));

	/* This key is good for a long time */
	tkeyout->inception = tkeyin->inception;
	tkeyout->expire = tkeyin->expire;

	tkeyout->key = randomdata;
	tkeyout->keylen = TKEY_RANDOM_AMOUNT;

	return (ISC_R_SUCCESS);

 failure:
	if (!ISC_LIST_EMPTY(*namelist))
		free_namelist(msg, namelist);
	if (shared != NULL)
		isc_buffer_free(&shared);
	if (pubkey != NULL)
		dst_key_free(&pubkey);
	if (randomdata != NULL)
		isc_mem_put(tkeyout->mctx, randomdata, TKEY_RANDOM_AMOUNT);
	return (result);
}