/*
* Copyright (C) 2004-2009, 2012, 2014 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2003 Internet Software Consortium.
*
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
/*
* $Id$
*/
/*! \file */
#include <config.h>
#include <stdlib.h>
#include <dns/fixedname.h>
#include <dns/keyvalues.h>
#include <dns/rdatalist.h>
#include <dns/rdataset.h>
#include <dns/rdatastruct.h>
#define RETERR(x) do { \
result = (x); \
if (result != ISC_R_SUCCESS) \
goto failure; \
} while (0)
#define TYPE_SIGN 0
static isc_result_t
static int
static isc_result_t
static isc_result_t
}
static inline void
if (dns_dnssec_stats != NULL)
}
/*
* Make qsort happy.
*/
static int
(const dns_rdata_t *)rdata2));
}
/*
* Sort the rdataset into an array.
*/
static isc_result_t
{
int i = 0, n;
n = dns_rdataset_count(set);
return (ISC_R_NOMEMORY);
if (ret != ISC_R_SUCCESS) {
return (ret);
}
/*
* Put them in the array.
*/
do {
dns_rdata_init(&data[i]);
/*
* Sort the array.
*/
*nrdata = n;
return (ISC_R_SUCCESS);
}
{
isc_buffer_t b;
isc_region_t r;
dns_rdata_toregion(rdata, &r);
isc_buffer_add(&b, r.length);
}
static isc_result_t
{
isc_region_t r;
dns_rdata_toregion(sigrdata, &r);
r.length = 18;
if (ret != ISC_R_SUCCESS)
return (ret);
if (downcase) {
NULL) == ISC_R_SUCCESS);
} else
return (dst_context_adddata(ctx, &r));
}
{
int nrdatas, i;
isc_region_t r;
unsigned int sigsize;
return (DNS_R_INVALIDTIME);
/*
* Is the key allowed to sign data?
*/
if (flags & DNS_KEYTYPE_NOAUTH)
return (DNS_R_KEYUNAUTHORIZED);
return (DNS_R_KEYUNAUTHORIZED);
/*
* Downcase signer.
*/
if (dns_name_iswildcard(name))
if (ret != ISC_R_SUCCESS)
return (ret);
/*
* The actual contents of sig.signature are not important yet, since
* they're not used in digest_sig().
*/
return (ISC_R_NOMEMORY);
if (ret != ISC_R_SUCCESS)
goto cleanup_signature;
if (ret != ISC_R_SUCCESS)
goto cleanup_databuf;
if (ret != ISC_R_SUCCESS)
goto cleanup_databuf;
/*
* Digest the SIG rdata.
*/
if (ret != ISC_R_SUCCESS)
goto cleanup_context;
NULL) == ISC_R_SUCCESS);
/*
* Create an envelope for each rdata: <name|type|class|ttl>.
*/
if (ret != ISC_R_SUCCESS)
goto cleanup_context;
isc_buffer_usedregion(&envbuf, &r);
for (i = 0; i < nrdatas; i++) {
/*
* Skip duplicates.
*/
continue;
/*
* Digest the envelope.
*/
if (ret != ISC_R_SUCCESS)
goto cleanup_array;
/*
* Digest the length of the rdata.
*/
if (ret != ISC_R_SUCCESS)
goto cleanup_array;
/*
* Digest the rdata.
*/
if (ret != ISC_R_SUCCESS)
goto cleanup_array;
}
if (ret != ISC_R_SUCCESS)
goto cleanup_array;
isc_buffer_usedregion(&sigbuf, &r);
ret = ISC_R_NOSPACE;
goto cleanup_array;
}
return (ret);
}
{
isc_region_t r;
int nrdatas, i;
int labels = 0;
if (ret != ISC_R_SUCCESS)
return (ret);
return (DNS_R_SIGINVALID);
return (DNS_R_SIGINVALID);
}
if (!ignoretime) {
/*
* Is SIG temporally valid?
*/
return (DNS_R_SIGFUTURE);
return (DNS_R_SIGEXPIRED);
}
}
/*
* NS, SOA and DNSSKEY records are signed by their owner.
* DS records are signed by the parent.
*/
case dns_rdatatype_ns:
case dns_rdatatype_soa:
case dns_rdatatype_dnskey:
return (DNS_R_SIGINVALID);
}
break;
case dns_rdatatype_ds:
return (DNS_R_SIGINVALID);
}
/* FALLTHROUGH */
default:
return (DNS_R_SIGINVALID);
}
break;
}
/*
* Is the key allowed to sign data?
*/
if (flags & DNS_KEYTYPE_NOAUTH) {
return (DNS_R_KEYUNAUTHORIZED);
}
return (DNS_R_KEYUNAUTHORIZED);
}
if (ret != ISC_R_SUCCESS)
goto cleanup_struct;
/*
* Digest the SIG rdata (not including the signature).
*/
if (ret != ISC_R_SUCCESS)
goto cleanup_context;
/*
* If the name is an expanded wildcard, use the wildcard name.
*/
NULL) == ISC_R_SUCCESS);
/*
* Create an envelope for each rdata: <name|type|class|ttl>.
*/
}
else
if (ret != ISC_R_SUCCESS)
goto cleanup_context;
isc_buffer_usedregion(&envbuf, &r);
for (i = 0; i < nrdatas; i++) {
/*
* Skip duplicates.
*/
continue;
/*
* Digest the envelope.
*/
if (ret != ISC_R_SUCCESS)
goto cleanup_array;
/*
* Digest the rdata length.
*/
/*
* Digest the rdata.
*/
if (ret != ISC_R_SUCCESS)
goto cleanup_array;
if (ret != ISC_R_SUCCESS)
goto cleanup_array;
}
"successfully validated after lower casing "
"signer '%s'", namebuf);
} else if (ret == ISC_R_SUCCESS)
goto again;
}
if (ret == DST_R_VERIFYFAILURE)
if (ret != ISC_R_SUCCESS)
}
return (ret);
}
{
if (result == DNS_R_FROMWILDCARD)
return (result);
}
unsigned int *nkeys)
{
unsigned int count = 0;
*nkeys = 0;
if (!is_zone_key(pubkey) ||
goto next;
/* Corrupted .key file? */
goto next;
if (result == ISC_R_FILENOTFOUND) {
count++;
goto next;
}
if (result != ISC_R_SUCCESS)
goto failure;
/* We should never get here. */
goto next;
}
count++;
next:
}
if (result != ISC_R_NOMORE)
goto failure;
if (count == 0)
else
if (result != ISC_R_SUCCESS)
while (count > 0)
return (result);
}
unsigned int *nkeys)
{
}
unsigned int sigsize;
isc_region_t r;
if (is_response(msg))
sig.originalttl = 0;
/*
* Digest the fields of the SIG - we can cheat and use
* dns_rdata_fromstruct. Since siglen is 0, the digested data
* is identical to dns format.
*/
dns_rdatatype_sig /* SIG(0) */,
isc_buffer_usedregion(&databuf, &r);
/*
* If this is a response, digest the query.
*/
if (is_response(msg))
/*
* Digest the header.
*/
isc_buffer_usedregion(&headerbuf, &r);
/*
* Digest the remainder of the message.
*/
goto failure;
}
dns_rdatatype_sig /* SIG(0) */,
return (ISC_R_SUCCESS);
if (signeedsfree)
return (result);
}
{
if (is_response(msg)) {
return (DNS_R_UNEXPECTEDTSIG);
}
goto failure;
}
goto failure;
}
goto failure;
}
goto failure;
}
goto failure;
}
/*
* Digest the SIG(0) record, except for the signature.
*/
dns_rdata_toregion(&rdata, &r);
/*
* If this is a response, digest the query.
*/
if (is_response(msg))
/*
* Extract the header.
*/
/*
* Decrement the additional field counter.
*/
/*
* Digest the modified header.
*/
/*
* Digest all non-SIG(0) records.
*/
if (result != ISC_R_SUCCESS) {
goto failure;
}
return (ISC_R_SUCCESS);
if (signeedsfree)
return (result);
}
/*%
* Does this key ('rdata') self sign the rrset ('rdataset')?
*/
{
} else {
}
if (result != ISC_R_SUCCESS)
return (ISC_FALSE);
result == ISC_R_SUCCESS;
{
if (result == ISC_R_SUCCESS) {
return (ISC_TRUE);
}
}
}
return (ISC_FALSE);
}