signer.c revision 7a152bdae33caae47eb48a291eb0ccb346ce7934
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence/*
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence * Copyright (C) 1999, 2000 Internet Software Consortium.
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence *
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence * Permission to use, copy, modify, and distribute this software for any
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence * purpose with or without fee is hereby granted, provided that the above
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence * copyright notice and this permission notice appear in all copies.
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence *
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence * SOFTWARE.
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence */
ea31416b4fcdf23732355a8002f93f29e3b3d2dbAndreas Gustafsson
64e41159a919b0711321fe688ca5da4f4d1b7d80Bob Halley#include <config.h>
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley#include <stdlib.h>
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley#include <isc/commandline.h>
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley#include <isc/mem.h>
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley#include <isc/string.h>
ccdac53c027e8964753b36c4d8c7b0e98af501c2Michael Graff#include <isc/util.h>
ccdac53c027e8964753b36c4d8c7b0e98af501c2Michael Graff
ccdac53c027e8964753b36c4d8c7b0e98af501c2Michael Graff#include <dns/db.h>
ccdac53c027e8964753b36c4d8c7b0e98af501c2Michael Graff#include <dns/dbiterator.h>
ccdac53c027e8964753b36c4d8c7b0e98af501c2Michael Graff#include <dns/dnssec.h>
ccdac53c027e8964753b36c4d8c7b0e98af501c2Michael Graff#include <dns/keyvalues.h>
ccdac53c027e8964753b36c4d8c7b0e98af501c2Michael Graff#include <dns/log.h>
ccdac53c027e8964753b36c4d8c7b0e98af501c2Michael Graff#include <dns/nxt.h>
ccdac53c027e8964753b36c4d8c7b0e98af501c2Michael Graff#include <dns/rdata.h>
ccdac53c027e8964753b36c4d8c7b0e98af501c2Michael Graff#include <dns/rdatalist.h>
ccdac53c027e8964753b36c4d8c7b0e98af501c2Michael Graff#include <dns/rdataset.h>
75a4dd0d377dca2f85cea44e28bf110314c1fe8cDavid Lawrence#include <dns/rdatasetiter.h>
75a4dd0d377dca2f85cea44e28bf110314c1fe8cDavid Lawrence#include <dns/rdatastruct.h>
75a4dd0d377dca2f85cea44e28bf110314c1fe8cDavid Lawrence#include <dns/rdatatype.h>
75a4dd0d377dca2f85cea44e28bf110314c1fe8cDavid Lawrence#include <dns/result.h>
75a4dd0d377dca2f85cea44e28bf110314c1fe8cDavid Lawrence#include <dns/secalg.h>
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence#include <dns/time.h>
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence#include <dst/result.h>
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence#define PROGRAM "signer"
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence/*#define USE_ZONESTATUS*/
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence#define BUFSIZE 2048
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrencetypedef struct signer_key_struct signer_key_t;
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrencetypedef struct signer_array_struct signer_array_t;
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrencestruct signer_key_struct {
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence dst_key_t *key;
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence isc_boolean_t isdefault;
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence ISC_LINK(signer_key_t) link;
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence};
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrencestruct signer_array_struct {
ae4cbb69eef32ced103fe4561e8d2031ee4c3497David Lawrence unsigned char array[BUFSIZE];
ae4cbb69eef32ced103fe4561e8d2031ee4c3497David Lawrence ISC_LINK(signer_array_t) link;
ae4cbb69eef32ced103fe4561e8d2031ee4c3497David Lawrence};
ae4cbb69eef32ced103fe4561e8d2031ee4c3497David Lawrence
ae4cbb69eef32ced103fe4561e8d2031ee4c3497David Lawrencestatic ISC_LIST(signer_key_t) keylist;
ae4cbb69eef32ced103fe4561e8d2031ee4c3497David Lawrencestatic isc_stdtime_t starttime = 0, endtime = 0, now;
ae4cbb69eef32ced103fe4561e8d2031ee4c3497David Lawrencestatic int cycle = -1;
ae4cbb69eef32ced103fe4561e8d2031ee4c3497David Lawrencestatic int verbose;
ae4cbb69eef32ced103fe4561e8d2031ee4c3497David Lawrencestatic isc_boolean_t tryverify = ISC_FALSE;
ae4cbb69eef32ced103fe4561e8d2031ee4c3497David Lawrence
ae4cbb69eef32ced103fe4561e8d2031ee4c3497David Lawrencestatic isc_mem_t *mctx = NULL;
ae4cbb69eef32ced103fe4561e8d2031ee4c3497David Lawrence
ae4cbb69eef32ced103fe4561e8d2031ee4c3497David Lawrencestatic inline void
ae4cbb69eef32ced103fe4561e8d2031ee4c3497David Lawrencefatal(char *format, ...) {
ae4cbb69eef32ced103fe4561e8d2031ee4c3497David Lawrence va_list args;
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence fprintf(stderr, "%s: ", PROGRAM);
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence va_start(args, format);
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence vfprintf(stderr, format, args);
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence va_end(args);
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence fprintf(stderr, "\n");
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence exit(1);
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence}
0293ad13207aa29bd5844cdc87d085ffc009d749David Lawrence
0293ad13207aa29bd5844cdc87d085ffc009d749David Lawrencestatic inline void
0293ad13207aa29bd5844cdc87d085ffc009d749David Lawrencecheck_result(isc_result_t result, char *message) {
0293ad13207aa29bd5844cdc87d085ffc009d749David Lawrence if (result != ISC_R_SUCCESS) {
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence fprintf(stderr, "%s: %s: %s\n", PROGRAM, message,
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence isc_result_totext(result));
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence exit(1);
0293ad13207aa29bd5844cdc87d085ffc009d749David Lawrence }
0293ad13207aa29bd5844cdc87d085ffc009d749David Lawrence}
0293ad13207aa29bd5844cdc87d085ffc009d749David Lawrence
0293ad13207aa29bd5844cdc87d085ffc009d749David Lawrencestatic void
0293ad13207aa29bd5844cdc87d085ffc009d749David Lawrencevbprintf(int level, const char *fmt, ...) {
0293ad13207aa29bd5844cdc87d085ffc009d749David Lawrence va_list ap;
0293ad13207aa29bd5844cdc87d085ffc009d749David Lawrence if (level > verbose)
0293ad13207aa29bd5844cdc87d085ffc009d749David Lawrence return;
0293ad13207aa29bd5844cdc87d085ffc009d749David Lawrence va_start(ap, fmt);
0293ad13207aa29bd5844cdc87d085ffc009d749David Lawrence fprintf(stderr, "%s: ", PROGRAM);
0293ad13207aa29bd5844cdc87d085ffc009d749David Lawrence vfprintf(stderr, fmt, ap);
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence va_end(ap);
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence}
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence/* Not thread-safe! */
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrencestatic char *
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrencenametostr(dns_name_t *name) {
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence isc_buffer_t b;
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence isc_region_t r;
657ce0b9d84fbd66514df53d61a087e8f1161187Michael Graff isc_result_t result;
657ce0b9d84fbd66514df53d61a087e8f1161187Michael Graff static char data[1025];
657ce0b9d84fbd66514df53d61a087e8f1161187Michael Graff
657ce0b9d84fbd66514df53d61a087e8f1161187Michael Graff isc_buffer_init(&b, data, sizeof(data));
657ce0b9d84fbd66514df53d61a087e8f1161187Michael Graff result = dns_name_totext(name, ISC_FALSE, &b);
657ce0b9d84fbd66514df53d61a087e8f1161187Michael Graff check_result(result, "dns_name_totext()");
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence isc_buffer_usedregion(&b, &r);
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence r.base[r.length] = 0;
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence return (char *) r.base;
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence}
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence/* Not thread-safe! */
4bcaefbcd3ced942139fdc830e007c6ea2b8d2feDavid Lawrencestatic char *
4bcaefbcd3ced942139fdc830e007c6ea2b8d2feDavid Lawrencetypetostr(const dns_rdatatype_t type) {
4bcaefbcd3ced942139fdc830e007c6ea2b8d2feDavid Lawrence isc_buffer_t b;
4bcaefbcd3ced942139fdc830e007c6ea2b8d2feDavid Lawrence isc_region_t r;
4bcaefbcd3ced942139fdc830e007c6ea2b8d2feDavid Lawrence isc_result_t result;
4bcaefbcd3ced942139fdc830e007c6ea2b8d2feDavid Lawrence static char data[10];
4bcaefbcd3ced942139fdc830e007c6ea2b8d2feDavid Lawrence
4bcaefbcd3ced942139fdc830e007c6ea2b8d2feDavid Lawrence isc_buffer_init(&b, data, sizeof(data));
4bcaefbcd3ced942139fdc830e007c6ea2b8d2feDavid Lawrence result = dns_rdatatype_totext(type, &b);
4bcaefbcd3ced942139fdc830e007c6ea2b8d2feDavid Lawrence check_result(result, "dns_rdatatype_totext()");
4bcaefbcd3ced942139fdc830e007c6ea2b8d2feDavid Lawrence isc_buffer_usedregion(&b, &r);
4bcaefbcd3ced942139fdc830e007c6ea2b8d2feDavid Lawrence r.base[r.length] = 0;
4bcaefbcd3ced942139fdc830e007c6ea2b8d2feDavid Lawrence return (char *) r.base;
4bcaefbcd3ced942139fdc830e007c6ea2b8d2feDavid Lawrence}
4bcaefbcd3ced942139fdc830e007c6ea2b8d2feDavid Lawrence
4bcaefbcd3ced942139fdc830e007c6ea2b8d2feDavid Lawrence/* Not thread-safe! */
657ce0b9d84fbd66514df53d61a087e8f1161187Michael Graffstatic char *
657ce0b9d84fbd66514df53d61a087e8f1161187Michael Graffalgtostr(const dns_secalg_t alg) {
657ce0b9d84fbd66514df53d61a087e8f1161187Michael Graff isc_buffer_t b;
657ce0b9d84fbd66514df53d61a087e8f1161187Michael Graff isc_region_t r;
657ce0b9d84fbd66514df53d61a087e8f1161187Michael Graff isc_result_t result;
657ce0b9d84fbd66514df53d61a087e8f1161187Michael Graff static char data[10];
657ce0b9d84fbd66514df53d61a087e8f1161187Michael Graff
657ce0b9d84fbd66514df53d61a087e8f1161187Michael Graff isc_buffer_init(&b, data, sizeof(data));
657ce0b9d84fbd66514df53d61a087e8f1161187Michael Graff result = dns_secalg_totext(alg, &b);
657ce0b9d84fbd66514df53d61a087e8f1161187Michael Graff check_result(result, "dns_secalg_totext()");
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence isc_buffer_usedregion(&b, &r);
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence r.base[r.length] = 0;
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence return (char *) r.base;
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence}
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence
ea31416b4fcdf23732355a8002f93f29e3b3d2dbAndreas Gustafssonstatic inline void
ea31416b4fcdf23732355a8002f93f29e3b3d2dbAndreas Gustafssonset_bit(unsigned char *array, unsigned int index, unsigned int bit) {
ea31416b4fcdf23732355a8002f93f29e3b3d2dbAndreas Gustafsson unsigned int byte, shift, mask;
ea31416b4fcdf23732355a8002f93f29e3b3d2dbAndreas Gustafsson
ea31416b4fcdf23732355a8002f93f29e3b3d2dbAndreas Gustafsson byte = array[index / 8];
ea31416b4fcdf23732355a8002f93f29e3b3d2dbAndreas Gustafsson shift = 7 - (index % 8);
8a9b755d32a4f6ace792ac3fd17c968cf96d2487David Lawrence mask = 1 << shift;
ea31416b4fcdf23732355a8002f93f29e3b3d2dbAndreas Gustafsson
ea31416b4fcdf23732355a8002f93f29e3b3d2dbAndreas Gustafsson if (bit)
ea31416b4fcdf23732355a8002f93f29e3b3d2dbAndreas Gustafsson array[index / 8] |= mask;
8a9b755d32a4f6ace792ac3fd17c968cf96d2487David Lawrence else
ea31416b4fcdf23732355a8002f93f29e3b3d2dbAndreas Gustafsson array[index / 8] &= (~mask & 0xFF);
ea31416b4fcdf23732355a8002f93f29e3b3d2dbAndreas Gustafsson}
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrencestatic void
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrencesignwithkey(dns_name_t *name, dns_rdataset_t *rdataset, dns_rdata_t *rdata,
ea31416b4fcdf23732355a8002f93f29e3b3d2dbAndreas Gustafsson dst_key_t *key, isc_buffer_t *b)
ea31416b4fcdf23732355a8002f93f29e3b3d2dbAndreas Gustafsson{
ea31416b4fcdf23732355a8002f93f29e3b3d2dbAndreas Gustafsson isc_result_t result;
ea31416b4fcdf23732355a8002f93f29e3b3d2dbAndreas Gustafsson
ea31416b4fcdf23732355a8002f93f29e3b3d2dbAndreas Gustafsson dns_rdata_init(rdata);
ea31416b4fcdf23732355a8002f93f29e3b3d2dbAndreas Gustafsson result = dns_dnssec_sign(name, rdataset, key, &starttime, &endtime,
ea31416b4fcdf23732355a8002f93f29e3b3d2dbAndreas Gustafsson mctx, b, rdata);
ea31416b4fcdf23732355a8002f93f29e3b3d2dbAndreas Gustafsson if (result != ISC_R_SUCCESS)
ea31416b4fcdf23732355a8002f93f29e3b3d2dbAndreas Gustafsson fatal("key '%s/%s/%d' failed to sign data: %s",
ea31416b4fcdf23732355a8002f93f29e3b3d2dbAndreas Gustafsson dst_key_name(key), algtostr(dst_key_alg(key)),
ea31416b4fcdf23732355a8002f93f29e3b3d2dbAndreas Gustafsson dst_key_id(key), isc_result_totext(result));
ea31416b4fcdf23732355a8002f93f29e3b3d2dbAndreas Gustafsson
ea31416b4fcdf23732355a8002f93f29e3b3d2dbAndreas Gustafsson if (tryverify) {
ea31416b4fcdf23732355a8002f93f29e3b3d2dbAndreas Gustafsson result = dns_dnssec_verify(name, rdataset, key,
ea31416b4fcdf23732355a8002f93f29e3b3d2dbAndreas Gustafsson ISC_TRUE, mctx, rdata);
ea31416b4fcdf23732355a8002f93f29e3b3d2dbAndreas Gustafsson if (result == ISC_R_SUCCESS)
ea31416b4fcdf23732355a8002f93f29e3b3d2dbAndreas Gustafsson vbprintf(3, "\tsignature verified\n");
ea31416b4fcdf23732355a8002f93f29e3b3d2dbAndreas Gustafsson else
ea31416b4fcdf23732355a8002f93f29e3b3d2dbAndreas Gustafsson vbprintf(3, "\tsignature failed to verify\n");
ea31416b4fcdf23732355a8002f93f29e3b3d2dbAndreas Gustafsson }
ea31416b4fcdf23732355a8002f93f29e3b3d2dbAndreas Gustafsson}
6182613ef54ebb8369d951ffa4431c49b75cec51Mark Andrews
ea31416b4fcdf23732355a8002f93f29e3b3d2dbAndreas Gustafssonstatic inline isc_boolean_t
ea31416b4fcdf23732355a8002f93f29e3b3d2dbAndreas Gustafssonissigningkey(signer_key_t *key) {
ea31416b4fcdf23732355a8002f93f29e3b3d2dbAndreas Gustafsson return (key->isdefault);
ea31416b4fcdf23732355a8002f93f29e3b3d2dbAndreas Gustafsson}
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrencestatic inline isc_boolean_t
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrenceiszonekey(signer_key_t *key, dns_db_t *db) {
2c7e99b941c3f1ffa29f9034c710f358c09f13c9Michael Graff char origin[1024];
ea31416b4fcdf23732355a8002f93f29e3b3d2dbAndreas Gustafsson isc_buffer_t b;
ea31416b4fcdf23732355a8002f93f29e3b3d2dbAndreas Gustafsson isc_result_t result;
ea31416b4fcdf23732355a8002f93f29e3b3d2dbAndreas Gustafsson
ea31416b4fcdf23732355a8002f93f29e3b3d2dbAndreas Gustafsson isc_buffer_init(&b, origin, sizeof(origin));
ea31416b4fcdf23732355a8002f93f29e3b3d2dbAndreas Gustafsson result = dns_name_totext(dns_db_origin(db), ISC_FALSE, &b);
ea31416b4fcdf23732355a8002f93f29e3b3d2dbAndreas Gustafsson check_result(result, "dns_name_totext()");
ea31416b4fcdf23732355a8002f93f29e3b3d2dbAndreas Gustafsson
ea31416b4fcdf23732355a8002f93f29e3b3d2dbAndreas Gustafsson return (ISC_TF(strcasecmp(dst_key_name(key->key), origin) == 0 &&
ea31416b4fcdf23732355a8002f93f29e3b3d2dbAndreas Gustafsson (dst_key_flags(key->key) & DNS_KEYFLAG_OWNERMASK) ==
ea31416b4fcdf23732355a8002f93f29e3b3d2dbAndreas Gustafsson DNS_KEYOWNER_ZONE));
ea31416b4fcdf23732355a8002f93f29e3b3d2dbAndreas Gustafsson}
ea31416b4fcdf23732355a8002f93f29e3b3d2dbAndreas Gustafsson
ea31416b4fcdf23732355a8002f93f29e3b3d2dbAndreas Gustafsson/*
ea31416b4fcdf23732355a8002f93f29e3b3d2dbAndreas Gustafsson * Finds the key that generated a SIG, if possible. First look at the keys
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley * that we've loaded already, and then see if there's a key on disk.
13494a4d4bead37f22eb6c4779c73310109f7e4aJames Brister */
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halleystatic signer_key_t *
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halleykeythatsigned(dns_rdata_sig_t *sig) {
7bb707a34778fc4bd9624d6c5de95675424ea59fDavid Lawrence char *keyname;
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley isc_result_t result;
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence dst_key_t *pubkey = NULL, *privkey = NULL;
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence signer_key_t *key;
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence
2b556032fd78aff37e80e755044b944a017245cdDavid Lawrence keyname = nametostr(&sig->signer);
2b556032fd78aff37e80e755044b944a017245cdDavid Lawrence
2b556032fd78aff37e80e755044b944a017245cdDavid Lawrence key = ISC_LIST_HEAD(keylist);
35c842e05dc6382ce1d9161a658d3ff4b2c3d4c9Bob Halley while (key != NULL) {
2b556032fd78aff37e80e755044b944a017245cdDavid Lawrence if (sig->keyid == dst_key_id(key->key) &&
2b556032fd78aff37e80e755044b944a017245cdDavid Lawrence sig->algorithm == dst_key_alg(key->key) &&
2b556032fd78aff37e80e755044b944a017245cdDavid Lawrence strcasecmp(keyname, dst_key_name(key->key)) == 0)
35c842e05dc6382ce1d9161a658d3ff4b2c3d4c9Bob Halley return key;
2b556032fd78aff37e80e755044b944a017245cdDavid Lawrence key = ISC_LIST_NEXT(key, link);
2b556032fd78aff37e80e755044b944a017245cdDavid Lawrence }
2b556032fd78aff37e80e755044b944a017245cdDavid Lawrence
35c842e05dc6382ce1d9161a658d3ff4b2c3d4c9Bob Halley result = dst_key_fromfile(keyname, sig->keyid, sig->algorithm,
2b556032fd78aff37e80e755044b944a017245cdDavid Lawrence DST_TYPE_PUBLIC, mctx, &pubkey);
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley if (result != ISC_R_SUCCESS)
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley return (NULL);
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley key = isc_mem_get(mctx, sizeof(signer_key_t));
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley if (key == NULL)
a2171e092382f8f8a72b1f73436ddf93918c7719Bob Halley fatal("out of memory");
a2171e092382f8f8a72b1f73436ddf93918c7719Bob Halley
7c0876aa42e6abaa8779bcb83962ccf20a9f4da3Bob Halley result = dst_key_fromfile(keyname, sig->keyid, sig->algorithm,
a2171e092382f8f8a72b1f73436ddf93918c7719Bob Halley DST_TYPE_PRIVATE, mctx, &privkey);
491b48ec3f3ef014312688776ddbd4eab8a2c10cMichael Graff if (result == ISC_R_SUCCESS) {
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence key->key = privkey;
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence dst_key_free(pubkey);
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence }
12ccbb032ec1b5f6b93aac923f2645a19fc90c75David Lawrence else
facb97777a972f6c8035ca3e762a6a9248c12897Bob Halley key->key = pubkey;
12ccbb032ec1b5f6b93aac923f2645a19fc90c75David Lawrence key->isdefault = ISC_FALSE;
12ccbb032ec1b5f6b93aac923f2645a19fc90c75David Lawrence ISC_LIST_APPEND(keylist, key, link);
12ccbb032ec1b5f6b93aac923f2645a19fc90c75David Lawrence return key;
12ccbb032ec1b5f6b93aac923f2645a19fc90c75David Lawrence}
facb97777a972f6c8035ca3e762a6a9248c12897Bob Halley
facb97777a972f6c8035ca3e762a6a9248c12897Bob Halley/*
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence * Check to see if we expect to find a key at this name. If we see a SIG
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence * and can't find the signing key that we expect to find, we drop the sig.
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence * I'm not sure if this is completely correct, but it seems to work.
a505a3f6e09218bebac020fc49105b2e6cd9e25cBob Halley */
a505a3f6e09218bebac020fc49105b2e6cd9e25cBob Halleystatic isc_boolean_t
a505a3f6e09218bebac020fc49105b2e6cd9e25cBob Halleyexpecttofindkey(dns_name_t *name, dns_db_t *db, dns_dbversion_t *version) {
a505a3f6e09218bebac020fc49105b2e6cd9e25cBob Halley unsigned int options = DNS_DBFIND_NOWILD;
a505a3f6e09218bebac020fc49105b2e6cd9e25cBob Halley dns_fixedname_t fname;
a505a3f6e09218bebac020fc49105b2e6cd9e25cBob Halley isc_result_t result;
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence dns_fixedname_init(&fname);
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence result = dns_db_find(db, name, version, dns_rdatatype_key, options,
facb97777a972f6c8035ca3e762a6a9248c12897Bob Halley 0, NULL, dns_fixedname_name(&fname), NULL, NULL);
facb97777a972f6c8035ca3e762a6a9248c12897Bob Halley switch (result) {
facb97777a972f6c8035ca3e762a6a9248c12897Bob Halley case ISC_R_SUCCESS:
facb97777a972f6c8035ca3e762a6a9248c12897Bob Halley case DNS_R_NXDOMAIN:
facb97777a972f6c8035ca3e762a6a9248c12897Bob Halley case DNS_R_NXRRSET:
facb97777a972f6c8035ca3e762a6a9248c12897Bob Halley return ISC_TRUE;
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence case DNS_R_DELEGATION:
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence case DNS_R_CNAME:
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence case DNS_R_DNAME:
d8dcd6ad4617cc8d7df979bd62101fa9c4bac1bcBob Halley return ISC_FALSE;
d8dcd6ad4617cc8d7df979bd62101fa9c4bac1bcBob Halley default:
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence fatal("failure looking for '%s KEY' in database: %s",
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence nametostr(name), isc_result_totext(result));
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence return ISC_FALSE; /* removes a warning */
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence }
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence}
facb97777a972f6c8035ca3e762a6a9248c12897Bob Halley
12ccbb032ec1b5f6b93aac923f2645a19fc90c75David Lawrencestatic inline isc_boolean_t
facb97777a972f6c8035ca3e762a6a9248c12897Bob Halleysetverifies(dns_name_t *name, dns_rdataset_t *set, signer_key_t *key,
facb97777a972f6c8035ca3e762a6a9248c12897Bob Halley dns_rdata_t *sig)
a829555ed724caa56b1ff7716d7eda2266491eafBob Halley{
a829555ed724caa56b1ff7716d7eda2266491eafBob Halley isc_result_t result;
a829555ed724caa56b1ff7716d7eda2266491eafBob Halley result = dns_dnssec_verify(name, set, key->key, ISC_FALSE, mctx, sig);
facb97777a972f6c8035ca3e762a6a9248c12897Bob Halley return (ISC_TF(result == ISC_R_SUCCESS));
facb97777a972f6c8035ca3e762a6a9248c12897Bob Halley}
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence#define allocbufferandrdata \
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence isc_buffer_t b; \
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence trdata = isc_mem_get(mctx, sizeof(dns_rdata_t)); \
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence tdata = isc_mem_get(mctx, sizeof(signer_array_t)); \
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence ISC_LIST_APPEND(arraylist, tdata, link); \
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence if (trdata == NULL || tdata == NULL) \
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence fatal("out of memory"); \
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence isc_buffer_init(&b, tdata->array, sizeof(tdata->array));
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence
882350d11c90de9de6fc1cead25690c8114b0b95Michael Graff/*
882350d11c90de9de6fc1cead25690c8114b0b95Michael Graff * Signs a set. Goes through contortions to decide if each SIG should
882350d11c90de9de6fc1cead25690c8114b0b95Michael Graff * be dropped or retained, and then determines if any new SIGs need to
882350d11c90de9de6fc1cead25690c8114b0b95Michael Graff * be generated.
882350d11c90de9de6fc1cead25690c8114b0b95Michael Graff */
882350d11c90de9de6fc1cead25690c8114b0b95Michael Graffstatic void
882350d11c90de9de6fc1cead25690c8114b0b95Michael Graffsignset(dns_db_t *db, dns_dbversion_t *version, dns_dbnode_t *node,
882350d11c90de9de6fc1cead25690c8114b0b95Michael Graff dns_name_t *name, dns_rdataset_t *set)
64ba6e4cc3a0ccf8c8c6349fa75b937ca9bad9a6Michael Graff{
694c897b20f06f8a5349fd9ac5df93947f6f5a2aBob Halley dns_rdatalist_t siglist;
694c897b20f06f8a5349fd9ac5df93947f6f5a2aBob Halley dns_rdataset_t sigset, oldsigset;
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley dns_rdata_t oldsigrdata;
491b48ec3f3ef014312688776ddbd4eab8a2c10cMichael Graff dns_rdata_t *trdata;
9fbc1afb8b08432e3a1adda1f41d5575620e9785Bob Halley dns_rdata_sig_t sig;
1443aa0adf4d262abdf2721a5239acd4812cdc06Bob Halley signer_key_t *key;
1443aa0adf4d262abdf2721a5239acd4812cdc06Bob Halley isc_result_t result;
1443aa0adf4d262abdf2721a5239acd4812cdc06Bob Halley isc_boolean_t notsigned = ISC_TRUE, nosigs = ISC_FALSE;
1443aa0adf4d262abdf2721a5239acd4812cdc06Bob Halley isc_boolean_t wassignedby[256], nowsignedby[256];
083699db84de2f7cc534c06ed3502248329145d4Bob Halley signer_array_t *tdata;
083699db84de2f7cc534c06ed3502248329145d4Bob Halley ISC_LIST(signer_array_t) arraylist;
083699db84de2f7cc534c06ed3502248329145d4Bob Halley int i;
9fbc1afb8b08432e3a1adda1f41d5575620e9785Bob Halley
9fbc1afb8b08432e3a1adda1f41d5575620e9785Bob Halley ISC_LIST_INIT(siglist.rdata);
9fbc1afb8b08432e3a1adda1f41d5575620e9785Bob Halley ISC_LIST_INIT(arraylist);
9fbc1afb8b08432e3a1adda1f41d5575620e9785Bob Halley
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley for (i = 0; i < 256; i++)
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley wassignedby[i] = nowsignedby[i] = ISC_FALSE;
a2171e092382f8f8a72b1f73436ddf93918c7719Bob Halley
68e46ce9ee6bbbc0e61e93f1705657d3ef83127bBob Halley dns_rdataset_init(&oldsigset);
694c897b20f06f8a5349fd9ac5df93947f6f5a2aBob Halley result = dns_db_findrdataset(db, node, version, dns_rdatatype_sig,
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley set->type, 0, &oldsigset, NULL);
9fbc1afb8b08432e3a1adda1f41d5575620e9785Bob Halley if (result == ISC_R_NOTFOUND) {
9fbc1afb8b08432e3a1adda1f41d5575620e9785Bob Halley result = ISC_R_SUCCESS;
694c897b20f06f8a5349fd9ac5df93947f6f5a2aBob Halley nosigs = ISC_TRUE;
694c897b20f06f8a5349fd9ac5df93947f6f5a2aBob Halley }
9fbc1afb8b08432e3a1adda1f41d5575620e9785Bob Halley if (result != ISC_R_SUCCESS)
7c0876aa42e6abaa8779bcb83962ccf20a9f4da3Bob Halley fatal("failed while looking for '%s SIG %s': %s",
16c46f3cf540d6e0fff38410ce04a0f26a8f883fBob Halley nametostr(name), typetostr(set->type),
9ca8ad2a26061acc92f224354f1496a339a41a9eBob Halley isc_result_totext(result));
7c0876aa42e6abaa8779bcb83962ccf20a9f4da3Bob Halley
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley vbprintf(1, "%s/%s:\n", nametostr(name), typetostr(set->type));
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley
694c897b20f06f8a5349fd9ac5df93947f6f5a2aBob Halley if (!nosigs) {
694c897b20f06f8a5349fd9ac5df93947f6f5a2aBob Halley result = dns_rdataset_first(&oldsigset);
694c897b20f06f8a5349fd9ac5df93947f6f5a2aBob Halley while (result == ISC_R_SUCCESS) {
491b48ec3f3ef014312688776ddbd4eab8a2c10cMichael Graff isc_boolean_t expired, future;
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence isc_boolean_t keep = ISC_FALSE, resign = ISC_FALSE;
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence dns_rdataset_current(&oldsigset, &oldsigrdata);
28ed3013196c373745dbde87b75a490148dab840Bob Halley
ea31416b4fcdf23732355a8002f93f29e3b3d2dbAndreas Gustafsson result = dns_rdata_tostruct(&oldsigrdata, &sig, mctx);
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence check_result(result, "dns_rdata_tostruct");
ee7c4a9d17435299f152c4753f0a0dfc890e800aMichael Graff
ea31416b4fcdf23732355a8002f93f29e3b3d2dbAndreas Gustafsson expired = ISC_TF(now + cycle > sig.timeexpire);
28ed3013196c373745dbde87b75a490148dab840Bob Halley future = ISC_TF(now < sig.timesigned);
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence key = keythatsigned(&sig);
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence if (sig.timesigned > sig.timeexpire) {
1922518d7f7b5e3e77b8e1c92569c98268b9c192Andreas Gustafsson /* sig is dropped and not replaced */
9cda9dc86efa0dde8f906759c4e3279da028b5f4Bob Halley vbprintf(2, "\tsig by %s/%s/%d dropped - "
9cda9dc86efa0dde8f906759c4e3279da028b5f4Bob Halley "invalid validity period\n",
9cda9dc86efa0dde8f906759c4e3279da028b5f4Bob Halley nametostr(&sig.signer),
70eb7879553eaa57c391f07e439911bfdaff7124Bob Halley algtostr(sig.algorithm),
9cda9dc86efa0dde8f906759c4e3279da028b5f4Bob Halley sig.keyid);
35c842e05dc6382ce1d9161a658d3ff4b2c3d4c9Bob Halley }
35c842e05dc6382ce1d9161a658d3ff4b2c3d4c9Bob Halley else if (key == NULL && !future &&
9cda9dc86efa0dde8f906759c4e3279da028b5f4Bob Halley expecttofindkey(&sig.signer, db, version))
35c842e05dc6382ce1d9161a658d3ff4b2c3d4c9Bob Halley {
35c842e05dc6382ce1d9161a658d3ff4b2c3d4c9Bob Halley /* sig is dropped and not replaced */
51917258dbb23cfe6069ae1cf2b7fc5aefc1e0c2Bob Halley vbprintf(2, "\tsig by %s/%s/%d dropped - "
35c842e05dc6382ce1d9161a658d3ff4b2c3d4c9Bob Halley "private key not found\n",
9cda9dc86efa0dde8f906759c4e3279da028b5f4Bob Halley nametostr(&sig.signer),
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence algtostr(sig.algorithm),
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence sig.keyid);
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence }
4c5faa6bcf41d8ba253b872a04105a2fcc88c07bMichael Graff else if (key == NULL || future) {
4c5faa6bcf41d8ba253b872a04105a2fcc88c07bMichael Graff vbprintf(2, "\tsig by %s/%s/%d %s - "
4c5faa6bcf41d8ba253b872a04105a2fcc88c07bMichael Graff "key not found\n",
4c5faa6bcf41d8ba253b872a04105a2fcc88c07bMichael Graff expired ? "retained" : "dropped",
4c5faa6bcf41d8ba253b872a04105a2fcc88c07bMichael Graff nametostr(&sig.signer),
4c5faa6bcf41d8ba253b872a04105a2fcc88c07bMichael Graff algtostr(sig.algorithm),
51917258dbb23cfe6069ae1cf2b7fc5aefc1e0c2Bob Halley sig.keyid);
4c5faa6bcf41d8ba253b872a04105a2fcc88c07bMichael Graff if (!expired)
51917258dbb23cfe6069ae1cf2b7fc5aefc1e0c2Bob Halley keep = ISC_TRUE;
51917258dbb23cfe6069ae1cf2b7fc5aefc1e0c2Bob Halley }
4c5faa6bcf41d8ba253b872a04105a2fcc88c07bMichael Graff else if (issigningkey(key)) {
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence if (!expired &&
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence setverifies(name, set, key, &oldsigrdata))
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence {
8671e8306b3f18abf0e19c2fb9d49205962e7ab7David Lawrence vbprintf(2,
8671e8306b3f18abf0e19c2fb9d49205962e7ab7David Lawrence "\tsig by %s/%s/%d retained\n",
6c327669ba1d9eca870572b930c46f43e781d4a3Andreas Gustafsson nametostr(&sig.signer),
8671e8306b3f18abf0e19c2fb9d49205962e7ab7David Lawrence algtostr(sig.algorithm),
8671e8306b3f18abf0e19c2fb9d49205962e7ab7David Lawrence sig.keyid);
8671e8306b3f18abf0e19c2fb9d49205962e7ab7David Lawrence keep = ISC_TRUE;
51917258dbb23cfe6069ae1cf2b7fc5aefc1e0c2Bob Halley wassignedby[sig.algorithm] = ISC_TRUE;
8671e8306b3f18abf0e19c2fb9d49205962e7ab7David Lawrence }
51917258dbb23cfe6069ae1cf2b7fc5aefc1e0c2Bob Halley else {
51917258dbb23cfe6069ae1cf2b7fc5aefc1e0c2Bob Halley vbprintf(2,
8671e8306b3f18abf0e19c2fb9d49205962e7ab7David Lawrence "\tsig by %s/%s/%d dropped - "
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence "%s\n",
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence nametostr(&sig.signer),
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence algtostr(sig.algorithm),
c7620c99f1139b77f14678e21a44f7c8c4236a7bMark Andrews sig.keyid,
c7620c99f1139b77f14678e21a44f7c8c4236a7bMark Andrews expired ? "expired" :
c7620c99f1139b77f14678e21a44f7c8c4236a7bMark Andrews "failed to verify");
c7620c99f1139b77f14678e21a44f7c8c4236a7bMark Andrews wassignedby[sig.algorithm] = ISC_TRUE;
c7620c99f1139b77f14678e21a44f7c8c4236a7bMark Andrews resign = ISC_TRUE;
c7620c99f1139b77f14678e21a44f7c8c4236a7bMark Andrews }
c7620c99f1139b77f14678e21a44f7c8c4236a7bMark Andrews }
c7620c99f1139b77f14678e21a44f7c8c4236a7bMark Andrews else if (iszonekey(key, db)) {
40f24178432de09181bc603cc90110546a0ddca2Mark Andrews if (!expired &&
40f24178432de09181bc603cc90110546a0ddca2Mark Andrews setverifies(name, set, key, &oldsigrdata))
40f24178432de09181bc603cc90110546a0ddca2Mark Andrews {
40f24178432de09181bc603cc90110546a0ddca2Mark Andrews vbprintf(2,
40f24178432de09181bc603cc90110546a0ddca2Mark Andrews "\tsig by %s/%s/%d retained\n",
40f24178432de09181bc603cc90110546a0ddca2Mark Andrews nametostr(&sig.signer),
40f24178432de09181bc603cc90110546a0ddca2Mark Andrews algtostr(sig.algorithm),
40f24178432de09181bc603cc90110546a0ddca2Mark Andrews sig.keyid);
40f24178432de09181bc603cc90110546a0ddca2Mark Andrews keep = ISC_TRUE;
40f24178432de09181bc603cc90110546a0ddca2Mark Andrews wassignedby[sig.algorithm] = ISC_TRUE;
40f24178432de09181bc603cc90110546a0ddca2Mark Andrews nowsignedby[sig.algorithm] = ISC_TRUE;
40f24178432de09181bc603cc90110546a0ddca2Mark Andrews }
40f24178432de09181bc603cc90110546a0ddca2Mark Andrews else {
40f24178432de09181bc603cc90110546a0ddca2Mark Andrews vbprintf(2,
40f24178432de09181bc603cc90110546a0ddca2Mark Andrews "\tsig by %s/%s/%d "
6182613ef54ebb8369d951ffa4431c49b75cec51Mark Andrews "dropped - %s\n",
40f24178432de09181bc603cc90110546a0ddca2Mark Andrews nametostr(&sig.signer),
40f24178432de09181bc603cc90110546a0ddca2Mark Andrews algtostr(sig.algorithm),
40f24178432de09181bc603cc90110546a0ddca2Mark Andrews sig.keyid,
40f24178432de09181bc603cc90110546a0ddca2Mark Andrews expired ? "expired" :
40f24178432de09181bc603cc90110546a0ddca2Mark Andrews "failed to verify");
40f24178432de09181bc603cc90110546a0ddca2Mark Andrews wassignedby[sig.algorithm] = ISC_TRUE;
afb4ad8f988591bccae0ee2ac73b2fef5d969366Mark Andrews if (dst_key_isprivate(key->key))
afb4ad8f988591bccae0ee2ac73b2fef5d969366Mark Andrews resign = ISC_TRUE;
afb4ad8f988591bccae0ee2ac73b2fef5d969366Mark Andrews }
afb4ad8f988591bccae0ee2ac73b2fef5d969366Mark Andrews }
afb4ad8f988591bccae0ee2ac73b2fef5d969366Mark Andrews else if (!expired) {
afb4ad8f988591bccae0ee2ac73b2fef5d969366Mark Andrews vbprintf(2, "\tsig by %s/%s/%d retained\n",
afb4ad8f988591bccae0ee2ac73b2fef5d969366Mark Andrews nametostr(&sig.signer),
afb4ad8f988591bccae0ee2ac73b2fef5d969366Mark Andrews algtostr(sig.algorithm),
afb4ad8f988591bccae0ee2ac73b2fef5d969366Mark Andrews sig.keyid);
afb4ad8f988591bccae0ee2ac73b2fef5d969366Mark Andrews keep = ISC_TRUE;
afb4ad8f988591bccae0ee2ac73b2fef5d969366Mark Andrews }
0e7e4562fd8222047b8ccf3a508d95df4f81bc47Mark Andrews else {
0e7e4562fd8222047b8ccf3a508d95df4f81bc47Mark Andrews vbprintf(2, "\tsig by %s/%s/%d expired\n",
0e7e4562fd8222047b8ccf3a508d95df4f81bc47Mark Andrews nametostr(&sig.signer),
0e7e4562fd8222047b8ccf3a508d95df4f81bc47Mark Andrews algtostr(sig.algorithm),
0e7e4562fd8222047b8ccf3a508d95df4f81bc47Mark Andrews sig.keyid);
0e7e4562fd8222047b8ccf3a508d95df4f81bc47Mark Andrews }
0e7e4562fd8222047b8ccf3a508d95df4f81bc47Mark Andrews
0e7e4562fd8222047b8ccf3a508d95df4f81bc47Mark Andrews if (keep) {
40f24178432de09181bc603cc90110546a0ddca2Mark Andrews allocbufferandrdata;
40f24178432de09181bc603cc90110546a0ddca2Mark Andrews result = dns_rdata_fromstruct(trdata,
23693a38979a5f30334176bd3ddd1c42004f55b2Mark Andrews set->rdclass,
23693a38979a5f30334176bd3ddd1c42004f55b2Mark Andrews dns_rdatatype_sig,
23693a38979a5f30334176bd3ddd1c42004f55b2Mark Andrews &sig, &b);
23693a38979a5f30334176bd3ddd1c42004f55b2Mark Andrews nowsignedby[sig.algorithm] = ISC_TRUE;
23693a38979a5f30334176bd3ddd1c42004f55b2Mark Andrews ISC_LIST_APPEND(siglist.rdata, trdata, link);
23693a38979a5f30334176bd3ddd1c42004f55b2Mark Andrews }
23693a38979a5f30334176bd3ddd1c42004f55b2Mark Andrews else if (resign) {
23693a38979a5f30334176bd3ddd1c42004f55b2Mark Andrews allocbufferandrdata;
b21d8bac45b614c39a106c9ee8137589328ea075Andreas Gustafsson vbprintf(1, "\tresigning with key %s/%s/%d\n",
23693a38979a5f30334176bd3ddd1c42004f55b2Mark Andrews dst_key_name(key->key),
a272a556314a892c0bd73bc302e08249f3d99ec2Mark Andrews algtostr(dst_key_alg(key->key)),
700f1442882eda0cce05a51e8c6f820c51054e8eMark Andrews dst_key_id(key->key));
700f1442882eda0cce05a51e8c6f820c51054e8eMark Andrews signwithkey(name, set, trdata, key->key, &b);
a272a556314a892c0bd73bc302e08249f3d99ec2Mark Andrews nowsignedby[sig.algorithm] = ISC_TRUE;
700f1442882eda0cce05a51e8c6f820c51054e8eMark Andrews ISC_LIST_APPEND(siglist.rdata, trdata, link);
700f1442882eda0cce05a51e8c6f820c51054e8eMark Andrews }
700f1442882eda0cce05a51e8c6f820c51054e8eMark Andrews
700f1442882eda0cce05a51e8c6f820c51054e8eMark Andrews dns_rdata_freestruct(&sig);
700f1442882eda0cce05a51e8c6f820c51054e8eMark Andrews result = dns_rdataset_next(&oldsigset);
40f24178432de09181bc603cc90110546a0ddca2Mark Andrews }
40f24178432de09181bc603cc90110546a0ddca2Mark Andrews if (result == ISC_R_NOMORE)
6182613ef54ebb8369d951ffa4431c49b75cec51Mark Andrews result = ISC_R_SUCCESS;
6182613ef54ebb8369d951ffa4431c49b75cec51Mark Andrews check_result(result, "dns_db_dns_rdataset_first()/next()");
6182613ef54ebb8369d951ffa4431c49b75cec51Mark Andrews dns_rdataset_disassociate(&oldsigset);
6182613ef54ebb8369d951ffa4431c49b75cec51Mark Andrews }
6182613ef54ebb8369d951ffa4431c49b75cec51Mark Andrews
6182613ef54ebb8369d951ffa4431c49b75cec51Mark Andrews for (i = 0; i < 256; i++)
6182613ef54ebb8369d951ffa4431c49b75cec51Mark Andrews if (wassignedby[i] != 0) {
6182613ef54ebb8369d951ffa4431c49b75cec51Mark Andrews notsigned = ISC_FALSE;
6182613ef54ebb8369d951ffa4431c49b75cec51Mark Andrews break;
6182613ef54ebb8369d951ffa4431c49b75cec51Mark Andrews }
c7620c99f1139b77f14678e21a44f7c8c4236a7bMark Andrews
c7620c99f1139b77f14678e21a44f7c8c4236a7bMark Andrews key = ISC_LIST_HEAD(keylist);
c7620c99f1139b77f14678e21a44f7c8c4236a7bMark Andrews while (key != NULL) {
c7620c99f1139b77f14678e21a44f7c8c4236a7bMark Andrews int alg = dst_key_alg(key->key);
c7620c99f1139b77f14678e21a44f7c8c4236a7bMark Andrews if (key->isdefault &&
c7620c99f1139b77f14678e21a44f7c8c4236a7bMark Andrews (notsigned || (wassignedby[alg] && !nowsignedby[alg])))
c7620c99f1139b77f14678e21a44f7c8c4236a7bMark Andrews {
c7620c99f1139b77f14678e21a44f7c8c4236a7bMark Andrews allocbufferandrdata;
c7620c99f1139b77f14678e21a44f7c8c4236a7bMark Andrews vbprintf(1, "\tsigning with key %s/%s/%d\n",
c7620c99f1139b77f14678e21a44f7c8c4236a7bMark Andrews dst_key_name(key->key),
c7620c99f1139b77f14678e21a44f7c8c4236a7bMark Andrews algtostr(dst_key_alg(key->key)),
c7620c99f1139b77f14678e21a44f7c8c4236a7bMark Andrews dst_key_id(key->key));
c7620c99f1139b77f14678e21a44f7c8c4236a7bMark Andrews signwithkey(name, set, trdata, key->key, &b);
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence ISC_LIST_APPEND(siglist.rdata, trdata, link);
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence }
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence key = ISC_LIST_NEXT(key, link);
ca485ab26fffa241a3eac1899b2d2012dd1fdb73Andreas Gustafsson }
ca485ab26fffa241a3eac1899b2d2012dd1fdb73Andreas Gustafsson
ca485ab26fffa241a3eac1899b2d2012dd1fdb73Andreas Gustafsson if (!ISC_LIST_EMPTY(siglist.rdata)) {
ca485ab26fffa241a3eac1899b2d2012dd1fdb73Andreas Gustafsson siglist.rdclass = set->rdclass;
ca485ab26fffa241a3eac1899b2d2012dd1fdb73Andreas Gustafsson siglist.type = dns_rdatatype_sig;
ca485ab26fffa241a3eac1899b2d2012dd1fdb73Andreas Gustafsson siglist.covers = set->type;
ca485ab26fffa241a3eac1899b2d2012dd1fdb73Andreas Gustafsson if (endtime - starttime < set->ttl)
ca485ab26fffa241a3eac1899b2d2012dd1fdb73Andreas Gustafsson siglist.ttl = endtime - starttime;
ca485ab26fffa241a3eac1899b2d2012dd1fdb73Andreas Gustafsson else
ca485ab26fffa241a3eac1899b2d2012dd1fdb73Andreas Gustafsson siglist.ttl = set->ttl;
ca485ab26fffa241a3eac1899b2d2012dd1fdb73Andreas Gustafsson dns_rdataset_init(&sigset);
ca485ab26fffa241a3eac1899b2d2012dd1fdb73Andreas Gustafsson result = dns_rdatalist_tordataset(&siglist, &sigset);
ca485ab26fffa241a3eac1899b2d2012dd1fdb73Andreas Gustafsson check_result(result, "dns_rdatalist_tordataset");
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence result = dns_db_addrdataset(db, node, version, 0, &sigset,
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence 0, NULL);
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence if (result == DNS_R_UNCHANGED)
64e41159a919b0711321fe688ca5da4f4d1b7d80Bob Halley result = ISC_R_SUCCESS;
8a9b755d32a4f6ace792ac3fd17c968cf96d2487David Lawrence check_result(result, "dns_db_addrdataset");
64e41159a919b0711321fe688ca5da4f4d1b7d80Bob Halley dns_rdataset_disassociate(&sigset);
64e41159a919b0711321fe688ca5da4f4d1b7d80Bob Halley }
64e41159a919b0711321fe688ca5da4f4d1b7d80Bob Halley else if (!nosigs) {
64e41159a919b0711321fe688ca5da4f4d1b7d80Bob Halley#if 0
64e41159a919b0711321fe688ca5da4f4d1b7d80Bob Halley /*
64e41159a919b0711321fe688ca5da4f4d1b7d80Bob Halley * If this is compiled in, running a signed set through the
64e41159a919b0711321fe688ca5da4f4d1b7d80Bob Halley * signer with no private keys causes DNS_R_BADDB to occur
64e41159a919b0711321fe688ca5da4f4d1b7d80Bob Halley * later. This is bad.
64e41159a919b0711321fe688ca5da4f4d1b7d80Bob Halley */
64e41159a919b0711321fe688ca5da4f4d1b7d80Bob Halley result = dns_db_deleterdataset(db, node, version,
64e41159a919b0711321fe688ca5da4f4d1b7d80Bob Halley dns_rdatatype_sig, set->type);
64e41159a919b0711321fe688ca5da4f4d1b7d80Bob Halley if (result == ISC_R_NOTFOUND)
64e41159a919b0711321fe688ca5da4f4d1b7d80Bob Halley result = ISC_R_SUCCESS;
64e41159a919b0711321fe688ca5da4f4d1b7d80Bob Halley check_result(result, "dns_db_deleterdataset");
64e41159a919b0711321fe688ca5da4f4d1b7d80Bob Halley#endif
64e41159a919b0711321fe688ca5da4f4d1b7d80Bob Halley fatal("File is currently signed but no private keys were "
64e41159a919b0711321fe688ca5da4f4d1b7d80Bob Halley "found. This won't work.");
64e41159a919b0711321fe688ca5da4f4d1b7d80Bob Halley }
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence trdata = ISC_LIST_HEAD(siglist.rdata);
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence while (trdata != NULL) {
7bb707a34778fc4bd9624d6c5de95675424ea59fDavid Lawrence dns_rdata_t *next = ISC_LIST_NEXT(trdata, link);
7bb707a34778fc4bd9624d6c5de95675424ea59fDavid Lawrence isc_mem_put(mctx, trdata, sizeof(dns_rdata_t));
7bb707a34778fc4bd9624d6c5de95675424ea59fDavid Lawrence trdata = next;
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence }
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence tdata = ISC_LIST_HEAD(arraylist);
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence while (tdata != NULL) {
7bb707a34778fc4bd9624d6c5de95675424ea59fDavid Lawrence signer_array_t *next = ISC_LIST_NEXT(tdata, link);
7bb707a34778fc4bd9624d6c5de95675424ea59fDavid Lawrence isc_mem_put(mctx, tdata, sizeof(signer_array_t));
7bb707a34778fc4bd9624d6c5de95675424ea59fDavid Lawrence tdata = next;
7bb707a34778fc4bd9624d6c5de95675424ea59fDavid Lawrence }
c0ef1acf49b383d8b6d3742cb963f7d08f5762e3Andreas Gustafsson}
c0ef1acf49b383d8b6d3742cb963f7d08f5762e3Andreas Gustafsson
c0ef1acf49b383d8b6d3742cb963f7d08f5762e3Andreas Gustafsson#ifndef USE_ZONESTATUS
7bb707a34778fc4bd9624d6c5de95675424ea59fDavid Lawrence/* Determine if a KEY set contains a null key */
7bb707a34778fc4bd9624d6c5de95675424ea59fDavid Lawrencestatic isc_boolean_t
7bb707a34778fc4bd9624d6c5de95675424ea59fDavid Lawrencehasnullkey(dns_rdataset_t *rdataset) {
7bb707a34778fc4bd9624d6c5de95675424ea59fDavid Lawrence isc_result_t result;
7bb707a34778fc4bd9624d6c5de95675424ea59fDavid Lawrence dns_rdata_t rdata;
7bb707a34778fc4bd9624d6c5de95675424ea59fDavid Lawrence isc_boolean_t found = ISC_FALSE;
7bb707a34778fc4bd9624d6c5de95675424ea59fDavid Lawrence
7bb707a34778fc4bd9624d6c5de95675424ea59fDavid Lawrence result = dns_rdataset_first(rdataset);
7bb707a34778fc4bd9624d6c5de95675424ea59fDavid Lawrence while (result == ISC_R_SUCCESS) {
7bb707a34778fc4bd9624d6c5de95675424ea59fDavid Lawrence dst_key_t *key = NULL;
7bb707a34778fc4bd9624d6c5de95675424ea59fDavid Lawrence
7bb707a34778fc4bd9624d6c5de95675424ea59fDavid Lawrence dns_rdataset_current(rdataset, &rdata);
7bb707a34778fc4bd9624d6c5de95675424ea59fDavid Lawrence result = dns_dnssec_keyfromrdata(dns_rootname,
35c842e05dc6382ce1d9161a658d3ff4b2c3d4c9Bob Halley &rdata, mctx, &key);
35c842e05dc6382ce1d9161a658d3ff4b2c3d4c9Bob Halley if (result != ISC_R_SUCCESS)
7bb707a34778fc4bd9624d6c5de95675424ea59fDavid Lawrence fatal("could not convert KEY into internal format");
7bb707a34778fc4bd9624d6c5de95675424ea59fDavid Lawrence if (dst_key_isnullkey(key))
7bb707a34778fc4bd9624d6c5de95675424ea59fDavid Lawrence found = ISC_TRUE;
35c842e05dc6382ce1d9161a658d3ff4b2c3d4c9Bob Halley dst_key_free(key);
7bb707a34778fc4bd9624d6c5de95675424ea59fDavid Lawrence if (found == ISC_TRUE)
7bb707a34778fc4bd9624d6c5de95675424ea59fDavid Lawrence return (ISC_TRUE);
7bb707a34778fc4bd9624d6c5de95675424ea59fDavid Lawrence result = dns_rdataset_next(rdataset);
7bb707a34778fc4bd9624d6c5de95675424ea59fDavid Lawrence }
7bb707a34778fc4bd9624d6c5de95675424ea59fDavid Lawrence if (result != ISC_R_NOMORE)
7bb707a34778fc4bd9624d6c5de95675424ea59fDavid Lawrence fatal("failure looking for null keys");
7bb707a34778fc4bd9624d6c5de95675424ea59fDavid Lawrence return (ISC_FALSE);
51917258dbb23cfe6069ae1cf2b7fc5aefc1e0c2Bob Halley}
35c842e05dc6382ce1d9161a658d3ff4b2c3d4c9Bob Halley#endif
0fde58a7673f28fcc08eb8f597581247a4c2db20Bob Halley
0fde58a7673f28fcc08eb8f597581247a4c2db20Bob Halley/*
0fde58a7673f28fcc08eb8f597581247a4c2db20Bob Halley * Looks for signatures of the zone keys by the parent, and imports them
0fde58a7673f28fcc08eb8f597581247a4c2db20Bob Halley * if found.
0fde58a7673f28fcc08eb8f597581247a4c2db20Bob Halley */
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrencestatic void
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrenceimportparentsig(dns_db_t *db, dns_dbversion_t *version, dns_dbnode_t *node,
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence dns_name_t *name, dns_rdataset_t *set)
8a9b755d32a4f6ace792ac3fd17c968cf96d2487David Lawrence{
8a9b755d32a4f6ace792ac3fd17c968cf96d2487David Lawrence unsigned char filename[256];
8a9b755d32a4f6ace792ac3fd17c968cf96d2487David Lawrence isc_buffer_t b;
8a9b755d32a4f6ace792ac3fd17c968cf96d2487David Lawrence isc_region_t r;
8a9b755d32a4f6ace792ac3fd17c968cf96d2487David Lawrence dns_db_t *newdb = NULL;
8a9b755d32a4f6ace792ac3fd17c968cf96d2487David Lawrence dns_dbnode_t *newnode = NULL;
8a9b755d32a4f6ace792ac3fd17c968cf96d2487David Lawrence dns_rdataset_t newset, sigset;
8a9b755d32a4f6ace792ac3fd17c968cf96d2487David Lawrence dns_rdata_t rdata, newrdata;
8a9b755d32a4f6ace792ac3fd17c968cf96d2487David Lawrence isc_result_t result;
8a9b755d32a4f6ace792ac3fd17c968cf96d2487David Lawrence
8a9b755d32a4f6ace792ac3fd17c968cf96d2487David Lawrence isc_buffer_init(&b, filename, sizeof(filename) - 10);
8a9b755d32a4f6ace792ac3fd17c968cf96d2487David Lawrence result = dns_name_totext(name, ISC_FALSE, &b);
8a9b755d32a4f6ace792ac3fd17c968cf96d2487David Lawrence check_result(result, "dns_name_totext()");
8a9b755d32a4f6ace792ac3fd17c968cf96d2487David Lawrence isc_buffer_usedregion(&b, &r);
8a9b755d32a4f6ace792ac3fd17c968cf96d2487David Lawrence strcpy((char *)r.base + r.length, "signedkey");
8a9b755d32a4f6ace792ac3fd17c968cf96d2487David Lawrence result = dns_db_create(mctx, "rbt", name, ISC_FALSE, dns_db_class(db),
8a9b755d32a4f6ace792ac3fd17c968cf96d2487David Lawrence 0, NULL, &newdb);
8a9b755d32a4f6ace792ac3fd17c968cf96d2487David Lawrence check_result(result, "dns_db_create()");
7bb707a34778fc4bd9624d6c5de95675424ea59fDavid Lawrence result = dns_db_load(newdb, (char *)filename);
8a9b755d32a4f6ace792ac3fd17c968cf96d2487David Lawrence if (result != ISC_R_SUCCESS)
8a9b755d32a4f6ace792ac3fd17c968cf96d2487David Lawrence goto failure;
8a9b755d32a4f6ace792ac3fd17c968cf96d2487David Lawrence result = dns_db_findnode(newdb, name, ISC_FALSE, &newnode);
8a9b755d32a4f6ace792ac3fd17c968cf96d2487David Lawrence if (result != ISC_R_SUCCESS)
e32971f6c437485d21245d8a4a96af643b73eef4David Lawrence goto failure;
8a9b755d32a4f6ace792ac3fd17c968cf96d2487David Lawrence dns_rdataset_init(&newset);
8a9b755d32a4f6ace792ac3fd17c968cf96d2487David Lawrence dns_rdataset_init(&sigset);
8a9b755d32a4f6ace792ac3fd17c968cf96d2487David Lawrence result = dns_db_findrdataset(newdb, newnode, NULL, dns_rdatatype_key,
8a9b755d32a4f6ace792ac3fd17c968cf96d2487David Lawrence 0, 0, &newset, &sigset);
8a9b755d32a4f6ace792ac3fd17c968cf96d2487David Lawrence if (result != ISC_R_SUCCESS)
8a9b755d32a4f6ace792ac3fd17c968cf96d2487David Lawrence goto failure;
8a9b755d32a4f6ace792ac3fd17c968cf96d2487David Lawrence
8a9b755d32a4f6ace792ac3fd17c968cf96d2487David Lawrence if (dns_rdataset_count(set) != dns_rdataset_count(&newset))
8a9b755d32a4f6ace792ac3fd17c968cf96d2487David Lawrence goto failure;
8a9b755d32a4f6ace792ac3fd17c968cf96d2487David Lawrence
8a9b755d32a4f6ace792ac3fd17c968cf96d2487David Lawrence dns_rdata_init(&rdata);
8a9b755d32a4f6ace792ac3fd17c968cf96d2487David Lawrence dns_rdata_init(&newrdata);
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence result = dns_rdataset_first(set);
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence check_result(result, "dns_rdataset_first()");
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence for (; result == ISC_R_SUCCESS; result = dns_rdataset_next(set)) {
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence dns_rdataset_current(set, &rdata);
a456d4c310a791cc83edc995afdf7190f7c7296bBob Halley result = dns_rdataset_first(&newset);
51917258dbb23cfe6069ae1cf2b7fc5aefc1e0c2Bob Halley check_result(result, "dns_rdataset_first()");
64e41159a919b0711321fe688ca5da4f4d1b7d80Bob Halley for (;
694c897b20f06f8a5349fd9ac5df93947f6f5a2aBob Halley result == ISC_R_SUCCESS;
51917258dbb23cfe6069ae1cf2b7fc5aefc1e0c2Bob Halley result = dns_rdataset_next(&newset))
64e41159a919b0711321fe688ca5da4f4d1b7d80Bob Halley {
a456d4c310a791cc83edc995afdf7190f7c7296bBob Halley dns_rdataset_current(&newset, &newrdata);
51917258dbb23cfe6069ae1cf2b7fc5aefc1e0c2Bob Halley if (dns_rdata_compare(&rdata, &newrdata) == 0)
64e41159a919b0711321fe688ca5da4f4d1b7d80Bob Halley break;
694c897b20f06f8a5349fd9ac5df93947f6f5a2aBob Halley }
51917258dbb23cfe6069ae1cf2b7fc5aefc1e0c2Bob Halley if (result != ISC_R_SUCCESS)
64e41159a919b0711321fe688ca5da4f4d1b7d80Bob Halley break;
a456d4c310a791cc83edc995afdf7190f7c7296bBob Halley }
51917258dbb23cfe6069ae1cf2b7fc5aefc1e0c2Bob Halley if (result != ISC_R_NOMORE)
64e41159a919b0711321fe688ca5da4f4d1b7d80Bob Halley goto failure;
694c897b20f06f8a5349fd9ac5df93947f6f5a2aBob Halley
51917258dbb23cfe6069ae1cf2b7fc5aefc1e0c2Bob Halley vbprintf(2, "found the parent's signature of our zone key\n");
64e41159a919b0711321fe688ca5da4f4d1b7d80Bob Halley
1bb509f58b57f1d9ef413762fb9e3dd2bcaf7ed4Mark Andrews result = dns_db_addrdataset(db, node, version, 0, &sigset, 0, NULL);
1bb509f58b57f1d9ef413762fb9e3dd2bcaf7ed4Mark Andrews check_result(result, "dns_db_addrdataset");
1bb509f58b57f1d9ef413762fb9e3dd2bcaf7ed4Mark Andrews dns_rdataset_disassociate(&newset);
1bb509f58b57f1d9ef413762fb9e3dd2bcaf7ed4Mark Andrews dns_rdataset_disassociate(&sigset);
1bb509f58b57f1d9ef413762fb9e3dd2bcaf7ed4Mark Andrews
affd6c025b39ec89a91056efb084fff7239ad6e3Mark Andrews failure:
51917258dbb23cfe6069ae1cf2b7fc5aefc1e0c2Bob Halley if (newnode != NULL)
f7bf83d0cc099e754327f8da8c4d6d320da1de01Mark Andrews dns_db_detachnode(newdb, &newnode);
f7bf83d0cc099e754327f8da8c4d6d320da1de01Mark Andrews if (newdb != NULL)
51917258dbb23cfe6069ae1cf2b7fc5aefc1e0c2Bob Halley dns_db_detach(&newdb);
51917258dbb23cfe6069ae1cf2b7fc5aefc1e0c2Bob Halley}
51917258dbb23cfe6069ae1cf2b7fc5aefc1e0c2Bob Halley
51917258dbb23cfe6069ae1cf2b7fc5aefc1e0c2Bob Halley/*
51a659eb711eb6a17891675d3de6b8085a766ab2Mark Andrews * Looks for our signatures of child keys. If present, inform the caller,
51917258dbb23cfe6069ae1cf2b7fc5aefc1e0c2Bob Halley * who will set the zone status (KEY) bit in the NXT record.
694c897b20f06f8a5349fd9ac5df93947f6f5a2aBob Halley */
694c897b20f06f8a5349fd9ac5df93947f6f5a2aBob Halleystatic isc_boolean_t
8a1930d026517e4733d680ac51abeb01353332c4Mark Andrewshaschildkey(dns_db_t *db, dns_name_t *name) {
8a1930d026517e4733d680ac51abeb01353332c4Mark Andrews unsigned char filename[256];
8a1930d026517e4733d680ac51abeb01353332c4Mark Andrews isc_buffer_t b;
8a1930d026517e4733d680ac51abeb01353332c4Mark Andrews isc_region_t r;
8a1930d026517e4733d680ac51abeb01353332c4Mark Andrews dns_db_t *newdb = NULL;
8a1930d026517e4733d680ac51abeb01353332c4Mark Andrews dns_dbnode_t *newnode = NULL;
8a1930d026517e4733d680ac51abeb01353332c4Mark Andrews dns_rdataset_t set, sigset;
8a1930d026517e4733d680ac51abeb01353332c4Mark Andrews dns_rdata_t sigrdata;
8a1930d026517e4733d680ac51abeb01353332c4Mark Andrews isc_result_t result;
5c00d1c90030a311d2700970fa7cffc8f828a48cBob Halley isc_boolean_t found = ISC_FALSE;
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence dns_rdata_sig_t sig;
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence signer_key_t *key;
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence
5c00d1c90030a311d2700970fa7cffc8f828a48cBob Halley isc_buffer_init(&b, filename, sizeof(filename) - 10);
5c00d1c90030a311d2700970fa7cffc8f828a48cBob Halley result = dns_name_totext(name, ISC_FALSE, &b);
5c00d1c90030a311d2700970fa7cffc8f828a48cBob Halley check_result(result, "dns_name_totext()");
5c00d1c90030a311d2700970fa7cffc8f828a48cBob Halley isc_buffer_usedregion(&b, &r);
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence strcpy((char *)r.base + r.length, "signedkey");
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence result = dns_db_create(mctx, "rbt", name, ISC_FALSE, dns_db_class(db),
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence 0, NULL, &newdb);
6d5dcd0dc9bdbd679282b1ffc47987d24c3a1346Bob Halley check_result(result, "dns_db_create()");
6d5dcd0dc9bdbd679282b1ffc47987d24c3a1346Bob Halley result = dns_db_load(newdb, (char *)filename);
6d5dcd0dc9bdbd679282b1ffc47987d24c3a1346Bob Halley if (result != ISC_R_SUCCESS)
51917258dbb23cfe6069ae1cf2b7fc5aefc1e0c2Bob Halley goto failure;
51917258dbb23cfe6069ae1cf2b7fc5aefc1e0c2Bob Halley result = dns_db_findnode(newdb, name, ISC_FALSE, &newnode);
4bcaefbcd3ced942139fdc830e007c6ea2b8d2feDavid Lawrence if (result != ISC_R_SUCCESS)
a3ab70dae26d009bf78b0594b2ab5eb9208f4b91Michael Graff goto failure;
51917258dbb23cfe6069ae1cf2b7fc5aefc1e0c2Bob Halley dns_rdataset_init(&set);
51917258dbb23cfe6069ae1cf2b7fc5aefc1e0c2Bob Halley dns_rdataset_init(&sigset);
51917258dbb23cfe6069ae1cf2b7fc5aefc1e0c2Bob Halley result = dns_db_findrdataset(newdb, newnode, NULL, dns_rdatatype_key,
4bcaefbcd3ced942139fdc830e007c6ea2b8d2feDavid Lawrence 0, 0, &set, &sigset);
a3ab70dae26d009bf78b0594b2ab5eb9208f4b91Michael Graff if (result != ISC_R_SUCCESS)
51917258dbb23cfe6069ae1cf2b7fc5aefc1e0c2Bob Halley goto failure;
51917258dbb23cfe6069ae1cf2b7fc5aefc1e0c2Bob Halley
51917258dbb23cfe6069ae1cf2b7fc5aefc1e0c2Bob Halley if (!dns_rdataset_isassociated(&set) ||
4bcaefbcd3ced942139fdc830e007c6ea2b8d2feDavid Lawrence !dns_rdataset_isassociated(&sigset))
a3ab70dae26d009bf78b0594b2ab5eb9208f4b91Michael Graff goto disfail;
51917258dbb23cfe6069ae1cf2b7fc5aefc1e0c2Bob Halley
51917258dbb23cfe6069ae1cf2b7fc5aefc1e0c2Bob Halley result = dns_rdataset_first(&sigset);
51917258dbb23cfe6069ae1cf2b7fc5aefc1e0c2Bob Halley check_result(result, "dns_rdataset_first()");
51917258dbb23cfe6069ae1cf2b7fc5aefc1e0c2Bob Halley dns_rdata_init(&sigrdata);
51917258dbb23cfe6069ae1cf2b7fc5aefc1e0c2Bob Halley for (; result == ISC_R_SUCCESS; result = dns_rdataset_next(&sigset)) {
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley dns_rdataset_current(&sigset, &sigrdata);
6d5dcd0dc9bdbd679282b1ffc47987d24c3a1346Bob Halley result = dns_rdata_tostruct(&sigrdata, &sig, mctx);
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley if (result != ISC_R_SUCCESS)
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley goto disfail;
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley key = keythatsigned(&sig);
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley dns_rdata_freestruct(&sig);
64e41159a919b0711321fe688ca5da4f4d1b7d80Bob Halley if (key == NULL)
64e41159a919b0711321fe688ca5da4f4d1b7d80Bob Halley goto disfail;
64e41159a919b0711321fe688ca5da4f4d1b7d80Bob Halley result = dns_dnssec_verify(name, &set, key->key,
64e41159a919b0711321fe688ca5da4f4d1b7d80Bob Halley ISC_FALSE, mctx, &sigrdata);
64e41159a919b0711321fe688ca5da4f4d1b7d80Bob Halley if (result == ISC_R_SUCCESS) {
64e41159a919b0711321fe688ca5da4f4d1b7d80Bob Halley found = ISC_TRUE;
860728724ad298f60d5c6e7485d37c3b2b1ad632David Lawrence break;
860728724ad298f60d5c6e7485d37c3b2b1ad632David Lawrence }
860728724ad298f60d5c6e7485d37c3b2b1ad632David Lawrence }
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley
9fbc1afb8b08432e3a1adda1f41d5575620e9785Bob Halley disfail:
51917258dbb23cfe6069ae1cf2b7fc5aefc1e0c2Bob Halley if (dns_rdataset_isassociated(&set))
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley dns_rdataset_disassociate(&set);
9fbc1afb8b08432e3a1adda1f41d5575620e9785Bob Halley if (dns_rdataset_isassociated(&sigset))
694c897b20f06f8a5349fd9ac5df93947f6f5a2aBob Halley dns_rdataset_disassociate(&sigset);
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley failure:
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley if (newnode != NULL)
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley dns_db_detachnode(newdb, &newnode);
51917258dbb23cfe6069ae1cf2b7fc5aefc1e0c2Bob Halley if (newdb != NULL)
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley dns_db_detach(&newdb);
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley return (found);
d8dcd6ad4617cc8d7df979bd62101fa9c4bac1bcBob Halley}
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley/*
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley * Signs all records at a name. This mostly just signs each set individually,
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley * but also adds the SIG bit to any NXTs generated earlier, deals with
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley * parent/child KEY signatures, and handles other exceptional cases.
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley */
65c4736d9c0ebc6d9b1d991593b55566909da9cdBrian Wellingtonstatic void
65c4736d9c0ebc6d9b1d991593b55566909da9cdBrian Wellingtonsignname(dns_db_t *db, dns_dbversion_t *version, dns_dbnode_t *node,
65c4736d9c0ebc6d9b1d991593b55566909da9cdBrian Wellington dns_name_t *name, isc_boolean_t atorigin)
65c4736d9c0ebc6d9b1d991593b55566909da9cdBrian Wellington{
65c4736d9c0ebc6d9b1d991593b55566909da9cdBrian Wellington isc_result_t result;
65c4736d9c0ebc6d9b1d991593b55566909da9cdBrian Wellington dns_rdata_t rdata;
65c4736d9c0ebc6d9b1d991593b55566909da9cdBrian Wellington dns_rdataset_t rdataset;
65c4736d9c0ebc6d9b1d991593b55566909da9cdBrian Wellington dns_rdatasetiter_t *rdsiter;
f8e602a972e393cdacadd9852e0965bf1105dc7bMark Andrews isc_boolean_t isdelegation = ISC_FALSE;
c68fa795a1c87fd5d0386e0503dc5666490ac77fMichael Graff isc_boolean_t childkey = ISC_FALSE;
c68fa795a1c87fd5d0386e0503dc5666490ac77fMichael Graff static int warnwild = 0;
c68fa795a1c87fd5d0386e0503dc5666490ac77fMichael Graff
c7620c99f1139b77f14678e21a44f7c8c4236a7bMark Andrews if (dns_name_iswildcard(name)) {
35c842e05dc6382ce1d9161a658d3ff4b2c3d4c9Bob Halley if (warnwild++ == 0)
860728724ad298f60d5c6e7485d37c3b2b1ad632David Lawrence fprintf(stderr, "%s: warning: BIND 9 doesn't "
860728724ad298f60d5c6e7485d37c3b2b1ad632David Lawrence "handle wildcards in secure zones\n", PROGRAM);
860728724ad298f60d5c6e7485d37c3b2b1ad632David Lawrence else
44aae046c38e796e581110b7ecdf4478167d684dBob Halley fprintf(stderr, "%s: warning: wildcard name seen: %s\n",
44aae046c38e796e581110b7ecdf4478167d684dBob Halley PROGRAM, nametostr(name));
44aae046c38e796e581110b7ecdf4478167d684dBob Halley }
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley if (!atorigin) {
690a68b8112039e633e26f9216c0d463751e011aMichael Graff dns_rdataset_t nsset;
1cafbcfa6f7560597e577f78795143b4964464d9Bob Halley
6448ffb2b9ec7ebf79897941629b225ec1431666Michael Graff dns_rdataset_init(&nsset);
12ccbb032ec1b5f6b93aac923f2645a19fc90c75David Lawrence result = dns_db_findrdataset(db, node, version,
44aae046c38e796e581110b7ecdf4478167d684dBob Halley dns_rdatatype_ns, 0, 0, &nsset,
44aae046c38e796e581110b7ecdf4478167d684dBob Halley NULL);
44aae046c38e796e581110b7ecdf4478167d684dBob Halley /* Is this a delegation point? */
44aae046c38e796e581110b7ecdf4478167d684dBob Halley if (result == ISC_R_SUCCESS) {
297a9ce042b977f2e4eb3b3e4bf9e7b72f96d640William King isdelegation = ISC_TRUE;
297a9ce042b977f2e4eb3b3e4bf9e7b72f96d640William King dns_rdataset_disassociate(&nsset);
297a9ce042b977f2e4eb3b3e4bf9e7b72f96d640William King }
65c4736d9c0ebc6d9b1d991593b55566909da9cdBrian Wellington }
a9f861e65b6544e16c23a44b239d80436b3e0414William King dns_rdataset_init(&rdataset);
683da0cd900532fc45fa4dfb687b5041156ec8abAndreas Gustafsson rdsiter = NULL;
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley result = dns_db_allrdatasets(db, node, version, 0, &rdsiter);
check_result(result, "dns_db_allrdatasets()");
result = dns_rdatasetiter_first(rdsiter);
while (result == ISC_R_SUCCESS) {
dns_rdatasetiter_current(rdsiter, &rdataset);
/* If this is a SIG set, skip it. */
if (rdataset.type == dns_rdatatype_sig)
goto skip;
/*
* If this is a KEY set at the apex, look for a signedkey file.
*/
if (rdataset.type == dns_rdatatype_key && atorigin) {
importparentsig(db, version, node, name, &rdataset);
goto skip;
}
/*
* If this name is a delegation point, skip all records
* except an NXT set, unless we're using null keys, in
* which case we need to check for a null key and add one
* if it's not present.
*/
if (isdelegation) {
switch (rdataset.type) {
case dns_rdatatype_nxt:
childkey = haschildkey(db, name);
break;
#ifndef USE_ZONESTATUS
case dns_rdatatype_key:
if (hasnullkey(&rdataset))
break;
goto skip;
#endif
default:
goto skip;
}
}
/*
* There probably should be a dns_nxtsetbit, but it can get
* complicated if we need to extend the length of the
* bit set. In this case, since the NXT bit is set and
* SIG < NXT and KEY < NXT, the easy way works.
*/
if (rdataset.type == dns_rdatatype_nxt) {
unsigned char *nxt_bits;
dns_name_t nxtname;
isc_region_t r, r2;
unsigned char keydata[4];
dst_key_t *dstkey;
isc_buffer_t b;
result = dns_rdataset_first(&rdataset);
check_result(result, "dns_rdataset_first()");
dns_rdataset_current(&rdataset, &rdata);
dns_rdata_toregion(&rdata, &r);
dns_name_init(&nxtname, NULL);
dns_name_fromregion(&nxtname, &r);
dns_name_toregion(&nxtname, &r2);
nxt_bits = r.base + r2.length;
set_bit(nxt_bits, dns_rdatatype_sig, 1);
#ifdef USE_ZONESTATUS
if (isdelegation && childkey) {
set_bit(nxt_bits, dns_rdatatype_key, 1);
vbprintf(2, "found a child key for %s, "
"setting KEY bit in NXT\n",
nametostr(name));
}
#else
if (isdelegation && !childkey) {
dns_rdataset_t keyset;
dns_rdatalist_t keyrdatalist;
dns_rdata_t keyrdata;
dns_rdataset_init(&keyset);
result = dns_db_findrdataset(db, node, version,
dns_rdatatype_key,
0, 0, &keyset,
NULL);
if (result == ISC_R_SUCCESS &&
hasnullkey(&keyset))
goto alreadyhavenullkey;
if (result == ISC_R_NOTFOUND)
result = ISC_R_SUCCESS;
if (result != ISC_R_SUCCESS)
fatal("failure looking for null key "
"at '%s': %s", nametostr(name),
isc_result_totext(result));
if (dns_rdataset_isassociated(&keyset))
dns_rdataset_disassociate(&keyset);
vbprintf(2, "no child key for %s, "
"adding null key\n",
nametostr(name));
dns_rdatalist_init(&keyrdatalist);
dstkey = NULL;
result = dst_key_generate("", DNS_KEYALG_DSA,
0, 0,
DNS_KEYTYPE_NOKEY,
DNS_KEYPROTO_DNSSEC,
mctx, &dstkey);
if (result != ISC_R_SUCCESS)
fatal("failed to generate null key");
isc_buffer_init(&b, keydata, sizeof keydata);
result = dst_key_todns(dstkey, &b);
dst_key_free(dstkey);
isc_buffer_usedregion(&b, &r);
dns_rdata_fromregion(&keyrdata,
rdataset.rdclass,
dns_rdatatype_key, &r);
ISC_LIST_APPEND(keyrdatalist.rdata, &keyrdata,
link);
keyrdatalist.rdclass = rdataset.rdclass;
keyrdatalist.type = dns_rdatatype_key;
keyrdatalist.covers = 0;
keyrdatalist.ttl = rdataset.ttl;
result =
dns_rdatalist_tordataset(&keyrdatalist,
&keyset);
check_result(result,
"dns_rdatalist_tordataset");
dns_db_addrdataset(db, node, version, 0,
&keyset, DNS_DBADD_MERGE,
NULL);
set_bit(nxt_bits, dns_rdatatype_key, 1);
signset(db, version, node, name, &keyset);
dns_rdataset_disassociate(&keyset);
alreadyhavenullkey:
;
}
#endif
}
signset(db, version, node, name, &rdataset);
skip:
dns_rdataset_disassociate(&rdataset);
result = dns_rdatasetiter_next(rdsiter);
}
if (result != ISC_R_NOMORE)
fatal("rdataset iteration for name '%s' failed: %s",
nametostr(name), isc_result_totext(result));
dns_rdatasetiter_destroy(&rdsiter);
}
static inline isc_boolean_t
active_node(dns_db_t *db, dns_dbversion_t *version, dns_dbnode_t *node) {
dns_rdatasetiter_t *rdsiter;
isc_boolean_t active = ISC_FALSE;
isc_result_t result;
dns_rdataset_t rdataset;
dns_rdataset_init(&rdataset);
rdsiter = NULL;
result = dns_db_allrdatasets(db, node, version, 0, &rdsiter);
check_result(result, "dns_db_allrdatasets()");
result = dns_rdatasetiter_first(rdsiter);
while (result == ISC_R_SUCCESS) {
dns_rdatasetiter_current(rdsiter, &rdataset);
if (rdataset.type != dns_rdatatype_nxt)
active = ISC_TRUE;
dns_rdataset_disassociate(&rdataset);
if (!active)
result = dns_rdatasetiter_next(rdsiter);
else
result = ISC_R_NOMORE;
}
if (result != ISC_R_NOMORE)
fatal("rdataset iteration failed: %s",
isc_result_totext(result));
dns_rdatasetiter_destroy(&rdsiter);
if (!active) {
/*
* Make sure there is no NXT record for this node.
*/
result = dns_db_deleterdataset(db, node, version,
dns_rdatatype_nxt, 0);
if (result == DNS_R_UNCHANGED)
result = ISC_R_SUCCESS;
check_result(result, "dns_db_deleterdataset");
}
return (active);
}
static inline isc_result_t
next_active(dns_db_t *db, dns_dbversion_t *version, dns_dbiterator_t *dbiter,
dns_name_t *name, dns_dbnode_t **nodep)
{
isc_result_t result;
isc_boolean_t active;
do {
active = ISC_FALSE;
result = dns_dbiterator_current(dbiter, nodep, name);
if (result == ISC_R_SUCCESS) {
active = active_node(db, version, *nodep);
if (!active) {
dns_db_detachnode(db, nodep);
result = dns_dbiterator_next(dbiter);
}
}
} while (result == ISC_R_SUCCESS && !active);
return (result);
}
static inline isc_result_t
next_nonglue(dns_db_t *db, dns_dbversion_t *version, dns_dbiterator_t *dbiter,
dns_name_t *name, dns_dbnode_t **nodep, dns_name_t *origin,
dns_name_t *lastcut)
{
isc_result_t result;
do {
result = next_active(db, version, dbiter, name, nodep);
if (result == ISC_R_SUCCESS) {
if (dns_name_issubdomain(name, origin) &&
(lastcut == NULL ||
!dns_name_issubdomain(name, lastcut)))
return (ISC_R_SUCCESS);
dns_db_detachnode(db, nodep);
result = dns_dbiterator_next(dbiter);
}
} while (result == ISC_R_SUCCESS);
return (result);
}
/*
* Generates NXTs and SIGs for each non-glue name in the zone.
*/
static void
signzone(dns_db_t *db, dns_dbversion_t *version) {
isc_result_t result, nxtresult;
dns_dbnode_t *node, *nextnode, *curnode;
dns_fixedname_t fname, fnextname, fcurname;
dns_name_t *name, *nextname, *target, *curname, *lastcut;
dns_dbiterator_t *dbiter;
isc_boolean_t atorigin = ISC_TRUE;
dns_name_t *origin;
dns_rdataset_t soaset;
dns_rdata_t soarr;
dns_rdata_soa_t soa;
dns_ttl_t zonettl;
dns_fixedname_init(&fname);
name = dns_fixedname_name(&fname);
dns_fixedname_init(&fnextname);
nextname = dns_fixedname_name(&fnextname);
dns_fixedname_init(&fcurname);
curname = dns_fixedname_name(&fcurname);
origin = dns_db_origin(db);
dns_rdataset_init(&soaset);
result = dns_db_find(db, origin, version, dns_rdatatype_soa,
0, 0, NULL, name, &soaset, NULL);
if (result != ISC_R_SUCCESS)
fatal("failed to find '%s SOA' in the zone: %s",
nametostr(name), isc_result_totext(result));
result = dns_rdataset_first(&soaset);
check_result(result, "dns_rdataset_first()");
dns_rdataset_current(&soaset, &soarr);
result = dns_rdata_tostruct(&soarr, &soa, mctx);
check_result(result, "dns_rdataset_tostruct()");
zonettl = soa.minimum;
dns_rdata_freestruct(&soa);
dns_rdataset_disassociate(&soaset);
lastcut = NULL;
dbiter = NULL;
result = dns_db_createiterator(db, ISC_FALSE, &dbiter);
check_result(result, "dns_db_createiterator()");
result = dns_dbiterator_first(dbiter);
node = NULL;
dns_name_clone(origin, name);
result = next_nonglue(db, version, dbiter, name, &node, origin,
lastcut);
while (result == ISC_R_SUCCESS) {
nextnode = NULL;
curnode = NULL;
dns_dbiterator_current(dbiter, &curnode, curname);
if (!atorigin) {
dns_rdatasetiter_t *rdsiter = NULL;
dns_rdataset_t set;
dns_rdataset_init(&set);
result = dns_db_allrdatasets(db, curnode, version,
0, &rdsiter);
check_result(result, "dns_db_allrdatasets");
result = dns_rdatasetiter_first(rdsiter);
while (result == ISC_R_SUCCESS) {
dns_rdatasetiter_current(rdsiter, &set);
if (set.type == dns_rdatatype_ns) {
dns_rdataset_disassociate(&set);
break;
}
dns_rdataset_disassociate(&set);
result = dns_rdatasetiter_next(rdsiter);
}
if (result != ISC_R_SUCCESS && result != ISC_R_NOMORE)
fatal("rdataset iteration failed: %s",
isc_result_totext(result));
if (result == ISC_R_SUCCESS) {
if (lastcut != NULL)
dns_name_free(lastcut, mctx);
else {
lastcut = isc_mem_get(mctx,
sizeof(dns_name_t));
if (lastcut == NULL)
fatal("out of memory");
}
dns_name_init(lastcut, NULL);
result = dns_name_dup(curname, mctx, lastcut);
check_result(result, "dns_name_dup()");
}
dns_rdatasetiter_destroy(&rdsiter);
}
result = dns_dbiterator_next(dbiter);
if (result == ISC_R_SUCCESS)
result = next_nonglue(db, version, dbiter, nextname,
&nextnode, origin, lastcut);
if (result == ISC_R_SUCCESS)
target = nextname;
else if (result == ISC_R_NOMORE)
target = origin;
else {
target = NULL; /* Make compiler happy. */
fatal("iterating through the database failed: %s",
isc_result_totext(result));
}
nxtresult = dns_buildnxt(db, version, node, target, zonettl);
check_result(nxtresult, "dns_buildnxt()");
signname(db, version, node, curname, atorigin);
atorigin = ISC_FALSE;
dns_db_detachnode(db, &node);
dns_db_detachnode(db, &curnode);
node = nextnode;
}
if (result != ISC_R_NOMORE)
fatal("iterating through the database failed: %s",
isc_result_totext(result));
if (lastcut != NULL) {
dns_name_free(lastcut, mctx);
isc_mem_put(mctx, lastcut, sizeof(dns_name_t));
}
dns_dbiterator_destroy(&dbiter);
}
static void
loadzone(char *file, char *origin, dns_db_t **db) {
isc_buffer_t b, b2;
unsigned char namedata[1024];
int len;
dns_name_t name;
isc_result_t result;
len = strlen(origin);
isc_buffer_init(&b, origin, len);
isc_buffer_add(&b, len);
isc_buffer_init(&b2, namedata, sizeof(namedata));
dns_name_init(&name, NULL);
result = dns_name_fromtext(&name, &b, dns_rootname, ISC_FALSE, &b2);
if (result != ISC_R_SUCCESS)
fatal("failed converting name '%s' to dns format: %s",
origin, isc_result_totext(result));
result = dns_db_create(mctx, "rbt", &name, ISC_FALSE,
dns_rdataclass_in, 0, NULL, db);
check_result(result, "dns_db_create()");
result = dns_db_load(*db, file);
if (result != ISC_R_SUCCESS)
fatal("failed loading zone from '%s': %s",
file, isc_result_totext(result));
}
static void
getversion(dns_db_t *db, dns_dbversion_t **version) {
isc_result_t result;
result = dns_db_newversion(db, version);
check_result(result, "dns_db_newversion()");
}
/*
* Finds all public zone keys in the zone, and attempts to load the
* private keys from disk.
*/
static void
loadzonekeys(dns_db_t *db, dns_dbversion_t *version) {
dns_name_t *origin;
dns_dbnode_t *node;
isc_result_t result;
dst_key_t *keys[20];
unsigned int nkeys, i;
origin = dns_db_origin(db);
node = NULL;
result = dns_db_findnode(db, origin, ISC_FALSE, &node);
if (result != ISC_R_SUCCESS)
fatal("failed to find the zone's origin: %s",
isc_result_totext(result));
result = dns_dnssec_findzonekeys(db, version, node, origin, mctx,
20, keys, &nkeys);
if (result == ISC_R_NOTFOUND)
result = ISC_R_SUCCESS;
if (result != ISC_R_SUCCESS)
fatal("failed to find the zone keys: %s",
isc_result_totext(result));
for (i = 0; i < nkeys; i++) {
signer_key_t *key;
key = isc_mem_get(mctx, sizeof(signer_key_t));
if (key == NULL)
fatal("out of memory");
key->key = keys[i];
key->isdefault = ISC_FALSE;
ISC_LIST_APPEND(keylist, key, link);
}
dns_db_detachnode(db, &node);
}
static isc_stdtime_t
strtotime(char *str, isc_int64_t now, isc_int64_t base) {
isc_int64_t val, offset;
isc_result_t result;
char *endp = "";
if (str[0] == '+') {
offset = strtol(str + 1, &endp, 0);
val = base + offset;
}
else if (strncmp(str, "now+", 4) == 0) {
offset = strtol(str + 4, &endp, 0);
val = now + offset;
}
else {
result = dns_time64_fromtext(str, &val);
if (result != ISC_R_SUCCESS)
fatal("time %s must be numeric", str);
}
if (*endp != '\0')
fatal("time value %s is invalid", str);
return ((isc_stdtime_t) val);
}
static void
usage() {
fprintf(stderr, "Usage:\n");
fprintf(stderr, "\tsigner [options] zonefile [keys]\n");
fprintf(stderr, "\n");
fprintf(stderr, "Options: (default value in parenthesis) \n");
fprintf(stderr, "\t-s YYYYMMDDHHMMSS|+offset:\n");
fprintf(stderr, "\t\tSIG start time - absolute|offset (now)\n");
fprintf(stderr, "\t-e YYYYMMDDHHMMSS|+offset|\"now\"+offset]:\n");
fprintf(stderr, "\t\tSIG end time - absolute|from start|from now (now + 30 days)\n");
fprintf(stderr, "\t-c ttl:\n");
fprintf(stderr, "\t\tcycle period - regenerate "
"if < cycle from end ( (end-start)/4 )\n");
fprintf(stderr, "\t-v level:\n");
fprintf(stderr, "\t\tverbose level (0)\n");
fprintf(stderr, "\t-o origin:\n");
fprintf(stderr, "\t\tzone origin (name of zonefile)\n");
fprintf(stderr, "\t-f outfile:\n");
fprintf(stderr, "\t\tfile the signed zone is written in " \
"(zonefile + .signed)\n");
fprintf(stderr, "\t-a:\n");
fprintf(stderr, "\t\tverify generated signatures "
"(if currently valid)\n");
fprintf(stderr, "\n");
fprintf(stderr, "Signing Keys: ");
fprintf(stderr, "(default: all zone keys that have private keys)\n");
fprintf(stderr, "\tkeyfile (Kname+alg+id)\n");
exit(0);
}
static void
setup_logging(int level, isc_log_t **logp) {
isc_result_t result;
isc_logdestination_t destination;
isc_logconfig_t *logconfig;
isc_log_t *log = 0;
RUNTIME_CHECK(isc_log_create(mctx, &log, &logconfig)
== ISC_R_SUCCESS);
isc_log_setcontext(log);
dns_log_init(log);
dns_log_setcontext(log);
/*
* Set up a channel similar to default_stderr except:
* - the logging level is passed in
* - the logging level is printed
* - no time stamp is printed
*/
destination.file.stream = stderr;
destination.file.name = NULL;
destination.file.versions = ISC_LOG_ROLLNEVER;
destination.file.maximum_size = 0;
result = isc_log_createchannel(logconfig, "stderr",
ISC_LOG_TOFILEDESC,
level,
&destination,
ISC_LOG_PRINTLEVEL);
check_result(result, "isc_log_createchannel()");
RUNTIME_CHECK(isc_log_usechannel(logconfig, "stderr",
NULL, NULL) == ISC_R_SUCCESS);
*logp = log;
}
int
main(int argc, char *argv[]) {
int i, ch;
char *startstr = NULL, *endstr = NULL;
char *origin = NULL, *file = NULL, *output = NULL;
char *endp;
dns_db_t *db;
dns_dbversion_t *version;
signer_key_t *key;
isc_result_t result;
isc_log_t *log = NULL;
int loglevel;
dns_result_register();
result = isc_mem_create(0, 0, &mctx);
if (result != ISC_R_SUCCESS)
fatal("out of memory");
while ((ch = isc_commandline_parse(argc, argv, "s:e:c:v:o:f:ah"))
!= -1) {
switch (ch) {
case 's':
startstr = isc_mem_strdup(mctx,
isc_commandline_argument);
if (startstr == NULL)
fatal("out of memory");
break;
case 'e':
endstr = isc_mem_strdup(mctx,
isc_commandline_argument);
if (endstr == NULL)
fatal("out of memory");
break;
case 'c':
endp = NULL;
cycle = strtol(isc_commandline_argument, &endp, 0);
if (*endp != '\0')
fatal("cycle period must be numeric");
break;
case 'v':
endp = NULL;
verbose = strtol(isc_commandline_argument, &endp, 0);
if (*endp != '\0')
fatal("verbose level must be numeric");
break;
case 'o':
origin = isc_mem_strdup(mctx,
isc_commandline_argument);
if (origin == NULL)
fatal("out of memory");
break;
case 'f':
output = isc_mem_strdup(mctx,
isc_commandline_argument);
if (output == NULL)
fatal("out of memory");
break;
case 'a':
tryverify = ISC_TRUE;
break;
case 'h':
default:
usage();
}
}
isc_stdtime_get(&now);
if (startstr != NULL) {
starttime = strtotime(startstr, now, now);
isc_mem_free(mctx, startstr);
}
else
starttime = now;
if (endstr != NULL) {
endtime = strtotime(endstr, now, starttime);
isc_mem_free(mctx, endstr);
}
else
endtime = starttime + (30 * 24 * 60 * 60);
if (cycle == -1) {
cycle = (endtime - starttime) / 4;
}
switch (verbose) {
case 0:
/*
* We want to see warnings about things like out-of-zone
* data in the master file even when not verbose.
*/
loglevel = ISC_LOG_WARNING;
break;
case 1:
loglevel = ISC_LOG_INFO;
break;
default:
loglevel = ISC_LOG_DEBUG(verbose - 2 + 1);
break;
}
setup_logging(loglevel, &log);
argc -= isc_commandline_index;
argv += isc_commandline_index;
if (argc < 1)
usage();
file = isc_mem_strdup(mctx, argv[0]);
if (file == NULL)
fatal("out of memory");
argc -= 1;
argv += 1;
if (output == NULL) {
output = isc_mem_allocate(mctx,
strlen(file) + strlen(".signed") + 1);
if (output == NULL)
fatal("out of memory");
sprintf(output, "%s.signed", file);
}
if (origin == NULL) {
origin = isc_mem_allocate(mctx, strlen(file) + 2);
if (origin == NULL)
fatal("out of memory");
strcpy(origin, file);
if (file[strlen(file) - 1] != '.')
strcat(origin, ".");
}
db = NULL;
loadzone(file, origin, &db);
version = NULL;
getversion(db, &version);
ISC_LIST_INIT(keylist);
loadzonekeys(db, version);
if (argc == 0) {
signer_key_t *key;
key = ISC_LIST_HEAD(keylist);
while (key != NULL) {
key->isdefault = ISC_TRUE;
key = ISC_LIST_NEXT(key, link);
}
}
else {
for (i = 0; i < argc; i++) {
isc_uint16_t id;
int alg;
char *namestr = NULL;
isc_buffer_t b;
isc_buffer_init(&b, argv[i], strlen(argv[i]));
isc_buffer_add(&b, strlen(argv[i]));
result = dst_key_parsefilename(&b, mctx, &namestr,
&id, &alg, NULL);
if (result != ISC_R_SUCCESS)
usage();
key = ISC_LIST_HEAD(keylist);
while (key != NULL) {
dst_key_t *dkey = key->key;
if (dst_key_id(dkey) == id &&
dst_key_alg(dkey) == alg &&
strcasecmp(namestr,
dst_key_name(dkey)) == 0)
{
key->isdefault = ISC_TRUE;
if (!dst_key_isprivate(dkey))
fatal("cannot sign zone with "
"non-private key "
"'%s/%s/%d'",
dst_key_name(dkey),
algtostr(dst_key_alg(dkey)),
dst_key_id(dkey));
break;
}
key = ISC_LIST_NEXT(key, link);
}
if (key == NULL) {
dst_key_t *dkey = NULL;
result = dst_key_fromfile(namestr, id, alg,
DST_TYPE_PRIVATE,
mctx, &dkey);
if (result != ISC_R_SUCCESS)
fatal("failed to load key '%s/%s/%d' "
"from disk: %s", namestr,
algtostr(alg), id,
isc_result_totext(result));
key = isc_mem_get(mctx, sizeof(signer_key_t));
if (key == NULL)
fatal("out of memory");
key->key = dkey;
key->isdefault = ISC_TRUE;
ISC_LIST_APPEND(keylist, key, link);
}
isc_mem_put(mctx, namestr, strlen(namestr) + 1);
}
}
signzone(db, version);
/*
* Should we update the SOA serial?
*/
result = dns_db_dump(db, version, output);
if (result != ISC_R_SUCCESS)
fatal("failed to write new database to '%s': %s",
output, isc_result_totext(result));
dns_db_closeversion(db, &version, ISC_TRUE);
dns_db_detach(&db);
key = ISC_LIST_HEAD(keylist);
while (key != NULL) {
signer_key_t *next = ISC_LIST_NEXT(key, link);
dst_key_free(key->key);
isc_mem_put(mctx, key, sizeof(signer_key_t));
key = next;
}
isc_mem_free(mctx, origin);
isc_mem_free(mctx, file);
isc_mem_free(mctx, output);
if (log != NULL)
isc_log_destroy(&log);
/* isc_mem_stats(mctx, stdout);*/
isc_mem_destroy(&mctx);
return (0);
}