예제 #1
0
파일: db.c 프로젝트: pecharmin/bind9
static isc_result_t
add_a(dns_db_t *db, dns_dbversion_t *version, const dns_name_t *name,
      struct in_addr addr)
{
	dns_dbnode_t *node = NULL;
	dns_rdata_in_a_t a;
	dns_rdata_t rdata = DNS_RDATA_INIT;
	dns_rdatalist_t rdatalist;
	dns_rdataset_t rdataset;
	isc_result_t result;
	isc_buffer_t b;
	unsigned char buf[DNS_NAME_MAXWIRE];

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

	dns_rdataset_init(&rdataset);
	dns_rdatalist_init(&rdatalist);
	a.common.rdtype = dns_rdatatype_a;
	a.common.rdclass = dns_db_class(db);
	a.in_addr = addr;
	CHECK(dns_rdata_fromstruct(&rdata, dns_db_class(db), dns_rdatatype_a,
				   &a, &b));
	rdatalist.type = rdata.type;
	rdatalist.covers = 0;
	rdatalist.rdclass = rdata.rdclass;
	rdatalist.ttl = 86400;
	ISC_LIST_APPEND(rdatalist.rdata, &rdata, link);
	CHECK(dns_rdatalist_tordataset(&rdatalist, &rdataset));
	CHECK(dns_db_findnode(db, name, ISC_TRUE, &node));
	CHECK(dns_db_addrdataset(db, node, version, 0, &rdataset, 0, NULL));
 cleanup:
	if (node != NULL)
		dns_db_detachnode(db, &node);
	return (result);
}
예제 #2
0
isc_result_t ATTR_NONNULLS
dns_ns_buildrdata(dns_name_t *origin, dns_name_t *ns_name,
		   dns_rdataclass_t rdclass,
		   unsigned char *buffer,
		   dns_rdata_t *rdata) {
	dns_rdata_ns_t ns;
	isc_buffer_t rdatabuf;

	REQUIRE(origin != NULL);
	REQUIRE(ns_name != NULL);

	memset(buffer, 0, DNS_SOA_BUFFERSIZE);
	isc_buffer_init(&rdatabuf, buffer, DNS_SOA_BUFFERSIZE);

	ns.common.rdtype = dns_rdatatype_ns;
	ns.common.rdclass = rdclass;
	ns.mctx = NULL;
	dns_name_init(&ns.name, NULL);
	dns_name_clone(ns_name, &ns.name);

	return (dns_rdata_fromstruct(rdata, rdclass, dns_rdatatype_ns,
				      &ns, &rdatabuf));
}
예제 #3
0
ATF_TC_BODY(csync, tc) {
	struct {
		const char *data;
		isc_boolean_t ok;
	} text_data[] = {
		{ "", ISC_FALSE },
		{ "0", ISC_FALSE },
		{ "0 0", ISC_TRUE },
		{ "0 0 A", ISC_TRUE },
		{ "0 0 NS", ISC_TRUE },
		{ "0 0 AAAA", ISC_TRUE },
		{ "0 0 A AAAA", ISC_TRUE },
		{ "0 0 A NS AAAA", ISC_TRUE },
		{ "0 0 A NS AAAA BOGUS", ISC_FALSE },
		{ NULL, ISC_FALSE },
	};
	struct {
		unsigned char data[64];
		size_t len;
		isc_boolean_t ok;
	} wire_data[] = {
		/* short */
		{ { 0x00 }, 0,  ISC_FALSE },
		/* short */
		{ { 0x00 }, 1, ISC_FALSE },
		/* short */
		{ { 0x00, 0x00 }, 2, ISC_FALSE },
		/* short */
		{ { 0x00, 0x00, 0x00 }, 3, ISC_FALSE },
		/* short */
		{ { 0x00, 0x00, 0x00, 0x00 }, 4, ISC_FALSE },
		/* short */
		{ { 0x00, 0x00, 0x00, 0x00, 0x00 }, 5, ISC_FALSE },
		/* serial + flags only  */
		{ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 6, ISC_TRUE },
		/* bad type map */
		{ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 7, ISC_FALSE },
		/* bad type map */
		{ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
		    8, ISC_FALSE },
		/* good type map */
		{ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02 },
		    9, ISC_TRUE }
	};
	unsigned char buf1[1024];
	unsigned char buf2[1024];
	isc_buffer_t source, target1, target2;
	isc_result_t result;
	size_t i;
	dns_rdataclass_t rdclass = dns_rdataclass_in;
	dns_rdatatype_t type = dns_rdatatype_csync;
	isc_lex_t *lex = NULL;
	dns_rdatacallbacks_t callbacks;
	dns_rdata_csync_t csync;
	dns_decompress_t dctx;

	UNUSED(tc);

	result = dns_test_begin(NULL, ISC_FALSE);
	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);

	result = isc_lex_create(mctx, 64, &lex);
	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);

	dns_rdatacallbacks_init(&callbacks);
	callbacks.error = error_callback;
	callbacks.warn = warn_callback;

	for (i = 0; text_data[i].data != NULL; i++) {
		size_t length = strlen(text_data[i].data);
		isc_buffer_constinit(&source, text_data[i].data, length);
		isc_buffer_add(&source, length);
		result = isc_lex_openbuffer(lex, &source);
		ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);

		isc_buffer_init(&target1, buf1, sizeof(buf1));

		result = dns_rdata_fromtext(NULL, rdclass, type, lex,
					    dns_rootname, 0, NULL, &target1,
					    &callbacks);
		if (text_data[i].ok)
			ATF_CHECK_EQ(result, ISC_R_SUCCESS);
		else
			ATF_CHECK(result != ISC_R_SUCCESS);
	}
	isc_lex_destroy(&lex);

	for (i = 0; i < sizeof(wire_data)/sizeof(wire_data[0]); i++) {
		dns_rdata_t rdata = DNS_RDATA_INIT;

		isc_buffer_init(&source, wire_data[i].data, wire_data[i].len);
		isc_buffer_add(&source, wire_data[i].len);
		isc_buffer_setactive(&source, wire_data[i].len);
		isc_buffer_init(&target1, buf1, sizeof(buf1));
		dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_ANY);
		result = dns_rdata_fromwire(&rdata, rdclass, type, &source,
					    &dctx, 0, &target1);
		dns_decompress_invalidate(&dctx);
		if (wire_data[i].ok)
			ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
		else
			ATF_REQUIRE(result != ISC_R_SUCCESS);
		if (result != ISC_R_SUCCESS)
			continue;
		result = dns_rdata_tostruct(&rdata, &csync, NULL);
		ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
		isc_buffer_init(&target2, buf2, sizeof(buf2));
		dns_rdata_reset(&rdata);
		result = dns_rdata_fromstruct(&rdata, rdclass, type,
					      &csync, &target2);
		ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
		ATF_REQUIRE_EQ(isc_buffer_usedlength(&target2),
						     wire_data[i].len);
		ATF_REQUIRE_EQ(memcmp(buf2, wire_data[i].data,
				      wire_data[i].len), 0);
	}
}
예제 #4
0
ATF_TC_BODY(isdn, tc) {
	struct {
		unsigned char data[64];
		size_t len;
		isc_boolean_t ok;
	} test_data[] = {
		{
			/* "" */
			{ 0x00 }, 1, ISC_TRUE
		},
		{
			/* "\001" */
			{ 0x1, 0x01 }, 2, ISC_TRUE
		},
		{
			/* "\001" "" */
			{ 0x1, 0x01, 0x00 }, 3, ISC_TRUE
		},
		{
			/* "\000" "\001" */
			{ 0x1, 0x01, 0x01, 0x01 }, 4, ISC_TRUE
		},
		{
			/* sentinal */
			{ 0x00 }, 0, ISC_FALSE
		}
	};
	unsigned char buf1[1024];
	unsigned char buf2[1024];
	isc_buffer_t source, target1, target2;
	dns_rdata_t rdata;
	dns_decompress_t dctx;
	isc_result_t result;
	size_t i;
	dns_rdata_isdn_t isdn;

	UNUSED(tc);

	for (i = 0; test_data[i].len != 0; i++) {
		isc_buffer_init(&source, test_data[i].data, test_data[i].len);
		isc_buffer_add(&source, test_data[i].len);
		isc_buffer_setactive(&source, test_data[i].len);
		isc_buffer_init(&target1, buf1, sizeof(buf1));
		dns_rdata_init(&rdata);
		dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_ANY);
		result = dns_rdata_fromwire(&rdata, dns_rdataclass_in,
					    dns_rdatatype_isdn, &source,
					    &dctx, 0, &target1);
		dns_decompress_invalidate(&dctx);
		if (test_data[i].ok)
			ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
		else
			ATF_REQUIRE(result != ISC_R_SUCCESS);
		if (result != ISC_R_SUCCESS)
			continue;
		result = dns_rdata_tostruct(&rdata, &isdn, NULL);
		ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
		isc_buffer_init(&target2, buf2, sizeof(buf2));
		dns_rdata_reset(&rdata);
		result = dns_rdata_fromstruct(&rdata, dns_rdataclass_in,
					      dns_rdatatype_isdn, &isdn,
					      &target2);
		ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
		ATF_REQUIRE_EQ(isc_buffer_usedlength(&target2),
						     test_data[i].len);
		ATF_REQUIRE_EQ(memcmp(buf2, test_data[i].data,
				      test_data[i].len), 0);
	}
}
예제 #5
0
static void
viastruct(dns_rdata_t *rdata, isc_mem_t *mctx,
	  dns_rdata_t *rdata2, isc_buffer_t *b)
{
	isc_result_t result;
	void *sp = NULL;
	isc_boolean_t need_free = ISC_FALSE;
	dns_rdatatype_t rdt;
	dns_rdataclass_t rdc;

	UNUSED(rdata2);	/* XXXMPA remove when fromstruct is ready. */
	UNUSED(b);

	switch (rdata->type) {
	case dns_rdatatype_a6: {
		static dns_rdata_in_a6_t in_a6;
		result = dns_rdata_tostruct(rdata, sp = &in_a6, NULL);
		break;
	}
	case dns_rdatatype_a: {
		switch (rdata->rdclass) {
		case dns_rdataclass_hs: {
			static dns_rdata_hs_a_t hs_a;
			result = dns_rdata_tostruct(rdata, sp = &hs_a, NULL);
			break;
		}
		case dns_rdataclass_in: {
			static dns_rdata_in_a_t in_a;
			result = dns_rdata_tostruct(rdata, sp = &in_a, NULL);
			break;
		}
		default:
			result = ISC_R_NOTIMPLEMENTED;
			break;
		}
		break;
	}
	case dns_rdatatype_aaaa: {
		static dns_rdata_in_aaaa_t in_aaaa;
		result = dns_rdata_tostruct(rdata, sp = &in_aaaa, NULL);
		break;
	}
	case dns_rdatatype_afsdb: {
		static dns_rdata_afsdb_t afsdb;
		result = dns_rdata_tostruct(rdata, sp = &afsdb, NULL);
		break;
	}
	case dns_rdatatype_any: {
		result = ISC_R_NOTIMPLEMENTED;
		break;
	}
	case dns_rdatatype_apl: {
		switch (rdata->rdclass) {
		case dns_rdataclass_in: {
			static dns_rdata_in_apl_t in_apl;
			result = dns_rdata_tostruct(rdata, sp = &in_apl, NULL);
			break;
		}
		default:
			result = ISC_R_NOTIMPLEMENTED;
			break;
		}
		break;
	}
	case dns_rdatatype_cert: {
		static dns_rdata_cert_t cert;
		result = dns_rdata_tostruct(rdata, sp = &cert, NULL);
		break;
	}
	case dns_rdatatype_cname: {
		static dns_rdata_cname_t cname;
		result = dns_rdata_tostruct(rdata, sp = &cname, NULL);
		break;
	}
	case dns_rdatatype_dname: {
		static dns_rdata_dname_t dname;
		result = dns_rdata_tostruct(rdata, sp = &dname, NULL);
		break;
	}
	case dns_rdatatype_gpos: {
		static dns_rdata_gpos_t gpos;
		result = dns_rdata_tostruct(rdata, sp = &gpos, NULL);
		break;
	}
	case dns_rdatatype_hinfo: {
		static dns_rdata_hinfo_t hinfo;
		result = dns_rdata_tostruct(rdata, sp = &hinfo, NULL);
		break;
	}
	case dns_rdatatype_isdn: {
		static dns_rdata_isdn_t isdn;
		result = dns_rdata_tostruct(rdata, sp = &isdn, NULL);
		break;
	}
	case dns_rdatatype_key: {
		static dns_rdata_key_t key;
		result = dns_rdata_tostruct(rdata, sp = &key, NULL);
		break;
	}
	case dns_rdatatype_kx: {
		static dns_rdata_in_kx_t in_kx;
		result = dns_rdata_tostruct(rdata, sp = &in_kx, NULL);
		break;
	}
	case dns_rdatatype_loc: {
		static dns_rdata_loc_t loc;
		result = dns_rdata_tostruct(rdata, sp = &loc, NULL);
		break;
	}
	case dns_rdatatype_mb: {
		static dns_rdata_mb_t mb;
		result = dns_rdata_tostruct(rdata, sp = &mb, NULL);
		break;
	}
	case dns_rdatatype_md: {
		static dns_rdata_md_t md;
		result = dns_rdata_tostruct(rdata, sp = &md, NULL);
		break;
	}
	case dns_rdatatype_mf: {
		static dns_rdata_mf_t mf;
		result = dns_rdata_tostruct(rdata, sp = &mf, NULL);
		break;
	}
	case dns_rdatatype_mg: {
		static dns_rdata_mg_t mg;
		result = dns_rdata_tostruct(rdata, sp = &mg, NULL);
		break;
	}
	case dns_rdatatype_minfo: {
		static dns_rdata_minfo_t minfo;
		result = dns_rdata_tostruct(rdata, sp = &minfo, NULL);
		break;
	}
	case dns_rdatatype_mr: {
		static dns_rdata_mr_t mr;
		result = dns_rdata_tostruct(rdata, sp = &mr, NULL);
		break;
	}
	case dns_rdatatype_mx: {
		static dns_rdata_mx_t mx;
		result = dns_rdata_tostruct(rdata, sp = &mx, NULL);
		break;
	}
	case dns_rdatatype_naptr: {
		static dns_rdata_naptr_t naptr;
		result = dns_rdata_tostruct(rdata, sp = &naptr, NULL);
		break;
	}
	case dns_rdatatype_ns: {
		static dns_rdata_ns_t ns;
		result = dns_rdata_tostruct(rdata, sp = &ns, NULL);
		break;
	}
	case dns_rdatatype_nsap: {
		static dns_rdata_in_nsap_t in_nsap;
		result = dns_rdata_tostruct(rdata, sp = &in_nsap, NULL);
		break;
	}
	case dns_rdatatype_nsap_ptr: {
		static dns_rdata_in_nsap_ptr_t in_nsap_ptr;
		result = dns_rdata_tostruct(rdata, sp = &in_nsap_ptr, NULL);
		break;
	}
	case dns_rdatatype_null: {
		static dns_rdata_null_t null;
		result = dns_rdata_tostruct(rdata, sp = &null, NULL);
		break;
	}
	case dns_rdatatype_nxt: {
		static dns_rdata_nxt_t nxt;
		result = dns_rdata_tostruct(rdata, sp = &nxt, NULL);
		break;
	}
	case dns_rdatatype_opt: {
		static dns_rdata_opt_t opt;
		result = dns_rdata_tostruct(rdata, sp = &opt, NULL);
		break;
	}
	case dns_rdatatype_ptr: {
		static dns_rdata_ptr_t ptr;
		result = dns_rdata_tostruct(rdata, sp = &ptr, NULL);
		break;
	}
	case dns_rdatatype_px: {
		static dns_rdata_in_px_t in_px;
		result = dns_rdata_tostruct(rdata, sp = &in_px, NULL);
		break;
	}
	case dns_rdatatype_rp: {
		static dns_rdata_rp_t rp;
		result = dns_rdata_tostruct(rdata, sp = &rp, NULL);
		break;
	}
	case dns_rdatatype_rt: {
		static dns_rdata_rt_t rt;
		result = dns_rdata_tostruct(rdata, sp = &rt, NULL);
		break;
	}
	case dns_rdatatype_sig: {
		static dns_rdata_sig_t sig;
		result = dns_rdata_tostruct(rdata, sp = &sig, NULL);
		break;
	}
	case dns_rdatatype_soa: {
		static dns_rdata_soa_t soa;
		result = dns_rdata_tostruct(rdata, sp = &soa, NULL);
		break;
	}
	case dns_rdatatype_srv: {
		static dns_rdata_in_srv_t in_srv;
		result = dns_rdata_tostruct(rdata, sp = &in_srv, NULL);
		break;
	}
	case dns_rdatatype_tkey: {
		static dns_rdata_tkey_t tkey;
		result = dns_rdata_tostruct(rdata, sp = &tkey, NULL);
		break;
	}
	case dns_rdatatype_tsig: {
		static dns_rdata_any_tsig_t tsig;
		result = dns_rdata_tostruct(rdata, sp = &tsig, NULL);
		break;
	}
	case dns_rdatatype_txt: {
		static dns_rdata_txt_t txt;
		result = dns_rdata_tostruct(rdata, sp = &txt, NULL);
		break;
	}
	case dns_rdatatype_spf: {
		static dns_rdata_spf_t spf;
		result = dns_rdata_tostruct(rdata, sp = &spf, NULL);
		break;
	}
	case dns_rdatatype_unspec: {
		static dns_rdata_unspec_t unspec;
		result = dns_rdata_tostruct(rdata, sp = &unspec, NULL);
		break;
	}
	case dns_rdatatype_uri: {
		static dns_rdata_uri_t uri;
		result = dns_rdata_tostruct(rdata, sp = &uri, NULL);
		break;
	}
	case dns_rdatatype_wks: {
		static dns_rdata_in_wks_t in_wks;
		result = dns_rdata_tostruct(rdata, sp = &in_wks, NULL);
		break;
	}
	case dns_rdatatype_x25: {
		static dns_rdata_x25_t x25;
		result = dns_rdata_tostruct(rdata, sp = &x25, NULL);
		break;
	}
	case dns_rdatatype_nsec: {
		static dns_rdata_nsec_t nsec;
		result = dns_rdata_tostruct(rdata, sp = &nsec, NULL);
		break;
	}
	case dns_rdatatype_rrsig: {
		static dns_rdata_rrsig_t rrsig;
		result = dns_rdata_tostruct(rdata, sp = &rrsig, NULL);
		break;
	}
	case dns_rdatatype_dnskey: {
		static dns_rdata_dnskey_t dnskey;
		result = dns_rdata_tostruct(rdata, sp = &dnskey, NULL);
		break;
	}
	default:
		result = ISC_R_NOTIMPLEMENTED;
		break;
	}
	if (result != ISC_R_SUCCESS)
		fprintf(stdout, "viastruct: tostruct %d %d return %s\n",
			rdata->type, rdata->rdclass,
			dns_result_totext(result));
	else
		dns_rdata_freestruct(sp);

	switch (rdata->type) {
	case dns_rdatatype_a6: {
		static dns_rdata_in_a6_t in_a6;
		result = dns_rdata_tostruct(rdata, sp = &in_a6, mctx);
		break;
	}
	case dns_rdatatype_a: {
		switch (rdata->rdclass) {
		case dns_rdataclass_hs: {
			static dns_rdata_hs_a_t hs_a;
			result = dns_rdata_tostruct(rdata, sp = &hs_a, mctx);
			break;
		}
		case dns_rdataclass_in: {
			static dns_rdata_in_a_t in_a;
			result = dns_rdata_tostruct(rdata, sp = &in_a, mctx);
			break;
		}
		default:
			result = ISC_R_NOTIMPLEMENTED;
			break;
		}
		break;
	}
	case dns_rdatatype_aaaa: {
		static dns_rdata_in_aaaa_t in_aaaa;
		result = dns_rdata_tostruct(rdata, sp = &in_aaaa, mctx);
		break;
	}
	case dns_rdatatype_afsdb: {
		static dns_rdata_afsdb_t afsdb;
		result = dns_rdata_tostruct(rdata, sp = &afsdb, mctx);
		break;
	}
	case dns_rdatatype_any: {
		result = ISC_R_NOTIMPLEMENTED;
		break;
	}
	case dns_rdatatype_apl: {
		switch (rdata->rdclass) {
		case dns_rdataclass_in: {
			static dns_rdata_in_apl_t in_apl;
			result = dns_rdata_tostruct(rdata, sp = &in_apl, mctx);
			break;
		}
		default:
			result = ISC_R_NOTIMPLEMENTED;
			break;
		}
		break;
	}
	case dns_rdatatype_cert: {
		static dns_rdata_cert_t cert;
		result = dns_rdata_tostruct(rdata, sp = &cert, mctx);
		break;
	}
	case dns_rdatatype_cname: {
		static dns_rdata_cname_t cname;
		result = dns_rdata_tostruct(rdata, sp = &cname, mctx);
		break;
	}
	case dns_rdatatype_dname: {
		static dns_rdata_dname_t dname;
		result = dns_rdata_tostruct(rdata, sp = &dname, mctx);
		break;
	}
	case dns_rdatatype_gpos: {
		static dns_rdata_gpos_t gpos;
		result = dns_rdata_tostruct(rdata, sp = &gpos, mctx);
		break;
	}
	case dns_rdatatype_hinfo: {
		static dns_rdata_hinfo_t hinfo;
		result = dns_rdata_tostruct(rdata, sp = &hinfo, mctx);
		break;
	}
	case dns_rdatatype_isdn: {
		static dns_rdata_isdn_t isdn;
		result = dns_rdata_tostruct(rdata, sp = &isdn, mctx);
		break;
	}
	case dns_rdatatype_key: {
		static dns_rdata_key_t key;
		result = dns_rdata_tostruct(rdata, sp = &key, mctx);
		break;
	}
	case dns_rdatatype_kx: {
		static dns_rdata_in_kx_t in_kx;
		result = dns_rdata_tostruct(rdata, sp = &in_kx, mctx);
		break;
	}
	case dns_rdatatype_loc: {
		static dns_rdata_loc_t loc;
		result = dns_rdata_tostruct(rdata, sp = &loc, mctx);
		break;
	}
	case dns_rdatatype_mb: {
		static dns_rdata_mb_t mb;
		result = dns_rdata_tostruct(rdata, sp = &mb, mctx);
		break;
	}
	case dns_rdatatype_md: {
		static dns_rdata_md_t md;
		result = dns_rdata_tostruct(rdata, sp = &md, mctx);
		break;
	}
	case dns_rdatatype_mf: {
		static dns_rdata_mf_t mf;
		result = dns_rdata_tostruct(rdata, sp = &mf, mctx);
		break;
	}
	case dns_rdatatype_mg: {
		static dns_rdata_mg_t mg;
		result = dns_rdata_tostruct(rdata, sp = &mg, mctx);
		break;
	}
	case dns_rdatatype_minfo: {
		static dns_rdata_minfo_t minfo;
		result = dns_rdata_tostruct(rdata, sp = &minfo, mctx);
		break;
	}
	case dns_rdatatype_mr: {
		static dns_rdata_mr_t mr;
		result = dns_rdata_tostruct(rdata, sp = &mr, mctx);
		break;
	}
	case dns_rdatatype_mx: {
		static dns_rdata_mx_t mx;
		result = dns_rdata_tostruct(rdata, sp = &mx, mctx);
		break;
	}
	case dns_rdatatype_naptr: {
		static dns_rdata_naptr_t naptr;
		result = dns_rdata_tostruct(rdata, sp = &naptr, mctx);
		break;
	}
	case dns_rdatatype_ns: {
		static dns_rdata_ns_t ns;
		result = dns_rdata_tostruct(rdata, sp = &ns, mctx);
		break;
	}
	case dns_rdatatype_nsap: {
		static dns_rdata_in_nsap_t in_nsap;
		result = dns_rdata_tostruct(rdata, sp = &in_nsap, mctx);
		break;
	}
	case dns_rdatatype_nsap_ptr: {
		static dns_rdata_in_nsap_ptr_t in_nsap_ptr;
		result = dns_rdata_tostruct(rdata, sp = &in_nsap_ptr, mctx);
		break;
	}
	case dns_rdatatype_null: {
		static dns_rdata_null_t null;
		result = dns_rdata_tostruct(rdata, sp = &null, mctx);
		break;
	}
	case dns_rdatatype_nxt: {
		static dns_rdata_nxt_t nxt;
		result = dns_rdata_tostruct(rdata, sp = &nxt, mctx);
		break;
	}
	case dns_rdatatype_opt: {
		static dns_rdata_opt_t opt;
		result = dns_rdata_tostruct(rdata, sp = &opt, mctx);
		break;
	}
	case dns_rdatatype_ptr: {
		static dns_rdata_ptr_t ptr;
		result = dns_rdata_tostruct(rdata, sp = &ptr, mctx);
		break;
	}
	case dns_rdatatype_px: {
		static dns_rdata_in_px_t in_px;
		result = dns_rdata_tostruct(rdata, sp = &in_px, mctx);
		break;
	}
	case dns_rdatatype_rp: {
		static dns_rdata_rp_t rp;
		result = dns_rdata_tostruct(rdata, sp = &rp, mctx);
		break;
	}
	case dns_rdatatype_rt: {
		static dns_rdata_rt_t rt;
		result = dns_rdata_tostruct(rdata, sp = &rt, mctx);
		break;
	}
	case dns_rdatatype_sig: {
		static dns_rdata_sig_t sig;
		result = dns_rdata_tostruct(rdata, sp = &sig, mctx);
		break;
	}
	case dns_rdatatype_soa: {
		static dns_rdata_soa_t soa;
		result = dns_rdata_tostruct(rdata, sp = &soa, mctx);
		break;
	}
	case dns_rdatatype_srv: {
		static dns_rdata_in_srv_t in_srv;
		result = dns_rdata_tostruct(rdata, sp = &in_srv, mctx);
		break;
	}
	case dns_rdatatype_tkey: {
		static dns_rdata_tkey_t tkey;
		result = dns_rdata_tostruct(rdata, sp = &tkey, mctx);
		break;
	}
	case dns_rdatatype_tsig: {
		static dns_rdata_any_tsig_t tsig;
		result = dns_rdata_tostruct(rdata, sp = &tsig, mctx);
		break;
	}
	case dns_rdatatype_txt: {
		static dns_rdata_txt_t txt;
		result = dns_rdata_tostruct(rdata, sp = &txt, mctx);
		break;
	}
	case dns_rdatatype_spf: {
		static dns_rdata_spf_t spf;
		result = dns_rdata_tostruct(rdata, sp = &spf, mctx);
		break;
	}
	case dns_rdatatype_unspec: {
		static dns_rdata_unspec_t unspec;
		result = dns_rdata_tostruct(rdata, sp = &unspec, mctx);
		break;
	}
	case dns_rdatatype_uri: {
		static dns_rdata_uri_t uri;
		result = dns_rdata_tostruct(rdata, sp = &uri, mctx);
		break;
	}
	case dns_rdatatype_wks: {
		static dns_rdata_in_wks_t in_wks;
		result = dns_rdata_tostruct(rdata, sp = &in_wks, mctx);
		break;
	}
	case dns_rdatatype_x25: {
		static dns_rdata_x25_t x25;
		result = dns_rdata_tostruct(rdata, sp = &x25, mctx);
		break;
	}
	case dns_rdatatype_nsec: {
		static dns_rdata_nsec_t nsec;
		result = dns_rdata_tostruct(rdata, sp = &nsec, mctx);
		break;
	}
	case dns_rdatatype_rrsig: {
		static dns_rdata_rrsig_t rrsig;
		result = dns_rdata_tostruct(rdata, sp = &rrsig, mctx);
		break;
	}
	case dns_rdatatype_dnskey: {
		static dns_rdata_dnskey_t dnskey;
		result = dns_rdata_tostruct(rdata, sp = &dnskey, mctx);
		break;
	}
	default:
		result = ISC_R_NOTIMPLEMENTED;
		break;
	}
	if (result != ISC_R_SUCCESS)
		fprintf(stdout, "viastruct: tostruct %d %d return %s\n",
			rdata->type, rdata->rdclass,
			dns_result_totext(result));
	else {
		need_free = ISC_TRUE;

		rdc = rdata->rdclass;
		rdt = rdata->type;
		result = dns_rdata_fromstruct(rdata2, rdc, rdt, sp, b);
		if (result != ISC_R_SUCCESS)
			fprintf(stdout,
				"viastruct: fromstruct %d %d return %s\n",
				rdata->type, rdata->rdclass,
				dns_result_totext(result));
		else if (rdata->length != rdata2->length ||
			 memcmp(rdata->data, rdata2->data, rdata->length) != 0)
		{
			isc_uint32_t i;
			isc_uint32_t l;

			fprintf(stdout, "viastruct: memcmp failed\n");

			fprintf(stdout, "%d %d\n",
				rdata->length, rdata2->length);
			l = rdata->length;
			if (rdata2->length < l)
				l = rdata2->length;
			for (i = 0; i < l; i++)
				fprintf(stdout, "%02x %02x\n",
					rdata->data[i], rdata2->data[i]);
		}
	}
#if 0
	switch (rdata->type) {
	case dns_rdatatype_a6: {
		dns_rdata_in_a6_t in_a6;
		result = dns_rdata_fromstruct(rdata2, rdc, rdt, &in_a6, b);
		break;
	}
	case dns_rdatatype_a: {
		switch (rdata->rdclass) {
		case dns_rdataclass_hs: {
			dns_rdata_hs_a_t hs_a;
			result = dns_rdata_fromstruct(rdata2, rdc, rdt,
						      &hs_a, b);
			break;
		}
		case dns_rdataclass_in: {
			dns_rdata_in_a_t in_a;
			result = dns_rdata_fromstruct(rdata2, rdc, rdt,
						      &in_a, b);
			break;
		}
		default:
			result = ISC_R_NOTIMPLEMENTED;
			break;
		}
		break;
	}
	case dns_rdatatype_aaaa: {
		dns_rdata_in_aaaa_t in_aaaa;
		result = dns_rdata_fromstruct(rdata2, rdc, rdt, &in_aaaa, b);
		break;
	}
	case dns_rdatatype_afsdb: {
		dns_rdata_afsdb_t afsdb;
		result = dns_rdata_fromstruct(rdata2, rdc, rdt, &afsdb, b);
		break;
	}
	case dns_rdatatype_any: {
		result = ISC_R_NOTIMPLEMENTED;
		break;
	}
	case dns_rdatatype_apl: {
		switch (rdata->rdclass) {
		case dns_rdataclass_in: {
			dns_rdata_in_apl_t in_apl;
			result = dns_rdata_fromstruct(rdata, rdc, rdt, &in_apl,							      b);
			break;
		}
		default:
			result = ISC_R_NOTIMPLEMENTED;
			break;
		}
		break;
	}
	case dns_rdatatype_cert: {
		dns_rdata_cert_t cert;
		result = dns_rdata_fromstruct(rdata2, rdc, rdt, &cert, b);
		break;
	}
	case dns_rdatatype_cname: {
		dns_rdata_cname_t cname;
		result = dns_rdata_fromstruct(rdata2, rdc, rdt, &cname, b);
		break;
	}
	case dns_rdatatype_dname: {
		dns_rdata_dname_t dname;
		result = dns_rdata_fromstruct(rdata2, rdc, rdt, &dname, b);
		break;
	}
	case dns_rdatatype_gpos: {
		dns_rdata_gpos_t gpos;
		result = dns_rdata_fromstruct(rdata2, rdc, rdt, &gpos, b);
		break;
	}
	case dns_rdatatype_hinfo: {
		dns_rdata_hinfo_t hinfo;
		result = dns_rdata_fromstruct(rdata2, rdc, rdt, &hinfo, b);
		break;
	}
	case dns_rdatatype_isdn: {
		dns_rdata_isdn_t isdn;
		result = dns_rdata_fromstruct(rdata2, rdc, rdt, &isdn, b);
		break;
	}
	case dns_rdatatype_key: {
		dns_rdata_key_t key;
		result = dns_rdata_fromstruct(rdata2, rdc, rdt, &key, b);
		break;
	}
	case dns_rdatatype_kx: {
		dns_rdata_in_kx_t in_kx;
		result = dns_rdata_fromstruct(rdata2, rdc, rdt, &in_kx, b);
		break;
	}
	case dns_rdatatype_loc: {
		dns_rdata_loc_t loc;
		result = dns_rdata_fromstruct(rdata2, rdc, rdt, &loc, b);
		break;
	}
	case dns_rdatatype_mb: {
		dns_rdata_mb_t mb;
		result = dns_rdata_fromstruct(rdata2, rdc, rdt, &mb, b);
		break;
	}
	case dns_rdatatype_md: {
		dns_rdata_md_t md;
		result = dns_rdata_fromstruct(rdata2, rdc, rdt, &md, b);
		break;
	}
	case dns_rdatatype_mf: {
		dns_rdata_mf_t mf;
		result = dns_rdata_fromstruct(rdata2, rdc, rdt, &mf, b);
		break;
	}
	case dns_rdatatype_mg: {
		dns_rdata_mg_t mg;
		result = dns_rdata_fromstruct(rdata2, rdc, rdt, &mg, b);
		break;
	}
	case dns_rdatatype_minfo: {
		dns_rdata_minfo_t minfo;
		result = dns_rdata_fromstruct(rdata2, rdc, rdt, &minfo, b);
		break;
	}
	case dns_rdatatype_mr: {
		dns_rdata_mr_t mr;
		result = dns_rdata_fromstruct(rdata2, rdc, rdt, &mr, b);
		break;
	}
	case dns_rdatatype_mx: {
		dns_rdata_mx_t mx;
		result = dns_rdata_fromstruct(rdata2, rdc, rdt, &mx, b);
		break;
	}
	case dns_rdatatype_naptr: {
		dns_rdata_naptr_t naptr;
		result = dns_rdata_fromstruct(rdata2, rdc, rdt, &naptr, b);
		break;
	}
	case dns_rdatatype_ns: {
		dns_rdata_ns_t ns;
		result = dns_rdata_fromstruct(rdata2, rdc, rdt, &ns, b);
		break;
	}
	case dns_rdatatype_nsap: {
		dns_rdata_in_nsap_t in_nsap;
		result = dns_rdata_fromstruct(rdata2, rdc, rdt, &in_nsap, b);
		break;
	}
	case dns_rdatatype_nsap_ptr: {
		dns_rdata_in_nsap_ptr_t in_nsap_ptr;
		result = dns_rdata_fromstruct(rdata2, rdc, rdt, &in_nsap_ptr,
					      b);
		break;
	}
	case dns_rdatatype_null: {
		dns_rdata_null_t null;
		result = dns_rdata_fromstruct(rdata2, rdc, rdt, &null, b);
		break;
	}
	case dns_rdatatype_nxt: {
		dns_rdata_nxt_t nxt;
		result = dns_rdata_fromstruct(rdata2, rdc, rdt, &nxt, b);
		break;
	}
	case dns_rdatatype_opt: {
		dns_rdata_opt_t opt;
		result = dns_rdata_fromstruct(rdata2, rdc, rdt, &opt, b);
		break;
	}
	case dns_rdatatype_ptr: {
		dns_rdata_ptr_t ptr;
		result = dns_rdata_fromstruct(rdata2, rdc, rdt, &ptr, b);
		break;
	}
	case dns_rdatatype_px: {
		dns_rdata_in_px_t in_px;
		result = dns_rdata_fromstruct(rdata2, rdc, rdt, &in_px, b);
		break;
	}
	case dns_rdatatype_rp: {
		dns_rdata_rp_t rp;
		result = dns_rdata_fromstruct(rdata2, rdc, rdt, &rp, b);
		break;
	}
	case dns_rdatatype_rt: {
		dns_rdata_rt_t rt;
		result = dns_rdata_fromstruct(rdata2, rdc, rdt, &rt, b);
		break;
	}
	case dns_rdatatype_sig: {
		dns_rdata_sig_t sig;
		result = dns_rdata_fromstruct(rdata2, rdc, rdt, &sig, b);
		break;
	}
	case dns_rdatatype_soa: {
		dns_rdata_soa_t soa;
		result = dns_rdata_fromstruct(rdata2, rdc, rdt, &soa, b);
		break;
	}
	case dns_rdatatype_srv: {
		dns_rdata_in_srv_t in_srv;
		result = dns_rdata_fromstruct(rdata2, rdc, rdt, &in_srv, b);
		break;
	}
	case dns_rdatatype_tkey: {
		dns_rdata_tkey_t tkey;
		result = dns_rdata_fromstruct(rdata2, rdc, rdt, &tkey, b);
		break;
	}
	case dns_rdatatype_tsig: {
		dns_rdata_any_tsig_t tsig;
		result = dns_rdata_fromstruct(rdata2, rdc, rdt, &tsig, b);
		break;
	}
	case dns_rdatatype_txt: {
		dns_rdata_txt_t txt;
		result = dns_rdata_fromstruct(rdata2, rdc, rdt, &txt, b);
		break;
	}
	case dns_rdatatype_spf: {
		dns_rdata_spf_t spf;
		result = dns_rdata_fromstruct(rdata2, rdc, rdt, &spf, b);
		break;
	}
	case dns_rdatatype_unspec: {
		dns_rdata_unspec_t unspec;
		result = dns_rdata_fromstruct(rdata2, rdc, rdt, &unspec, b);
		break;
	}
	case dns_rdatatype_uri: {
		dns_rdata_uri_t uri;
		result = dns_rdata_fromstruct(rdata2, rdc, rdt, &uri, b);
		break;
	}
	case dns_rdatatype_wks: {
		dns_rdata_in_wks_t in_wks;
		result = dns_rdata_fromstruct(rdata2, rdc, rdt, &in_wks, b);
		break;
	}
	case dns_rdatatype_x25: {
		dns_rdata_x25_t x25;
		result = dns_rdata_fromstruct(rdata2, rdc, rdt, &x25, b);
		break;
	}
	case dns_rdatatype_nsec: {
		dns_rdata_nsec_t nsec;
		result = dns_rdata_fromstruct(rdata2, rdc, rdt, &nsec, b);
		break;
	}
	case dns_rdatatype_rrsig: {
		dns_rdata_rrsig_t rrsig;
		result = dns_rdata_fromstruct(rdata2, rdc, rdt, &rrsig, b);
		break;
	}
	case dns_rdatatype_dnskey: {
		dns_rdata_dnskey_t dnskey;
		result = dns_rdata_fromstruct(rdata2, rdc, rdt, &dnskey, b);
		break;
	}
	default:
		result = ISC_R_NOTIMPLEMENTED;
		break;
	}
#endif
	if (need_free)
		dns_rdata_freestruct(sp);
}
예제 #6
0
파일: tsig.c 프로젝트: execunix/vinos
isc_result_t
dns_tsig_sign(dns_message_t *msg) {
	dns_tsigkey_t *key;
	dns_rdata_any_tsig_t tsig, querytsig;
	unsigned char data[128];
	isc_buffer_t databuf, sigbuf;
	isc_buffer_t *dynbuf;
	dns_name_t *owner;
	dns_rdata_t *rdata = NULL;
	dns_rdatalist_t *datalist;
	dns_rdataset_t *dataset;
	isc_region_t r;
	isc_stdtime_t now;
	isc_mem_t *mctx;
	dst_context_t *ctx = NULL;
	isc_result_t ret;
	unsigned char badtimedata[BADTIMELEN];
	unsigned int sigsize = 0;
	isc_boolean_t response = is_response(msg);

	REQUIRE(msg != NULL);
	REQUIRE(VALID_TSIG_KEY(dns_message_gettsigkey(msg)));

	/*
	 * If this is a response, there should be a query tsig.
	 */
	if (response && msg->querytsig == NULL)
		return (DNS_R_EXPECTEDTSIG);

	dynbuf = NULL;

	mctx = msg->mctx;
	key = dns_message_gettsigkey(msg);

	tsig.mctx = mctx;
	tsig.common.rdclass = dns_rdataclass_any;
	tsig.common.rdtype = dns_rdatatype_tsig;
	ISC_LINK_INIT(&tsig.common, link);
	dns_name_init(&tsig.algorithm, NULL);
	dns_name_clone(key->algorithm, &tsig.algorithm);

	isc_stdtime_get(&now);
	tsig.timesigned = now + msg->timeadjust;
	tsig.fudge = DNS_TSIG_FUDGE;

	tsig.originalid = msg->id;

	isc_buffer_init(&databuf, data, sizeof(data));

	if (response)
		tsig.error = msg->querytsigstatus;
	else
		tsig.error = dns_rcode_noerror;

	if (tsig.error != dns_tsigerror_badtime) {
		tsig.otherlen = 0;
		tsig.other = NULL;
	} else {
		isc_buffer_t otherbuf;

		tsig.otherlen = BADTIMELEN;
		tsig.other = badtimedata;
		isc_buffer_init(&otherbuf, tsig.other, tsig.otherlen);
		isc_buffer_putuint48(&otherbuf, tsig.timesigned);
	}

	if (key->key != NULL && tsig.error != dns_tsigerror_badsig) {
		unsigned char header[DNS_MESSAGE_HEADERLEN];
		isc_buffer_t headerbuf;
		isc_uint16_t digestbits;

		ret = dst_context_create3(key->key, mctx,
					  DNS_LOGCATEGORY_DNSSEC,
					  ISC_TRUE, &ctx);
		if (ret != ISC_R_SUCCESS)
			return (ret);

		/*
		 * If this is a response, digest the query signature.
		 */
		if (response) {
			dns_rdata_t querytsigrdata = DNS_RDATA_INIT;

			ret = dns_rdataset_first(msg->querytsig);
			if (ret != ISC_R_SUCCESS)
				goto cleanup_context;
			dns_rdataset_current(msg->querytsig, &querytsigrdata);
			ret = dns_rdata_tostruct(&querytsigrdata, &querytsig,
						 NULL);
			if (ret != ISC_R_SUCCESS)
				goto cleanup_context;
			isc_buffer_putuint16(&databuf, querytsig.siglen);
			if (isc_buffer_availablelength(&databuf) <
			    querytsig.siglen) {
				ret = ISC_R_NOSPACE;
				goto cleanup_context;
			}
			isc_buffer_putmem(&databuf, querytsig.signature,
					  querytsig.siglen);
			isc_buffer_usedregion(&databuf, &r);
			ret = dst_context_adddata(ctx, &r);
			if (ret != ISC_R_SUCCESS)
				goto cleanup_context;
		}
#if defined(__clang__)  && \
       ( __clang_major__ < 3 || \
	(__clang_major__ == 3 && __clang_minor__ < 2) || \
	(__clang_major__ == 4 && __clang_minor__ < 2))
	/* false positive: http://llvm.org/bugs/show_bug.cgi?id=14461 */
		else memset(&querytsig, 0, sizeof(querytsig));
#endif

		/*
		 * Digest the header.
		 */
		isc_buffer_init(&headerbuf, header, sizeof(header));
		dns_message_renderheader(msg, &headerbuf);
		isc_buffer_usedregion(&headerbuf, &r);
		ret = dst_context_adddata(ctx, &r);
		if (ret != ISC_R_SUCCESS)
			goto cleanup_context;

		/*
		 * Digest the remainder of the message.
		 */
		isc_buffer_usedregion(msg->buffer, &r);
		isc_region_consume(&r, DNS_MESSAGE_HEADERLEN);
		ret = dst_context_adddata(ctx, &r);
		if (ret != ISC_R_SUCCESS)
			goto cleanup_context;

		if (msg->tcp_continuation == 0) {
			/*
			 * Digest the name, class, ttl, alg.
			 */
			dns_name_toregion(&key->name, &r);
			ret = dst_context_adddata(ctx, &r);
			if (ret != ISC_R_SUCCESS)
				goto cleanup_context;

			isc_buffer_clear(&databuf);
			isc_buffer_putuint16(&databuf, dns_rdataclass_any);
			isc_buffer_putuint32(&databuf, 0); /* ttl */
			isc_buffer_usedregion(&databuf, &r);
			ret = dst_context_adddata(ctx, &r);
			if (ret != ISC_R_SUCCESS)
				goto cleanup_context;

			dns_name_toregion(&tsig.algorithm, &r);
			ret = dst_context_adddata(ctx, &r);
			if (ret != ISC_R_SUCCESS)
				goto cleanup_context;

		}
		/* Digest the timesigned and fudge */
		isc_buffer_clear(&databuf);
		if (tsig.error == dns_tsigerror_badtime) {
			INSIST(response);
			tsig.timesigned = querytsig.timesigned;
		}
		isc_buffer_putuint48(&databuf, tsig.timesigned);
		isc_buffer_putuint16(&databuf, tsig.fudge);
		isc_buffer_usedregion(&databuf, &r);
		ret = dst_context_adddata(ctx, &r);
		if (ret != ISC_R_SUCCESS)
			goto cleanup_context;

		if (msg->tcp_continuation == 0) {
			/*
			 * Digest the error and other data length.
			 */
			isc_buffer_clear(&databuf);
			isc_buffer_putuint16(&databuf, tsig.error);
			isc_buffer_putuint16(&databuf, tsig.otherlen);

			isc_buffer_usedregion(&databuf, &r);
			ret = dst_context_adddata(ctx, &r);
			if (ret != ISC_R_SUCCESS)
				goto cleanup_context;

			/*
			 * Digest other data.
			 */
			if (tsig.otherlen > 0) {
				r.length = tsig.otherlen;
				r.base = tsig.other;
				ret = dst_context_adddata(ctx, &r);
				if (ret != ISC_R_SUCCESS)
					goto cleanup_context;
			}
		}

		ret = dst_key_sigsize(key->key, &sigsize);
		if (ret != ISC_R_SUCCESS)
			goto cleanup_context;
		tsig.signature = (unsigned char *) isc_mem_get(mctx, sigsize);
		if (tsig.signature == NULL) {
			ret = ISC_R_NOMEMORY;
			goto cleanup_context;
		}

		isc_buffer_init(&sigbuf, tsig.signature, sigsize);
		ret = dst_context_sign(ctx, &sigbuf);
		if (ret != ISC_R_SUCCESS)
			goto cleanup_signature;
		dst_context_destroy(&ctx);
		digestbits = dst_key_getbits(key->key);
		if (digestbits != 0) {
			unsigned int bytes = (digestbits + 1) / 8;
			if (response && bytes < querytsig.siglen)
				bytes = querytsig.siglen;
			if (bytes > isc_buffer_usedlength(&sigbuf))
				bytes = isc_buffer_usedlength(&sigbuf);
			tsig.siglen = bytes;
		} else
			tsig.siglen = isc_buffer_usedlength(&sigbuf);
	} else {
		tsig.siglen = 0;
		tsig.signature = NULL;
	}

	ret = dns_message_gettemprdata(msg, &rdata);
	if (ret != ISC_R_SUCCESS)
		goto cleanup_signature;
	ret = isc_buffer_allocate(msg->mctx, &dynbuf, 512);
	if (ret != ISC_R_SUCCESS)
		goto cleanup_rdata;
	ret = dns_rdata_fromstruct(rdata, dns_rdataclass_any,
				   dns_rdatatype_tsig, &tsig, dynbuf);
	if (ret != ISC_R_SUCCESS)
		goto cleanup_dynbuf;

	dns_message_takebuffer(msg, &dynbuf);

	if (tsig.signature != NULL) {
		isc_mem_put(mctx, tsig.signature, sigsize);
		tsig.signature = NULL;
	}

	owner = NULL;
	ret = dns_message_gettempname(msg, &owner);
	if (ret != ISC_R_SUCCESS)
		goto cleanup_rdata;
	dns_name_init(owner, NULL);
	ret = dns_name_dup(&key->name, msg->mctx, owner);
	if (ret != ISC_R_SUCCESS)
		goto cleanup_owner;

	datalist = NULL;
	ret = dns_message_gettemprdatalist(msg, &datalist);
	if (ret != ISC_R_SUCCESS)
		goto cleanup_owner;
	dataset = NULL;
	ret = dns_message_gettemprdataset(msg, &dataset);
	if (ret != ISC_R_SUCCESS)
		goto cleanup_rdatalist;
	datalist->rdclass = dns_rdataclass_any;
	datalist->type = dns_rdatatype_tsig;
	datalist->covers = 0;
	datalist->ttl = 0;
	ISC_LIST_INIT(datalist->rdata);
	ISC_LIST_APPEND(datalist->rdata, rdata, link);
	RUNTIME_CHECK(dns_rdatalist_tordataset(datalist, dataset)
		      == ISC_R_SUCCESS);
	msg->tsig = dataset;
	msg->tsigname = owner;

	/* Windows does not like the tsig name being compressed. */
	msg->tsigname->attributes |= DNS_NAMEATTR_NOCOMPRESS;

	return (ISC_R_SUCCESS);

 cleanup_rdatalist:
	dns_message_puttemprdatalist(msg, &datalist);
 cleanup_owner:
	dns_message_puttempname(msg, &owner);
	goto cleanup_rdata;
 cleanup_dynbuf:
	isc_buffer_free(&dynbuf);
 cleanup_rdata:
	dns_message_puttemprdata(msg, &rdata);
 cleanup_signature:
	if (tsig.signature != NULL)
		isc_mem_put(mctx, tsig.signature, sigsize);
 cleanup_context:
	if (ctx != NULL)
		dst_context_destroy(&ctx);
	return (ret);
}
예제 #7
0
isc_result_t
dns_tsig_sign(dns_message_t *msg) {
	dns_tsigkey_t *key;
	dns_rdata_any_tsig_t tsig, querytsig;
	unsigned char data[128];
	isc_buffer_t databuf, sigbuf;
	isc_buffer_t *dynbuf;
	dns_name_t *owner;
	dns_rdata_t *rdata;
	dns_rdatalist_t *datalist;
	dns_rdataset_t *dataset;
	isc_region_t r;
	isc_stdtime_t now;
	isc_mem_t *mctx;
	dst_context_t *ctx = NULL;
	isc_result_t ret;
	unsigned char badtimedata[BADTIMELEN];
	unsigned int sigsize = 0;

	REQUIRE(msg != NULL);
	REQUIRE(VALID_TSIG_KEY(dns_message_gettsigkey(msg)));

	/*
	 * If this is a response, there should be a query tsig.
	 */
	if (is_response(msg) && msg->querytsig == NULL)
		return (DNS_R_EXPECTEDTSIG);

	dynbuf = NULL;

	mctx = msg->mctx;
	key = dns_message_gettsigkey(msg);

	tsig.mctx = mctx;
	tsig.common.rdclass = dns_rdataclass_any;
	tsig.common.rdtype = dns_rdatatype_tsig;
	ISC_LINK_INIT(&tsig.common, link);
	dns_name_init(&tsig.algorithm, NULL);
	dns_name_clone(key->algorithm, &tsig.algorithm);

	isc_stdtime_get(&now);
	tsig.timesigned = now + msg->timeadjust;
	tsig.fudge = DNS_TSIG_FUDGE;

	tsig.originalid = msg->id;

	isc_buffer_init(&databuf, data, sizeof(data));

	if (is_response(msg))
		tsig.error = msg->querytsigstatus;
	else
		tsig.error = dns_rcode_noerror;

	if (tsig.error != dns_tsigerror_badtime) {
		tsig.otherlen = 0;
		tsig.other = NULL;
	} else {
		isc_buffer_t otherbuf;

		tsig.otherlen = BADTIMELEN;
		tsig.other = badtimedata;
		isc_buffer_init(&otherbuf, tsig.other, tsig.otherlen);
		buffer_putuint48(&otherbuf, tsig.timesigned);
	}

	if (key->key != NULL && tsig.error != dns_tsigerror_badsig) {
		unsigned char header[DNS_MESSAGE_HEADERLEN];
		isc_buffer_t headerbuf;

		ret = dst_context_create(key->key, mctx, &ctx);
		if (ret != ISC_R_SUCCESS)
			return (ret);

		/*
		 * If this is a response, digest the query signature.
		 */
		if (is_response(msg)) {
			dns_rdata_t querytsigrdata = DNS_RDATA_INIT;

			ret = dns_rdataset_first(msg->querytsig);
			if (ret != ISC_R_SUCCESS)
				goto cleanup_context;
			dns_rdataset_current(msg->querytsig, &querytsigrdata);
			ret = dns_rdata_tostruct(&querytsigrdata, &querytsig,
						 NULL);
			if (ret != ISC_R_SUCCESS)
				goto cleanup_context;
			isc_buffer_putuint16(&databuf, querytsig.siglen);
			if (isc_buffer_availablelength(&databuf) <
			    querytsig.siglen)
			{
				ret = ISC_R_NOSPACE;
				goto cleanup_context;
			}
			isc_buffer_putmem(&databuf, querytsig.signature,
					  querytsig.siglen);
			isc_buffer_usedregion(&databuf, &r);
			ret = dst_context_adddata(ctx, &r);
			if (ret != ISC_R_SUCCESS)
				goto cleanup_context;
		}

		/*
		 * Digest the header.
		 */
		isc_buffer_init(&headerbuf, header, sizeof(header));
		dns_message_renderheader(msg, &headerbuf);
		isc_buffer_usedregion(&headerbuf, &r);
		ret = dst_context_adddata(ctx, &r);
		if (ret != ISC_R_SUCCESS)
			goto cleanup_context;

		/*
		 * Digest the remainder of the message.
		 */
		isc_buffer_usedregion(msg->buffer, &r);
		isc_region_consume(&r, DNS_MESSAGE_HEADERLEN);
		ret = dst_context_adddata(ctx, &r);
		if (ret != ISC_R_SUCCESS)
			goto cleanup_context;

		if (msg->tcp_continuation == 0) {
			/*
			 * Digest the name, class, ttl, alg.
			 */
			dns_name_toregion(&key->name, &r);
			ret = dst_context_adddata(ctx, &r);
			if (ret != ISC_R_SUCCESS)
				goto cleanup_context;

			isc_buffer_clear(&databuf);
			isc_buffer_putuint16(&databuf, dns_rdataclass_any);
			isc_buffer_putuint32(&databuf, 0); /* ttl */
			isc_buffer_usedregion(&databuf, &r);
			ret = dst_context_adddata(ctx, &r);
			if (ret != ISC_R_SUCCESS)
				goto cleanup_context;

			dns_name_toregion(&tsig.algorithm, &r);
			ret = dst_context_adddata(ctx, &r);
			if (ret != ISC_R_SUCCESS)
				goto cleanup_context;

		}
		/* Digest the timesigned and fudge */
		isc_buffer_clear(&databuf);
		if (tsig.error == dns_tsigerror_badtime)
			tsig.timesigned = querytsig.timesigned;
		buffer_putuint48(&databuf, tsig.timesigned);
		isc_buffer_putuint16(&databuf, tsig.fudge);
		isc_buffer_usedregion(&databuf, &r);
		ret = dst_context_adddata(ctx, &r);
		if (ret != ISC_R_SUCCESS)
			goto cleanup_context;

		if (msg->tcp_continuation == 0) {
			/*
			 * Digest the error and other data length.
			 */
			isc_buffer_clear(&databuf);
			isc_buffer_putuint16(&databuf, tsig.error);
			isc_buffer_putuint16(&databuf, tsig.otherlen);

			isc_buffer_usedregion(&databuf, &r);
			ret = dst_context_adddata(ctx, &r);
			if (ret != ISC_R_SUCCESS)
				goto cleanup_context;

			/*
			 * Digest the error and other data.
			 */
			if (tsig.otherlen > 0) {
				r.length = tsig.otherlen;
				r.base = tsig.other;
				ret = dst_context_adddata(ctx, &r);
				if (ret != ISC_R_SUCCESS)
					goto cleanup_context;
			}
		}

		ret = dst_key_sigsize(key->key, &sigsize);
		if (ret != ISC_R_SUCCESS)
			goto cleanup_context;
		tsig.signature = (unsigned char *) isc_mem_get(mctx, sigsize);
		if (tsig.signature == NULL) {
			ret = ISC_R_NOMEMORY;
			goto cleanup_context;
		}

		isc_buffer_init(&sigbuf, tsig.signature, sigsize);
		ret = dst_context_sign(ctx, &sigbuf);
		if (ret != ISC_R_SUCCESS)
			goto cleanup_signature;
		dst_context_destroy(&ctx);
		tsig.siglen = isc_buffer_usedlength(&sigbuf);
	} else {
		tsig.siglen = 0;
		tsig.signature = NULL;
	}

	rdata = NULL;
	ret = dns_message_gettemprdata(msg, &rdata);
	if (ret != ISC_R_SUCCESS)
		goto cleanup_signature;
	ret = isc_buffer_allocate(msg->mctx, &dynbuf, 512);
	if (ret != ISC_R_SUCCESS)
		goto cleanup_signature;
	ret = dns_rdata_fromstruct(rdata, dns_rdataclass_any,
				   dns_rdatatype_tsig, &tsig, dynbuf);
	if (ret != ISC_R_SUCCESS)
		goto cleanup_dynbuf;

	dns_message_takebuffer(msg, &dynbuf);

	if (tsig.signature != NULL) {
		isc_mem_put(mctx, tsig.signature, sigsize);
		tsig.signature = NULL;
	}

	owner = NULL;
	ret = dns_message_gettempname(msg, &owner);
	if (ret != ISC_R_SUCCESS)
		goto cleanup_dynbuf;
	dns_name_init(owner, NULL);
	ret = dns_name_dup(&key->name, msg->mctx, owner);
	if (ret != ISC_R_SUCCESS)
		goto cleanup_owner;

	datalist = NULL;
	ret = dns_message_gettemprdatalist(msg, &datalist);
	if (ret != ISC_R_SUCCESS)
		goto cleanup_owner;
	datalist->rdclass = dns_rdataclass_any;
	datalist->type = dns_rdatatype_tsig;
	datalist->covers = 0;
	datalist->ttl = 0;
	ISC_LIST_INIT(datalist->rdata);
	ISC_LIST_APPEND(datalist->rdata, rdata, link);
	dataset = NULL;
	ret = dns_message_gettemprdataset(msg, &dataset);
	if (ret != ISC_R_SUCCESS)
		goto cleanup_owner;
	dns_rdataset_init(dataset);
	RUNTIME_CHECK(dns_rdatalist_tordataset(datalist, dataset)
		      == ISC_R_SUCCESS);
	msg->tsig = dataset;
	msg->tsigname = owner;

	return (ISC_R_SUCCESS);

cleanup_owner:
	if (owner != NULL)
		dns_message_puttempname(msg, &owner);
cleanup_dynbuf:
	if (dynbuf != NULL)
		isc_buffer_free(&dynbuf);
cleanup_signature:
	if (tsig.signature != NULL)
		isc_mem_put(mctx, tsig.signature, sigsize);
cleanup_context:
	if (ctx != NULL)
		dst_context_destroy(&ctx);
	return (ret);
}
예제 #8
0
static void
resigned(isc_assertioncallback_t callback) {
	isc_result_t result;
	dns_rdataset_t rdataset, added;
	dns_dbnode_t *node = NULL;
	dns_rdatalist_t rdatalist;
	dns_rdata_rrsig_t rrsig;
	dns_rdata_t rdata = DNS_RDATA_INIT;
	isc_buffer_t b;
	unsigned char buf[1024];

	result = dns_test_begin(NULL, ISC_FALSE);
	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);

	setup_db();

	/*
	 * Create a dummy RRSIG record and set a resigning time.
	 */
	dns_rdataset_init(&added);
	dns_rdataset_init(&rdataset);
	dns_rdatalist_init(&rdatalist);
	isc_buffer_init(&b, buf, sizeof(buf));

	DNS_RDATACOMMON_INIT(&rrsig, dns_rdatatype_rrsig, dns_rdataclass_in);
	rrsig.covered = dns_rdatatype_a;
	rrsig.algorithm = 100;
	rrsig.labels = 0;
	rrsig.originalttl = 0;
	rrsig.timeexpire = 3600;
	rrsig.timesigned = 0;
	rrsig.keyid = 0;
	dns_name_init(&rrsig.signer, NULL);
	dns_name_clone(dns_rootname, &rrsig.signer);
	rrsig.siglen = 0;
	rrsig.signature = NULL;

	result = dns_rdata_fromstruct(&rdata, dns_rdataclass_in,
				      dns_rdatatype_rrsig, &rrsig, &b);
	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);

	rdatalist.rdclass = dns_rdataclass_in;
	rdatalist.type = dns_rdatatype_rrsig;
	ISC_LIST_APPEND(rdatalist.rdata, &rdata, link);

	result = dns_rdatalist_tordataset(&rdatalist, &rdataset);
	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);

	rdataset.attributes |= DNS_RDATASETATTR_RESIGN;
	rdataset.resign = 7200;

	result = dns_db_findnode(db1, dns_rootname, ISC_FALSE, &node);
	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);

	result = dns_db_addrdataset(db1, node, v1, 0, &rdataset, 0, &added);
	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);

	dns_db_detachnode(db1, &node);
	ATF_REQUIRE_EQ(node, NULL);

	isc_assertion_setcallback(callback);
	dns_db_resigned(db1, &added, VERSION(callback));
	if (callback != NULL)
		atf_tc_fail("dns_db_resigned did not assert");

	dns_rdataset_disassociate(&added);

	close_db();

	dns_test_end();
}
예제 #9
0
파일: dnssec.c 프로젝트: OPSF/uClinux
isc_result_t
dns_dnssec_signmessage(dns_message_t *msg, dst_key_t *key) {
	dns_rdata_sig_t sig;	/* SIG(0) */
	unsigned char data[512];
	unsigned char header[DNS_MESSAGE_HEADERLEN];
	isc_buffer_t headerbuf, databuf, sigbuf;
	unsigned int sigsize;
	isc_buffer_t *dynbuf = NULL;
	dns_rdata_t *rdata;
	dns_rdatalist_t *datalist;
	dns_rdataset_t *dataset;
	isc_region_t r;
	isc_stdtime_t now;
	dst_context_t *ctx = NULL;
	isc_mem_t *mctx;
	isc_result_t result;
	isc_boolean_t signeedsfree = ISC_TRUE;

	REQUIRE(msg != NULL);
	REQUIRE(key != NULL);

	if (is_response(msg))
		REQUIRE(msg->query.base != NULL);

	mctx = msg->mctx;

	memset(&sig, 0, sizeof(sig));

	sig.mctx = mctx;
	sig.common.rdclass = dns_rdataclass_any;
	sig.common.rdtype = dns_rdatatype_sig;	/* SIG(0) */
	ISC_LINK_INIT(&sig.common, link);

	sig.covered = 0;
	sig.algorithm = dst_key_alg(key);
	sig.labels = 0; /* the root name */
	sig.originalttl = 0;

	isc_stdtime_get(&now);
	sig.timesigned = now - DNS_TSIG_FUDGE;
	sig.timeexpire = now + DNS_TSIG_FUDGE;

	sig.keyid = dst_key_id(key);

	dns_name_init(&sig.signer, NULL);
	dns_name_clone(dst_key_name(key), &sig.signer);

	sig.siglen = 0;
	sig.signature = NULL;

	isc_buffer_init(&databuf, data, sizeof(data));

	RETERR(dst_context_create(key, mctx, &ctx));

	/*
	 * Digest the fields of the SIG - we can cheat and use
	 * dns_rdata_fromstruct.  Since siglen is 0, the digested data
	 * is identical to dns format.
	 */
	RETERR(dns_rdata_fromstruct(NULL, dns_rdataclass_any,
				    dns_rdatatype_sig /* SIG(0) */,
				    &sig, &databuf));
	isc_buffer_usedregion(&databuf, &r);
	RETERR(dst_context_adddata(ctx, &r));

	/*
	 * If this is a response, digest the query.
	 */
	if (is_response(msg))
		RETERR(dst_context_adddata(ctx, &msg->query));

	/*
	 * Digest the header.
	 */
	isc_buffer_init(&headerbuf, header, sizeof(header));
	dns_message_renderheader(msg, &headerbuf);
	isc_buffer_usedregion(&headerbuf, &r);
	RETERR(dst_context_adddata(ctx, &r));

	/*
	 * Digest the remainder of the message.
	 */
	isc_buffer_usedregion(msg->buffer, &r);
	isc_region_consume(&r, DNS_MESSAGE_HEADERLEN);
	RETERR(dst_context_adddata(ctx, &r));

	RETERR(dst_key_sigsize(key, &sigsize));
	sig.siglen = sigsize;
	sig.signature = (unsigned char *) isc_mem_get(mctx, sig.siglen);
	if (sig.signature == NULL) {
		result = ISC_R_NOMEMORY;
		goto failure;
	}

	isc_buffer_init(&sigbuf, sig.signature, sig.siglen);
	RETERR(dst_context_sign(ctx, &sigbuf));
	dst_context_destroy(&ctx);

	rdata = NULL;
	RETERR(dns_message_gettemprdata(msg, &rdata));
	RETERR(isc_buffer_allocate(msg->mctx, &dynbuf, 1024));
	RETERR(dns_rdata_fromstruct(rdata, dns_rdataclass_any,
				    dns_rdatatype_sig /* SIG(0) */,
				    &sig, dynbuf));

	isc_mem_put(mctx, sig.signature, sig.siglen);
	signeedsfree = ISC_FALSE;

	dns_message_takebuffer(msg, &dynbuf);

	datalist = NULL;
	RETERR(dns_message_gettemprdatalist(msg, &datalist));
	datalist->rdclass = dns_rdataclass_any;
	datalist->type = dns_rdatatype_sig;	/* SIG(0) */
	datalist->covers = 0;
	datalist->ttl = 0;
	ISC_LIST_INIT(datalist->rdata);
	ISC_LIST_APPEND(datalist->rdata, rdata, link);
	dataset = NULL;
	RETERR(dns_message_gettemprdataset(msg, &dataset));
	dns_rdataset_init(dataset);
	RUNTIME_CHECK(dns_rdatalist_tordataset(datalist, dataset) == ISC_R_SUCCESS);
	msg->sig0 = dataset;

	return (ISC_R_SUCCESS);

failure:
	if (dynbuf != NULL)
		isc_buffer_free(&dynbuf);
	if (signeedsfree)
		isc_mem_put(mctx, sig.signature, sig.siglen);
	if (ctx != NULL)
		dst_context_destroy(&ctx);

	return (result);
}
예제 #10
0
파일: dnssec.c 프로젝트: OPSF/uClinux
isc_result_t
dns_dnssec_sign(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
		isc_stdtime_t *inception, isc_stdtime_t *expire,
		isc_mem_t *mctx, isc_buffer_t *buffer, dns_rdata_t *sigrdata)
{
	dns_rdata_rrsig_t sig;
	dns_rdata_t tmpsigrdata;
	dns_rdata_t *rdatas;
	int nrdatas, i;
	isc_buffer_t sigbuf, envbuf;
	isc_region_t r;
	dst_context_t *ctx = NULL;
	isc_result_t ret;
	isc_buffer_t *databuf = NULL;
	char data[256 + 8];
	isc_uint32_t flags;
	unsigned int sigsize;
	dns_fixedname_t fnewname;

	REQUIRE(name != NULL);
	REQUIRE(dns_name_countlabels(name) <= 255);
	REQUIRE(set != NULL);
	REQUIRE(key != NULL);
	REQUIRE(inception != NULL);
	REQUIRE(expire != NULL);
	REQUIRE(mctx != NULL);
	REQUIRE(sigrdata != NULL);

	if (*inception >= *expire)
		return (DNS_R_INVALIDTIME);

	/*
	 * Is the key allowed to sign data?
	 */
	flags = dst_key_flags(key);
	if (flags & DNS_KEYTYPE_NOAUTH)
		return (DNS_R_KEYUNAUTHORIZED);
	if ((flags & DNS_KEYFLAG_OWNERMASK) != DNS_KEYOWNER_ZONE)
		return (DNS_R_KEYUNAUTHORIZED);

	sig.mctx = mctx;
	sig.common.rdclass = set->rdclass;
	sig.common.rdtype = dns_rdatatype_rrsig;
	ISC_LINK_INIT(&sig.common, link);

	dns_name_init(&sig.signer, NULL);
	dns_name_clone(dst_key_name(key), &sig.signer);

	sig.covered = set->type;
	sig.algorithm = dst_key_alg(key);
	sig.labels = dns_name_countlabels(name) - 1;
	if (dns_name_iswildcard(name))
		sig.labels--;
	sig.originalttl = set->ttl;
	sig.timesigned = *inception;
	sig.timeexpire = *expire;
	sig.keyid = dst_key_id(key);
	ret = dst_key_sigsize(key, &sigsize);
	if (ret != ISC_R_SUCCESS)
		return (ret);
	sig.siglen = sigsize;
	/*
	 * The actual contents of sig.signature are not important yet, since
	 * they're not used in digest_sig().
	 */
	sig.signature = isc_mem_get(mctx, sig.siglen);
	if (sig.signature == NULL)
		return (ISC_R_NOMEMORY);

	ret = isc_buffer_allocate(mctx, &databuf, sigsize + 256 + 18);
	if (ret != ISC_R_SUCCESS)
		goto cleanup_signature;

	dns_rdata_init(&tmpsigrdata);
	ret = dns_rdata_fromstruct(&tmpsigrdata, sig.common.rdclass,
				   sig.common.rdtype, &sig, databuf);
	if (ret != ISC_R_SUCCESS)
		goto cleanup_databuf;

	ret = dst_context_create(key, mctx, &ctx);
	if (ret != ISC_R_SUCCESS)
		goto cleanup_databuf;

	/*
	 * Digest the SIG rdata.
	 */
	ret = digest_sig(ctx, &tmpsigrdata, &sig);
	if (ret != ISC_R_SUCCESS)
		goto cleanup_context;

	dns_fixedname_init(&fnewname);
	RUNTIME_CHECK(dns_name_downcase(name, dns_fixedname_name(&fnewname),
					NULL) == ISC_R_SUCCESS);
	dns_name_toregion(dns_fixedname_name(&fnewname), &r);

	/*
	 * Create an envelope for each rdata: <name|type|class|ttl>.
	 */
	isc_buffer_init(&envbuf, data, sizeof(data));
	memcpy(data, r.base, r.length);
	isc_buffer_add(&envbuf, r.length);
	isc_buffer_putuint16(&envbuf, set->type);
	isc_buffer_putuint16(&envbuf, set->rdclass);
	isc_buffer_putuint32(&envbuf, set->ttl);

	ret = rdataset_to_sortedarray(set, mctx, &rdatas, &nrdatas);
	if (ret != ISC_R_SUCCESS)
		goto cleanup_context;
	isc_buffer_usedregion(&envbuf, &r);

	for (i = 0; i < nrdatas; i++) {
		isc_uint16_t len;
		isc_buffer_t lenbuf;
		isc_region_t lenr;

		/*
		 * Skip duplicates.
		 */
		if (i > 0 && dns_rdata_compare(&rdatas[i], &rdatas[i-1]) == 0)
		    continue;

		/*
		 * Digest the envelope.
		 */
		ret = dst_context_adddata(ctx, &r);
		if (ret != ISC_R_SUCCESS)
			goto cleanup_array;

		/*
		 * Digest the length of the rdata.
		 */
		isc_buffer_init(&lenbuf, &len, sizeof(len));
		INSIST(rdatas[i].length < 65536);
		isc_buffer_putuint16(&lenbuf, (isc_uint16_t)rdatas[i].length);
		isc_buffer_usedregion(&lenbuf, &lenr);
		ret = dst_context_adddata(ctx, &lenr);
		if (ret != ISC_R_SUCCESS)
			goto cleanup_array;

		/*
		 * Digest the rdata.
		 */
		ret = dns_rdata_digest(&rdatas[i], digest_callback, ctx);
		if (ret != ISC_R_SUCCESS)
			goto cleanup_array;
	}

	isc_buffer_init(&sigbuf, sig.signature, sig.siglen);
	ret = dst_context_sign(ctx, &sigbuf);
	if (ret != ISC_R_SUCCESS)
		goto cleanup_array;
	isc_buffer_usedregion(&sigbuf, &r);
	if (r.length != sig.siglen) {
		ret = ISC_R_NOSPACE;
		goto cleanup_array;
	}
	memcpy(sig.signature, r.base, sig.siglen);

	ret = dns_rdata_fromstruct(sigrdata, sig.common.rdclass,
				  sig.common.rdtype, &sig, buffer);

cleanup_array:
	isc_mem_put(mctx, rdatas, nrdatas * sizeof(dns_rdata_t));
cleanup_context:
	dst_context_destroy(&ctx);
cleanup_databuf:
	isc_buffer_free(&databuf);
cleanup_signature:
	isc_mem_put(mctx, sig.signature, sig.siglen);

	return (ret);
}
예제 #11
0
파일: ds.c 프로젝트: 2014-class/freerouter
isc_result_t
dns_ds_buildrdata(dns_name_t *owner, dns_rdata_t *key,
		  unsigned int digest_type, unsigned char *buffer,
		  dns_rdata_t *rdata)
{
	dns_fixedname_t fname;
	dns_name_t *name;
	unsigned char digest[ISC_SHA256_DIGESTLENGTH];
	isc_region_t r;
	isc_buffer_t b;
	dns_rdata_ds_t ds;
	isc_sha1_t sha1;
	isc_sha256_t sha256;
#ifdef HAVE_OPENSSL_GOST
	EVP_MD_CTX ctx;
	const EVP_MD *md;
#endif

	REQUIRE(key != NULL);
	REQUIRE(key->type == dns_rdatatype_dnskey);

	if (!dns_ds_digest_supported(digest_type))
		return (ISC_R_NOTIMPLEMENTED);

	dns_fixedname_init(&fname);
	name = dns_fixedname_name(&fname);
	(void)dns_name_downcase(owner, name, NULL);

	memset(buffer, 0, DNS_DS_BUFFERSIZE);
	isc_buffer_init(&b, buffer, DNS_DS_BUFFERSIZE);

	switch (digest_type) {
	case DNS_DSDIGEST_SHA1:
		isc_sha1_init(&sha1);
		dns_name_toregion(name, &r);
		isc_sha1_update(&sha1, r.base, r.length);
		dns_rdata_toregion(key, &r);
		INSIST(r.length >= 4);
		isc_sha1_update(&sha1, r.base, r.length);
		isc_sha1_final(&sha1, digest);
		break;
#ifdef HAVE_OPENSSL_GOST
#define CHECK(x)					\
	if ((x) != 1) {					\
		EVP_MD_CTX_cleanup(&ctx);		\
		return (DST_R_OPENSSLFAILURE);		\
	}

	case DNS_DSDIGEST_GOST:
		md = EVP_gost();
		if (md == NULL)
			return (DST_R_OPENSSLFAILURE);
		EVP_MD_CTX_init(&ctx);
		CHECK(EVP_DigestInit(&ctx, md));
		dns_name_toregion(name, &r);
		CHECK(EVP_DigestUpdate(&ctx,
				       (const void *) r.base,
				       (size_t) r.length));
		dns_rdata_toregion(key, &r);
		INSIST(r.length >= 4);
		CHECK(EVP_DigestUpdate(&ctx,
				       (const void *) r.base,
				       (size_t) r.length));
		CHECK(EVP_DigestFinal(&ctx, digest, NULL));
		break;
#endif
	default:
		isc_sha256_init(&sha256);
		dns_name_toregion(name, &r);
		isc_sha256_update(&sha256, r.base, r.length);
		dns_rdata_toregion(key, &r);
		INSIST(r.length >= 4);
		isc_sha256_update(&sha256, r.base, r.length);
		isc_sha256_final(digest, &sha256);
		break;
	}

	ds.mctx = NULL;
	ds.common.rdclass = key->rdclass;
	ds.common.rdtype = dns_rdatatype_ds;
	ds.algorithm = r.base[3];
	ds.key_tag = dst_region_computeid(&r, ds.algorithm);
	ds.digest_type = digest_type;
	switch (digest_type) {
	case DNS_DSDIGEST_SHA1:
		ds.length = ISC_SHA1_DIGESTLENGTH;
		break;
#ifdef HAVE_OPENSSL_GOST
	case DNS_DSDIGEST_GOST:
		ds.length = ISC_GOST_DIGESTLENGTH;
		break;
#endif
	default:
		ds.length = ISC_SHA256_DIGESTLENGTH;
		break;
	}
	ds.digest = digest;

	return (dns_rdata_fromstruct(rdata, key->rdclass, dns_rdatatype_ds,
				     &ds, &b));
}
예제 #12
0
static isc_result_t
add_tsig(dst_context_t *tsigctx, dns_tsigkey_t *key, isc_buffer_t *target) {
	dns_compress_t cctx;
	dns_rdata_any_tsig_t tsig;
	dns_rdata_t rdata = DNS_RDATA_INIT;
	dns_rdatalist_t rdatalist;
	dns_rdataset_t rdataset;
	isc_buffer_t *dynbuf = NULL;
	isc_buffer_t databuf;
	isc_buffer_t sigbuf;
	isc_region_t r;
	isc_result_t result = ISC_R_SUCCESS;
	isc_stdtime_t now;
	unsigned char tsigbuf[1024];
	unsigned int count;
	unsigned int sigsize;
	isc_boolean_t invalidate_ctx = ISC_FALSE;

	CHECK(dns_compress_init(&cctx, -1, mctx));
	invalidate_ctx = ISC_TRUE;

	memset(&tsig, 0, sizeof(tsig));
	       tsig.common.rdclass = dns_rdataclass_any;
	tsig.common.rdtype = dns_rdatatype_tsig;
	ISC_LINK_INIT(&tsig.common, link);
	dns_name_init(&tsig.algorithm, NULL);
	dns_name_clone(key->algorithm, &tsig.algorithm);

	isc_stdtime_get(&now);
	tsig.timesigned = now;
	tsig.fudge = DNS_TSIG_FUDGE;
	tsig.originalid = 50;
	tsig.error = dns_rcode_noerror;
	tsig.otherlen = 0;
	tsig.other = NULL;

	isc_buffer_init(&databuf, tsigbuf, sizeof(tsigbuf));
	isc_buffer_putuint48(&databuf, tsig.timesigned);
	isc_buffer_putuint16(&databuf, tsig.fudge);
	isc_buffer_usedregion(&databuf, &r);
	CHECK(dst_context_adddata(tsigctx, &r));

	CHECK(dst_key_sigsize(key->key, &sigsize));
	tsig.signature = (unsigned char *) isc_mem_get(mctx, sigsize);
	if (tsig.signature == NULL)
		CHECK(ISC_R_NOMEMORY);
	isc_buffer_init(&sigbuf, tsig.signature, sigsize);
	CHECK(dst_context_sign(tsigctx, &sigbuf));
	tsig.siglen = isc_buffer_usedlength(&sigbuf);

	CHECK(isc_buffer_allocate(mctx, &dynbuf, 512));
	CHECK(dns_rdata_fromstruct(&rdata, dns_rdataclass_any,
				   dns_rdatatype_tsig, &tsig, dynbuf));
	dns_rdatalist_init(&rdatalist);
	rdatalist.rdclass = dns_rdataclass_any;
	rdatalist.type = dns_rdatatype_tsig;
	ISC_LIST_APPEND(rdatalist.rdata, &rdata, link);
	dns_rdataset_init(&rdataset);
	CHECK(dns_rdatalist_tordataset(&rdatalist, &rdataset));
	CHECK(dns_rdataset_towire(&rdataset, &key->name, &cctx,
				  target, 0, &count));

	/*
	 * Fixup additional record count.
	 */
	((unsigned char*)target->base)[11]++;
	if (((unsigned char*)target->base)[11] == 0)
		((unsigned char*)target->base)[10]++;
 cleanup:
	if (tsig.signature != NULL)
		isc_mem_put(mctx, tsig.signature, sigsize);
	if (dynbuf != NULL)
		isc_buffer_free(&dynbuf);
	if (invalidate_ctx)
		dns_compress_invalidate(&cctx);

	return (result);
}
예제 #13
0
파일: dnsconf.c 프로젝트: crossbuild/bind
static isc_result_t
configure_dnsseckeys(irs_dnsconf_t *conf, cfg_obj_t *cfgobj,
		     dns_rdataclass_t rdclass)
{
	isc_mem_t *mctx = conf->mctx;
	const cfg_obj_t *keys = NULL;
	const cfg_obj_t *key, *keylist;
	dns_fixedname_t fkeyname;
	dns_name_t *keyname_base, *keyname;
	const cfg_listelt_t *element, *element2;
	isc_result_t result;
	isc_uint32_t flags, proto, alg;
	const char *keystr, *keynamestr;
	unsigned char keydata[4096];
	isc_buffer_t keydatabuf_base, *keydatabuf;
	dns_rdata_dnskey_t keystruct;
	unsigned char rrdata[4096];
	isc_buffer_t rrdatabuf;
	isc_region_t r;
	isc_buffer_t namebuf;
	irs_dnsconf_dnskey_t *keyent;

	cfg_map_get(cfgobj, "trusted-keys", &keys);
	if (keys == NULL)
		return (ISC_R_SUCCESS);

	for (element = cfg_list_first(keys);
	     element != NULL;
	     element = cfg_list_next(element)) {
		keylist = cfg_listelt_value(element);
		for (element2 = cfg_list_first(keylist);
		     element2 != NULL;
		     element2 = cfg_list_next(element2))
		{
			keydatabuf = NULL;
			keyname = NULL;

			key = cfg_listelt_value(element2);

			flags = cfg_obj_asuint32(cfg_tuple_get(key, "flags"));
			proto = cfg_obj_asuint32(cfg_tuple_get(key,
							       "protocol"));
			alg = cfg_obj_asuint32(cfg_tuple_get(key,
							     "algorithm"));
			keynamestr = cfg_obj_asstring(cfg_tuple_get(key,
								    "name"));

			keystruct.common.rdclass = rdclass;
			keystruct.common.rdtype = dns_rdatatype_dnskey;
			keystruct.mctx = NULL;
			ISC_LINK_INIT(&keystruct.common, link);

			if (flags > 0xffff)
				return (ISC_R_RANGE);
			if (proto > 0xff)
				return (ISC_R_RANGE);
			if (alg > 0xff)
				return (ISC_R_RANGE);
			keystruct.flags = (isc_uint16_t)flags;
			keystruct.protocol = (isc_uint8_t)proto;
			keystruct.algorithm = (isc_uint8_t)alg;

			isc_buffer_init(&keydatabuf_base, keydata,
					sizeof(keydata));
			isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata));

			/* Configure key value */
			keystr = cfg_obj_asstring(cfg_tuple_get(key, "key"));
			result = isc_base64_decodestring(keystr,
							 &keydatabuf_base);
			if (result != ISC_R_SUCCESS)
				return (result);
			isc_buffer_usedregion(&keydatabuf_base, &r);
			keystruct.datalen = r.length;
			keystruct.data = r.base;

			result = dns_rdata_fromstruct(NULL,
						      keystruct.common.rdclass,
						      keystruct.common.rdtype,
						      &keystruct, &rrdatabuf);
			if (result != ISC_R_SUCCESS)
				return (result);
			isc_buffer_usedregion(&rrdatabuf, &r);
			result = isc_buffer_allocate(mctx, &keydatabuf,
						     r.length);
			if (result != ISC_R_SUCCESS)
				return (result);
			result = isc_buffer_copyregion(keydatabuf, &r);
			if (result != ISC_R_SUCCESS)
				goto cleanup;

			/* Configure key name */
			dns_fixedname_init(&fkeyname);
			keyname_base = dns_fixedname_name(&fkeyname);
			isc_buffer_constinit(&namebuf, keynamestr,
					     strlen(keynamestr));
			isc_buffer_add(&namebuf, strlen(keynamestr));
			result = dns_name_fromtext(keyname_base, &namebuf,
						   dns_rootname, 0, NULL);
			if (result != ISC_R_SUCCESS)
				return (result);
			keyname = isc_mem_get(mctx, sizeof(*keyname));
			if (keyname == NULL) {
				result = ISC_R_NOMEMORY;
				goto cleanup;
			}
			dns_name_init(keyname, NULL);
			result = dns_name_dup(keyname_base, mctx, keyname);
			if (result != ISC_R_SUCCESS)
				goto cleanup;

			/* Add the key data to the list */
			keyent = isc_mem_get(mctx, sizeof(*keyent));
			if (keyent == NULL) {
				dns_name_free(keyname, mctx);
				result = ISC_R_NOMEMORY;
				goto cleanup;
			}
			keyent->keyname = keyname;
			keyent->keydatabuf = keydatabuf;

			ISC_LIST_APPEND(conf->trusted_keylist, keyent, link);
		}
	}

	return (ISC_R_SUCCESS);

 cleanup:
	if (keydatabuf != NULL)
		isc_buffer_free(&keydatabuf);
	if (keyname != NULL)
		isc_mem_put(mctx, keyname, sizeof(*keyname));

	return (result);
}
예제 #14
0
파일: ds.c 프로젝트: execunix/vinos
isc_result_t
dns_ds_buildrdata(dns_name_t *owner, dns_rdata_t *key,
		  unsigned int digest_type, unsigned char *buffer,
		  dns_rdata_t *rdata)
{
	dns_fixedname_t fname;
	dns_name_t *name;
	unsigned char digest[ISC_SHA384_DIGESTLENGTH];
	isc_region_t r;
	isc_buffer_t b;
	dns_rdata_ds_t ds;
	isc_sha1_t sha1;
	isc_sha256_t sha256;
	isc_sha384_t sha384;
#if defined(HAVE_OPENSSL_GOST) || defined(HAVE_PKCS11_GOST)
	isc_gost_t gost;
#endif

	REQUIRE(key != NULL);
	REQUIRE(key->type == dns_rdatatype_dnskey);

	if (!dst_ds_digest_supported(digest_type))
		return (ISC_R_NOTIMPLEMENTED);

	dns_fixedname_init(&fname);
	name = dns_fixedname_name(&fname);
	(void)dns_name_downcase(owner, name, NULL);

	memset(buffer, 0, DNS_DS_BUFFERSIZE);
	isc_buffer_init(&b, buffer, DNS_DS_BUFFERSIZE);

	switch (digest_type) {
	case DNS_DSDIGEST_SHA1:
		isc_sha1_init(&sha1);
		dns_name_toregion(name, &r);
		isc_sha1_update(&sha1, r.base, r.length);
		dns_rdata_toregion(key, &r);
		INSIST(r.length >= 4);
		isc_sha1_update(&sha1, r.base, r.length);
		isc_sha1_final(&sha1, digest);
		break;

#if defined(HAVE_OPENSSL_GOST) || defined(HAVE_PKCS11_GOST)
#define RETERR(x) do {					\
	isc_result_t ret = (x);				\
	if (ret != ISC_R_SUCCESS) {			\
		isc_gost_invalidate(&gost);		\
		return (ret);				\
	}						\
} while (/*CONSTCOND*/0)

	case DNS_DSDIGEST_GOST:
		RETERR(isc_gost_init(&gost));
		dns_name_toregion(name, &r);
		RETERR(isc_gost_update(&gost, r.base, r.length));
		dns_rdata_toregion(key, &r);
		INSIST(r.length >= 4);
		RETERR(isc_gost_update(&gost, r.base, r.length));
		RETERR(isc_gost_final(&gost, digest));
		break;
#endif

	case DNS_DSDIGEST_SHA384:
		isc_sha384_init(&sha384);
		dns_name_toregion(name, &r);
		isc_sha384_update(&sha384, r.base, r.length);
		dns_rdata_toregion(key, &r);
		INSIST(r.length >= 4);
		isc_sha384_update(&sha384, r.base, r.length);
		isc_sha384_final(digest, &sha384);
		break;

	case DNS_DSDIGEST_SHA256:
	default:
		isc_sha256_init(&sha256);
		dns_name_toregion(name, &r);
		isc_sha256_update(&sha256, r.base, r.length);
		dns_rdata_toregion(key, &r);
		INSIST(r.length >= 4);
		isc_sha256_update(&sha256, r.base, r.length);
		isc_sha256_final(digest, &sha256);
		break;
	}

	ds.mctx = NULL;
	ds.common.rdclass = key->rdclass;
	ds.common.rdtype = dns_rdatatype_ds;
	ds.algorithm = r.base[3];
	ds.key_tag = dst_region_computeid(&r, ds.algorithm);
	ds.digest_type = digest_type;
	switch (digest_type) {
	case DNS_DSDIGEST_SHA1:
		ds.length = ISC_SHA1_DIGESTLENGTH;
		break;

#if defined(HAVE_OPENSSL_GOST) || defined(HAVE_PKCS11_GOST)
	case DNS_DSDIGEST_GOST:
		ds.length = ISC_GOST_DIGESTLENGTH;
		break;
#endif

	case DNS_DSDIGEST_SHA384:
		ds.length = ISC_SHA384_DIGESTLENGTH;
		break;

	case DNS_DSDIGEST_SHA256:
	default:
		ds.length = ISC_SHA256_DIGESTLENGTH;
		break;
	}
	ds.digest = digest;

	return (dns_rdata_fromstruct(rdata, key->rdclass, dns_rdatatype_ds,
				     &ds, &b));
}
예제 #15
0
static isc_result_t
key_fromconfig(const cfg_obj_t *key, dns_client_t *client) {
	dns_rdata_dnskey_t keystruct;
	isc_uint32_t flags, proto, alg;
	const char *keystr, *keynamestr;
	unsigned char keydata[4096];
	isc_buffer_t keydatabuf;
	unsigned char rrdata[4096];
	isc_buffer_t rrdatabuf;
	isc_region_t r;
	dns_fixedname_t fkeyname;
	dns_name_t *keyname;
	isc_result_t result;
	isc_boolean_t match_root = ISC_FALSE, match_dlv = ISC_FALSE;

	keynamestr = cfg_obj_asstring(cfg_tuple_get(key, "name"));
	CHECK(convert_name(&fkeyname, &keyname, keynamestr));

	if (!root_validation && !dlv_validation)
		return (ISC_R_SUCCESS);

	if (anchor_name)
		match_root = dns_name_equal(keyname, anchor_name);
	if (dlv_name)
		match_dlv = dns_name_equal(keyname, dlv_name);

	if (!match_root && !match_dlv)
		return (ISC_R_SUCCESS);
	if ((!root_validation && match_root) || (!dlv_validation && match_dlv))
		return (ISC_R_SUCCESS);

	if (match_root)
		delv_log(ISC_LOG_DEBUG(3), "adding trust anchor %s",
			  trust_anchor);
	if (match_dlv)
		delv_log(ISC_LOG_DEBUG(3), "adding DLV trust anchor %s",
			  dlv_anchor);

	flags = cfg_obj_asuint32(cfg_tuple_get(key, "flags"));
	proto = cfg_obj_asuint32(cfg_tuple_get(key, "protocol"));
	alg = cfg_obj_asuint32(cfg_tuple_get(key, "algorithm"));

	keystruct.common.rdclass = dns_rdataclass_in;
	keystruct.common.rdtype = dns_rdatatype_dnskey;
	/*
	 * The key data in keystruct is not dynamically allocated.
	 */
	keystruct.mctx = NULL;

	ISC_LINK_INIT(&keystruct.common, link);

	if (flags > 0xffff)
		CHECK(ISC_R_RANGE);
	if (proto > 0xff)
		CHECK(ISC_R_RANGE);
	if (alg > 0xff)
		CHECK(ISC_R_RANGE);

	keystruct.flags = (isc_uint16_t)flags;
	keystruct.protocol = (isc_uint8_t)proto;
	keystruct.algorithm = (isc_uint8_t)alg;

	isc_buffer_init(&keydatabuf, keydata, sizeof(keydata));
	isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata));

	keystr = cfg_obj_asstring(cfg_tuple_get(key, "key"));
	CHECK(isc_base64_decodestring(keystr, &keydatabuf));
	isc_buffer_usedregion(&keydatabuf, &r);
	keystruct.datalen = r.length;
	keystruct.data = r.base;

	CHECK(dns_rdata_fromstruct(NULL,
				   keystruct.common.rdclass,
				   keystruct.common.rdtype,
				   &keystruct, &rrdatabuf));

	CHECK(dns_client_addtrustedkey(client, dns_rdataclass_in,
				       keyname, &rrdatabuf));
	trusted_keys++;

 cleanup:
	if (result == DST_R_NOCRYPTO)
		cfg_obj_log(key, lctx, ISC_LOG_ERROR, "no crypto support");
	else if (result == DST_R_UNSUPPORTEDALG) {
		cfg_obj_log(key, lctx, ISC_LOG_WARNING,
			    "skipping trusted key '%s': %s",
			    keynamestr, isc_result_totext(result));
		result = ISC_R_SUCCESS;
	} else if (result != ISC_R_SUCCESS) {
		cfg_obj_log(key, lctx, ISC_LOG_ERROR,
			    "failed to add trusted key '%s': %s",
			    keynamestr, isc_result_totext(result));
		result = ISC_R_FAILURE;
	}

	return (result);
}
예제 #16
0
static void
set_key(dns_client_t *client, char *keynamestr, char *keystr,
	isc_boolean_t is_sep, isc_mem_t **mctxp)
{
	isc_result_t result;
	dns_fixedname_t fkeyname;
	size_t namelen;
	dns_name_t *keyname;
	dns_rdata_dnskey_t keystruct;
	unsigned char keydata[4096];
	isc_buffer_t keydatabuf;
	unsigned char rrdata[4096];
	isc_buffer_t rrdatabuf;
	isc_buffer_t b;
	isc_textregion_t tr;
	isc_region_t r;
	dns_secalg_t alg;

	result = isc_mem_create(0, 0, mctxp);
	if (result != ISC_R_SUCCESS) {
		fprintf(stderr, "failed to crate mctx\n");
		exit(1);
	}

	if (algname != NULL) {
		tr.base = algname;
		tr.length = strlen(algname);
		result = dns_secalg_fromtext(&alg, &tr);
		if (result != ISC_R_SUCCESS) {
			fprintf(stderr, "failed to identify the algorithm\n");
			exit(1);
		}
	} else
		alg = DNS_KEYALG_RSASHA1;

	keystruct.common.rdclass = dns_rdataclass_in;
	keystruct.common.rdtype = dns_rdatatype_dnskey;
	keystruct.flags = DNS_KEYOWNER_ZONE; /* fixed */
	if (is_sep)
		keystruct.flags |= DNS_KEYFLAG_KSK;
	keystruct.protocol = DNS_KEYPROTO_DNSSEC; /* fixed */
	keystruct.algorithm = alg;

	isc_buffer_init(&keydatabuf, keydata, sizeof(keydata));
	isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata));
	result = isc_base64_decodestring(keystr, &keydatabuf);
	if (result != ISC_R_SUCCESS) {
		fprintf(stderr, "base64 decode failed\n");
		exit(1);
	}
	isc_buffer_usedregion(&keydatabuf, &r);
	keystruct.datalen = r.length;
	keystruct.data = r.base;

	result = dns_rdata_fromstruct(NULL, keystruct.common.rdclass,
				      keystruct.common.rdtype,
				      &keystruct, &rrdatabuf);
	if (result != ISC_R_SUCCESS) {
		fprintf(stderr, "failed to construct key rdata\n");
		exit(1);
	}
	namelen = strlen(keynamestr);
	isc_buffer_init(&b, keynamestr, namelen);
	isc_buffer_add(&b, namelen);
	dns_fixedname_init(&fkeyname);
	keyname = dns_fixedname_name(&fkeyname);
	result = dns_name_fromtext(keyname, &b, dns_rootname, 0, NULL);
	if (result != ISC_R_SUCCESS) {
		fprintf(stderr, "failed to construct key name\n");
		exit(1);
	}
	result = dns_client_addtrustedkey(client, dns_rdataclass_in,
					  keyname, &rrdatabuf);
	if (result != ISC_R_SUCCESS) {
		fprintf(stderr, "failed to add key for %s\n",
			keynamestr);
		exit(1);
	}
}