00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include <config.h>
00035
00036 #include <stdlib.h>
00037 #include <time.h>
00038 #include <unistd.h>
00039
00040 #include <isc/app.h>
00041 #include <isc/base32.h>
00042 #include <isc/commandline.h>
00043 #include <isc/entropy.h>
00044 #include <isc/event.h>
00045 #include <isc/file.h>
00046 #include <isc/hash.h>
00047 #include <isc/hex.h>
00048 #include <isc/mem.h>
00049 #include <isc/mutex.h>
00050 #include <isc/os.h>
00051 #include <isc/print.h>
00052 #include <isc/random.h>
00053 #include <isc/rwlock.h>
00054 #include <isc/serial.h>
00055 #include <isc/stdio.h>
00056 #include <isc/stdlib.h>
00057 #include <isc/string.h>
00058 #include <isc/task.h>
00059 #include <isc/time.h>
00060 #include <isc/util.h>
00061
00062 #include <dns/db.h>
00063 #include <dns/dbiterator.h>
00064 #include <dns/diff.h>
00065 #include <dns/dnssec.h>
00066 #include <dns/ds.h>
00067 #include <dns/fixedname.h>
00068 #include <dns/keyvalues.h>
00069 #include <dns/log.h>
00070 #include <dns/master.h>
00071 #include <dns/masterdump.h>
00072 #include <dns/nsec.h>
00073 #include <dns/nsec3.h>
00074 #include <dns/rdata.h>
00075 #include <dns/rdatalist.h>
00076 #include <dns/rdataset.h>
00077 #include <dns/rdataclass.h>
00078 #include <dns/rdatasetiter.h>
00079 #include <dns/rdatastruct.h>
00080 #include <dns/rdatatype.h>
00081 #include <dns/result.h>
00082 #include <dns/soa.h>
00083 #include <dns/time.h>
00084 #include <dns/update.h>
00085
00086 #include <dst/dst.h>
00087
00088 #ifdef PKCS11CRYPTO
00089 #include <pk11/result.h>
00090 #endif
00091
00092 #include "dnssectool.h"
00093
00094 #ifndef PATH_MAX
00095 #define PATH_MAX 1024
00096 #endif
00097
00098 const char *program = "dnssec-signzone";
00099 int verbose;
00100
00101 typedef struct hashlist hashlist_t;
00102
00103 static int nsec_datatype = dns_rdatatype_nsec;
00104
00105 #define IS_NSEC3 (nsec_datatype == dns_rdatatype_nsec3)
00106 #define OPTOUT(x) (((x) & DNS_NSEC3FLAG_OPTOUT) != 0)
00107
00108 #define REVOKE(x) ((dst_key_flags(x) & DNS_KEYFLAG_REVOKE) != 0)
00109
00110 #define BUFSIZE 2048
00111 #define MAXDSKEYS 8
00112
00113 #define SIGNER_EVENTCLASS ISC_EVENTCLASS(0x4453)
00114 #define SIGNER_EVENT_WRITE (SIGNER_EVENTCLASS + 0)
00115 #define SIGNER_EVENT_WORK (SIGNER_EVENTCLASS + 1)
00116
00117 #define SOA_SERIAL_KEEP 0
00118 #define SOA_SERIAL_INCREMENT 1
00119 #define SOA_SERIAL_UNIXTIME 2
00120 #define SOA_SERIAL_DATE 3
00121
00122 typedef struct signer_event sevent_t;
00123 struct signer_event {
00124 ISC_EVENT_COMMON(sevent_t);
00125 dns_fixedname_t *fname;
00126 dns_dbnode_t *node;
00127 };
00128
00129 static dns_dnsseckeylist_t keylist;
00130 static unsigned int keycount = 0;
00131 isc_rwlock_t keylist_lock;
00132 static isc_stdtime_t starttime = 0, endtime = 0, dnskey_endtime = 0, now;
00133 static int cycle = -1;
00134 static int jitter = 0;
00135 static isc_boolean_t tryverify = ISC_FALSE;
00136 static isc_boolean_t printstats = ISC_FALSE;
00137 static isc_mem_t *mctx = NULL;
00138 static isc_entropy_t *ectx = NULL;
00139 static dns_ttl_t zone_soa_min_ttl;
00140 static dns_ttl_t soa_ttl;
00141 static FILE *outfp = NULL;
00142 static char *tempfile = NULL;
00143 static const dns_master_style_t *masterstyle;
00144 static dns_masterformat_t inputformat = dns_masterformat_text;
00145 static dns_masterformat_t outputformat = dns_masterformat_text;
00146 static isc_uint32_t rawversion = 1, serialnum = 0;
00147 static isc_boolean_t snset = ISC_FALSE;
00148 static unsigned int nsigned = 0, nretained = 0, ndropped = 0;
00149 static unsigned int nverified = 0, nverifyfailed = 0;
00150 static const char *directory = NULL, *dsdir = NULL;
00151 static isc_mutex_t namelock, statslock;
00152 static isc_taskmgr_t *taskmgr = NULL;
00153 static dns_db_t *gdb;
00154 static dns_dbversion_t *gversion;
00155 static dns_dbiterator_t *gdbiter;
00156 static dns_rdataclass_t gclass;
00157 static dns_name_t *gorigin;
00158 static int nsec3flags = 0;
00159 static dns_iterations_t nsec3iter = 10U;
00160 static unsigned char saltbuf[255];
00161 static unsigned char *gsalt = saltbuf;
00162 static size_t salt_length = 0;
00163 static isc_task_t *master = NULL;
00164 static unsigned int ntasks = 0;
00165 static isc_boolean_t shuttingdown = ISC_FALSE, finished = ISC_FALSE;
00166 static isc_boolean_t nokeys = ISC_FALSE;
00167 static isc_boolean_t removefile = ISC_FALSE;
00168 static isc_boolean_t generateds = ISC_FALSE;
00169 static isc_boolean_t ignore_kskflag = ISC_FALSE;
00170 static isc_boolean_t keyset_kskonly = ISC_FALSE;
00171 static dns_name_t *dlv = NULL;
00172 static dns_fixedname_t dlv_fixed;
00173 static dns_master_style_t *dsstyle = NULL;
00174 static unsigned int serialformat = SOA_SERIAL_KEEP;
00175 static unsigned int hash_length = 0;
00176 static isc_boolean_t unknownalg = ISC_FALSE;
00177 static isc_boolean_t disable_zone_check = ISC_FALSE;
00178 static isc_boolean_t update_chain = ISC_FALSE;
00179 static isc_boolean_t set_keyttl = ISC_FALSE;
00180 static dns_ttl_t keyttl;
00181 static isc_boolean_t smartsign = ISC_FALSE;
00182 static isc_boolean_t remove_orphansigs = ISC_FALSE;
00183 static isc_boolean_t remove_inactkeysigs = ISC_FALSE;
00184 static isc_boolean_t output_dnssec_only = ISC_FALSE;
00185 static isc_boolean_t output_stdout = ISC_FALSE;
00186 isc_boolean_t set_maxttl = ISC_FALSE;
00187 static dns_ttl_t maxttl = 0;
00188
00189 #define INCSTAT(counter) \
00190 if (printstats) { \
00191 LOCK(&statslock); \
00192 counter++; \
00193 UNLOCK(&statslock); \
00194 }
00195
00196 static void
00197 sign(isc_task_t *task, isc_event_t *event);
00198
00199 static void
00200 dumpnode(dns_name_t *name, dns_dbnode_t *node) {
00201 dns_rdataset_t rds;
00202 dns_rdatasetiter_t *iter = NULL;
00203 isc_buffer_t *buffer = NULL;
00204 isc_region_t r;
00205 isc_result_t result;
00206 unsigned bufsize = 4096;
00207
00208 if (outputformat != dns_masterformat_text)
00209 return;
00210
00211 if (!output_dnssec_only) {
00212 result = dns_master_dumpnodetostream(mctx, gdb, gversion, node,
00213 name, masterstyle, outfp);
00214 check_result(result, "dns_master_dumpnodetostream");
00215 return;
00216 }
00217
00218 result = dns_db_allrdatasets(gdb, node, gversion, 0, &iter);
00219 check_result(result, "dns_db_allrdatasets");
00220
00221 dns_rdataset_init(&rds);
00222
00223 result = isc_buffer_allocate(mctx, &buffer, bufsize);
00224 check_result(result, "isc_buffer_allocate");
00225
00226 for (result = dns_rdatasetiter_first(iter);
00227 result == ISC_R_SUCCESS;
00228 result = dns_rdatasetiter_next(iter)) {
00229
00230 dns_rdatasetiter_current(iter, &rds);
00231
00232 if (rds.type != dns_rdatatype_rrsig &&
00233 rds.type != dns_rdatatype_nsec &&
00234 rds.type != dns_rdatatype_nsec3 &&
00235 rds.type != dns_rdatatype_nsec3param &&
00236 (!smartsign || rds.type != dns_rdatatype_dnskey)) {
00237 dns_rdataset_disassociate(&rds);
00238 continue;
00239 }
00240
00241 for (;;) {
00242 result = dns_master_rdatasettotext(name, &rds,
00243 masterstyle, buffer);
00244 if (result != ISC_R_NOSPACE)
00245 break;
00246
00247 bufsize <<= 1;
00248 isc_buffer_free(&buffer);
00249 result = isc_buffer_allocate(mctx, &buffer, bufsize);
00250 check_result(result, "isc_buffer_allocate");
00251 }
00252 check_result(result, "dns_master_rdatasettotext");
00253
00254 isc_buffer_usedregion(buffer, &r);
00255 result = isc_stdio_write(r.base, 1, r.length, outfp, NULL);
00256 check_result(result, "isc_stdio_write");
00257 isc_buffer_clear(buffer);
00258
00259 dns_rdataset_disassociate(&rds);
00260 }
00261
00262 isc_buffer_free(&buffer);
00263 dns_rdatasetiter_destroy(&iter);
00264 }
00265
00266
00267
00268
00269
00270 static void
00271 signwithkey(dns_name_t *name, dns_rdataset_t *rdataset, dst_key_t *key,
00272 dns_ttl_t ttl, dns_diff_t *add, const char *logmsg)
00273 {
00274 isc_result_t result;
00275 isc_stdtime_t jendtime, expiry;
00276 char keystr[DST_KEY_FORMATSIZE];
00277 dns_rdata_t trdata = DNS_RDATA_INIT;
00278 unsigned char array[BUFSIZE];
00279 isc_buffer_t b;
00280 dns_difftuple_t *tuple;
00281
00282 dst_key_format(key, keystr, sizeof(keystr));
00283 vbprintf(1, "\t%s %s\n", logmsg, keystr);
00284
00285 if (rdataset->type == dns_rdatatype_dnskey)
00286 expiry = dnskey_endtime;
00287 else
00288 expiry = endtime;
00289
00290 jendtime = (jitter != 0) ? isc_random_jitter(expiry, jitter) : expiry;
00291 isc_buffer_init(&b, array, sizeof(array));
00292 result = dns_dnssec_sign(name, rdataset, key, &starttime, &jendtime,
00293 mctx, &b, &trdata);
00294 isc_entropy_stopcallbacksources(ectx);
00295 if (result != ISC_R_SUCCESS) {
00296 fatal("dnskey '%s' failed to sign data: %s",
00297 keystr, isc_result_totext(result));
00298 }
00299 INCSTAT(nsigned);
00300
00301 if (tryverify) {
00302 result = dns_dnssec_verify(name, rdataset, key,
00303 ISC_TRUE, mctx, &trdata);
00304 if (result == ISC_R_SUCCESS) {
00305 vbprintf(3, "\tsignature verified\n");
00306 INCSTAT(nverified);
00307 } else {
00308 vbprintf(3, "\tsignature failed to verify\n");
00309 INCSTAT(nverifyfailed);
00310 }
00311 }
00312
00313 tuple = NULL;
00314 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADDRESIGN,
00315 name, ttl, &trdata, &tuple);
00316 check_result(result, "dns_difftuple_create");
00317 dns_diff_append(add, &tuple);
00318 }
00319
00320 static inline isc_boolean_t
00321 issigningkey(dns_dnsseckey_t *key) {
00322 return (key->force_sign || key->hint_sign);
00323 }
00324
00325 static inline isc_boolean_t
00326 ispublishedkey(dns_dnsseckey_t *key) {
00327 return ((key->force_publish || key->hint_publish) &&
00328 !key->hint_remove);
00329 }
00330
00331 static inline isc_boolean_t
00332 iszonekey(dns_dnsseckey_t *key) {
00333 return (ISC_TF(dns_name_equal(dst_key_name(key->key), gorigin) &&
00334 dst_key_iszonekey(key->key)));
00335 }
00336
00337 static inline isc_boolean_t
00338 isksk(dns_dnsseckey_t *key) {
00339 return (key->ksk);
00340 }
00341
00342 static inline isc_boolean_t
00343 iszsk(dns_dnsseckey_t *key) {
00344 return (ignore_kskflag || !key->ksk);
00345 }
00346
00347
00348
00349
00350
00351
00352
00353 static dns_dnsseckey_t *
00354 keythatsigned_unlocked(dns_rdata_rrsig_t *rrsig) {
00355 dns_dnsseckey_t *key;
00356
00357 for (key = ISC_LIST_HEAD(keylist);
00358 key != NULL;
00359 key = ISC_LIST_NEXT(key, link)) {
00360 if (rrsig->keyid == dst_key_id(key->key) &&
00361 rrsig->algorithm == dst_key_alg(key->key) &&
00362 dns_name_equal(&rrsig->signer, dst_key_name(key->key)))
00363 return (key);
00364 }
00365 return (NULL);
00366 }
00367
00368
00369
00370
00371
00372 static dns_dnsseckey_t *
00373 keythatsigned(dns_rdata_rrsig_t *rrsig) {
00374 isc_result_t result;
00375 dst_key_t *pubkey = NULL, *privkey = NULL;
00376 dns_dnsseckey_t *key = NULL;
00377
00378 isc_rwlock_lock(&keylist_lock, isc_rwlocktype_read);
00379 key = keythatsigned_unlocked(rrsig);
00380 isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_read);
00381 if (key != NULL)
00382 return (key);
00383
00384
00385
00386
00387
00388
00389
00390
00391 isc_rwlock_lock(&keylist_lock, isc_rwlocktype_write);
00392 key = keythatsigned_unlocked(rrsig);
00393 if (key != NULL) {
00394 isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_write);
00395 return (key);
00396 }
00397
00398 result = dst_key_fromfile(&rrsig->signer, rrsig->keyid,
00399 rrsig->algorithm, DST_TYPE_PUBLIC,
00400 directory, mctx, &pubkey);
00401 if (result != ISC_R_SUCCESS) {
00402 isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_write);
00403 return (NULL);
00404 }
00405
00406 result = dst_key_fromfile(&rrsig->signer, rrsig->keyid,
00407 rrsig->algorithm,
00408 DST_TYPE_PUBLIC | DST_TYPE_PRIVATE,
00409 directory, mctx, &privkey);
00410 if (result == ISC_R_SUCCESS) {
00411 dst_key_free(&pubkey);
00412 result = dns_dnsseckey_create(mctx, &privkey, &key);
00413 } else
00414 result = dns_dnsseckey_create(mctx, &pubkey, &key);
00415
00416 if (result == ISC_R_SUCCESS) {
00417 key->force_publish = ISC_FALSE;
00418 key->force_sign = ISC_FALSE;
00419 key->index = keycount++;
00420 ISC_LIST_APPEND(keylist, key, link);
00421 }
00422
00423 isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_write);
00424 return (key);
00425 }
00426
00427
00428
00429
00430
00431
00432 static isc_boolean_t
00433 expecttofindkey(dns_name_t *name) {
00434 unsigned int options = DNS_DBFIND_NOWILD;
00435 dns_fixedname_t fname;
00436 isc_result_t result;
00437 char namestr[DNS_NAME_FORMATSIZE];
00438
00439 dns_fixedname_init(&fname);
00440 result = dns_db_find(gdb, name, gversion, dns_rdatatype_dnskey, options,
00441 0, NULL, dns_fixedname_name(&fname), NULL, NULL);
00442 switch (result) {
00443 case ISC_R_SUCCESS:
00444 case DNS_R_NXDOMAIN:
00445 case DNS_R_NXRRSET:
00446 return (ISC_TRUE);
00447 case DNS_R_DELEGATION:
00448 case DNS_R_CNAME:
00449 case DNS_R_DNAME:
00450 return (ISC_FALSE);
00451 }
00452 dns_name_format(name, namestr, sizeof(namestr));
00453 fatal("failure looking for '%s DNSKEY' in database: %s",
00454 namestr, isc_result_totext(result));
00455
00456 return (ISC_FALSE);
00457 }
00458
00459 static inline isc_boolean_t
00460 setverifies(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
00461 dns_rdata_t *rrsig)
00462 {
00463 isc_result_t result;
00464 result = dns_dnssec_verify(name, set, key, ISC_FALSE, mctx, rrsig);
00465 if (result == ISC_R_SUCCESS) {
00466 INCSTAT(nverified);
00467 return (ISC_TRUE);
00468 } else {
00469 INCSTAT(nverifyfailed);
00470 return (ISC_FALSE);
00471 }
00472 }
00473
00474
00475
00476
00477
00478
00479 static void
00480 signset(dns_diff_t *del, dns_diff_t *add, dns_dbnode_t *node, dns_name_t *name,
00481 dns_rdataset_t *set)
00482 {
00483 dns_rdataset_t sigset;
00484 dns_rdata_t sigrdata = DNS_RDATA_INIT;
00485 dns_rdata_rrsig_t rrsig;
00486 dns_dnsseckey_t *key;
00487 isc_result_t result;
00488 isc_boolean_t nosigs = ISC_FALSE;
00489 isc_boolean_t *wassignedby, *nowsignedby;
00490 int arraysize;
00491 dns_difftuple_t *tuple;
00492 dns_ttl_t ttl;
00493 int i;
00494 char namestr[DNS_NAME_FORMATSIZE];
00495 char typestr[TYPE_FORMATSIZE];
00496 char sigstr[SIG_FORMATSIZE];
00497
00498 dns_name_format(name, namestr, sizeof(namestr));
00499 type_format(set->type, typestr, sizeof(typestr));
00500
00501 ttl = ISC_MIN(set->ttl, endtime - starttime);
00502
00503 dns_rdataset_init(&sigset);
00504 result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_rrsig,
00505 set->type, 0, &sigset, NULL);
00506 if (result == ISC_R_NOTFOUND) {
00507 vbprintf(2, "no existing signatures for %s/%s\n",
00508 namestr, typestr);
00509 result = ISC_R_SUCCESS;
00510 nosigs = ISC_TRUE;
00511 }
00512 if (result != ISC_R_SUCCESS)
00513 fatal("failed while looking for '%s RRSIG %s': %s",
00514 namestr, typestr, isc_result_totext(result));
00515
00516 vbprintf(1, "%s/%s:\n", namestr, typestr);
00517
00518 arraysize = keycount;
00519 if (!nosigs)
00520 arraysize += dns_rdataset_count(&sigset);
00521 wassignedby = isc_mem_get(mctx, arraysize * sizeof(isc_boolean_t));
00522 nowsignedby = isc_mem_get(mctx, arraysize * sizeof(isc_boolean_t));
00523 if (wassignedby == NULL || nowsignedby == NULL)
00524 fatal("out of memory");
00525
00526 for (i = 0; i < arraysize; i++)
00527 wassignedby[i] = nowsignedby[i] = ISC_FALSE;
00528
00529 if (nosigs)
00530 result = ISC_R_NOMORE;
00531 else
00532 result = dns_rdataset_first(&sigset);
00533
00534 while (result == ISC_R_SUCCESS) {
00535 isc_boolean_t expired, future;
00536 isc_boolean_t keep = ISC_FALSE, resign = ISC_FALSE;
00537
00538 dns_rdataset_current(&sigset, &sigrdata);
00539
00540 result = dns_rdata_tostruct(&sigrdata, &rrsig, NULL);
00541 check_result(result, "dns_rdata_tostruct");
00542
00543 future = isc_serial_lt(now, rrsig.timesigned);
00544
00545 key = keythatsigned(&rrsig);
00546 sig_format(&rrsig, sigstr, sizeof(sigstr));
00547 if (key != NULL && issigningkey(key))
00548 expired = isc_serial_gt(now + cycle, rrsig.timeexpire);
00549 else
00550 expired = isc_serial_gt(now, rrsig.timeexpire);
00551
00552 if (isc_serial_gt(rrsig.timesigned, rrsig.timeexpire)) {
00553
00554 vbprintf(2, "\trrsig by %s dropped - "
00555 "invalid validity period\n",
00556 sigstr);
00557 } else if (key == NULL && !future &&
00558 expecttofindkey(&rrsig.signer)) {
00559
00560 vbprintf(2, "\trrsig by %s dropped - "
00561 "private dnskey not found\n",
00562 sigstr);
00563 } else if (key == NULL || future) {
00564 keep = (!expired && !remove_orphansigs);
00565 vbprintf(2, "\trrsig by %s %s - dnskey not found\n",
00566 keep ? "retained" : "dropped", sigstr);
00567 } else if (!dns_dnssec_keyactive(key->key, now) &&
00568 remove_inactkeysigs) {
00569 keep = ISC_FALSE;
00570 vbprintf(2, "\trrsig by %s dropped - key inactive\n",
00571 sigstr);
00572 } else if (issigningkey(key)) {
00573 wassignedby[key->index] = ISC_TRUE;
00574
00575 if (!expired && rrsig.originalttl == set->ttl &&
00576 setverifies(name, set, key->key, &sigrdata)) {
00577 vbprintf(2, "\trrsig by %s retained\n", sigstr);
00578 keep = ISC_TRUE;
00579 } else {
00580 vbprintf(2, "\trrsig by %s dropped - %s\n",
00581 sigstr, expired ? "expired" :
00582 rrsig.originalttl != set->ttl ?
00583 "ttl change" : "failed to verify");
00584 resign = ISC_TRUE;
00585 }
00586 } else if (!ispublishedkey(key) && remove_orphansigs) {
00587 vbprintf(2, "\trrsig by %s dropped - dnskey removed\n",
00588 sigstr);
00589 } else if (iszonekey(key)) {
00590 wassignedby[key->index] = ISC_TRUE;
00591
00592 if (!expired && rrsig.originalttl == set->ttl &&
00593 setverifies(name, set, key->key, &sigrdata)) {
00594 vbprintf(2, "\trrsig by %s retained\n", sigstr);
00595 keep = ISC_TRUE;
00596 } else {
00597 vbprintf(2, "\trrsig by %s dropped - %s\n",
00598 sigstr, expired ? "expired" :
00599 rrsig.originalttl != set->ttl ?
00600 "ttl change" : "failed to verify");
00601 }
00602 } else if (!expired) {
00603 vbprintf(2, "\trrsig by %s retained\n", sigstr);
00604 keep = ISC_TRUE;
00605 } else {
00606 vbprintf(2, "\trrsig by %s expired\n", sigstr);
00607 }
00608
00609 if (keep) {
00610 if (key != NULL)
00611 nowsignedby[key->index] = ISC_TRUE;
00612 INCSTAT(nretained);
00613 if (sigset.ttl != ttl) {
00614 vbprintf(2, "\tfixing ttl %s\n", sigstr);
00615 tuple = NULL;
00616 result = dns_difftuple_create(mctx,
00617 DNS_DIFFOP_DELRESIGN,
00618 name, sigset.ttl,
00619 &sigrdata, &tuple);
00620 check_result(result, "dns_difftuple_create");
00621 dns_diff_append(del, &tuple);
00622 result = dns_difftuple_create(mctx,
00623 DNS_DIFFOP_ADDRESIGN,
00624 name, ttl,
00625 &sigrdata, &tuple);
00626 check_result(result, "dns_difftuple_create");
00627 dns_diff_append(add, &tuple);
00628 }
00629 } else {
00630 tuple = NULL;
00631 vbprintf(2, "removing signature by %s\n", sigstr);
00632 result = dns_difftuple_create(mctx,
00633 DNS_DIFFOP_DELRESIGN,
00634 name, sigset.ttl,
00635 &sigrdata, &tuple);
00636 check_result(result, "dns_difftuple_create");
00637 dns_diff_append(del, &tuple);
00638 INCSTAT(ndropped);
00639 }
00640
00641 if (resign) {
00642 INSIST(!keep);
00643
00644 signwithkey(name, set, key->key, ttl, add,
00645 "resigning with dnskey");
00646 nowsignedby[key->index] = ISC_TRUE;
00647 }
00648
00649 dns_rdata_reset(&sigrdata);
00650 dns_rdata_freestruct(&rrsig);
00651 result = dns_rdataset_next(&sigset);
00652 }
00653 if (result == ISC_R_NOMORE)
00654 result = ISC_R_SUCCESS;
00655
00656 check_result(result, "dns_rdataset_first/next");
00657 if (dns_rdataset_isassociated(&sigset))
00658 dns_rdataset_disassociate(&sigset);
00659
00660 for (key = ISC_LIST_HEAD(keylist);
00661 key != NULL;
00662 key = ISC_LIST_NEXT(key, link))
00663 {
00664 if (nowsignedby[key->index])
00665 continue;
00666
00667 if (!issigningkey(key))
00668 continue;
00669
00670 if (set->type == dns_rdatatype_dnskey &&
00671 dns_name_equal(name, gorigin)) {
00672 isc_boolean_t have_ksk;
00673 dns_dnsseckey_t *tmpkey;
00674
00675 have_ksk = isksk(key);
00676 for (tmpkey = ISC_LIST_HEAD(keylist);
00677 tmpkey != NULL;
00678 tmpkey = ISC_LIST_NEXT(tmpkey, link)) {
00679 if (dst_key_alg(key->key) !=
00680 dst_key_alg(tmpkey->key))
00681 continue;
00682 if (REVOKE(tmpkey->key))
00683 continue;
00684 if (isksk(tmpkey))
00685 have_ksk = ISC_TRUE;
00686 }
00687 if (isksk(key) || !have_ksk ||
00688 (iszsk(key) && !keyset_kskonly))
00689 signwithkey(name, set, key->key, ttl, add,
00690 "signing with dnskey");
00691 } else if (iszsk(key)) {
00692 signwithkey(name, set, key->key, ttl, add,
00693 "signing with dnskey");
00694 }
00695 }
00696
00697 isc_mem_put(mctx, wassignedby, arraysize * sizeof(isc_boolean_t));
00698 isc_mem_put(mctx, nowsignedby, arraysize * sizeof(isc_boolean_t));
00699 }
00700
00701 struct hashlist {
00702 unsigned char *hashbuf;
00703 size_t entries;
00704 size_t size;
00705 size_t length;
00706 };
00707
00708 static void
00709 hashlist_init(hashlist_t *l, unsigned int nodes, unsigned int length) {
00710
00711 l->entries = 0;
00712 l->length = length + 1;
00713
00714 if (nodes != 0) {
00715 l->size = nodes;
00716 l->hashbuf = malloc(l->size * l->length);
00717 if (l->hashbuf == NULL)
00718 l->size = 0;
00719 } else {
00720 l->size = 0;
00721 l->hashbuf = NULL;
00722 }
00723 }
00724
00725 static void
00726 hashlist_add(hashlist_t *l, const unsigned char *hash, size_t len)
00727 {
00728
00729 REQUIRE(len <= l->length);
00730
00731 if (l->entries == l->size) {
00732 l->size = l->size * 2 + 100;
00733 l->hashbuf = realloc(l->hashbuf, l->size * l->length);
00734 if (l->hashbuf == NULL)
00735 fatal("unable to grow hashlist: out of memory");
00736 }
00737 memset(l->hashbuf + l->entries * l->length, 0, l->length);
00738 memmove(l->hashbuf + l->entries * l->length, hash, len);
00739 l->entries++;
00740 }
00741
00742 static void
00743 hashlist_add_dns_name(hashlist_t *l, dns_name_t *name,
00744 unsigned int hashalg, unsigned int iterations,
00745 const unsigned char *salt, size_t salt_len,
00746 isc_boolean_t speculative)
00747 {
00748 char nametext[DNS_NAME_FORMATSIZE];
00749 unsigned char hash[NSEC3_MAX_HASH_LENGTH + 1];
00750 unsigned int len;
00751 size_t i;
00752
00753 len = isc_iterated_hash(hash, hashalg, iterations,
00754 salt, (int)salt_len,
00755 name->ndata, name->length);
00756 if (verbose) {
00757 dns_name_format(name, nametext, sizeof nametext);
00758 for (i = 0 ; i < len; i++)
00759 fprintf(stderr, "%02x", hash[i]);
00760 fprintf(stderr, " %s\n", nametext);
00761 }
00762 hash[len++] = speculative ? 1 : 0;
00763 hashlist_add(l, hash, len);
00764 }
00765
00766 static int
00767 hashlist_comp(const void *a, const void *b) {
00768 return (memcmp(a, b, hash_length + 1));
00769 }
00770
00771 static void
00772 hashlist_sort(hashlist_t *l) {
00773 qsort(l->hashbuf, l->entries, l->length, hashlist_comp);
00774 }
00775
00776 static isc_boolean_t
00777 hashlist_hasdup(hashlist_t *l) {
00778 unsigned char *current;
00779 unsigned char *next = l->hashbuf;
00780 size_t entries = l->entries;
00781
00782
00783
00784
00785 while (entries > 0U && next[l->length-1] != 0U) {
00786 next += l->length;
00787 entries--;
00788 }
00789
00790 current = next;
00791 while (entries-- > 1U) {
00792 next += l->length;
00793 if (next[l->length-1] != 0)
00794 continue;
00795 if (memcmp(current, next, l->length - 1) == 0)
00796 return (ISC_TRUE);
00797 current = next;
00798 }
00799 return (ISC_FALSE);
00800 }
00801
00802 static const unsigned char *
00803 hashlist_findnext(const hashlist_t *l,
00804 const unsigned char hash[NSEC3_MAX_HASH_LENGTH])
00805 {
00806 size_t entries = l->entries;
00807 const unsigned char *next = bsearch(hash, l->hashbuf, l->entries,
00808 l->length, hashlist_comp);
00809 INSIST(next != NULL);
00810
00811 do {
00812 if (next < l->hashbuf + (l->entries - 1) * l->length)
00813 next += l->length;
00814 else
00815 next = l->hashbuf;
00816 if (next[l->length - 1] == 0)
00817 break;
00818 } while (entries-- > 1U);
00819 INSIST(entries != 0U);
00820 return (next);
00821 }
00822
00823 static isc_boolean_t
00824 hashlist_exists(const hashlist_t *l,
00825 const unsigned char hash[NSEC3_MAX_HASH_LENGTH])
00826 {
00827 if (bsearch(hash, l->hashbuf, l->entries, l->length, hashlist_comp))
00828 return (ISC_TRUE);
00829 else
00830 return (ISC_FALSE);
00831 }
00832
00833 static void
00834 addnowildcardhash(hashlist_t *l, dns_name_t *name,
00835 unsigned int hashalg, unsigned int iterations,
00836 const unsigned char *salt, size_t salt_len)
00837 {
00838 dns_fixedname_t fixed;
00839 dns_name_t *wild;
00840 dns_dbnode_t *node = NULL;
00841 isc_result_t result;
00842 char namestr[DNS_NAME_FORMATSIZE];
00843
00844 dns_fixedname_init(&fixed);
00845 wild = dns_fixedname_name(&fixed);
00846
00847 result = dns_name_concatenate(dns_wildcardname, name, wild, NULL);
00848 if (result == ISC_R_NOSPACE)
00849 return;
00850 check_result(result,"addnowildcardhash: dns_name_concatenate()");
00851
00852 result = dns_db_findnode(gdb, wild, ISC_FALSE, &node);
00853 if (result == ISC_R_SUCCESS) {
00854 dns_db_detachnode(gdb, &node);
00855 return;
00856 }
00857
00858 if (verbose) {
00859 dns_name_format(wild, namestr, sizeof(namestr));
00860 fprintf(stderr, "adding no-wildcardhash for %s\n", namestr);
00861 }
00862
00863 hashlist_add_dns_name(l, wild, hashalg, iterations, salt, salt_len,
00864 ISC_TRUE);
00865 }
00866
00867 static void
00868 opendb(const char *prefix, dns_name_t *name, dns_rdataclass_t rdclass,
00869 dns_db_t **dbp)
00870 {
00871 char filename[PATH_MAX];
00872 isc_buffer_t b;
00873 isc_result_t result;
00874
00875 isc_buffer_init(&b, filename, sizeof(filename));
00876 if (dsdir != NULL) {
00877
00878 if (strlen(dsdir) >= isc_buffer_availablelength(&b))
00879 fatal("path '%s' is too long", dsdir);
00880 isc_buffer_putstr(&b, dsdir);
00881 if (dsdir[strlen(dsdir) - 1] != '/')
00882 isc_buffer_putstr(&b, "/");
00883 }
00884 if (strlen(prefix) > isc_buffer_availablelength(&b))
00885 fatal("path '%s' is too long", dsdir);
00886 isc_buffer_putstr(&b, prefix);
00887 result = dns_name_tofilenametext(name, ISC_FALSE, &b);
00888 check_result(result, "dns_name_tofilenametext()");
00889 if (isc_buffer_availablelength(&b) == 0) {
00890 char namestr[DNS_NAME_FORMATSIZE];
00891 dns_name_format(name, namestr, sizeof(namestr));
00892 fatal("name '%s' is too long", namestr);
00893 }
00894 isc_buffer_putuint8(&b, 0);
00895
00896 result = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_zone,
00897 rdclass, 0, NULL, dbp);
00898 check_result(result, "dns_db_create()");
00899
00900 result = dns_db_load3(*dbp, filename, inputformat, DNS_MASTER_HINT);
00901 if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE)
00902 dns_db_detach(dbp);
00903 }
00904
00905
00906
00907
00908
00909
00910 static isc_result_t
00911 loadds(dns_name_t *name, isc_uint32_t ttl, dns_rdataset_t *dsset) {
00912 dns_db_t *db = NULL;
00913 dns_dbversion_t *ver = NULL;
00914 dns_dbnode_t *node = NULL;
00915 isc_result_t result;
00916 dns_rdataset_t keyset;
00917 dns_rdata_t key, ds;
00918 unsigned char dsbuf[DNS_DS_BUFFERSIZE];
00919 dns_diff_t diff;
00920 dns_difftuple_t *tuple = NULL;
00921
00922 opendb("dsset-", name, gclass, &db);
00923 if (db != NULL) {
00924 result = dns_db_findnode(db, name, ISC_FALSE, &node);
00925 if (result == ISC_R_SUCCESS) {
00926 dns_rdataset_init(dsset);
00927 result = dns_db_findrdataset(db, node, NULL,
00928 dns_rdatatype_ds, 0, 0,
00929 dsset, NULL);
00930 dns_db_detachnode(db, &node);
00931 if (result == ISC_R_SUCCESS) {
00932 vbprintf(2, "found DS records\n");
00933 dsset->ttl = ttl;
00934 dns_db_detach(&db);
00935 return (result);
00936 }
00937 }
00938 dns_db_detach(&db);
00939 }
00940
00941
00942 opendb("keyset-", name, gclass, &db);
00943 if (db == NULL) {
00944 return (ISC_R_NOTFOUND);
00945 }
00946
00947 result = dns_db_findnode(db, name, ISC_FALSE, &node);
00948 if (result != ISC_R_SUCCESS) {
00949 dns_db_detach(&db);
00950 return (result);
00951 }
00952
00953 dns_rdataset_init(&keyset);
00954 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_dnskey, 0, 0,
00955 &keyset, NULL);
00956 if (result != ISC_R_SUCCESS) {
00957 dns_db_detachnode(db, &node);
00958 dns_db_detach(&db);
00959 return (result);
00960 }
00961 vbprintf(2, "found DNSKEY records\n");
00962
00963 result = dns_db_newversion(db, &ver);
00964 check_result(result, "dns_db_newversion");
00965 dns_diff_init(mctx, &diff);
00966
00967 for (result = dns_rdataset_first(&keyset);
00968 result == ISC_R_SUCCESS;
00969 result = dns_rdataset_next(&keyset))
00970 {
00971 dns_rdata_init(&key);
00972 dns_rdata_init(&ds);
00973 dns_rdataset_current(&keyset, &key);
00974 result = dns_ds_buildrdata(name, &key, DNS_DSDIGEST_SHA1,
00975 dsbuf, &ds);
00976 check_result(result, "dns_ds_buildrdata");
00977
00978 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADDRESIGN, name,
00979 ttl, &ds, &tuple);
00980 check_result(result, "dns_difftuple_create");
00981 dns_diff_append(&diff, &tuple);
00982
00983 dns_rdata_reset(&ds);
00984 result = dns_ds_buildrdata(name, &key, DNS_DSDIGEST_SHA256,
00985 dsbuf, &ds);
00986 check_result(result, "dns_ds_buildrdata");
00987
00988 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADDRESIGN, name,
00989 ttl, &ds, &tuple);
00990 check_result(result, "dns_difftuple_create");
00991 dns_diff_append(&diff, &tuple);
00992 }
00993
00994 result = dns_diff_apply(&diff, db, ver);
00995 check_result(result, "dns_diff_apply");
00996 dns_diff_clear(&diff);
00997
00998 dns_db_closeversion(db, &ver, ISC_TRUE);
00999
01000 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ds, 0, 0,
01001 dsset, NULL);
01002 check_result(result, "dns_db_findrdataset");
01003
01004 dns_rdataset_disassociate(&keyset);
01005 dns_db_detachnode(db, &node);
01006 dns_db_detach(&db);
01007 return (result);
01008 }
01009
01010 static isc_boolean_t
01011 secure(dns_name_t *name, dns_dbnode_t *node) {
01012 dns_rdataset_t dsset;
01013 isc_result_t result;
01014
01015 if (dns_name_equal(name, gorigin))
01016 return (ISC_FALSE);
01017
01018 dns_rdataset_init(&dsset);
01019 result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_ds,
01020 0, 0, &dsset, NULL);
01021 if (dns_rdataset_isassociated(&dsset))
01022 dns_rdataset_disassociate(&dsset);
01023
01024 return (ISC_TF(result == ISC_R_SUCCESS));
01025 }
01026
01027
01028
01029
01030 static void
01031 signname(dns_dbnode_t *node, dns_name_t *name) {
01032 isc_result_t result;
01033 dns_rdataset_t rdataset;
01034 dns_rdatasetiter_t *rdsiter;
01035 isc_boolean_t isdelegation = ISC_FALSE;
01036 dns_diff_t del, add;
01037 char namestr[DNS_NAME_FORMATSIZE];
01038
01039 dns_rdataset_init(&rdataset);
01040 dns_name_format(name, namestr, sizeof(namestr));
01041
01042
01043
01044
01045 if (is_delegation(gdb, gversion, gorigin, name, node, NULL))
01046 isdelegation = ISC_TRUE;
01047
01048
01049
01050
01051 dns_diff_init(mctx, &del);
01052 dns_diff_init(mctx, &add);
01053 rdsiter = NULL;
01054 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
01055 check_result(result, "dns_db_allrdatasets()");
01056 result = dns_rdatasetiter_first(rdsiter);
01057 while (result == ISC_R_SUCCESS) {
01058 dns_rdatasetiter_current(rdsiter, &rdataset);
01059
01060
01061 if (rdataset.type == dns_rdatatype_rrsig)
01062 goto skip;
01063
01064
01065
01066
01067
01068
01069 if (isdelegation) {
01070 if (rdataset.type != nsec_datatype &&
01071 rdataset.type != dns_rdatatype_ds)
01072 goto skip;
01073 } else if (rdataset.type == dns_rdatatype_ds) {
01074 char namebuf[DNS_NAME_FORMATSIZE];
01075 dns_name_format(name, namebuf, sizeof(namebuf));
01076 fatal("'%s': found DS RRset without NS RRset\n",
01077 namebuf);
01078 }
01079
01080 signset(&del, &add, node, name, &rdataset);
01081
01082 skip:
01083 dns_rdataset_disassociate(&rdataset);
01084 result = dns_rdatasetiter_next(rdsiter);
01085 }
01086 if (result != ISC_R_NOMORE)
01087 fatal("rdataset iteration for name '%s' failed: %s",
01088 namestr, isc_result_totext(result));
01089
01090 dns_rdatasetiter_destroy(&rdsiter);
01091
01092 result = dns_diff_applysilently(&del, gdb, gversion);
01093 if (result != ISC_R_SUCCESS)
01094 fatal("failed to delete SIGs at node '%s': %s",
01095 namestr, isc_result_totext(result));
01096
01097 result = dns_diff_applysilently(&add, gdb, gversion);
01098 if (result != ISC_R_SUCCESS)
01099 fatal("failed to add SIGs at node '%s': %s",
01100 namestr, isc_result_totext(result));
01101
01102 dns_diff_clear(&del);
01103 dns_diff_clear(&add);
01104 }
01105
01106 static inline isc_boolean_t
01107 active_node(dns_dbnode_t *node) {
01108 dns_rdatasetiter_t *rdsiter = NULL;
01109 dns_rdatasetiter_t *rdsiter2 = NULL;
01110 isc_boolean_t active = ISC_FALSE;
01111 isc_result_t result;
01112 dns_rdataset_t rdataset;
01113 dns_rdatatype_t type;
01114 dns_rdatatype_t covers;
01115 isc_boolean_t found;
01116
01117 dns_rdataset_init(&rdataset);
01118 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
01119 check_result(result, "dns_db_allrdatasets()");
01120 result = dns_rdatasetiter_first(rdsiter);
01121 while (result == ISC_R_SUCCESS) {
01122 dns_rdatasetiter_current(rdsiter, &rdataset);
01123 if (rdataset.type != dns_rdatatype_nsec &&
01124 rdataset.type != dns_rdatatype_nsec3 &&
01125 rdataset.type != dns_rdatatype_rrsig)
01126 active = ISC_TRUE;
01127 dns_rdataset_disassociate(&rdataset);
01128 if (!active)
01129 result = dns_rdatasetiter_next(rdsiter);
01130 else
01131 result = ISC_R_NOMORE;
01132 }
01133 if (result != ISC_R_NOMORE)
01134 fatal("rdataset iteration failed: %s",
01135 isc_result_totext(result));
01136
01137 if (!active && nsec_datatype == dns_rdatatype_nsec) {
01138
01139
01140
01141 for (result = dns_rdatasetiter_first(rdsiter);
01142 result == ISC_R_SUCCESS;
01143 result = dns_rdatasetiter_next(rdsiter)) {
01144 dns_rdatasetiter_current(rdsiter, &rdataset);
01145 result = dns_db_deleterdataset(gdb, node, gversion,
01146 rdataset.type,
01147 rdataset.covers);
01148 check_result(result, "dns_db_deleterdataset()");
01149 dns_rdataset_disassociate(&rdataset);
01150 }
01151 if (result != ISC_R_NOMORE)
01152 fatal("rdataset iteration failed: %s",
01153 isc_result_totext(result));
01154 } else {
01155
01156
01157
01158 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter2);
01159 check_result(result, "dns_db_allrdatasets()");
01160 for (result = dns_rdatasetiter_first(rdsiter);
01161 result == ISC_R_SUCCESS;
01162 result = dns_rdatasetiter_next(rdsiter)) {
01163 dns_rdatasetiter_current(rdsiter, &rdataset);
01164 type = rdataset.type;
01165 covers = rdataset.covers;
01166 dns_rdataset_disassociate(&rdataset);
01167
01168
01169
01170
01171 if (nsec_datatype == dns_rdatatype_nsec3 &&
01172 (type == dns_rdatatype_nsec ||
01173 covers == dns_rdatatype_nsec)) {
01174 result = dns_db_deleterdataset(gdb, node,
01175 gversion, type,
01176 covers);
01177 check_result(result,
01178 "dns_db_deleterdataset(nsec/rrsig)");
01179 continue;
01180 }
01181 if (type != dns_rdatatype_rrsig)
01182 continue;
01183 found = ISC_FALSE;
01184 for (result = dns_rdatasetiter_first(rdsiter2);
01185 !found && result == ISC_R_SUCCESS;
01186 result = dns_rdatasetiter_next(rdsiter2)) {
01187 dns_rdatasetiter_current(rdsiter2, &rdataset);
01188 if (rdataset.type == covers)
01189 found = ISC_TRUE;
01190 dns_rdataset_disassociate(&rdataset);
01191 }
01192 if (!found) {
01193 if (result != ISC_R_NOMORE)
01194 fatal("rdataset iteration failed: %s",
01195 isc_result_totext(result));
01196 result = dns_db_deleterdataset(gdb, node,
01197 gversion, type,
01198 covers);
01199 check_result(result,
01200 "dns_db_deleterdataset(rrsig)");
01201 } else if (result != ISC_R_NOMORE &&
01202 result != ISC_R_SUCCESS)
01203 fatal("rdataset iteration failed: %s",
01204 isc_result_totext(result));
01205 }
01206 if (result != ISC_R_NOMORE)
01207 fatal("rdataset iteration failed: %s",
01208 isc_result_totext(result));
01209 dns_rdatasetiter_destroy(&rdsiter2);
01210 }
01211 dns_rdatasetiter_destroy(&rdsiter);
01212
01213 return (active);
01214 }
01215
01216
01217
01218
01219 static void
01220 get_soa_ttls(void) {
01221 dns_rdataset_t soaset;
01222 dns_fixedname_t fname;
01223 dns_name_t *name;
01224 isc_result_t result;
01225 dns_rdata_t rdata = DNS_RDATA_INIT;
01226
01227 dns_fixedname_init(&fname);
01228 name = dns_fixedname_name(&fname);
01229 dns_rdataset_init(&soaset);
01230 result = dns_db_find(gdb, gorigin, gversion, dns_rdatatype_soa,
01231 0, 0, NULL, name, &soaset, NULL);
01232 if (result != ISC_R_SUCCESS)
01233 fatal("failed to find an SOA at the zone apex: %s",
01234 isc_result_totext(result));
01235
01236 result = dns_rdataset_first(&soaset);
01237 check_result(result, "dns_rdataset_first");
01238 dns_rdataset_current(&soaset, &rdata);
01239 zone_soa_min_ttl = dns_soa_getminimum(&rdata);
01240 soa_ttl = soaset.ttl;
01241 if (set_maxttl) {
01242 zone_soa_min_ttl = ISC_MIN(zone_soa_min_ttl, maxttl);
01243 soa_ttl = ISC_MIN(soa_ttl, maxttl);
01244 }
01245 dns_rdataset_disassociate(&soaset);
01246 }
01247
01248
01249
01250
01251 static isc_result_t
01252 setsoaserial(isc_uint32_t serial, dns_updatemethod_t method) {
01253 isc_result_t result;
01254 dns_dbnode_t *node = NULL;
01255 dns_rdataset_t rdataset;
01256 dns_rdata_t rdata = DNS_RDATA_INIT;
01257 isc_uint32_t old_serial, new_serial;
01258
01259 result = dns_db_getoriginnode(gdb, &node);
01260 if (result != ISC_R_SUCCESS)
01261 return result;
01262
01263 dns_rdataset_init(&rdataset);
01264
01265 result = dns_db_findrdataset(gdb, node, gversion,
01266 dns_rdatatype_soa, 0,
01267 0, &rdataset, NULL);
01268 if (result != ISC_R_SUCCESS)
01269 goto cleanup;
01270
01271 result = dns_rdataset_first(&rdataset);
01272 RUNTIME_CHECK(result == ISC_R_SUCCESS);
01273
01274 dns_rdataset_current(&rdataset, &rdata);
01275
01276 old_serial = dns_soa_getserial(&rdata);
01277
01278 if (method == dns_updatemethod_date ||
01279 method == dns_updatemethod_unixtime) {
01280 new_serial = dns_update_soaserial(old_serial, method);
01281 } else if (serial != 0 || method == dns_updatemethod_none) {
01282
01283 new_serial = serial;
01284 } else {
01285
01286 new_serial = (old_serial + 1) & 0xFFFFFFFF;
01287 if (new_serial == 0)
01288 new_serial = 1;
01289 }
01290
01291
01292
01293
01294
01295
01296
01297
01298 if (new_serial == old_serial ||
01299 (new_serial - old_serial) > 0x7fffffffU)
01300 fprintf(stderr, "%s: warning: Serial number not advanced, "
01301 "zone may not transfer\n", program);
01302
01303 dns_soa_setserial(new_serial, &rdata);
01304
01305 result = dns_db_deleterdataset(gdb, node, gversion,
01306 dns_rdatatype_soa, 0);
01307 check_result(result, "dns_db_deleterdataset");
01308 if (result != ISC_R_SUCCESS)
01309 goto cleanup;
01310
01311 result = dns_db_addrdataset(gdb, node, gversion,
01312 0, &rdataset, 0, NULL);
01313 check_result(result, "dns_db_addrdataset");
01314 if (result != ISC_R_SUCCESS)
01315 goto cleanup;
01316
01317 cleanup:
01318 dns_rdataset_disassociate(&rdataset);
01319 if (node != NULL)
01320 dns_db_detachnode(gdb, &node);
01321 dns_rdata_reset(&rdata);
01322
01323 return (result);
01324 }
01325
01326
01327
01328
01329 static void
01330 cleannode(dns_db_t *db, dns_dbversion_t *dbversion, dns_dbnode_t *node) {
01331 dns_rdatasetiter_t *rdsiter = NULL;
01332 dns_rdataset_t set;
01333 isc_result_t result, dresult;
01334
01335 if (outputformat != dns_masterformat_text || !disable_zone_check)
01336 return;
01337
01338 dns_rdataset_init(&set);
01339 result = dns_db_allrdatasets(db, node, dbversion, 0, &rdsiter);
01340 check_result(result, "dns_db_allrdatasets");
01341 result = dns_rdatasetiter_first(rdsiter);
01342 while (result == ISC_R_SUCCESS) {
01343 isc_boolean_t destroy = ISC_FALSE;
01344 dns_rdatatype_t covers = 0;
01345 dns_rdatasetiter_current(rdsiter, &set);
01346 if (set.type == dns_rdatatype_rrsig) {
01347 covers = set.covers;
01348 destroy = ISC_TRUE;
01349 }
01350 dns_rdataset_disassociate(&set);
01351 result = dns_rdatasetiter_next(rdsiter);
01352 if (destroy) {
01353 dresult = dns_db_deleterdataset(db, node, dbversion,
01354 dns_rdatatype_rrsig,
01355 covers);
01356 check_result(dresult, "dns_db_deleterdataset");
01357 }
01358 }
01359 if (result != ISC_R_NOMORE)
01360 fatal("rdataset iteration failed: %s",
01361 isc_result_totext(result));
01362 dns_rdatasetiter_destroy(&rdsiter);
01363 }
01364
01365
01366
01367
01368 static void
01369 presign(void) {
01370 isc_result_t result;
01371
01372 gdbiter = NULL;
01373 result = dns_db_createiterator(gdb, 0, &gdbiter);
01374 check_result(result, "dns_db_createiterator()");
01375 }
01376
01377
01378
01379
01380 static void
01381 postsign(void) {
01382 dns_dbiterator_destroy(&gdbiter);
01383 }
01384
01385
01386
01387
01388
01389
01390 static void
01391 signapex(void) {
01392 dns_dbnode_t *node = NULL;
01393 dns_fixedname_t fixed;
01394 dns_name_t *name;
01395 isc_result_t result;
01396
01397 dns_fixedname_init(&fixed);
01398 name = dns_fixedname_name(&fixed);
01399 result = dns_dbiterator_seek(gdbiter, gorigin);
01400 check_result(result, "dns_dbiterator_seek()");
01401 result = dns_dbiterator_current(gdbiter, &node, name);
01402 check_dns_dbiterator_current(result);
01403 signname(node, name);
01404 dumpnode(name, node);
01405 cleannode(gdb, gversion, node);
01406 dns_db_detachnode(gdb, &node);
01407 result = dns_dbiterator_first(gdbiter);
01408 if (result == ISC_R_NOMORE)
01409 finished = ISC_TRUE;
01410 else if (result != ISC_R_SUCCESS)
01411 fatal("failure iterating database: %s",
01412 isc_result_totext(result));
01413 }
01414
01415
01416
01417
01418
01419 static void
01420 assignwork(isc_task_t *task, isc_task_t *worker) {
01421 dns_fixedname_t *fname;
01422 dns_name_t *name;
01423 dns_dbnode_t *node;
01424 sevent_t *sevent;
01425 dns_rdataset_t nsec;
01426 isc_boolean_t found;
01427 isc_result_t result;
01428 static dns_name_t *zonecut = NULL;
01429 static dns_fixedname_t fzonecut;
01430 static unsigned int ended = 0;
01431
01432 if (shuttingdown)
01433 return;
01434
01435 LOCK(&namelock);
01436 if (finished) {
01437 ended++;
01438 if (ended == ntasks) {
01439 isc_task_detach(&task);
01440 isc_app_shutdown();
01441 }
01442 goto unlock;
01443 }
01444
01445 fname = isc_mem_get(mctx, sizeof(dns_fixedname_t));
01446 if (fname == NULL)
01447 fatal("out of memory");
01448 dns_fixedname_init(fname);
01449 name = dns_fixedname_name(fname);
01450 node = NULL;
01451 found = ISC_FALSE;
01452 while (!found) {
01453 result = dns_dbiterator_current(gdbiter, &node, name);
01454 check_dns_dbiterator_current(result);
01455
01456
01457
01458 if (dns_name_equal(name, gorigin)) {
01459 dns_db_detachnode(gdb, &node);
01460 goto next;
01461 }
01462
01463
01464
01465
01466
01467
01468
01469
01470 dns_rdataset_init(&nsec);
01471 result = dns_db_findrdataset(gdb, node, gversion,
01472 nsec_datatype, 0, 0,
01473 &nsec, NULL);
01474 if (dns_rdataset_isassociated(&nsec))
01475 dns_rdataset_disassociate(&nsec);
01476 if (result == ISC_R_SUCCESS) {
01477 found = ISC_TRUE;
01478 } else if (nsec_datatype == dns_rdatatype_nsec3) {
01479 if (dns_name_issubdomain(name, gorigin) &&
01480 (zonecut == NULL ||
01481 !dns_name_issubdomain(name, zonecut))) {
01482 if (is_delegation(gdb, gversion, gorigin, name, node, NULL)) {
01483 dns_fixedname_init(&fzonecut);
01484 zonecut = dns_fixedname_name(&fzonecut);
01485 dns_name_copy(name, zonecut, NULL);
01486 if (!OPTOUT(nsec3flags) ||
01487 secure(name, node))
01488 found = ISC_TRUE;
01489 } else
01490 found = ISC_TRUE;
01491 }
01492 }
01493
01494 if (!found) {
01495 dumpnode(name, node);
01496 dns_db_detachnode(gdb, &node);
01497 }
01498
01499 next:
01500 result = dns_dbiterator_next(gdbiter);
01501 if (result == ISC_R_NOMORE) {
01502 finished = ISC_TRUE;
01503 break;
01504 } else if (result != ISC_R_SUCCESS)
01505 fatal("failure iterating database: %s",
01506 isc_result_totext(result));
01507 }
01508 if (!found) {
01509 ended++;
01510 if (ended == ntasks) {
01511 isc_task_detach(&task);
01512 isc_app_shutdown();
01513 }
01514 isc_mem_put(mctx, fname, sizeof(dns_fixedname_t));
01515 goto unlock;
01516 }
01517 sevent = (sevent_t *)
01518 isc_event_allocate(mctx, task, SIGNER_EVENT_WORK,
01519 sign, NULL, sizeof(sevent_t));
01520 if (sevent == NULL)
01521 fatal("failed to allocate event\n");
01522
01523 sevent->node = node;
01524 sevent->fname = fname;
01525 isc_task_send(worker, ISC_EVENT_PTR(&sevent));
01526 unlock:
01527 UNLOCK(&namelock);
01528 }
01529
01530
01531
01532
01533 static void
01534 startworker(isc_task_t *task, isc_event_t *event) {
01535 isc_task_t *worker;
01536
01537 worker = (isc_task_t *)event->ev_arg;
01538 assignwork(task, worker);
01539 isc_event_free(&event);
01540 }
01541
01542
01543
01544
01545 static void
01546 writenode(isc_task_t *task, isc_event_t *event) {
01547 isc_task_t *worker;
01548 sevent_t *sevent = (sevent_t *)event;
01549
01550 worker = (isc_task_t *)event->ev_sender;
01551 dumpnode(dns_fixedname_name(sevent->fname), sevent->node);
01552 cleannode(gdb, gversion, sevent->node);
01553 dns_db_detachnode(gdb, &sevent->node);
01554 isc_mem_put(mctx, sevent->fname, sizeof(dns_fixedname_t));
01555 assignwork(task, worker);
01556 isc_event_free(&event);
01557 }
01558
01559
01560
01561
01562 static void
01563 sign(isc_task_t *task, isc_event_t *event) {
01564 dns_fixedname_t *fname;
01565 dns_dbnode_t *node;
01566 sevent_t *sevent, *wevent;
01567
01568 sevent = (sevent_t *)event;
01569 node = sevent->node;
01570 fname = sevent->fname;
01571 isc_event_free(&event);
01572
01573 signname(node, dns_fixedname_name(fname));
01574 wevent = (sevent_t *)
01575 isc_event_allocate(mctx, task, SIGNER_EVENT_WRITE,
01576 writenode, NULL, sizeof(sevent_t));
01577 if (wevent == NULL)
01578 fatal("failed to allocate event\n");
01579 wevent->node = node;
01580 wevent->fname = fname;
01581 isc_task_send(master, ISC_EVENT_PTR(&wevent));
01582 }
01583
01584
01585
01586
01587 static void
01588 add_ds(dns_name_t *name, dns_dbnode_t *node, isc_uint32_t nsttl) {
01589 dns_rdataset_t dsset;
01590 dns_rdataset_t sigdsset;
01591 isc_result_t result;
01592
01593 dns_rdataset_init(&dsset);
01594 dns_rdataset_init(&sigdsset);
01595 result = dns_db_findrdataset(gdb, node, gversion,
01596 dns_rdatatype_ds,
01597 0, 0, &dsset, &sigdsset);
01598 if (result == ISC_R_SUCCESS) {
01599 dns_rdataset_disassociate(&dsset);
01600 result = dns_db_deleterdataset(gdb, node, gversion,
01601 dns_rdatatype_ds, 0);
01602 check_result(result, "dns_db_deleterdataset");
01603 }
01604
01605 result = loadds(name, nsttl, &dsset);
01606 if (result == ISC_R_SUCCESS) {
01607 result = dns_db_addrdataset(gdb, node, gversion, 0,
01608 &dsset, 0, NULL);
01609 check_result(result, "dns_db_addrdataset");
01610 dns_rdataset_disassociate(&dsset);
01611 if (dns_rdataset_isassociated(&sigdsset))
01612 dns_rdataset_disassociate(&sigdsset);
01613 } else if (dns_rdataset_isassociated(&sigdsset)) {
01614 result = dns_db_deleterdataset(gdb, node, gversion,
01615 dns_rdatatype_rrsig,
01616 dns_rdatatype_ds);
01617 check_result(result, "dns_db_deleterdataset");
01618 dns_rdataset_disassociate(&sigdsset);
01619 }
01620 }
01621
01622
01623
01624
01625 static void
01626 remove_records(dns_dbnode_t *node, dns_rdatatype_t which,
01627 isc_boolean_t checknsec)
01628 {
01629 isc_result_t result;
01630 dns_rdatatype_t type, covers;
01631 dns_rdatasetiter_t *rdsiter = NULL;
01632 dns_rdataset_t rdataset;
01633
01634 dns_rdataset_init(&rdataset);
01635
01636
01637
01638
01639 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
01640 check_result(result, "dns_db_allrdatasets()");
01641 for (result = dns_rdatasetiter_first(rdsiter);
01642 result == ISC_R_SUCCESS;
01643 result = dns_rdatasetiter_next(rdsiter)) {
01644 dns_rdatasetiter_current(rdsiter, &rdataset);
01645 type = rdataset.type;
01646 covers = rdataset.covers;
01647 dns_rdataset_disassociate(&rdataset);
01648 if (type == which || covers == which) {
01649 if (which == dns_rdatatype_nsec &&
01650 checknsec && !update_chain)
01651 fatal("Zone contains NSEC records. Use -u "
01652 "to update to NSEC3.");
01653 if (which == dns_rdatatype_nsec3param &&
01654 checknsec && !update_chain)
01655 fatal("Zone contains NSEC3 chains. Use -u "
01656 "to update to NSEC.");
01657 result = dns_db_deleterdataset(gdb, node, gversion,
01658 type, covers);
01659 check_result(result, "dns_db_deleterdataset()");
01660 continue;
01661 }
01662 }
01663 dns_rdatasetiter_destroy(&rdsiter);
01664 }
01665
01666
01667
01668
01669
01670
01671 static void
01672 remove_sigs(dns_dbnode_t *node, isc_boolean_t delegation,
01673 dns_rdatatype_t which)
01674 {
01675 isc_result_t result;
01676 dns_rdatatype_t type, covers;
01677 dns_rdatasetiter_t *rdsiter = NULL;
01678 dns_rdataset_t rdataset;
01679
01680 dns_rdataset_init(&rdataset);
01681 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
01682 check_result(result, "dns_db_allrdatasets()");
01683 for (result = dns_rdatasetiter_first(rdsiter);
01684 result == ISC_R_SUCCESS;
01685 result = dns_rdatasetiter_next(rdsiter)) {
01686 dns_rdatasetiter_current(rdsiter, &rdataset);
01687 type = rdataset.type;
01688 covers = rdataset.covers;
01689 dns_rdataset_disassociate(&rdataset);
01690
01691 if (type != dns_rdatatype_rrsig)
01692 continue;
01693
01694 if (which == 0 && delegation &&
01695 (dns_rdatatype_atparent(covers) ||
01696 (nsec_datatype == dns_rdatatype_nsec &&
01697 covers == nsec_datatype)))
01698 continue;
01699
01700 if (which != 0 && covers != which)
01701 continue;
01702
01703 result = dns_db_deleterdataset(gdb, node, gversion,
01704 type, covers);
01705 check_result(result, "dns_db_deleterdataset()");
01706 }
01707 dns_rdatasetiter_destroy(&rdsiter);
01708 }
01709
01710
01711
01712
01713 static void
01714 nsecify(void) {
01715 dns_dbiterator_t *dbiter = NULL;
01716 dns_dbnode_t *node = NULL, *nextnode = NULL;
01717 dns_fixedname_t fname, fnextname, fzonecut;
01718 dns_name_t *name, *nextname, *zonecut;
01719 dns_rdataset_t rdataset;
01720 dns_rdatasetiter_t *rdsiter = NULL;
01721 dns_rdatatype_t type, covers;
01722 isc_boolean_t done = ISC_FALSE;
01723 isc_result_t result;
01724 isc_uint32_t nsttl = 0;
01725
01726 dns_rdataset_init(&rdataset);
01727 dns_fixedname_init(&fname);
01728 name = dns_fixedname_name(&fname);
01729 dns_fixedname_init(&fnextname);
01730 nextname = dns_fixedname_name(&fnextname);
01731 dns_fixedname_init(&fzonecut);
01732 zonecut = NULL;
01733
01734
01735
01736
01737 result = dns_db_createiterator(gdb, DNS_DB_NSEC3ONLY, &dbiter);
01738 check_result(result, "dns_db_createiterator()");
01739 for (result = dns_dbiterator_first(dbiter);
01740 result == ISC_R_SUCCESS;
01741 result = dns_dbiterator_next(dbiter)) {
01742 result = dns_dbiterator_current(dbiter, &node, name);
01743 check_dns_dbiterator_current(result);
01744 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
01745 check_result(result, "dns_db_allrdatasets()");
01746 for (result = dns_rdatasetiter_first(rdsiter);
01747 result == ISC_R_SUCCESS;
01748 result = dns_rdatasetiter_next(rdsiter)) {
01749 dns_rdatasetiter_current(rdsiter, &rdataset);
01750 type = rdataset.type;
01751 covers = rdataset.covers;
01752 dns_rdataset_disassociate(&rdataset);
01753 result = dns_db_deleterdataset(gdb, node, gversion,
01754 type, covers);
01755 check_result(result,
01756 "dns_db_deleterdataset(nsec3param/rrsig)");
01757 }
01758 dns_rdatasetiter_destroy(&rdsiter);
01759 dns_db_detachnode(gdb, &node);
01760 }
01761 dns_dbiterator_destroy(&dbiter);
01762
01763 result = dns_db_createiterator(gdb, DNS_DB_NONSEC3, &dbiter);
01764 check_result(result, "dns_db_createiterator()");
01765
01766 result = dns_dbiterator_first(dbiter);
01767 check_result(result, "dns_dbiterator_first()");
01768
01769 while (!done) {
01770 result = dns_dbiterator_current(dbiter, &node, name);
01771 check_dns_dbiterator_current(result);
01772
01773
01774
01775 if (!dns_name_issubdomain(name, gorigin)) {
01776 result = dns_dbiterator_next(dbiter);
01777 if (result == ISC_R_NOMORE)
01778 done = ISC_TRUE;
01779 else
01780 check_result(result, "dns_dbiterator_next()");
01781 dns_db_detachnode(gdb, &node);
01782 continue;
01783 }
01784
01785 if (dns_name_equal(name, gorigin))
01786 remove_records(node, dns_rdatatype_nsec3param,
01787 ISC_TRUE);
01788
01789 if (is_delegation(gdb, gversion, gorigin, name, node, &nsttl)) {
01790 zonecut = dns_fixedname_name(&fzonecut);
01791 dns_name_copy(name, zonecut, NULL);
01792 remove_sigs(node, ISC_TRUE, 0);
01793 if (generateds)
01794 add_ds(name, node, nsttl);
01795 }
01796
01797 result = dns_dbiterator_next(dbiter);
01798 nextnode = NULL;
01799 while (result == ISC_R_SUCCESS) {
01800 isc_boolean_t active = ISC_FALSE;
01801 result = dns_dbiterator_current(dbiter, &nextnode,
01802 nextname);
01803 check_dns_dbiterator_current(result);
01804 active = active_node(nextnode);
01805 if (!active) {
01806 dns_db_detachnode(gdb, &nextnode);
01807 result = dns_dbiterator_next(dbiter);
01808 continue;
01809 }
01810 if (!dns_name_issubdomain(nextname, gorigin) ||
01811 (zonecut != NULL &&
01812 dns_name_issubdomain(nextname, zonecut)))
01813 {
01814 remove_sigs(nextnode, ISC_FALSE, 0);
01815 remove_records(nextnode, dns_rdatatype_nsec,
01816 ISC_FALSE);
01817 dns_db_detachnode(gdb, &nextnode);
01818 result = dns_dbiterator_next(dbiter);
01819 continue;
01820 }
01821 dns_db_detachnode(gdb, &nextnode);
01822 break;
01823 }
01824 if (result == ISC_R_NOMORE) {
01825 dns_name_clone(gorigin, nextname);
01826 done = ISC_TRUE;
01827 } else if (result != ISC_R_SUCCESS)
01828 fatal("iterating through the database failed: %s",
01829 isc_result_totext(result));
01830 dns_dbiterator_pause(dbiter);
01831 result = dns_nsec_build(gdb, gversion, node, nextname,
01832 zone_soa_min_ttl);
01833 check_result(result, "dns_nsec_build()");
01834 dns_db_detachnode(gdb, &node);
01835 }
01836
01837 dns_dbiterator_destroy(&dbiter);
01838 }
01839
01840 static void
01841 addnsec3param(const unsigned char *salt, size_t salt_len,
01842 dns_iterations_t iterations)
01843 {
01844 dns_dbnode_t *node = NULL;
01845 dns_rdata_nsec3param_t nsec3param;
01846 unsigned char nsec3parambuf[5 + 255];
01847 dns_rdatalist_t rdatalist;
01848 dns_rdataset_t rdataset;
01849 dns_rdata_t rdata = DNS_RDATA_INIT;
01850 isc_buffer_t b;
01851 isc_result_t result;
01852
01853 dns_rdataset_init(&rdataset);
01854
01855 nsec3param.common.rdclass = gclass;
01856 nsec3param.common.rdtype = dns_rdatatype_nsec3param;
01857 ISC_LINK_INIT(&nsec3param.common, link);
01858 nsec3param.mctx = NULL;
01859 nsec3param.flags = 0;
01860 nsec3param.hash = unknownalg ? DNS_NSEC3_UNKNOWNALG : dns_hash_sha1;
01861 nsec3param.iterations = iterations;
01862 nsec3param.salt_length = (unsigned char)salt_len;
01863 DE_CONST(salt, nsec3param.salt);
01864
01865 isc_buffer_init(&b, nsec3parambuf, sizeof(nsec3parambuf));
01866 result = dns_rdata_fromstruct(&rdata, gclass,
01867 dns_rdatatype_nsec3param,
01868 &nsec3param, &b);
01869 check_result(result, "dns_rdata_fromstruct()");
01870 dns_rdatalist_init(&rdatalist);
01871 rdatalist.rdclass = rdata.rdclass;
01872 rdatalist.type = rdata.type;
01873 ISC_LIST_APPEND(rdatalist.rdata, &rdata, link);
01874 result = dns_rdatalist_tordataset(&rdatalist, &rdataset);
01875 check_result(result, "dns_rdatalist_tordataset()");
01876
01877 result = dns_db_findnode(gdb, gorigin, ISC_TRUE, &node);
01878 check_result(result, "dns_db_find(gorigin)");
01879
01880
01881
01882
01883 result = dns_db_deleterdataset(gdb, node, gversion,
01884 dns_rdatatype_nsec3param, 0);
01885 if (result == DNS_R_UNCHANGED)
01886 result = ISC_R_SUCCESS;
01887 check_result(result, "dddnsec3param: dns_db_deleterdataset()");
01888
01889 result = dns_db_addrdataset(gdb, node, gversion, 0, &rdataset,
01890 DNS_DBADD_MERGE, NULL);
01891 if (result == DNS_R_UNCHANGED)
01892 result = ISC_R_SUCCESS;
01893 check_result(result, "addnsec3param: dns_db_addrdataset()");
01894 dns_db_detachnode(gdb, &node);
01895 }
01896
01897 static void
01898 addnsec3(dns_name_t *name, dns_dbnode_t *node,
01899 const unsigned char *salt, size_t salt_len,
01900 unsigned int iterations, hashlist_t *hashlist,
01901 dns_ttl_t ttl)
01902 {
01903 unsigned char hash[NSEC3_MAX_HASH_LENGTH];
01904 const unsigned char *nexthash;
01905 unsigned char nsec3buffer[DNS_NSEC3_BUFFERSIZE];
01906 dns_fixedname_t hashname;
01907 dns_rdatalist_t rdatalist;
01908 dns_rdataset_t rdataset;
01909 dns_rdata_t rdata = DNS_RDATA_INIT;
01910 isc_result_t result;
01911 dns_dbnode_t *nsec3node = NULL;
01912 char namebuf[DNS_NAME_FORMATSIZE];
01913 size_t hash_len;
01914
01915 dns_name_format(name, namebuf, sizeof(namebuf));
01916
01917 dns_fixedname_init(&hashname);
01918 dns_rdataset_init(&rdataset);
01919
01920 dns_name_downcase(name, name, NULL);
01921 result = dns_nsec3_hashname(&hashname, hash, &hash_len,
01922 name, gorigin, dns_hash_sha1, iterations,
01923 salt, salt_len);
01924 check_result(result, "addnsec3: dns_nsec3_hashname()");
01925 nexthash = hashlist_findnext(hashlist, hash);
01926 result = dns_nsec3_buildrdata(gdb, gversion, node,
01927 unknownalg ?
01928 DNS_NSEC3_UNKNOWNALG : dns_hash_sha1,
01929 nsec3flags, iterations,
01930 salt, salt_len,
01931 nexthash, ISC_SHA1_DIGESTLENGTH,
01932 nsec3buffer, &rdata);
01933 check_result(result, "addnsec3: dns_nsec3_buildrdata()");
01934 dns_rdatalist_init(&rdatalist);
01935 rdatalist.rdclass = rdata.rdclass;
01936 rdatalist.type = rdata.type;
01937 rdatalist.ttl = ttl;
01938 ISC_LIST_APPEND(rdatalist.rdata, &rdata, link);
01939 result = dns_rdatalist_tordataset(&rdatalist, &rdataset);
01940 check_result(result, "dns_rdatalist_tordataset()");
01941 result = dns_db_findnsec3node(gdb, dns_fixedname_name(&hashname),
01942 ISC_TRUE, &nsec3node);
01943 check_result(result, "addnsec3: dns_db_findnode()");
01944 result = dns_db_addrdataset(gdb, nsec3node, gversion, 0, &rdataset,
01945 0, NULL);
01946 if (result == DNS_R_UNCHANGED)
01947 result = ISC_R_SUCCESS;
01948 check_result(result, "addnsec3: dns_db_addrdataset()");
01949 dns_db_detachnode(gdb, &nsec3node);
01950 }
01951
01952
01953
01954
01955
01956
01957
01958
01959
01960
01961
01962 static void
01963 nsec3clean(dns_name_t *name, dns_dbnode_t *node,
01964 unsigned int hashalg, unsigned int iterations,
01965 const unsigned char *salt, size_t salt_len, hashlist_t *hashlist)
01966 {
01967 dns_label_t label;
01968 dns_rdata_nsec3_t nsec3;
01969 dns_rdata_t rdata, delrdata;
01970 dns_rdatalist_t rdatalist;
01971 dns_rdataset_t rdataset, delrdataset;
01972 isc_boolean_t delete_rrsigs = ISC_FALSE;
01973 isc_buffer_t target;
01974 isc_result_t result;
01975 unsigned char hash[NSEC3_MAX_HASH_LENGTH + 1];
01976 isc_boolean_t exists;
01977
01978
01979
01980
01981 dns_name_getlabel(name, 0, &label);
01982
01983
01984
01985
01986 isc_region_consume(&label, 1);
01987
01988
01989
01990
01991 isc_buffer_init(&target, hash, sizeof(hash) - 1);
01992 result = isc_base32hex_decoderegion(&label, &target);
01993 if (result != ISC_R_SUCCESS)
01994 return;
01995
01996 hash[isc_buffer_usedlength(&target)] = 0;
01997
01998 exists = hashlist_exists(hashlist, hash);
01999
02000
02001
02002
02003
02004 dns_rdataset_init(&rdataset);
02005 dns_rdataset_init(&delrdataset);
02006
02007 result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_nsec3,
02008 0, 0, &rdataset, NULL);
02009 if (result != ISC_R_SUCCESS)
02010 return;
02011
02012
02013
02014
02015
02016 for (result = dns_rdataset_first(&rdataset);
02017 result == ISC_R_SUCCESS;
02018 result = dns_rdataset_next(&rdataset)) {
02019 dns_rdata_init(&rdata);
02020 dns_rdataset_current(&rdataset, &rdata);
02021 result = dns_rdata_tostruct(&rdata, &nsec3, NULL);
02022 check_result(result, "dns_rdata_tostruct");
02023 if (exists && nsec3.hash == hashalg &&
02024 nsec3.iterations == iterations &&
02025 nsec3.salt_length == salt_len &&
02026 !memcmp(nsec3.salt, salt, salt_len))
02027 continue;
02028 dns_rdatalist_init(&rdatalist);
02029 rdatalist.rdclass = rdata.rdclass;
02030 rdatalist.type = rdata.type;
02031 if (set_maxttl)
02032 rdatalist.ttl = ISC_MIN(rdataset.ttl, maxttl);
02033 dns_rdata_init(&delrdata);
02034 dns_rdata_clone(&rdata, &delrdata);
02035 ISC_LIST_APPEND(rdatalist.rdata, &delrdata, link);
02036 result = dns_rdatalist_tordataset(&rdatalist, &delrdataset);
02037 check_result(result, "dns_rdatalist_tordataset()");
02038 result = dns_db_subtractrdataset(gdb, node, gversion,
02039 &delrdataset, 0, NULL);
02040 dns_rdataset_disassociate(&delrdataset);
02041 if (result != ISC_R_SUCCESS && result != DNS_R_NXRRSET)
02042 check_result(result, "dns_db_subtractrdataset(NSEC3)");
02043 delete_rrsigs = ISC_TRUE;
02044 }
02045 dns_rdataset_disassociate(&rdataset);
02046 if (result != ISC_R_NOMORE)
02047 check_result(result, "dns_rdataset_first/next");
02048
02049 if (!delete_rrsigs)
02050 return;
02051
02052
02053
02054 result = dns_db_deleterdataset(gdb, node, gversion,
02055 dns_rdatatype_rrsig,
02056 dns_rdatatype_nsec3);
02057 if (result != ISC_R_SUCCESS && result != DNS_R_UNCHANGED)
02058 check_result(result, "dns_db_deleterdataset(RRSIG(NSEC3))");
02059 }
02060
02061 static void
02062 rrset_cleanup(dns_name_t *name, dns_rdataset_t *rdataset,
02063 dns_diff_t *add, dns_diff_t *del)
02064 {
02065 isc_result_t result;
02066 unsigned int count1 = 0;
02067 dns_rdataset_t tmprdataset;
02068 char namestr[DNS_NAME_FORMATSIZE];
02069 char typestr[TYPE_FORMATSIZE];
02070
02071 dns_name_format(name, namestr, sizeof(namestr));
02072 type_format(rdataset->type, typestr, sizeof(typestr));
02073
02074 dns_rdataset_init(&tmprdataset);
02075 for (result = dns_rdataset_first(rdataset);
02076 result == ISC_R_SUCCESS;
02077 result = dns_rdataset_next(rdataset)) {
02078 dns_rdata_t rdata1 = DNS_RDATA_INIT;
02079 unsigned int count2 = 0;
02080
02081 count1++;
02082 dns_rdataset_current(rdataset, &rdata1);
02083 dns_rdataset_clone(rdataset, &tmprdataset);
02084 for (result = dns_rdataset_first(&tmprdataset);
02085 result == ISC_R_SUCCESS;
02086 result = dns_rdataset_next(&tmprdataset)) {
02087 dns_rdata_t rdata2 = DNS_RDATA_INIT;
02088 dns_difftuple_t *tuple = NULL;
02089 count2++;
02090 dns_rdataset_current(&tmprdataset, &rdata2);
02091 if (count1 < count2 &&
02092 dns_rdata_casecompare(&rdata1, &rdata2) == 0)
02093 {
02094 vbprintf(2, "removing duplicate at %s/%s\n",
02095 namestr, typestr);
02096 result = dns_difftuple_create(mctx,
02097 DNS_DIFFOP_DELRESIGN,
02098 name, rdataset->ttl,
02099 &rdata2, &tuple);
02100 check_result(result, "dns_difftuple_create");
02101 dns_diff_append(del, &tuple);
02102 } else if (set_maxttl && rdataset->ttl > maxttl) {
02103 vbprintf(2, "reducing ttl of %s/%s "
02104 "from %d to %d\n",
02105 namestr, typestr,
02106 rdataset->ttl, maxttl);
02107 result = dns_difftuple_create(mctx,
02108 DNS_DIFFOP_DELRESIGN,
02109 name, rdataset->ttl,
02110 &rdata2, &tuple);
02111 check_result(result, "dns_difftuple_create");
02112 dns_diff_append(del, &tuple);
02113 tuple = NULL;
02114 result = dns_difftuple_create(mctx,
02115 DNS_DIFFOP_ADDRESIGN,
02116 name, maxttl,
02117 &rdata2, &tuple);
02118 check_result(result, "dns_difftuple_create");
02119 dns_diff_append(add, &tuple);
02120 }
02121 }
02122 dns_rdataset_disassociate(&tmprdataset);
02123 }
02124 }
02125
02126 static void
02127 cleanup_zone(void) {
02128 isc_result_t result;
02129 dns_dbiterator_t *dbiter = NULL;
02130 dns_rdatasetiter_t *rdsiter = NULL;
02131 dns_diff_t add, del;
02132 dns_dbnode_t *node = NULL;
02133 dns_rdataset_t rdataset;
02134 dns_fixedname_t fname;
02135 dns_name_t *name;
02136
02137 dns_diff_init(mctx, &add);
02138 dns_diff_init(mctx, &del);
02139 dns_fixedname_init(&fname);
02140 name = dns_fixedname_name(&fname);
02141 dns_rdataset_init(&rdataset);
02142
02143 result = dns_db_createiterator(gdb, 0, &dbiter);
02144 check_result(result, "dns_db_createiterator()");
02145
02146 for (result = dns_dbiterator_first(dbiter);
02147 result == ISC_R_SUCCESS;
02148 result = dns_dbiterator_next(dbiter)) {
02149
02150 result = dns_dbiterator_current(dbiter, &node, name);
02151 check_dns_dbiterator_current(result);
02152 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
02153 check_result(result, "dns_db_allrdatasets()");
02154 for (result = dns_rdatasetiter_first(rdsiter);
02155 result == ISC_R_SUCCESS;
02156 result = dns_rdatasetiter_next(rdsiter)) {
02157 dns_rdatasetiter_current(rdsiter, &rdataset);
02158 rrset_cleanup(name, &rdataset, &add, &del);
02159 dns_rdataset_disassociate(&rdataset);
02160 }
02161 if (result != ISC_R_NOMORE)
02162 fatal("rdatasets iteration failed.");
02163 dns_rdatasetiter_destroy(&rdsiter);
02164 dns_db_detachnode(gdb, &node);
02165 }
02166 if (result != ISC_R_NOMORE)
02167 fatal("zone iteration failed.");
02168
02169 result = dns_diff_applysilently(&del, gdb, gversion);
02170 check_result(result, "dns_diff_applysilently");
02171
02172 result = dns_diff_applysilently(&add, gdb, gversion);
02173 check_result(result, "dns_diff_applysilently");
02174
02175 dns_diff_clear(&del);
02176 dns_diff_clear(&add);
02177 dns_dbiterator_destroy(&dbiter);
02178 }
02179
02180
02181
02182
02183 static void
02184 nsec3ify(unsigned int hashalg, dns_iterations_t iterations,
02185 const unsigned char *salt, size_t salt_len, hashlist_t *hashlist)
02186 {
02187 dns_dbiterator_t *dbiter = NULL;
02188 dns_dbnode_t *node = NULL, *nextnode = NULL;
02189 dns_fixedname_t fname, fnextname, fzonecut;
02190 dns_name_t *name, *nextname, *zonecut;
02191 dns_rdataset_t rdataset;
02192 int order;
02193 isc_boolean_t active;
02194 isc_boolean_t done = ISC_FALSE;
02195 isc_result_t result;
02196 isc_uint32_t nsttl = 0;
02197 unsigned int count, nlabels;
02198
02199 dns_rdataset_init(&rdataset);
02200 dns_fixedname_init(&fname);
02201 name = dns_fixedname_name(&fname);
02202 dns_fixedname_init(&fnextname);
02203 nextname = dns_fixedname_name(&fnextname);
02204 dns_fixedname_init(&fzonecut);
02205 zonecut = NULL;
02206
02207
02208
02209
02210 result = dns_db_createiterator(gdb, DNS_DB_NONSEC3, &dbiter);
02211 check_result(result, "dns_db_createiterator()");
02212
02213 result = dns_dbiterator_first(dbiter);
02214 check_result(result, "dns_dbiterator_first()");
02215
02216 while (!done) {
02217 result = dns_dbiterator_current(dbiter, &node, name);
02218 check_dns_dbiterator_current(result);
02219
02220
02221
02222 if (!dns_name_issubdomain(name, gorigin)) {
02223 result = dns_dbiterator_next(dbiter);
02224 if (result == ISC_R_NOMORE)
02225 done = ISC_TRUE;
02226 else
02227 check_result(result, "dns_dbiterator_next()");
02228 dns_db_detachnode(gdb, &node);
02229 continue;
02230 }
02231
02232 if (dns_name_equal(name, gorigin))
02233 remove_records(node, dns_rdatatype_nsec, ISC_TRUE);
02234
02235 result = dns_dbiterator_next(dbiter);
02236 nextnode = NULL;
02237 while (result == ISC_R_SUCCESS) {
02238 result = dns_dbiterator_current(dbiter, &nextnode,
02239 nextname);
02240 check_dns_dbiterator_current(result);
02241 active = active_node(nextnode);
02242 if (!active) {
02243 dns_db_detachnode(gdb, &nextnode);
02244 result = dns_dbiterator_next(dbiter);
02245 continue;
02246 }
02247 if (!dns_name_issubdomain(nextname, gorigin) ||
02248 (zonecut != NULL &&
02249 dns_name_issubdomain(nextname, zonecut))) {
02250 remove_sigs(nextnode, ISC_FALSE, 0);
02251 dns_db_detachnode(gdb, &nextnode);
02252 result = dns_dbiterator_next(dbiter);
02253 continue;
02254 }
02255 if (is_delegation(gdb, gversion, gorigin,
02256 nextname, nextnode, &nsttl))
02257 {
02258 zonecut = dns_fixedname_name(&fzonecut);
02259 dns_name_copy(nextname, zonecut, NULL);
02260 remove_sigs(nextnode, ISC_TRUE, 0);
02261 if (generateds)
02262 add_ds(nextname, nextnode, nsttl);
02263 if (OPTOUT(nsec3flags) &&
02264 !secure(nextname, nextnode)) {
02265 dns_db_detachnode(gdb, &nextnode);
02266 result = dns_dbiterator_next(dbiter);
02267 continue;
02268 }
02269 }
02270 dns_db_detachnode(gdb, &nextnode);
02271 break;
02272 }
02273 if (result == ISC_R_NOMORE) {
02274 dns_name_copy(gorigin, nextname, NULL);
02275 done = ISC_TRUE;
02276 } else if (result != ISC_R_SUCCESS)
02277 fatal("iterating through the database failed: %s",
02278 isc_result_totext(result));
02279 dns_name_downcase(name, name, NULL);
02280 hashlist_add_dns_name(hashlist, name, hashalg, iterations,
02281 salt, salt_len, ISC_FALSE);
02282 dns_db_detachnode(gdb, &node);
02283
02284
02285
02286
02287
02288
02289 dns_name_downcase(nextname, nextname, NULL);
02290 dns_name_fullcompare(name, nextname, &order, &nlabels);
02291 addnowildcardhash(hashlist, name, hashalg, iterations,
02292 salt, salt_len);
02293 count = dns_name_countlabels(nextname);
02294 while (count > nlabels + 1) {
02295 count--;
02296 dns_name_split(nextname, count, NULL, nextname);
02297 hashlist_add_dns_name(hashlist, nextname, hashalg,
02298 iterations, salt, salt_len,
02299 ISC_FALSE);
02300 addnowildcardhash(hashlist, nextname, hashalg,
02301 iterations, salt, salt_len);
02302 }
02303 }
02304 dns_dbiterator_destroy(&dbiter);
02305
02306
02307
02308
02309 hashlist_sort(hashlist);
02310
02311
02312
02313
02314
02315 if (hashlist_hasdup(hashlist))
02316 fatal("Duplicate hash detected. Pick a different salt.");
02317
02318
02319
02320
02321 zonecut = NULL;
02322 done = ISC_FALSE;
02323
02324 addnsec3param(salt, salt_len, iterations);
02325
02326
02327
02328
02329 result = dns_db_createiterator(gdb, DNS_DB_NSEC3ONLY, &dbiter);
02330 check_result(result, "dns_db_createiterator()");
02331
02332 for (result = dns_dbiterator_first(dbiter);
02333 result == ISC_R_SUCCESS;
02334 result = dns_dbiterator_next(dbiter)) {
02335 result = dns_dbiterator_current(dbiter, &node, name);
02336 check_dns_dbiterator_current(result);
02337 nsec3clean(name, node, hashalg, iterations, salt, salt_len,
02338 hashlist);
02339 dns_db_detachnode(gdb, &node);
02340 }
02341 dns_dbiterator_destroy(&dbiter);
02342
02343
02344
02345
02346 result = dns_db_createiterator(gdb, DNS_DB_NONSEC3, &dbiter);
02347 check_result(result, "dns_db_createiterator()");
02348
02349 result = dns_dbiterator_first(dbiter);
02350 check_result(result, "dns_dbiterator_first()");
02351
02352 while (!done) {
02353 result = dns_dbiterator_current(dbiter, &node, name);
02354 check_dns_dbiterator_current(result);
02355
02356
02357
02358 if (!dns_name_issubdomain(name, gorigin)) {
02359 result = dns_dbiterator_next(dbiter);
02360 if (result == ISC_R_NOMORE)
02361 done = ISC_TRUE;
02362 else
02363 check_result(result, "dns_dbiterator_next()");
02364 dns_db_detachnode(gdb, &node);
02365 continue;
02366 }
02367 result = dns_dbiterator_next(dbiter);
02368 nextnode = NULL;
02369 while (result == ISC_R_SUCCESS) {
02370 result = dns_dbiterator_current(dbiter, &nextnode,
02371 nextname);
02372 check_dns_dbiterator_current(result);
02373 active = active_node(nextnode);
02374 if (!active) {
02375 dns_db_detachnode(gdb, &nextnode);
02376 result = dns_dbiterator_next(dbiter);
02377 continue;
02378 }
02379 if (!dns_name_issubdomain(nextname, gorigin) ||
02380 (zonecut != NULL &&
02381 dns_name_issubdomain(nextname, zonecut))) {
02382 dns_db_detachnode(gdb, &nextnode);
02383 result = dns_dbiterator_next(dbiter);
02384 continue;
02385 }
02386 if (is_delegation(gdb, gversion, gorigin,
02387 nextname, nextnode, NULL))
02388 {
02389 zonecut = dns_fixedname_name(&fzonecut);
02390 dns_name_copy(nextname, zonecut, NULL);
02391 if (OPTOUT(nsec3flags) &&
02392 !secure(nextname, nextnode)) {
02393 dns_db_detachnode(gdb, &nextnode);
02394 result = dns_dbiterator_next(dbiter);
02395 continue;
02396 }
02397 }
02398 dns_db_detachnode(gdb, &nextnode);
02399 break;
02400 }
02401 if (result == ISC_R_NOMORE) {
02402 dns_name_copy(gorigin, nextname, NULL);
02403 done = ISC_TRUE;
02404 } else if (result != ISC_R_SUCCESS)
02405 fatal("iterating through the database failed: %s",
02406 isc_result_totext(result));
02407
02408
02409
02410 dns_dbiterator_pause(dbiter);
02411 addnsec3(name, node, salt, salt_len, iterations,
02412 hashlist, zone_soa_min_ttl);
02413 dns_db_detachnode(gdb, &node);
02414
02415
02416
02417 dns_name_fullcompare(name, nextname, &order, &nlabels);
02418 count = dns_name_countlabels(nextname);
02419 while (count > nlabels + 1) {
02420 count--;
02421 dns_name_split(nextname, count, NULL, nextname);
02422 addnsec3(nextname, NULL, salt, salt_len,
02423 iterations, hashlist, zone_soa_min_ttl);
02424 }
02425 }
02426 dns_dbiterator_destroy(&dbiter);
02427 }
02428
02429
02430
02431
02432 static void
02433 loadzone(char *file, char *origin, dns_rdataclass_t rdclass, dns_db_t **db) {
02434 isc_buffer_t b;
02435 int len;
02436 dns_fixedname_t fname;
02437 dns_name_t *name;
02438 isc_result_t result;
02439
02440 len = strlen(origin);
02441 isc_buffer_init(&b, origin, len);
02442 isc_buffer_add(&b, len);
02443
02444 dns_fixedname_init(&fname);
02445 name = dns_fixedname_name(&fname);
02446 result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL);
02447 if (result != ISC_R_SUCCESS)
02448 fatal("failed converting name '%s' to dns format: %s",
02449 origin, isc_result_totext(result));
02450
02451 result = dns_db_create(mctx, "rbt", name, dns_dbtype_zone,
02452 rdclass, 0, NULL, db);
02453 check_result(result, "dns_db_create()");
02454
02455 result = dns_db_load2(*db, file, inputformat);
02456 if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE)
02457 fatal("failed loading zone from '%s': %s",
02458 file, isc_result_totext(result));
02459 }
02460
02461
02462
02463
02464
02465 static void
02466 loadzonekeys(isc_boolean_t preserve_keys, isc_boolean_t load_public) {
02467 dns_dbnode_t *node;
02468 dns_dbversion_t *currentversion = NULL;
02469 isc_result_t result;
02470 dns_rdataset_t rdataset, keysigs, soasigs;
02471
02472 node = NULL;
02473 result = dns_db_findnode(gdb, gorigin, ISC_FALSE, &node);
02474 if (result != ISC_R_SUCCESS)
02475 fatal("failed to find the zone's origin: %s",
02476 isc_result_totext(result));
02477
02478 dns_db_currentversion(gdb, ¤tversion);
02479
02480 dns_rdataset_init(&rdataset);
02481 dns_rdataset_init(&soasigs);
02482 dns_rdataset_init(&keysigs);
02483
02484
02485 result = dns_db_findrdataset(gdb, node, currentversion,
02486 dns_rdatatype_soa, 0, 0,
02487 &rdataset, &soasigs);
02488 if (result != ISC_R_SUCCESS)
02489 goto cleanup;
02490
02491
02492 dns_rdataset_disassociate(&rdataset);
02493 result = dns_db_findrdataset(gdb, node, currentversion,
02494 dns_rdatatype_dnskey, 0, 0,
02495 &rdataset, &keysigs);
02496
02497 if (result != ISC_R_SUCCESS)
02498 goto cleanup;
02499
02500 if (set_keyttl && keyttl != rdataset.ttl) {
02501 fprintf(stderr, "User-specified TTL %d conflicts "
02502 "with existing DNSKEY RRset TTL.\n",
02503 keyttl);
02504 fprintf(stderr, "Imported keys will use the RRSet "
02505 "TTL %d instead.\n",
02506 rdataset.ttl);
02507 }
02508 keyttl = rdataset.ttl;
02509
02510
02511 result = dns_dnssec_keylistfromrdataset(gorigin, directory, mctx,
02512 &rdataset, &keysigs, &soasigs,
02513 preserve_keys, load_public,
02514 &keylist);
02515 if (result != ISC_R_SUCCESS)
02516 fatal("failed to load the zone keys: %s",
02517 isc_result_totext(result));
02518
02519 cleanup:
02520 if (dns_rdataset_isassociated(&rdataset))
02521 dns_rdataset_disassociate(&rdataset);
02522 if (dns_rdataset_isassociated(&keysigs))
02523 dns_rdataset_disassociate(&keysigs);
02524 if (dns_rdataset_isassociated(&soasigs))
02525 dns_rdataset_disassociate(&soasigs);
02526 dns_db_detachnode(gdb, &node);
02527 dns_db_closeversion(gdb, ¤tversion, ISC_FALSE);
02528 }
02529
02530 static void
02531 loadexplicitkeys(char *keyfiles[], int n, isc_boolean_t setksk) {
02532 isc_result_t result;
02533 int i;
02534
02535 for (i = 0; i < n; i++) {
02536 dns_dnsseckey_t *key = NULL;
02537 dst_key_t *newkey = NULL;
02538
02539 result = dst_key_fromnamedfile(keyfiles[i], directory,
02540 DST_TYPE_PUBLIC |
02541 DST_TYPE_PRIVATE,
02542 mctx, &newkey);
02543 if (result != ISC_R_SUCCESS)
02544 fatal("cannot load dnskey %s: %s", keyfiles[i],
02545 isc_result_totext(result));
02546
02547 if (!dns_name_equal(gorigin, dst_key_name(newkey)))
02548 fatal("key %s not at origin\n", keyfiles[i]);
02549
02550 if (!dst_key_isprivate(newkey))
02551 fatal("cannot sign zone with non-private dnskey %s",
02552 keyfiles[i]);
02553
02554
02555 for (key = ISC_LIST_HEAD(keylist);
02556 key != NULL;
02557 key = ISC_LIST_NEXT(key, link)) {
02558 if (dst_key_id(key->key) == dst_key_id(newkey) &&
02559 dst_key_alg(key->key) == dst_key_alg(newkey))
02560 break;
02561 }
02562
02563 if (key == NULL) {
02564
02565 dns_dnsseckey_create(mctx, &newkey, &key);
02566 ISC_LIST_APPEND(keylist, key, link);
02567 key->source = dns_keysource_user;
02568 } else {
02569 dst_key_free(&key->key);
02570 key->key = newkey;
02571 }
02572
02573 key->force_publish = ISC_TRUE;
02574 key->force_sign = ISC_TRUE;
02575
02576 if (setksk)
02577 key->ksk = ISC_TRUE;
02578 }
02579 }
02580
02581 static void
02582 report(const char *format, ...) {
02583 va_list args;
02584 va_start(args, format);
02585 vfprintf(stderr, format, args);
02586 va_end(args);
02587 putc('\n', stderr);
02588 }
02589
02590 static void
02591 build_final_keylist(void) {
02592 isc_result_t result;
02593 dns_dbversion_t *ver = NULL;
02594 dns_diff_t diff;
02595 dns_dnsseckeylist_t matchkeys;
02596 char name[DNS_NAME_FORMATSIZE];
02597
02598
02599
02600
02601 ISC_LIST_INIT(matchkeys);
02602 result = dns_dnssec_findmatchingkeys(gorigin, directory,
02603 mctx, &matchkeys);
02604 if (result == ISC_R_NOTFOUND)
02605 result = ISC_R_SUCCESS;
02606 check_result(result, "dns_dnssec_findmatchingkeys");
02607
02608 result = dns_db_newversion(gdb, &ver);
02609 check_result(result, "dns_db_newversion");
02610
02611 dns_diff_init(mctx, &diff);
02612
02613
02614
02615
02616 dns_dnssec_updatekeys(&keylist, &matchkeys, NULL, gorigin, keyttl,
02617 &diff, ignore_kskflag, mctx, report);
02618
02619 dns_name_format(gorigin, name, sizeof(name));
02620
02621 result = dns_diff_applysilently(&diff, gdb, ver);
02622 if (result != ISC_R_SUCCESS)
02623 fatal("failed to update DNSKEY RRset at node '%s': %s",
02624 name, isc_result_totext(result));
02625
02626 dns_db_closeversion(gdb, &ver, ISC_TRUE);
02627
02628 dns_diff_clear(&diff);
02629 }
02630
02631 static void
02632 warnifallksk(dns_db_t *db) {
02633 dns_dbversion_t *currentversion = NULL;
02634 dns_dbnode_t *node = NULL;
02635 dns_rdataset_t rdataset;
02636 dns_rdata_t rdata = DNS_RDATA_INIT;
02637 isc_result_t result;
02638 dns_rdata_dnskey_t dnskey;
02639 isc_boolean_t have_non_ksk = ISC_FALSE;
02640
02641 dns_db_currentversion(db, ¤tversion);
02642
02643 result = dns_db_findnode(db, gorigin, ISC_FALSE, &node);
02644 if (result != ISC_R_SUCCESS)
02645 fatal("failed to find the zone's origin: %s",
02646 isc_result_totext(result));
02647
02648 dns_rdataset_init(&rdataset);
02649 result = dns_db_findrdataset(db, node, currentversion,
02650 dns_rdatatype_dnskey, 0, 0, &rdataset,
02651 NULL);
02652 if (result != ISC_R_SUCCESS)
02653 fatal("failed to find keys at the zone apex: %s",
02654 isc_result_totext(result));
02655 result = dns_rdataset_first(&rdataset);
02656 check_result(result, "dns_rdataset_first");
02657 while (result == ISC_R_SUCCESS) {
02658 dns_rdata_reset(&rdata);
02659 dns_rdataset_current(&rdataset, &rdata);
02660 result = dns_rdata_tostruct(&rdata, &dnskey, NULL);
02661 check_result(result, "dns_rdata_tostruct");
02662 if ((dnskey.flags & DNS_KEYFLAG_KSK) == 0) {
02663 have_non_ksk = ISC_TRUE;
02664 result = ISC_R_NOMORE;
02665 } else
02666 result = dns_rdataset_next(&rdataset);
02667 dns_rdata_freestruct(&dnskey);
02668 }
02669 dns_rdataset_disassociate(&rdataset);
02670 dns_db_detachnode(db, &node);
02671 dns_db_closeversion(db, ¤tversion, ISC_FALSE);
02672 if (!have_non_ksk && !ignore_kskflag) {
02673 if (disable_zone_check)
02674 fprintf(stderr, "%s: warning: No non-KSK DNSKEY found; "
02675 "supply a ZSK or use '-z'.\n",
02676 program);
02677 else
02678 fatal("No non-KSK DNSKEY found; "
02679 "supply a ZSK or use '-z'.");
02680 }
02681 }
02682
02683 static void
02684 set_nsec3params(isc_boolean_t update, isc_boolean_t set_salt,
02685 isc_boolean_t set_optout, isc_boolean_t set_iter)
02686 {
02687 isc_result_t result;
02688 dns_dbversion_t *ver = NULL;
02689 dns_dbnode_t *node = NULL;
02690 dns_rdataset_t rdataset;
02691 dns_rdata_t rdata = DNS_RDATA_INIT;
02692 dns_rdata_nsec3_t nsec3;
02693 dns_fixedname_t fname;
02694 dns_name_t *hashname;
02695 unsigned char orig_salt[255];
02696 size_t orig_saltlen;
02697 dns_hash_t orig_hash;
02698 isc_uint16_t orig_iter;
02699
02700 dns_db_currentversion(gdb, &ver);
02701 dns_rdataset_init(&rdataset);
02702
02703 orig_saltlen = sizeof(orig_salt);
02704 result = dns_db_getnsec3parameters(gdb, ver, &orig_hash, NULL,
02705 &orig_iter, orig_salt,
02706 &orig_saltlen);
02707 if (result != ISC_R_SUCCESS)
02708 goto cleanup;
02709
02710 nsec_datatype = dns_rdatatype_nsec3;
02711
02712 if (!update && set_salt) {
02713 if (salt_length != orig_saltlen ||
02714 memcmp(saltbuf, orig_salt, salt_length) != 0)
02715 fatal("An NSEC3 chain exists with a different salt. "
02716 "Use -u to update it.");
02717 } else if (!set_salt) {
02718 salt_length = orig_saltlen;
02719 memmove(saltbuf, orig_salt, orig_saltlen);
02720 gsalt = saltbuf;
02721 }
02722
02723 if (!update && set_iter) {
02724 if (nsec3iter != orig_iter)
02725 fatal("An NSEC3 chain exists with different "
02726 "iterations. Use -u to update it.");
02727 } else if (!set_iter)
02728 nsec3iter = orig_iter;
02729
02730
02731
02732
02733
02734
02735 dns_fixedname_init(&fname);
02736 hashname = dns_fixedname_name(&fname);
02737 result = dns_nsec3_hashname(&fname, NULL, NULL,
02738 gorigin, gorigin, dns_hash_sha1,
02739 orig_iter, orig_salt, orig_saltlen);
02740 check_result(result, "dns_nsec3_hashname");
02741
02742 result = dns_db_findnsec3node(gdb, hashname, ISC_FALSE, &node);
02743 if (result != ISC_R_SUCCESS)
02744 goto cleanup;
02745
02746 result = dns_db_findrdataset(gdb, node, ver, dns_rdatatype_nsec3,
02747 0, 0, &rdataset, NULL);
02748 if (result != ISC_R_SUCCESS)
02749 goto cleanup;
02750
02751 result = dns_rdataset_first(&rdataset);
02752 check_result(result, "dns_rdataset_first");
02753 dns_rdataset_current(&rdataset, &rdata);
02754 result = dns_rdata_tostruct(&rdata, &nsec3, NULL);
02755 check_result(result, "dns_rdata_tostruct");
02756
02757 if (!update && set_optout) {
02758 if (nsec3flags != nsec3.flags)
02759 fatal("An NSEC3 chain exists with%s OPTOUT. "
02760 "Use -u -%s to %s it.",
02761 OPTOUT(nsec3.flags) ? "" : "out",
02762 OPTOUT(nsec3.flags) ? "AA" : "A",
02763 OPTOUT(nsec3.flags) ? "clear" : "set");
02764 } else if (!set_optout)
02765 nsec3flags = nsec3.flags;
02766
02767 dns_rdata_freestruct(&nsec3);
02768
02769 cleanup:
02770 if (dns_rdataset_isassociated(&rdataset))
02771 dns_rdataset_disassociate(&rdataset);
02772 if (node != NULL)
02773 dns_db_detachnode(gdb, &node);
02774 dns_db_closeversion(gdb, &ver, ISC_FALSE);
02775 }
02776
02777 static void
02778 writeset(const char *prefix, dns_rdatatype_t type) {
02779 char *filename;
02780 char namestr[DNS_NAME_FORMATSIZE];
02781 dns_db_t *db = NULL;
02782 dns_dbversion_t *dbversion = NULL;
02783 dns_diff_t diff;
02784 dns_difftuple_t *tuple = NULL;
02785 dns_fixedname_t fixed;
02786 dns_name_t *name;
02787 dns_rdata_t rdata, ds;
02788 isc_boolean_t have_ksk = ISC_FALSE;
02789 isc_boolean_t have_non_ksk = ISC_FALSE;
02790 isc_buffer_t b;
02791 isc_buffer_t namebuf;
02792 isc_region_t r;
02793 isc_result_t result;
02794 dns_dnsseckey_t *key, *tmpkey;
02795 unsigned char dsbuf[DNS_DS_BUFFERSIZE];
02796 unsigned char keybuf[DST_KEY_MAXSIZE];
02797 unsigned int filenamelen;
02798 const dns_master_style_t *style =
02799 (type == dns_rdatatype_dnskey) ? masterstyle : dsstyle;
02800
02801 isc_buffer_init(&namebuf, namestr, sizeof(namestr));
02802 result = dns_name_tofilenametext(gorigin, ISC_FALSE, &namebuf);
02803 check_result(result, "dns_name_tofilenametext");
02804 isc_buffer_putuint8(&namebuf, 0);
02805 filenamelen = strlen(prefix) + strlen(namestr);
02806 if (dsdir != NULL)
02807 filenamelen += strlen(dsdir) + 1;
02808 filename = isc_mem_get(mctx, filenamelen + 1);
02809 if (filename == NULL)
02810 fatal("out of memory");
02811 if (dsdir != NULL)
02812 sprintf(filename, "%s/", dsdir);
02813 else
02814 filename[0] = 0;
02815 strcat(filename, prefix);
02816 strcat(filename, namestr);
02817
02818 dns_diff_init(mctx, &diff);
02819
02820 if (type == dns_rdatatype_dlv) {
02821 dns_name_t tname;
02822 unsigned int labels;
02823
02824 dns_name_init(&tname, NULL);
02825 dns_fixedname_init(&fixed);
02826 name = dns_fixedname_name(&fixed);
02827 labels = dns_name_countlabels(gorigin);
02828 dns_name_getlabelsequence(gorigin, 0, labels - 1, &tname);
02829 result = dns_name_concatenate(&tname, dlv, name, NULL);
02830 check_result(result, "dns_name_concatenate");
02831 } else
02832 name = gorigin;
02833
02834 for (key = ISC_LIST_HEAD(keylist);
02835 key != NULL;
02836 key = ISC_LIST_NEXT(key, link))
02837 {
02838 if (REVOKE(key->key))
02839 continue;
02840 if (isksk(key)) {
02841 have_ksk = ISC_TRUE;
02842 have_non_ksk = ISC_FALSE;
02843 } else {
02844 have_ksk = ISC_FALSE;
02845 have_non_ksk = ISC_TRUE;
02846 }
02847 for (tmpkey = ISC_LIST_HEAD(keylist);
02848 tmpkey != NULL;
02849 tmpkey = ISC_LIST_NEXT(tmpkey, link)) {
02850 if (dst_key_alg(key->key) != dst_key_alg(tmpkey->key))
02851 continue;
02852 if (REVOKE(tmpkey->key))
02853 continue;
02854 if (isksk(tmpkey))
02855 have_ksk = ISC_TRUE;
02856 else
02857 have_non_ksk = ISC_TRUE;
02858 }
02859 if (have_ksk && have_non_ksk && !isksk(key))
02860 continue;
02861 dns_rdata_init(&rdata);
02862 dns_rdata_init(&ds);
02863 isc_buffer_init(&b, keybuf, sizeof(keybuf));
02864 result = dst_key_todns(key->key, &b);
02865 check_result(result, "dst_key_todns");
02866 isc_buffer_usedregion(&b, &r);
02867 dns_rdata_fromregion(&rdata, gclass, dns_rdatatype_dnskey, &r);
02868 if (type != dns_rdatatype_dnskey) {
02869 result = dns_ds_buildrdata(gorigin, &rdata,
02870 DNS_DSDIGEST_SHA1,
02871 dsbuf, &ds);
02872 check_result(result, "dns_ds_buildrdata");
02873 if (type == dns_rdatatype_dlv)
02874 ds.type = dns_rdatatype_dlv;
02875 result = dns_difftuple_create(mctx,
02876 DNS_DIFFOP_ADDRESIGN,
02877 name, 0, &ds, &tuple);
02878 check_result(result, "dns_difftuple_create");
02879 dns_diff_append(&diff, &tuple);
02880
02881 dns_rdata_reset(&ds);
02882 result = dns_ds_buildrdata(gorigin, &rdata,
02883 DNS_DSDIGEST_SHA256,
02884 dsbuf, &ds);
02885 check_result(result, "dns_ds_buildrdata");
02886 if (type == dns_rdatatype_dlv)
02887 ds.type = dns_rdatatype_dlv;
02888 result = dns_difftuple_create(mctx,
02889 DNS_DIFFOP_ADDRESIGN,
02890 name, 0, &ds, &tuple);
02891
02892 } else
02893 result = dns_difftuple_create(mctx,
02894 DNS_DIFFOP_ADDRESIGN,
02895 gorigin, zone_soa_min_ttl,
02896 &rdata, &tuple);
02897 check_result(result, "dns_difftuple_create");
02898 dns_diff_append(&diff, &tuple);
02899 }
02900
02901 result = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_zone,
02902 gclass, 0, NULL, &db);
02903 check_result(result, "dns_db_create");
02904
02905 result = dns_db_newversion(db, &dbversion);
02906 check_result(result, "dns_db_newversion");
02907
02908 result = dns_diff_apply(&diff, db, dbversion);
02909 check_result(result, "dns_diff_apply");
02910 dns_diff_clear(&diff);
02911
02912 result = dns_master_dump(mctx, db, dbversion, style, filename);
02913 check_result(result, "dns_master_dump");
02914
02915 isc_mem_put(mctx, filename, filenamelen + 1);
02916
02917 dns_db_closeversion(db, &dbversion, ISC_FALSE);
02918 dns_db_detach(&db);
02919 }
02920
02921 static void
02922 print_time(FILE *fp) {
02923 time_t currenttime;
02924
02925 if (outputformat != dns_masterformat_text)
02926 return;
02927
02928 currenttime = time(NULL);
02929 fprintf(fp, "; File written on %s", ctime(¤ttime));
02930 }
02931
02932 static void
02933 print_version(FILE *fp) {
02934 if (outputformat != dns_masterformat_text)
02935 return;
02936
02937 fprintf(fp, "; dnssec_signzone version " VERSION "\n");
02938 }
02939
02940 ISC_PLATFORM_NORETURN_PRE static void
02941 usage(void) ISC_PLATFORM_NORETURN_POST;
02942
02943 static void
02944 usage(void) {
02945 fprintf(stderr, "Usage:\n");
02946 fprintf(stderr, "\t%s [options] zonefile [keys]\n", program);
02947
02948 fprintf(stderr, "\n");
02949
02950 fprintf(stderr, "Version: %s\n", VERSION);
02951
02952 fprintf(stderr, "Options: (default value in parenthesis) \n");
02953 fprintf(stderr, "\t-S:\tsmart signing: automatically finds key files\n"
02954 "\t\tfor the zone and determines how they are to "
02955 "be used\n");
02956 fprintf(stderr, "\t-K directory:\n");
02957 fprintf(stderr, "\t\tdirectory to find key files (.)\n");
02958 fprintf(stderr, "\t-d directory:\n");
02959 fprintf(stderr, "\t\tdirectory to find dsset-* files (.)\n");
02960 fprintf(stderr, "\t-g:\t");
02961 fprintf(stderr, "update DS records based on child zones' "
02962 "dsset-* files\n");
02963 fprintf(stderr, "\t-s [YYYYMMDDHHMMSS|+offset]:\n");
02964 fprintf(stderr, "\t\tRRSIG start time "
02965 "- absolute|offset (now - 1 hour)\n");
02966 fprintf(stderr, "\t-e [YYYYMMDDHHMMSS|+offset|\"now\"+offset]:\n");
02967 fprintf(stderr, "\t\tRRSIG end time "
02968 "- absolute|from start|from now "
02969 "(now + 30 days)\n");
02970 fprintf(stderr, "\t-X [YYYYMMDDHHMMSS|+offset|\"now\"+offset]:\n");
02971 fprintf(stderr, "\t\tDNSKEY RRSIG end "
02972 "- absolute|from start|from now "
02973 "(matches -e)\n");
02974 fprintf(stderr, "\t-i interval:\n");
02975 fprintf(stderr, "\t\tcycle interval - resign "
02976 "if < interval from end ( (end-start)/4 )\n");
02977 fprintf(stderr, "\t-j jitter:\n");
02978 fprintf(stderr, "\t\trandomize signature end time up to jitter seconds\n");
02979 fprintf(stderr, "\t-v debuglevel (0)\n");
02980 fprintf(stderr, "\t-V:\tprint version information\n");
02981 fprintf(stderr, "\t-o origin:\n");
02982 fprintf(stderr, "\t\tzone origin (name of zonefile)\n");
02983 fprintf(stderr, "\t-f outfile:\n");
02984 fprintf(stderr, "\t\tfile the signed zone is written in "
02985 "(zonefile + .signed)\n");
02986 fprintf(stderr, "\t-I format:\n");
02987 fprintf(stderr, "\t\tfile format of input zonefile (text)\n");
02988 fprintf(stderr, "\t-O format:\n");
02989 fprintf(stderr, "\t\tfile format of signed zone file (text)\n");
02990 fprintf(stderr, "\t-N format:\n");
02991 fprintf(stderr, "\t\tsoa serial format of signed zone file (keep)\n");
02992 fprintf(stderr, "\t-D:\n");
02993 fprintf(stderr, "\t\toutput only DNSSEC-related records\n");
02994 fprintf(stderr, "\t-r randomdev:\n");
02995 fprintf(stderr, "\t\ta file containing random data\n");
02996 fprintf(stderr, "\t-a:\t");
02997 fprintf(stderr, "verify generated signatures\n");
02998 fprintf(stderr, "\t-c class (IN)\n");
02999 fprintf(stderr, "\t-E engine:\n");
03000 #if defined(PKCS11CRYPTO)
03001 fprintf(stderr, "\t\tpath to PKCS#11 provider library "
03002 "(default is %s)\n", PK11_LIB_LOCATION);
03003 #elif defined(USE_PKCS11)
03004 fprintf(stderr, "\t\tname of an OpenSSL engine to use "
03005 "(default is \"pkcs11\")\n");
03006 #else
03007 fprintf(stderr, "\t\tname of an OpenSSL engine to use\n");
03008 #endif
03009 fprintf(stderr, "\t-p:\t");
03010 fprintf(stderr, "use pseudorandom data (faster but less secure)\n");
03011 fprintf(stderr, "\t-P:\t");
03012 fprintf(stderr, "disable post-sign verification\n");
03013 fprintf(stderr, "\t-Q:\t");
03014 fprintf(stderr, "remove signatures from keys that are no "
03015 "longer active\n");
03016 fprintf(stderr, "\t-R:\t");
03017 fprintf(stderr, "remove signatures from keys that no longer exist\n");
03018 fprintf(stderr, "\t-T TTL:\tTTL for newly added DNSKEYs\n");
03019 fprintf(stderr, "\t-t:\t");
03020 fprintf(stderr, "print statistics\n");
03021 fprintf(stderr, "\t-u:\t");
03022 fprintf(stderr, "update or replace an existing NSEC/NSEC3 chain\n");
03023 fprintf(stderr, "\t-x:\tsign DNSKEY record with KSKs only, not ZSKs\n");
03024 fprintf(stderr, "\t-z:\tsign all records with KSKs\n");
03025 fprintf(stderr, "\t-C:\tgenerate a keyset file, for compatibility\n"
03026 "\t\twith older versions of dnssec-signzone -g\n");
03027 fprintf(stderr, "\t-n ncpus (number of cpus present)\n");
03028 fprintf(stderr, "\t-k key_signing_key\n");
03029 fprintf(stderr, "\t-l lookasidezone\n");
03030 fprintf(stderr, "\t-3 NSEC3 salt\n");
03031 fprintf(stderr, "\t-H NSEC3 iterations (10)\n");
03032 fprintf(stderr, "\t-A NSEC3 optout\n");
03033
03034 fprintf(stderr, "\n");
03035
03036 fprintf(stderr, "Signing Keys: ");
03037 fprintf(stderr, "(default: all zone keys that have private keys)\n");
03038 fprintf(stderr, "\tkeyfile (Kname+alg+tag)\n");
03039
03040 exit(0);
03041 }
03042
03043 static void
03044 removetempfile(void) {
03045 if (removefile)
03046 isc_file_remove(tempfile);
03047 }
03048
03049 static void
03050 print_stats(isc_time_t *timer_start, isc_time_t *timer_finish,
03051 isc_time_t *sign_start, isc_time_t *sign_finish)
03052 {
03053 isc_uint64_t time_us;
03054 isc_uint64_t time_ms;
03055 isc_uint64_t sig_ms;
03056 FILE *out = output_stdout ? stderr : stdout;
03057
03058 fprintf(out, "Signatures generated: %10d\n", nsigned);
03059 fprintf(out, "Signatures retained: %10d\n", nretained);
03060 fprintf(out, "Signatures dropped: %10d\n", ndropped);
03061 fprintf(out, "Signatures successfully verified: %10d\n", nverified);
03062 fprintf(out, "Signatures unsuccessfully "
03063 "verified: %10d\n", nverifyfailed);
03064
03065 time_us = isc_time_microdiff(sign_finish, sign_start);
03066 time_ms = time_us / 1000;
03067 fprintf(out, "Signing time in seconds: %7u.%03u\n",
03068 (unsigned int) (time_ms / 1000),
03069 (unsigned int) (time_ms % 1000));
03070 if (time_us > 0) {
03071 sig_ms = ((isc_uint64_t)nsigned * 1000000000) / time_us;
03072 fprintf(out, "Signatures per second: %7u.%03u\n",
03073 (unsigned int) sig_ms / 1000,
03074 (unsigned int) sig_ms % 1000);
03075 }
03076
03077 time_us = isc_time_microdiff(timer_finish, timer_start);
03078 time_ms = time_us / 1000;
03079 fprintf(out, "Runtime in seconds: %7u.%03u\n",
03080 (unsigned int) (time_ms / 1000),
03081 (unsigned int) (time_ms % 1000));
03082 }
03083
03084 int
03085 main(int argc, char *argv[]) {
03086 int i, ch;
03087 char *startstr = NULL, *endstr = NULL, *classname = NULL;
03088 char *dnskey_endstr = NULL;
03089 char *origin = NULL, *file = NULL, *output = NULL;
03090 char *inputformatstr = NULL, *outputformatstr = NULL;
03091 char *serialformatstr = NULL;
03092 char *dskeyfile[MAXDSKEYS];
03093 int ndskeys = 0;
03094 char *endp;
03095 isc_time_t timer_start, timer_finish;
03096 isc_time_t sign_start, sign_finish;
03097 dns_dnsseckey_t *key;
03098 isc_result_t result;
03099 isc_log_t *log = NULL;
03100 isc_boolean_t pseudorandom = ISC_FALSE;
03101 #ifdef USE_PKCS11
03102 const char *engine = PKCS11_ENGINE;
03103 #else
03104 const char *engine = NULL;
03105 #endif
03106 unsigned int eflags;
03107 isc_boolean_t free_output = ISC_FALSE;
03108 int tempfilelen = 0;
03109 dns_rdataclass_t rdclass;
03110 isc_task_t **tasks = NULL;
03111 isc_buffer_t b;
03112 int len;
03113 hashlist_t hashlist;
03114 isc_boolean_t make_keyset = ISC_FALSE;
03115 isc_boolean_t set_salt = ISC_FALSE;
03116 isc_boolean_t set_optout = ISC_FALSE;
03117 isc_boolean_t set_iter = ISC_FALSE;
03118 isc_boolean_t nonsecify = ISC_FALSE;
03119
03120
03121 #define CMDLINE_FLAGS \
03122 "3:AaCc:Dd:E:e:f:FghH:i:I:j:K:k:L:l:m:M:n:N:o:O:PpQRr:s:ST:tuUv:VX:xzZ:"
03123
03124
03125
03126
03127 while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
03128 switch (ch) {
03129 case 'm':
03130 if (strcasecmp(isc_commandline_argument, "record") == 0)
03131 isc_mem_debugging |= ISC_MEM_DEBUGRECORD;
03132 if (strcasecmp(isc_commandline_argument, "trace") == 0)
03133 isc_mem_debugging |= ISC_MEM_DEBUGTRACE;
03134 if (strcasecmp(isc_commandline_argument, "usage") == 0)
03135 isc_mem_debugging |= ISC_MEM_DEBUGUSAGE;
03136 if (strcasecmp(isc_commandline_argument, "size") == 0)
03137 isc_mem_debugging |= ISC_MEM_DEBUGSIZE;
03138 if (strcasecmp(isc_commandline_argument, "mctx") == 0)
03139 isc_mem_debugging |= ISC_MEM_DEBUGCTX;
03140 break;
03141 default:
03142 break;
03143 }
03144 }
03145 isc_commandline_reset = ISC_TRUE;
03146
03147 masterstyle = &dns_master_style_explicitttl;
03148
03149 check_result(isc_app_start(), "isc_app_start");
03150
03151 result = isc_mem_create(0, 0, &mctx);
03152 if (result != ISC_R_SUCCESS)
03153 fatal("out of memory");
03154
03155 #ifdef PKCS11CRYPTO
03156 pk11_result_register();
03157 #endif
03158 dns_result_register();
03159
03160 isc_commandline_errprint = ISC_FALSE;
03161
03162 while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
03163 switch (ch) {
03164 case '3':
03165 set_salt = ISC_TRUE;
03166 nsec_datatype = dns_rdatatype_nsec3;
03167 if (strcmp(isc_commandline_argument, "-") != 0) {
03168 isc_buffer_t target;
03169 char *sarg;
03170
03171 sarg = isc_commandline_argument;
03172 isc_buffer_init(&target, saltbuf,
03173 sizeof(saltbuf));
03174 result = isc_hex_decodestring(sarg, &target);
03175 check_result(result,
03176 "isc_hex_decodestring(salt)");
03177 salt_length = isc_buffer_usedlength(&target);
03178 }
03179 break;
03180
03181 case 'A':
03182 set_optout = ISC_TRUE;
03183 if (OPTOUT(nsec3flags))
03184 nsec3flags &= ~DNS_NSEC3FLAG_OPTOUT;
03185 else
03186 nsec3flags |= DNS_NSEC3FLAG_OPTOUT;
03187 break;
03188
03189 case 'a':
03190 tryverify = ISC_TRUE;
03191 break;
03192
03193 case 'C':
03194 make_keyset = ISC_TRUE;
03195 break;
03196
03197 case 'c':
03198 classname = isc_commandline_argument;
03199 break;
03200
03201 case 'd':
03202 dsdir = isc_commandline_argument;
03203 if (strlen(dsdir) == 0U)
03204 fatal("DS directory must be non-empty string");
03205 result = try_dir(dsdir);
03206 if (result != ISC_R_SUCCESS)
03207 fatal("cannot open directory %s: %s",
03208 dsdir, isc_result_totext(result));
03209 break;
03210
03211 case 'D':
03212 output_dnssec_only = ISC_TRUE;
03213 break;
03214
03215 case 'E':
03216 engine = isc_commandline_argument;
03217 break;
03218
03219 case 'e':
03220 endstr = isc_commandline_argument;
03221 break;
03222
03223 case 'f':
03224 output = isc_commandline_argument;
03225 if (strcmp(output, "-") == 0)
03226 output_stdout = ISC_TRUE;
03227 break;
03228
03229 case 'g':
03230 generateds = ISC_TRUE;
03231 break;
03232
03233 case 'H':
03234 set_iter = ISC_TRUE;
03235 nsec3iter = strtoul(isc_commandline_argument, &endp, 0);
03236 if (*endp != '\0')
03237 fatal("iterations must be numeric");
03238 if (nsec3iter > 0xffffU)
03239 fatal("iterations too big");
03240 break;
03241
03242 case 'I':
03243 inputformatstr = isc_commandline_argument;
03244 break;
03245
03246 case 'i':
03247 endp = NULL;
03248 cycle = strtol(isc_commandline_argument, &endp, 0);
03249 if (*endp != '\0' || cycle < 0)
03250 fatal("cycle period must be numeric and "
03251 "positive");
03252 break;
03253
03254 case 'j':
03255 endp = NULL;
03256 jitter = strtol(isc_commandline_argument, &endp, 0);
03257 if (*endp != '\0' || jitter < 0)
03258 fatal("jitter must be numeric and positive");
03259 break;
03260
03261 case 'K':
03262 directory = isc_commandline_argument;
03263 break;
03264
03265 case 'k':
03266 if (ndskeys == MAXDSKEYS)
03267 fatal("too many key-signing keys specified");
03268 dskeyfile[ndskeys++] = isc_commandline_argument;
03269 break;
03270
03271 case 'L':
03272 snset = ISC_TRUE;
03273 endp = NULL;
03274 serialnum = strtol(isc_commandline_argument, &endp, 0);
03275 if (*endp != '\0') {
03276 fprintf(stderr, "source serial number "
03277 "must be numeric");
03278 exit(1);
03279 }
03280 break;
03281
03282 case 'l':
03283 len = strlen(isc_commandline_argument);
03284 isc_buffer_init(&b, isc_commandline_argument, len);
03285 isc_buffer_add(&b, len);
03286
03287 dns_fixedname_init(&dlv_fixed);
03288 dlv = dns_fixedname_name(&dlv_fixed);
03289 result = dns_name_fromtext(dlv, &b, dns_rootname, 0,
03290 NULL);
03291 check_result(result, "dns_name_fromtext(dlv)");
03292 break;
03293
03294 case 'M':
03295 endp = NULL;
03296 set_maxttl = ISC_TRUE;
03297 maxttl = strtol(isc_commandline_argument, &endp, 0);
03298 if (*endp != '\0') {
03299 fprintf(stderr, "maximum TTL "
03300 "must be numeric");
03301 exit(1);
03302 }
03303 break;
03304
03305 case 'm':
03306 break;
03307
03308 case 'N':
03309 serialformatstr = isc_commandline_argument;
03310 break;
03311
03312 case 'n':
03313 endp = NULL;
03314 ntasks = strtol(isc_commandline_argument, &endp, 0);
03315 if (*endp != '\0' || ntasks > ISC_INT32_MAX)
03316 fatal("number of cpus must be numeric");
03317 break;
03318
03319 case 'O':
03320 outputformatstr = isc_commandline_argument;
03321 break;
03322
03323 case 'o':
03324 origin = isc_commandline_argument;
03325 break;
03326
03327 case 'P':
03328 disable_zone_check = ISC_TRUE;
03329 break;
03330
03331 case 'p':
03332 pseudorandom = ISC_TRUE;
03333 break;
03334
03335 case 'Q':
03336 remove_inactkeysigs = ISC_TRUE;
03337 break;
03338
03339 case 'R':
03340 remove_orphansigs = ISC_TRUE;
03341 break;
03342
03343 case 'r':
03344 setup_entropy(mctx, isc_commandline_argument, &ectx);
03345 break;
03346
03347 case 'S':
03348 smartsign = ISC_TRUE;
03349 break;
03350
03351 case 's':
03352 startstr = isc_commandline_argument;
03353 break;
03354
03355 case 'T':
03356 endp = NULL;
03357 set_keyttl = ISC_TRUE;
03358 keyttl = strtottl(isc_commandline_argument);
03359 break;
03360
03361 case 't':
03362 printstats = ISC_TRUE;
03363 break;
03364
03365 case 'U':
03366 unknownalg = ISC_TRUE;
03367 break;
03368
03369 case 'u':
03370 update_chain = ISC_TRUE;
03371 break;
03372
03373 case 'v':
03374 endp = NULL;
03375 verbose = strtol(isc_commandline_argument, &endp, 0);
03376 if (*endp != '\0')
03377 fatal("verbose level must be numeric");
03378 break;
03379
03380 case 'X':
03381 dnskey_endstr = isc_commandline_argument;
03382 break;
03383
03384 case 'x':
03385 keyset_kskonly = ISC_TRUE;
03386 break;
03387
03388 case 'z':
03389 ignore_kskflag = ISC_TRUE;
03390 break;
03391
03392 case 'F':
03393
03394
03395 case '?':
03396 if (isc_commandline_option != '?')
03397 fprintf(stderr, "%s: invalid argument -%c\n",
03398 program, isc_commandline_option);
03399
03400 case 'h':
03401
03402 usage();
03403
03404 case 'V':
03405
03406 version(program);
03407
03408 case 'Z':
03409 if (!strcmp(isc_commandline_argument, "nonsecify"))
03410 nonsecify = ISC_TRUE;
03411 break;
03412
03413 default:
03414 fprintf(stderr, "%s: unhandled option -%c\n",
03415 program, isc_commandline_option);
03416 exit(1);
03417 }
03418 }
03419
03420 if (ectx == NULL)
03421 setup_entropy(mctx, NULL, &ectx);
03422 eflags = ISC_ENTROPY_BLOCKING;
03423 if (!pseudorandom)
03424 eflags |= ISC_ENTROPY_GOODONLY;
03425
03426 result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
03427 if (result != ISC_R_SUCCESS)
03428 fatal("could not create hash context");
03429
03430 result = dst_lib_init2(mctx, ectx, engine, eflags);
03431 if (result != ISC_R_SUCCESS)
03432 fatal("could not initialize dst: %s",
03433 isc_result_totext(result));
03434 isc_stdtime_get(&now);
03435
03436 if (startstr != NULL) {
03437 starttime = strtotime(startstr, now, now, NULL);
03438 } else
03439 starttime = now - 3600;
03440
03441 if (endstr != NULL)
03442 endtime = strtotime(endstr, now, starttime, NULL);
03443 else
03444 endtime = starttime + (30 * 24 * 60 * 60);
03445
03446 if (dnskey_endstr != NULL) {
03447 dnskey_endtime = strtotime(dnskey_endstr, now, starttime,
03448 NULL);
03449 if (endstr != NULL && dnskey_endtime == endtime)
03450 fprintf(stderr, "WARNING: -e and -X were both set, "
03451 "but have identical values.\n");
03452 } else
03453 dnskey_endtime = endtime;
03454
03455 if (cycle == -1)
03456 cycle = (endtime - starttime) / 4;
03457
03458 if (ntasks == 0)
03459 ntasks = isc_os_ncpus() * 2;
03460 vbprintf(4, "using %d cpus\n", ntasks);
03461
03462 rdclass = strtoclass(classname);
03463
03464 if (directory == NULL)
03465 directory = ".";
03466
03467 setup_logging(mctx, &log);
03468
03469 argc -= isc_commandline_index;
03470 argv += isc_commandline_index;
03471
03472 if (argc < 1)
03473 usage();
03474
03475 file = argv[0];
03476
03477 argc -= 1;
03478 argv += 1;
03479
03480 if (origin == NULL)
03481 origin = file;
03482
03483 if (output == NULL) {
03484 free_output = ISC_TRUE;
03485 output = isc_mem_allocate(mctx,
03486 strlen(file) + strlen(".signed") + 1);
03487 if (output == NULL)
03488 fatal("out of memory");
03489 sprintf(output, "%s.signed", file);
03490 }
03491
03492 if (inputformatstr != NULL) {
03493 if (strcasecmp(inputformatstr, "text") == 0)
03494 inputformat = dns_masterformat_text;
03495 else if (strcasecmp(inputformatstr, "map") == 0)
03496 inputformat = dns_masterformat_map;
03497 else if (strcasecmp(inputformatstr, "raw") == 0)
03498 inputformat = dns_masterformat_raw;
03499 else if (strncasecmp(inputformatstr, "raw=", 4) == 0) {
03500 inputformat = dns_masterformat_raw;
03501 fprintf(stderr,
03502 "WARNING: input format version ignored\n");
03503 } else
03504 fatal("unknown file format: %s", inputformatstr);
03505
03506 }
03507
03508 if (outputformatstr != NULL) {
03509 if (strcasecmp(outputformatstr, "text") == 0) {
03510 outputformat = dns_masterformat_text;
03511 } else if (strcasecmp(outputformatstr, "full") == 0) {
03512 outputformat = dns_masterformat_text;
03513 masterstyle = &dns_master_style_full;
03514 } else if (strcasecmp(outputformatstr, "map") == 0) {
03515 outputformat = dns_masterformat_map;
03516 } else if (strcasecmp(outputformatstr, "raw") == 0) {
03517 outputformat = dns_masterformat_raw;
03518 } else if (strncasecmp(outputformatstr, "raw=", 4) == 0) {
03519 char *end;
03520 outputformat = dns_masterformat_raw;
03521
03522 outputformat = dns_masterformat_raw;
03523 rawversion = strtol(outputformatstr + 4, &end, 10);
03524 if (end == outputformatstr + 4 || *end != '\0' ||
03525 rawversion > 1U) {
03526 fprintf(stderr,
03527 "unknown raw format version\n");
03528 exit(1);
03529 }
03530 } else
03531 fatal("unknown file format: %s", outputformatstr);
03532 }
03533
03534 if (serialformatstr != NULL) {
03535 if (strcasecmp(serialformatstr, "keep") == 0)
03536 serialformat = SOA_SERIAL_KEEP;
03537 else if (strcasecmp(serialformatstr, "increment") == 0 ||
03538 strcasecmp(serialformatstr, "incr") == 0)
03539 serialformat = SOA_SERIAL_INCREMENT;
03540 else if (strcasecmp(serialformatstr, "unixtime") == 0)
03541 serialformat = SOA_SERIAL_UNIXTIME;
03542 else if (strcasecmp(serialformatstr, "date") == 0)
03543 serialformat = SOA_SERIAL_DATE;
03544 else
03545 fatal("unknown soa serial format: %s",
03546 serialformatstr);
03547 }
03548
03549 if (output_dnssec_only && outputformat != dns_masterformat_text)
03550 fatal("option -D can only be used with \"-O text\"");
03551
03552 if (output_dnssec_only && serialformat != SOA_SERIAL_KEEP)
03553 fatal("option -D can only be used with \"-N keep\"");
03554
03555 if (output_dnssec_only && set_maxttl)
03556 fatal("option -D cannot be used with -M");
03557
03558 result = dns_master_stylecreate(&dsstyle, DNS_STYLEFLAG_NO_TTL,
03559 0, 24, 0, 0, 0, 8, mctx);
03560 check_result(result, "dns_master_stylecreate");
03561
03562 gdb = NULL;
03563 TIME_NOW(&timer_start);
03564 loadzone(file, origin, rdclass, &gdb);
03565 gorigin = dns_db_origin(gdb);
03566 gclass = dns_db_class(gdb);
03567 get_soa_ttls();
03568
03569 if (set_maxttl && set_keyttl && keyttl > maxttl) {
03570 fprintf(stderr, "%s: warning: Specified key TTL %d "
03571 "exceeds maximum zone TTL; reducing to %d\n",
03572 program, keyttl, maxttl);
03573 keyttl = maxttl;
03574 }
03575
03576 if (!set_keyttl)
03577 keyttl = soa_ttl;
03578
03579
03580
03581
03582
03583 if (update_chain && !set_optout && !set_iter && !set_salt)
03584 nsec_datatype = dns_rdatatype_nsec;
03585 else
03586 set_nsec3params(update_chain, set_salt, set_optout, set_iter);
03587
03588
03589
03590
03591
03592 ISC_LIST_INIT(keylist);
03593 isc_rwlock_init(&keylist_lock, 0, 0);
03594
03595
03596
03597
03598
03599
03600
03601
03602
03603
03604
03605
03606 if (argc == 0 || smartsign)
03607 loadzonekeys(!smartsign, ISC_FALSE);
03608 loadexplicitkeys(argv, argc, ISC_FALSE);
03609 loadexplicitkeys(dskeyfile, ndskeys, ISC_TRUE);
03610 loadzonekeys(!smartsign, ISC_TRUE);
03611
03612
03613
03614
03615
03616
03617 if (smartsign)
03618 build_final_keylist();
03619
03620
03621 for (key = ISC_LIST_HEAD(keylist);
03622 key != NULL;
03623 key = ISC_LIST_NEXT(key, link)) {
03624 key->index = keycount++;
03625 }
03626
03627 if (keycount == 0) {
03628 if (disable_zone_check)
03629 fprintf(stderr, "%s: warning: No keys specified "
03630 "or found\n", program);
03631 else
03632 fatal("No signing keys specified or found.");
03633 nokeys = ISC_TRUE;
03634 }
03635
03636 warnifallksk(gdb);
03637
03638 if (IS_NSEC3) {
03639 unsigned int max;
03640 isc_boolean_t answer;
03641
03642 hash_length = dns_nsec3_hashlength(dns_hash_sha1);
03643 hashlist_init(&hashlist, dns_db_nodecount(gdb) * 2,
03644 hash_length);
03645 result = dns_nsec_nseconly(gdb, gversion, &answer);
03646 if (result == ISC_R_NOTFOUND)
03647 fprintf(stderr, "%s: warning: NSEC3 generation "
03648 "requested with no DNSKEY; ignoring\n",
03649 program);
03650 else if (result != ISC_R_SUCCESS)
03651 check_result(result, "dns_nsec_nseconly");
03652 else if (answer)
03653 fatal("NSEC3 generation requested with "
03654 "NSEC-only DNSKEY");
03655
03656 result = dns_nsec3_maxiterations(gdb, NULL, mctx, &max);
03657 check_result(result, "dns_nsec3_maxiterations()");
03658 if (nsec3iter > max)
03659 fatal("NSEC3 iterations too big for weakest DNSKEY "
03660 "strength. Maximum iterations allowed %u.", max);
03661 }
03662
03663 gversion = NULL;
03664 result = dns_db_newversion(gdb, &gversion);
03665 check_result(result, "dns_db_newversion()");
03666
03667 switch (serialformat) {
03668 case SOA_SERIAL_INCREMENT:
03669 setsoaserial(0, dns_updatemethod_increment);
03670 break;
03671 case SOA_SERIAL_UNIXTIME:
03672 setsoaserial(now, dns_updatemethod_unixtime);
03673 break;
03674 case SOA_SERIAL_DATE:
03675 setsoaserial(now, dns_updatemethod_date);
03676 break;
03677 case SOA_SERIAL_KEEP:
03678 default:
03679
03680 break;
03681 }
03682
03683
03684 cleanup_zone();
03685
03686 if (!nonsecify) {
03687 if (IS_NSEC3)
03688 nsec3ify(dns_hash_sha1, nsec3iter, gsalt, salt_length,
03689 &hashlist);
03690 else
03691 nsecify();
03692 }
03693
03694 if (!nokeys) {
03695 writeset("dsset-", dns_rdatatype_ds);
03696 if (make_keyset)
03697 writeset("keyset-", dns_rdatatype_dnskey);
03698 if (dlv != NULL) {
03699 writeset("dlvset-", dns_rdatatype_dlv);
03700 }
03701 }
03702
03703 if (output_stdout) {
03704 outfp = stdout;
03705 if (outputformatstr == NULL)
03706 masterstyle = &dns_master_style_full;
03707 } else {
03708 tempfilelen = strlen(output) + 20;
03709 tempfile = isc_mem_get(mctx, tempfilelen);
03710 if (tempfile == NULL)
03711 fatal("out of memory");
03712
03713 result = isc_file_mktemplate(output, tempfile, tempfilelen);
03714 check_result(result, "isc_file_mktemplate");
03715
03716 if (outputformat == dns_masterformat_text)
03717 result = isc_file_openunique(tempfile, &outfp);
03718 else
03719 result = isc_file_bopenunique(tempfile, &outfp);
03720 if (result != ISC_R_SUCCESS)
03721 fatal("failed to open temporary output file: %s",
03722 isc_result_totext(result));
03723 removefile = ISC_TRUE;
03724 setfatalcallback(&removetempfile);
03725 }
03726
03727 print_time(outfp);
03728 print_version(outfp);
03729
03730 result = isc_taskmgr_create(mctx, ntasks, 0, &taskmgr);
03731 if (result != ISC_R_SUCCESS)
03732 fatal("failed to create task manager: %s",
03733 isc_result_totext(result));
03734
03735 master = NULL;
03736 result = isc_task_create(taskmgr, 0, &master);
03737 if (result != ISC_R_SUCCESS)
03738 fatal("failed to create task: %s", isc_result_totext(result));
03739
03740 tasks = isc_mem_get(mctx, ntasks * sizeof(isc_task_t *));
03741 if (tasks == NULL)
03742 fatal("out of memory");
03743 for (i = 0; i < (int)ntasks; i++) {
03744 tasks[i] = NULL;
03745 result = isc_task_create(taskmgr, 0, &tasks[i]);
03746 if (result != ISC_R_SUCCESS)
03747 fatal("failed to create task: %s",
03748 isc_result_totext(result));
03749 }
03750
03751 RUNTIME_CHECK(isc_mutex_init(&namelock) == ISC_R_SUCCESS);
03752 if (printstats)
03753 RUNTIME_CHECK(isc_mutex_init(&statslock) == ISC_R_SUCCESS);
03754
03755 presign();
03756 TIME_NOW(&sign_start);
03757 signapex();
03758 if (!finished) {
03759
03760
03761
03762
03763 for (i = 0; i < (int)ntasks; i++) {
03764 result = isc_app_onrun(mctx, master, startworker,
03765 tasks[i]);
03766 if (result != ISC_R_SUCCESS)
03767 fatal("failed to start task: %s",
03768 isc_result_totext(result));
03769 }
03770 (void)isc_app_run();
03771 if (!finished)
03772 fatal("process aborted by user");
03773 } else
03774 isc_task_detach(&master);
03775 shuttingdown = ISC_TRUE;
03776 for (i = 0; i < (int)ntasks; i++)
03777 isc_task_detach(&tasks[i]);
03778 isc_taskmgr_destroy(&taskmgr);
03779 isc_mem_put(mctx, tasks, ntasks * sizeof(isc_task_t *));
03780 postsign();
03781 TIME_NOW(&sign_finish);
03782
03783 if (!disable_zone_check)
03784 verifyzone(gdb, gversion, gorigin, mctx,
03785 ignore_kskflag, keyset_kskonly);
03786
03787 if (outputformat != dns_masterformat_text) {
03788 dns_masterrawheader_t header;
03789 dns_master_initrawheader(&header);
03790 if (rawversion == 0U)
03791 header.flags = DNS_MASTERRAW_COMPAT;
03792 else if (snset) {
03793 header.flags = DNS_MASTERRAW_SOURCESERIALSET;
03794 header.sourceserial = serialnum;
03795 }
03796 result = dns_master_dumptostream3(mctx, gdb, gversion,
03797 masterstyle, outputformat,
03798 &header, outfp);
03799 check_result(result, "dns_master_dumptostream3");
03800 }
03801
03802 DESTROYLOCK(&namelock);
03803 if (printstats)
03804 DESTROYLOCK(&statslock);
03805
03806 if (!output_stdout) {
03807 result = isc_stdio_close(outfp);
03808 check_result(result, "isc_stdio_close");
03809 removefile = ISC_FALSE;
03810
03811 result = isc_file_rename(tempfile, output);
03812 if (result != ISC_R_SUCCESS)
03813 fatal("failed to rename temp file to %s: %s",
03814 output, isc_result_totext(result));
03815
03816 printf("%s\n", output);
03817 }
03818
03819 dns_db_closeversion(gdb, &gversion, ISC_FALSE);
03820 dns_db_detach(&gdb);
03821
03822 while (!ISC_LIST_EMPTY(keylist)) {
03823 key = ISC_LIST_HEAD(keylist);
03824 ISC_LIST_UNLINK(keylist, key, link);
03825 dns_dnsseckey_destroy(mctx, &key);
03826 }
03827
03828 if (tempfilelen != 0)
03829 isc_mem_put(mctx, tempfile, tempfilelen);
03830
03831 if (free_output)
03832 isc_mem_free(mctx, output);
03833
03834 dns_master_styledestroy(&dsstyle, mctx);
03835
03836 cleanup_logging(&log);
03837 dst_lib_destroy();
03838 isc_hash_destroy();
03839 cleanup_entropy(&ectx);
03840 dns_name_destroy();
03841 if (verbose > 10)
03842 isc_mem_stats(mctx, stdout);
03843 isc_mem_destroy(&mctx);
03844
03845 (void) isc_app_finish();
03846
03847 if (printstats) {
03848 TIME_NOW(&timer_finish);
03849 print_stats(&timer_start, &timer_finish,
03850 &sign_start, &sign_finish);
03851 }
03852
03853 return (0);
03854 }