dnssec.c revision 40f53fa8d9c6a4fc38c0014495e7a42b08f52481
/*
* Copyright (C) 1999, 2000 Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* 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 INTERNET SOFTWARE CONSORTIUM
* DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
* INTERNET SOFTWARE CONSORTIUM 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: dnssec.c,v 1.47 2000/08/01 01:22:20 tale Exp $
* Principal Author: Brian Wellington
*/
#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
#define TYPE_VERIFY 1
static isc_result_t
static int
static isc_result_t
static isc_result_t
}
/*
* Make qsort happy.
*/
static int
(const dns_rdata_t *)rdata2));
}
/*
* Sort the rdataset into an array.
*/
static isc_result_t
{
int i = 0, n = 1;
if (ret != ISC_R_SUCCESS)
return (ret);
/*
* Count the records.
*/
n++;
return (ISC_R_NOMEMORY);
if (ret != ISC_R_SUCCESS)
return (ret);
/*
* Put them in the array.
*/
do {
/*
* 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);
}
{
int nrdatas, i;
isc_region_t r;
unsigned char data[300];
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);
if (dns_name_iswildcard(name))
if (ret != ISC_R_SUCCESS)
return (ret);
return (ISC_R_NOMEMORY);
if (ret != ISC_R_SUCCESS)
goto cleanup_signature;
isc_buffer_usedregion(&b, &r);
if (ret != ISC_R_SUCCESS)
goto cleanup_signature;
/*
* Digest the SIG rdata.
*/
if (ret != ISC_R_SUCCESS)
goto cleanup_context;
dns_name_toregion(name, &r);
/*
* 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++) {
/*
* 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;
unsigned char data[300];
int labels;
if (ret != ISC_R_SUCCESS)
return (ret);
if (!ignoretime) {
/*
* Is SIG temporally valid?
*/
return (DNS_R_SIGFUTURE);
return (DNS_R_SIGEXPIRED);
}
/*
* Is the key allowed to sign data?
*/
if (flags & DNS_KEYTYPE_NOAUTH)
return (DNS_R_KEYUNAUTHORIZED);
return (DNS_R_KEYUNAUTHORIZED);
/*
* Digest the SIG rdata (not including the signature).
*/
dns_rdata_toregion(sigrdata, &r);
if (ret != ISC_R_SUCCESS)
goto cleanup_struct;
if (ret != ISC_R_SUCCESS)
goto cleanup_struct;
/*
* If the name is an expanded wildcard, use the wildcard name.
*/
}
else
dns_name_toregion(name, &r);
/*
* 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++) {
/*
* 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;
}
if (ret == DST_R_VERIFYFAILURE)
return (ret);
}
unsigned int *nkeys)
{
unsigned int count = 0;
*nkeys = 0;
if (!is_zone_key(pubkey))
goto next;
NULL,
if (result == DST_R_INVALIDPRIVATEKEY)
goto next;
if (result != ISC_R_SUCCESS)
goto failure;
goto next;
}
count++;
next:
}
if (result != ISC_R_NOMORE)
goto failure;
if (count == 0)
else
return (result);
}
unsigned char data[512];
unsigned char header[DNS_MESSAGE_HEADERLEN];
unsigned int sigsize;
isc_region_t r;
if (is_response(msg))
sig.originalttl = 0;
if (is_response(msg))
/*
* Digest the header.
*/
isc_buffer_usedregion(&headerbuf, &r);
/*
* Digest the remainder of the message.
*/
/*
* 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 with the last 2 bytes removed.
*/
isc_buffer_usedregion(&databuf, &r);
r.length -= 2;
goto failure;
}
return (ISC_R_SUCCESS);
if (signeedsfree)
return (result);
}
{
unsigned char header[DNS_MESSAGE_HEADERLEN];
if (is_response(msg))
goto failure;
}
goto failure;
}
goto failure;
}
goto failure;
}
/*
* 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.
*/
/*
* Digest the SIG(0) record . Find the start of the record, skip
* the name and 10 bytes for class, type, ttl, length to get to
* the start of the rdata.
*/
dns_name_fromregion(&tname, &r);
if (result != ISC_R_SUCCESS) {
goto failure;
}
return (ISC_R_SUCCESS);
if (signeedsfree)
return (result);
}