📄 dnssec-signzone.c
字号:
check_result(result, "dns_rdataset_first/next"); if (dns_rdataset_isassociated(&sigset)) dns_rdataset_disassociate(&sigset); for (key = ISC_LIST_HEAD(keylist); key != NULL; key = ISC_LIST_NEXT(key, link)) { isc_buffer_t b; dns_rdata_t trdata; unsigned char array[BUFSIZE]; char keystr[KEY_FORMATSIZE]; if (nowsignedby[key->position]) continue; if (!key->issigningkey) continue; if (!(ignoreksk || key->isdsk || (key->isksk && set->type == dns_rdatatype_dnskey && dns_name_equal(name, gorigin)))) continue; key_format(key->key, keystr, sizeof(keystr)); vbprintf(1, "\tsigning with dnskey %s\n", keystr); dns_rdata_init(&trdata); isc_buffer_init(&b, array, sizeof(array)); signwithkey(name, set, &trdata, key->key, &b); tuple = NULL; result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD, name, ttl, &trdata, &tuple); check_result(result, "dns_difftuple_create"); dns_diff_append(add, &tuple); } isc_mem_put(mctx, wassignedby, arraysize * sizeof(isc_boolean_t)); isc_mem_put(mctx, nowsignedby, arraysize * sizeof(isc_boolean_t));}static voidopendb(const char *prefix, dns_name_t *name, dns_rdataclass_t rdclass, dns_db_t **dbp){ char filename[256]; isc_buffer_t b; isc_result_t result; isc_buffer_init(&b, filename, sizeof(filename)); if (directory != NULL) { isc_buffer_putstr(&b, directory); if (directory[strlen(directory) - 1] != '/') isc_buffer_putstr(&b, "/"); } isc_buffer_putstr(&b, prefix); result = dns_name_tofilenametext(name, ISC_FALSE, &b); check_result(result, "dns_name_tofilenametext()"); if (isc_buffer_availablelength(&b) == 0) { char namestr[DNS_NAME_FORMATSIZE]; dns_name_format(name, namestr, sizeof(namestr)); fatal("name '%s' is too long", namestr); } isc_buffer_putuint8(&b, 0); result = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_zone, rdclass, 0, NULL, dbp); check_result(result, "dns_db_create()"); result = dns_db_load(*dbp, filename); if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) dns_db_detach(dbp);}/* * Loads the key set for a child zone, if there is one, and builds DS records. */static isc_result_tloadds(dns_name_t *name, isc_uint32_t ttl, dns_rdataset_t *dsset) { dns_db_t *db = NULL; dns_dbversion_t *ver = NULL; dns_dbnode_t *node = NULL; isc_result_t result; dns_rdataset_t keyset; dns_rdata_t key, ds; unsigned char dsbuf[DNS_DS_BUFFERSIZE]; dns_diff_t diff; dns_difftuple_t *tuple = NULL; opendb("keyset-", name, gclass, &db); if (db == NULL) return (ISC_R_NOTFOUND); result = dns_db_findnode(db, name, ISC_FALSE, &node); if (result != ISC_R_SUCCESS) { dns_db_detach(&db); return (DNS_R_BADDB); } dns_rdataset_init(&keyset); result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_dnskey, 0, 0, &keyset, NULL); if (result != ISC_R_SUCCESS) { dns_db_detachnode(db, &node); dns_db_detach(&db); return (result); } vbprintf(2, "found DNSKEY records\n"); result = dns_db_newversion(db, &ver); check_result(result, "dns_db_newversion"); dns_diff_init(mctx, &diff); for (result = dns_rdataset_first(&keyset); result == ISC_R_SUCCESS; result = dns_rdataset_next(&keyset)) { dns_rdata_init(&key); dns_rdata_init(&ds); dns_rdataset_current(&keyset, &key); result = dns_ds_buildrdata(name, &key, DNS_DSDIGEST_SHA1, dsbuf, &ds); check_result(result, "dns_ds_buildrdata"); result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD, name, ttl, &ds, &tuple); check_result(result, "dns_difftuple_create"); dns_diff_append(&diff, &tuple); } result = dns_diff_apply(&diff, db, ver); check_result(result, "dns_diff_apply"); dns_diff_clear(&diff); dns_db_closeversion(db, &ver, ISC_TRUE); result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ds, 0, 0, dsset, NULL); check_result(result, "dns_db_findrdataset"); dns_rdataset_disassociate(&keyset); dns_db_detachnode(db, &node); dns_db_detach(&db); return (result);}static isc_boolean_tnsec_setbit(dns_name_t *name, dns_rdataset_t *rdataset, dns_rdatatype_t type, unsigned int val){ isc_result_t result; dns_rdata_t rdata = DNS_RDATA_INIT; dns_rdata_nsec_t nsec; unsigned int newlen; unsigned char bitmap[8192 + 512]; unsigned char nsecdata[8192 + 512 + DNS_NAME_MAXWIRE]; isc_boolean_t answer = ISC_FALSE; unsigned int i, len, window; int octet; result = dns_rdataset_first(rdataset); check_result(result, "dns_rdataset_first()"); dns_rdataset_current(rdataset, &rdata); result = dns_rdata_tostruct(&rdata, &nsec, NULL); check_result(result, "dns_rdata_tostruct"); INSIST(nsec.len <= sizeof(bitmap)); newlen = 0; memset(bitmap, 0, sizeof(bitmap)); for (i = 0; i < nsec.len; i += len) { INSIST(i + 2 <= nsec.len); window = nsec.typebits[i]; len = nsec.typebits[i+1]; i += 2; INSIST(len > 0 && len <= 32); INSIST(i + len <= nsec.len); memmove(&bitmap[window * 32 + 512], &nsec.typebits[i], len); } set_bit(bitmap + 512, type, val); for (window = 0; window < 256; window++) { for (octet = 31; octet >= 0; octet--) if (bitmap[window * 32 + 512 + octet] != 0) break; if (octet < 0) continue; bitmap[newlen] = window; bitmap[newlen + 1] = octet + 1; newlen += 2; /* * Overlapping move. */ memmove(&bitmap[newlen], &bitmap[window * 32 + 512], octet + 1); newlen += octet + 1; } if (newlen != nsec.len || memcmp(nsec.typebits, bitmap, newlen) != 0) { dns_rdata_t newrdata = DNS_RDATA_INIT; isc_buffer_t b; dns_diff_t diff; dns_difftuple_t *tuple = NULL; dns_diff_init(mctx, &diff); result = dns_difftuple_create(mctx, DNS_DIFFOP_DEL, name, rdataset->ttl, &rdata, &tuple); check_result(result, "dns_difftuple_create"); dns_diff_append(&diff, &tuple); nsec.typebits = bitmap; nsec.len = newlen; isc_buffer_init(&b, nsecdata, sizeof(nsecdata)); result = dns_rdata_fromstruct(&newrdata, rdata.rdclass, dns_rdatatype_nsec, &nsec, &b); check_result(result, "dns_rdata_fromstruct"); result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD, name, rdataset->ttl, &newrdata, &tuple); check_result(result, "dns_difftuple_create"); dns_diff_append(&diff, &tuple); result = dns_diff_apply(&diff, gdb, gversion); check_result(result, "dns_difftuple_apply"); dns_diff_clear(&diff); answer = ISC_TRUE; } dns_rdata_freestruct(&nsec); return (answer);}static isc_boolean_tdelegation(dns_name_t *name, dns_dbnode_t *node, isc_uint32_t *ttlp) { dns_rdataset_t nsset; isc_result_t result; if (dns_name_equal(name, gorigin)) return (ISC_FALSE); dns_rdataset_init(&nsset); result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_ns, 0, 0, &nsset, NULL); if (dns_rdataset_isassociated(&nsset)) { if (ttlp != NULL) *ttlp = nsset.ttl; dns_rdataset_disassociate(&nsset); } return (ISC_TF(result == ISC_R_SUCCESS));}/* * Signs all records at a name. This mostly just signs each set individually, * but also adds the RRSIG bit to any NSECs generated earlier, deals with * parent/child KEY signatures, and handles other exceptional cases. */static voidsignname(dns_dbnode_t *node, dns_name_t *name) { isc_result_t result; dns_rdataset_t rdataset; dns_rdatasetiter_t *rdsiter; isc_boolean_t isdelegation = ISC_FALSE; isc_boolean_t hasds = ISC_FALSE; isc_boolean_t atorigin; isc_boolean_t changed = ISC_FALSE; dns_diff_t del, add; char namestr[DNS_NAME_FORMATSIZE]; isc_uint32_t nsttl = 0; dns_name_format(name, namestr, sizeof(namestr)); atorigin = dns_name_equal(name, gorigin); /* * Determine if this is a delegation point. */ if (delegation(name, node, &nsttl)) isdelegation = ISC_TRUE; /* * If this is a delegation point, look for a DS set. */ if (isdelegation) { dns_rdataset_t dsset; dns_rdataset_t sigdsset; dns_rdataset_init(&dsset); dns_rdataset_init(&sigdsset); result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_ds, 0, 0, &dsset, &sigdsset); if (result == ISC_R_SUCCESS) { dns_rdataset_disassociate(&dsset); if (generateds) { result = dns_db_deleterdataset(gdb, node, gversion, dns_rdatatype_ds, 0); check_result(result, "dns_db_deleterdataset"); } else hasds = ISC_TRUE; } if (generateds) { result = loadds(name, nsttl, &dsset); if (result == ISC_R_SUCCESS) { result = dns_db_addrdataset(gdb, node, gversion, 0, &dsset, 0, NULL); check_result(result, "dns_db_addrdataset"); hasds = ISC_TRUE; dns_rdataset_disassociate(&dsset); if (dns_rdataset_isassociated(&sigdsset)) dns_rdataset_disassociate(&sigdsset); } else if (dns_rdataset_isassociated(&sigdsset)) { result = dns_db_deleterdataset(gdb, node, gversion, dns_rdatatype_rrsig, dns_rdatatype_ds); check_result(result, "dns_db_deleterdataset"); dns_rdataset_disassociate(&sigdsset); } } else if (dns_rdataset_isassociated(&sigdsset)) dns_rdataset_disassociate(&sigdsset); } /* * Make sure that NSEC bits are appropriately set. */ dns_rdataset_init(&rdataset); RUNTIME_CHECK(dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_nsec, 0, 0, &rdataset, NULL) == ISC_R_SUCCESS); if (!nokeys) changed = nsec_setbit(name, &rdataset, dns_rdatatype_rrsig, 1); if (changed) { dns_rdataset_disassociate(&rdataset); RUNTIME_CHECK(dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_nsec, 0, 0, &rdataset, NULL) == ISC_R_SUCCESS); } if (hasds) (void)nsec_setbit(name, &rdataset, dns_rdatatype_ds, 1); else (void)nsec_setbit(name, &rdataset, dns_rdatatype_ds, 0); dns_rdataset_disassociate(&rdataset); /* * Now iterate through the rdatasets. */ dns_diff_init(mctx, &del); dns_diff_init(mctx, &add); rdsiter = NULL; result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter); check_result(result, "dns_db_allrdatasets()"); result = dns_rdatasetiter_first(rdsiter); while (result == ISC_R_SUCCESS) { dns_rdatasetiter_current(rdsiter, &rdataset); /* If this is a RRSIG set, skip it. */ if (rdataset.type == dns_rdatatype_rrsig) goto skip; /* * If this name is a delegation point, skip all records * except NSEC and DS sets. Otherwise check that there * isn't a DS record. */ if (isdelegation) { if (rdataset.type != dns_rdatatype_nsec && rdataset.type != dns_rdatatype_ds) goto skip; } else if (rdataset.type == dns_rdatatype_ds) { char namebuf[DNS_NAME_FORMATSIZE]; dns_name_format(name, namebuf, sizeof(namebuf)); fatal("'%s': found DS RRset without NS RRset\n", namebuf); } signset(&del, &add, node, name, &rdataset); skip: dns_rdataset_disassociate(&rdataset); result = dns_rdatasetiter_next(rdsiter); } if (result != ISC_R_NOMORE) fatal("rdataset iteration for name '%s' failed: %s", namestr, isc_result_totext(result)); dns_rdatasetiter_destroy(&rdsiter); result = dns_diff_applysilently(&del, gdb, gversion); if (result != ISC_R_SUCCESS) fatal("failed to delete SIGs at node '%s': %s", namestr, isc_result_totext(result)); result = dns_diff_applysilently(&add, gdb, gversion); if (result != ISC_R_SUCCESS) fatal("failed to add SIGs at node '%s': %s", namestr, isc_result_totext(result)); dns_diff_clear(&del); dns_diff_clear(&add);}static inline isc_boolean_tactive_node(dns_dbnode_t *node) { dns_rdatasetiter_t *rdsiter; isc_boolean_t active = ISC_FALSE; isc_result_t result; dns_rdataset_t rdataset; dns_rdataset_init(&rdataset); rdsiter = NULL; result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter); check_result(result, "dns_db_allrdatasets()"); result = dns_rdatasetiter_first(rdsiter); while (result == ISC_R_SUCCESS) { dns_rdatasetiter_current(rdsiter, &rdataset); if (rdataset.type != dns_rdatatype_nsec && rdataset.type != dns_rdatatype_rrsig) active = ISC_TRUE; dns_rdataset_disassociate(&rdataset); if (!active) result = dns_rdatasetiter_next(rdsiter); else result = ISC_R_NOMORE; } if (result != ISC_R_NOMORE) fatal("rdataset iteration failed: %s", isc_result_totext(result)); if (!active) { /* * Make sure there is no NSEC / RRSIG records for * this node. */ result = dns_db_deleterdataset(gdb, node, gversion, dns_rdatatype_nsec, 0); if (result == DNS_R_UNCHANGED) result = ISC_R_SUCCESS; check_result(result, "dns_db_deleterdataset(nsec)"); result = dns_rdatasetiter_first(rdsiter); for (result = dns_rdatasetiter_first(rdsiter); result == ISC_R_SUCCESS; result = dns_rdatasetiter_next(rdsiter)) { dns_rdatasetiter_current(rdsiter, &rdataset); if (rdataset.type == dns_rdatatype_rrsig) { dns_rdatatype_t type = rdataset.type; dns_rdatatype_t covers = rdataset.covers; result = dns_db_deleterdataset(gdb, node, gversion, type, covers); if (result == DNS_R_UNCHANGED) result = ISC_R_SUCCESS; check_result(result, "dns_db_deleterdataset(rrsig)"); } dns_rdataset_disassociate(&rdataset); } if (result != ISC_R_NOMORE) fatal("rdataset iteration failed: %s", isc_result_totext(result)); } dns_rdatasetiter_destroy(&rdsiter); return (active);}/* * Extracts the TTL from the SOA. */static dns_ttl_tsoattl(void) { dns_rdataset_t soaset; dns_fixedname_t fname; dns_name_t *name; isc_result_t result; dns_ttl_t ttl; dns_rdata_t rdata = DNS_RDATA_INIT; dns_rdata_soa_t soa; dns_fixedname_init(&fname); name = dns_fixedname_name(&fname); dns_rdataset_init(&soaset); result = dns_db_find(gdb, gorigin, gversion, dns_rdatatype_soa, 0, 0, NULL, name, &soaset, NULL); if (result != ISC_R_SUCCESS) fatal("failed to find an SOA at the zone apex: %s", isc_result_totext(result)); result = dns_rdataset_first(&soaset); check_result(result, "dns_rdataset_first"); dns_rdataset_current(&soaset, &rdata); result = dns_rdata_tostruct(&rdata, &soa, NULL); check_result(result, "dns_rdata_tostruct"); ttl = soa.minimum; dns_rdataset_disassociate(&soaset); return (ttl);}/* * Delete any RRSIG records at a node. */static voidcleannode(dns_db_t *db, dns_dbversion_t *version, dns_dbnode_t *node) { dns_rdatasetiter_t *rdsiter = NULL; dns_rdataset_t set; isc_result_t result, dresult; dns_rdataset_init(&set); result = dns_db_allrdatasets(db, node, version, 0, &rdsiter); check_result(result, "dns_db_allrdatasets"); result = dns_rdatasetiter_first(rdsiter); while (result == ISC_R_SUCCESS) { isc_boolean_t destroy = ISC_FALSE; dns_rdatatype_t covers = 0; dns_rdatasetiter_current(rdsiter, &set); if (set.type == dns_rdatatype_rrsig) { covers = set.covers; destroy = ISC_TRUE; } dns_rdataset_disassociate(&set); result = dns_rdatasetiter_next(rdsiter); if (destroy) { dresult = dns_db_deleterdataset(db, node, version,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -