d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews/*
6fb9b25791778f69002eb72be6235e20d98ec452Tinderbox User * Copyright (C) 2009, 2011, 2012, 2015-2017 Internet Systems Consortium, Inc. ("ISC")
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews *
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * This Source Code Form is subject to the terms of the Mozilla Public
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * License, v. 2.0. If a copy of the MPL was not distributed with this
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * file, You can obtain one at http://mozilla.org/MPL/2.0/.
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews */
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews#include "config.h"
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews
3759f10fc543747668b1ca4b4671f35b0dea8445Francis Dupont#include <isc/base64.h>
3759f10fc543747668b1ca4b4671f35b0dea8445Francis Dupont#include <isc/print.h>
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews#include <isc/result.h>
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews#include <isc/string.h>
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews#include <isc/types.h>
f44202ab640d22e17b4c74bdad7817622918bd27Mark Andrews#include <isc/util.h>
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews#include <dns/nsec3.h>
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews#include <dns/private.h>
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews/*
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews * We need to build the relevant chain if there exists a NSEC/NSEC3PARAM
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews * at the apex; normally only one or the other of NSEC/NSEC3PARAM will exist.
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews *
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews * If a NSEC3PARAM RRset exists then we will need to build a NSEC chain
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews * if all the NSEC3PARAM records (and associated chains) are slated for
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews * destruction and we have not been told to NOT build the NSEC chain.
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews *
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews * If the NSEC set exist then check to see if there is a request to create
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews * a NSEC3 chain.
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews *
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews * If neither NSEC/NSEC3PARAM RRsets exist at the origin and the private
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews * type exists then we need to examine it to determine if NSEC3 chain has
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews * been requested to be built otherwise a NSEC chain needs to be built.
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews */
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews#define REMOVE(x) (((x) & DNS_NSEC3FLAG_REMOVE) != 0)
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews#define CREATE(x) (((x) & DNS_NSEC3FLAG_CREATE) != 0)
79ce3a9e82384cc31fd6b86be8f3d1474fcfd9f4Evan Hunt#define INITIAL(x) (((x) & DNS_NSEC3FLAG_INITIAL) != 0)
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews#define NONSEC(x) (((x) & DNS_NSEC3FLAG_NONSEC) != 0)
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews#define CHECK(x) do { \
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews result = (x); \
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews if (result != ISC_R_SUCCESS) \
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews goto failure; \
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews } while (0)
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews/*
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews * Work out if 'param' should be ignored or not (i.e. it is in the process
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews * of being removed).
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews *
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews * Note: we 'belt-and-braces' here by also checking for a CREATE private
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews * record and keep the param record in this case.
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews */
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrewsstatic isc_boolean_t
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrewsignore(dns_rdata_t *param, dns_rdataset_t *privateset) {
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews isc_result_t result;
8a07de2f032b0137d89ae8af14faa1a915aaf9faAutomatic Updater
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews for (result = dns_rdataset_first(privateset);
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews result == ISC_R_SUCCESS;
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews result = dns_rdataset_next(privateset)) {
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews dns_rdata_t private = DNS_RDATA_INIT;
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews dns_rdata_t rdata = DNS_RDATA_INIT;
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews dns_rdataset_current(privateset, &private);
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews if (!dns_nsec3param_fromprivate(&private, &rdata,
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews buf, sizeof(buf)))
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews continue;
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews /*
8a07de2f032b0137d89ae8af14faa1a915aaf9faAutomatic Updater * We are going to create a new NSEC3 chain so it
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews * doesn't matter if we are removing this one.
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews */
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews if (CREATE(rdata.data[1]))
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews return (ISC_FALSE);
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews if (rdata.data[0] != param->data[0] ||
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews rdata.data[2] != param->data[2] ||
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews rdata.data[3] != param->data[3] ||
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews rdata.data[4] != param->data[4] ||
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews memcmp(&rdata.data[5], &param->data[5], param->data[4]))
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews continue;
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews /*
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews * The removal of this NSEC3 chain does NOT cause a
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews * NSEC chain to be created so we don't need to tell
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews * the caller that it will be removed.
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews */
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews if (NONSEC(rdata.data[1]))
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews return (ISC_FALSE);
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews return (ISC_TRUE);
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews }
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews return (ISC_FALSE);
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews}
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrewsisc_result_t
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrewsdns_private_chains(dns_db_t *db, dns_dbversion_t *ver,
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews dns_rdatatype_t privatetype,
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews isc_boolean_t *build_nsec, isc_boolean_t *build_nsec3)
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews{
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews dns_dbnode_t *node;
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews dns_rdataset_t nsecset, nsec3paramset, privateset;
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews isc_boolean_t nsec3chain;
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews isc_boolean_t signing;
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews isc_result_t result;
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews unsigned int count;
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews node = NULL;
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews dns_rdataset_init(&nsecset);
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews dns_rdataset_init(&nsec3paramset);
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews dns_rdataset_init(&privateset);
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews CHECK(dns_db_getoriginnode(db, &node));
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec,
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews 0, (isc_stdtime_t) 0, &nsecset, NULL);
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews goto failure;
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param,
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews 0, (isc_stdtime_t) 0, &nsec3paramset,
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews NULL);
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews goto failure;
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews if (dns_rdataset_isassociated(&nsecset) &&
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews dns_rdataset_isassociated(&nsec3paramset)) {
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews if (build_nsec != NULL)
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews *build_nsec = ISC_TRUE;
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews if (build_nsec3 != NULL)
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews *build_nsec3 = ISC_TRUE;
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews goto success;
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews }
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews if (privatetype != (dns_rdatatype_t)0) {
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews result = dns_db_findrdataset(db, node, ver, privatetype,
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews 0, (isc_stdtime_t) 0,
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews &privateset, NULL);
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews goto failure;
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews }
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews /*
931814de4ad11f20b85c3b50399e2e7dda2e7d47Francis Dupont * Look to see if we also need to be creating a NSEC3 chain.
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews */
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews if (dns_rdataset_isassociated(&nsecset)) {
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews if (build_nsec != NULL)
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews *build_nsec = ISC_TRUE;
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews if (build_nsec3 != NULL)
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews *build_nsec3 = ISC_FALSE;
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews if (!dns_rdataset_isassociated(&privateset))
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews goto success;
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews for (result = dns_rdataset_first(&privateset);
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews result == ISC_R_SUCCESS;
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews result = dns_rdataset_next(&privateset)) {
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews dns_rdata_t private = DNS_RDATA_INIT;
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews dns_rdata_t rdata = DNS_RDATA_INIT;
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews dns_rdataset_current(&privateset, &private);
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews if (!dns_nsec3param_fromprivate(&private, &rdata,
8a07de2f032b0137d89ae8af14faa1a915aaf9faAutomatic Updater buf, sizeof(buf)))
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews continue;
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews if (REMOVE(rdata.data[1]))
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews continue;
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews if (build_nsec3 != NULL)
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews *build_nsec3 = ISC_TRUE;
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews break;
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews }
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews goto success;
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews }
8a07de2f032b0137d89ae8af14faa1a915aaf9faAutomatic Updater
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews if (dns_rdataset_isassociated(&nsec3paramset)) {
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews if (build_nsec3 != NULL)
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews *build_nsec3 = ISC_TRUE;
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews if (build_nsec != NULL)
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews *build_nsec = ISC_FALSE;
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews if (!dns_rdataset_isassociated(&privateset))
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews goto success;
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews /*
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews * If we are in the process of building a new NSEC3 chain
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews * then we don't need to build a NSEC chain.
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews */
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews for (result = dns_rdataset_first(&privateset);
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews result == ISC_R_SUCCESS;
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews result = dns_rdataset_next(&privateset)) {
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews dns_rdata_t private = DNS_RDATA_INIT;
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews dns_rdata_t rdata = DNS_RDATA_INIT;
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews dns_rdataset_current(&privateset, &private);
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews if (!dns_nsec3param_fromprivate(&private, &rdata,
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews buf, sizeof(buf)))
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews continue;
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews if (CREATE(rdata.data[1]))
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews goto success;
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews }
8a07de2f032b0137d89ae8af14faa1a915aaf9faAutomatic Updater
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews /*
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews * Check to see if there will be a active NSEC3CHAIN once
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews * the changes queued complete.
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews */
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews count = 0;
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews for (result = dns_rdataset_first(&nsec3paramset);
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews result == ISC_R_SUCCESS;
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews result = dns_rdataset_next(&nsec3paramset)) {
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews dns_rdata_t rdata = DNS_RDATA_INIT;
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews /*
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews * If there is more that one NSEC3 chain present then
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews * we don't need to construct a NSEC chain.
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews */
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews if (++count > 1)
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews goto success;
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews dns_rdataset_current(&nsec3paramset, &rdata);
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews if (ignore(&rdata, &privateset))
8a07de2f032b0137d89ae8af14faa1a915aaf9faAutomatic Updater continue;
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews /*
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews * We still have a good NSEC3 chain or we are
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews * not creating a NSEC chain as NONSEC is set.
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews */
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews goto success;
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews }
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews /*
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews * The last NSEC3 chain is being removed and does not have
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews * have NONSEC set.
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews */
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews if (build_nsec != NULL)
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews *build_nsec = ISC_TRUE;
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews goto success;
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews }
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews if (build_nsec != NULL)
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews *build_nsec = ISC_FALSE;
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews if (build_nsec3 != NULL)
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews *build_nsec3 = ISC_FALSE;
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews if (!dns_rdataset_isassociated(&privateset))
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews goto success;
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews signing = ISC_FALSE;
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews nsec3chain = ISC_FALSE;
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews for (result = dns_rdataset_first(&privateset);
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews result == ISC_R_SUCCESS;
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews result = dns_rdataset_next(&privateset)) {
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews dns_rdata_t rdata = DNS_RDATA_INIT;
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews dns_rdata_t private = DNS_RDATA_INIT;
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews dns_rdataset_current(&privateset, &private);
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews if (!dns_nsec3param_fromprivate(&private, &rdata,
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews buf, sizeof(buf))) {
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews /*
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews * Look for record that says we are signing the
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews * zone with a key.
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews */
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews if (private.length == 5 && private.data[0] != 0 &&
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews private.data[3] == 0 && private.data[4] == 0)
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews signing = ISC_TRUE;
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews } else {
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews if (CREATE(rdata.data[1]))
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews nsec3chain = ISC_TRUE;
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews }
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews }
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews if (signing) {
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews if (nsec3chain) {
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews if (build_nsec3 != NULL)
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews *build_nsec3 = ISC_TRUE;
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews } else {
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews if (build_nsec != NULL)
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews *build_nsec = ISC_TRUE;
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews }
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews }
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews success:
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews result = ISC_R_SUCCESS;
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews failure:
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews if (dns_rdataset_isassociated(&nsecset))
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews dns_rdataset_disassociate(&nsecset);
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews if (dns_rdataset_isassociated(&nsec3paramset))
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews dns_rdataset_disassociate(&nsec3paramset);
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews if (dns_rdataset_isassociated(&privateset))
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews dns_rdataset_disassociate(&privateset);
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews if (node != NULL)
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews dns_db_detachnode(db, &node);
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews return (result);
d1bcaec0d6c3a2f6afe004c1a087314015cb77c0Mark Andrews}
9c03f13e18c1b0c32f62391a17300378605bbc7bEvan Hunt
9c03f13e18c1b0c32f62391a17300378605bbc7bEvan Huntisc_result_t
9c03f13e18c1b0c32f62391a17300378605bbc7bEvan Huntdns_private_totext(dns_rdata_t *private, isc_buffer_t *buf) {
9c03f13e18c1b0c32f62391a17300378605bbc7bEvan Hunt isc_result_t result;
9c03f13e18c1b0c32f62391a17300378605bbc7bEvan Hunt
f83542787f882444d2abf9fcaf47a34c29e4fec2Mark Andrews if (private->length < 5)
f83542787f882444d2abf9fcaf47a34c29e4fec2Mark Andrews return (ISC_R_NOTFOUND);
f83542787f882444d2abf9fcaf47a34c29e4fec2Mark Andrews
9c03f13e18c1b0c32f62391a17300378605bbc7bEvan Hunt if (private->data[0] == 0) {
9c03f13e18c1b0c32f62391a17300378605bbc7bEvan Hunt unsigned char nsec3buf[DNS_NSEC3PARAM_BUFFERSIZE];
9c03f13e18c1b0c32f62391a17300378605bbc7bEvan Hunt unsigned char newbuf[DNS_NSEC3PARAM_BUFFERSIZE];
9c03f13e18c1b0c32f62391a17300378605bbc7bEvan Hunt dns_rdata_t rdata = DNS_RDATA_INIT;
9c03f13e18c1b0c32f62391a17300378605bbc7bEvan Hunt dns_rdata_nsec3param_t nsec3param;
bfde61d5194a534d800f3b90008d1f52261922c5Mark Andrews isc_boolean_t del, init, nonsec;
9c03f13e18c1b0c32f62391a17300378605bbc7bEvan Hunt isc_buffer_t b;
9c03f13e18c1b0c32f62391a17300378605bbc7bEvan Hunt
9c03f13e18c1b0c32f62391a17300378605bbc7bEvan Hunt if (!dns_nsec3param_fromprivate(private, &rdata, nsec3buf,
9c03f13e18c1b0c32f62391a17300378605bbc7bEvan Hunt sizeof(nsec3buf)))
9c03f13e18c1b0c32f62391a17300378605bbc7bEvan Hunt CHECK(ISC_R_FAILURE);
9c03f13e18c1b0c32f62391a17300378605bbc7bEvan Hunt
9c03f13e18c1b0c32f62391a17300378605bbc7bEvan Hunt CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
9c03f13e18c1b0c32f62391a17300378605bbc7bEvan Hunt
bfde61d5194a534d800f3b90008d1f52261922c5Mark Andrews del = ISC_TF((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0);
9c03f13e18c1b0c32f62391a17300378605bbc7bEvan Hunt init = ISC_TF((nsec3param.flags & DNS_NSEC3FLAG_INITIAL) != 0);
9c03f13e18c1b0c32f62391a17300378605bbc7bEvan Hunt nonsec = ISC_TF((nsec3param.flags & DNS_NSEC3FLAG_NONSEC) != 0);
9c03f13e18c1b0c32f62391a17300378605bbc7bEvan Hunt
9c03f13e18c1b0c32f62391a17300378605bbc7bEvan Hunt nsec3param.flags &= ~(DNS_NSEC3FLAG_CREATE|
9c03f13e18c1b0c32f62391a17300378605bbc7bEvan Hunt DNS_NSEC3FLAG_REMOVE|
9c03f13e18c1b0c32f62391a17300378605bbc7bEvan Hunt DNS_NSEC3FLAG_INITIAL|
9c03f13e18c1b0c32f62391a17300378605bbc7bEvan Hunt DNS_NSEC3FLAG_NONSEC);
9c03f13e18c1b0c32f62391a17300378605bbc7bEvan Hunt
9c03f13e18c1b0c32f62391a17300378605bbc7bEvan Hunt if (init)
9c03f13e18c1b0c32f62391a17300378605bbc7bEvan Hunt isc_buffer_putstr(buf, "Pending NSEC3 chain ");
bfde61d5194a534d800f3b90008d1f52261922c5Mark Andrews else if (del)
9c03f13e18c1b0c32f62391a17300378605bbc7bEvan Hunt isc_buffer_putstr(buf, "Removing NSEC3 chain ");
9c03f13e18c1b0c32f62391a17300378605bbc7bEvan Hunt else
9c03f13e18c1b0c32f62391a17300378605bbc7bEvan Hunt isc_buffer_putstr(buf, "Creating NSEC3 chain ");
9c03f13e18c1b0c32f62391a17300378605bbc7bEvan Hunt
9c03f13e18c1b0c32f62391a17300378605bbc7bEvan Hunt dns_rdata_reset(&rdata);
9c03f13e18c1b0c32f62391a17300378605bbc7bEvan Hunt isc_buffer_init(&b, newbuf, sizeof(newbuf));
9c03f13e18c1b0c32f62391a17300378605bbc7bEvan Hunt CHECK(dns_rdata_fromstruct(&rdata, dns_rdataclass_in,
9c03f13e18c1b0c32f62391a17300378605bbc7bEvan Hunt dns_rdatatype_nsec3param,
9c03f13e18c1b0c32f62391a17300378605bbc7bEvan Hunt &nsec3param, &b));
9c03f13e18c1b0c32f62391a17300378605bbc7bEvan Hunt
9c03f13e18c1b0c32f62391a17300378605bbc7bEvan Hunt CHECK(dns_rdata_totext(&rdata, NULL, buf));
9c03f13e18c1b0c32f62391a17300378605bbc7bEvan Hunt
bfde61d5194a534d800f3b90008d1f52261922c5Mark Andrews if (del && !nonsec)
9c03f13e18c1b0c32f62391a17300378605bbc7bEvan Hunt isc_buffer_putstr(buf, " / creating NSEC chain");
f83542787f882444d2abf9fcaf47a34c29e4fec2Mark Andrews } else if (private->length == 5) {
9c03f13e18c1b0c32f62391a17300378605bbc7bEvan Hunt unsigned char alg = private->data[0];
9c03f13e18c1b0c32f62391a17300378605bbc7bEvan Hunt dns_keytag_t keyid = (private->data[2] | private->data[1] << 8);
9c03f13e18c1b0c32f62391a17300378605bbc7bEvan Hunt char keybuf[BUFSIZ], algbuf[DNS_SECALG_FORMATSIZE];
bfde61d5194a534d800f3b90008d1f52261922c5Mark Andrews isc_boolean_t del = ISC_TF(private->data[3] != 0);
9c03f13e18c1b0c32f62391a17300378605bbc7bEvan Hunt isc_boolean_t complete = ISC_TF(private->data[4] != 0);
9c03f13e18c1b0c32f62391a17300378605bbc7bEvan Hunt
bfde61d5194a534d800f3b90008d1f52261922c5Mark Andrews if (del && complete)
9c03f13e18c1b0c32f62391a17300378605bbc7bEvan Hunt isc_buffer_putstr(buf, "Done removing signatures for ");
bfde61d5194a534d800f3b90008d1f52261922c5Mark Andrews else if (del)
9c03f13e18c1b0c32f62391a17300378605bbc7bEvan Hunt isc_buffer_putstr(buf, "Removing signatures for ");
9c03f13e18c1b0c32f62391a17300378605bbc7bEvan Hunt else if (complete)
9c03f13e18c1b0c32f62391a17300378605bbc7bEvan Hunt isc_buffer_putstr(buf, "Done signing with ");
9c03f13e18c1b0c32f62391a17300378605bbc7bEvan Hunt else
9c03f13e18c1b0c32f62391a17300378605bbc7bEvan Hunt isc_buffer_putstr(buf, "Signing with ");
9c03f13e18c1b0c32f62391a17300378605bbc7bEvan Hunt
9c03f13e18c1b0c32f62391a17300378605bbc7bEvan Hunt dns_secalg_format(alg, algbuf, sizeof(algbuf));
ad1317338af79edad878c9c3e4361798503310baMark Andrews snprintf(keybuf, sizeof(keybuf), "key %d/%s", keyid, algbuf);
9c03f13e18c1b0c32f62391a17300378605bbc7bEvan Hunt isc_buffer_putstr(buf, keybuf);
f83542787f882444d2abf9fcaf47a34c29e4fec2Mark Andrews } else
f83542787f882444d2abf9fcaf47a34c29e4fec2Mark Andrews return (ISC_R_NOTFOUND);
9c03f13e18c1b0c32f62391a17300378605bbc7bEvan Hunt
9c03f13e18c1b0c32f62391a17300378605bbc7bEvan Hunt isc_buffer_putuint8(buf, 0);
9c03f13e18c1b0c32f62391a17300378605bbc7bEvan Hunt result = ISC_R_SUCCESS;
9c03f13e18c1b0c32f62391a17300378605bbc7bEvan Hunt failure:
9c03f13e18c1b0c32f62391a17300378605bbc7bEvan Hunt return (result);
9c03f13e18c1b0c32f62391a17300378605bbc7bEvan Hunt}