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); }
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)); }
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); } }
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); } }
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); }
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); }
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); }
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(); }
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); }
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); }
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)); }
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); }
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); }
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)); }
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); }
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); } }