dnssec.c revision 364a82f7c25b62967678027043425201a5e5171a
/*
* 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.31 2000/04/28 01:10:00 halley Exp $
* Principal Author: Brian Wellington
*/
#include <config.h>
#include <stdlib.h>
#include <string.h>
#include <isc/assertions.h>
#include <dns/keyvalues.h>
#include <dns/rdataset.h>
#include <dns/rdatalist.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
typedef struct digestctx {
} digestctx_t;
dns_name_t *name);
static isc_result_t
else
return (result);
}
/* converts the name of a key into a canonical isc_name_t */
static isc_result_t
unsigned char data[1024];
if (ret != ISC_R_SUCCESS)
return (ret);
return (ret);
}
/* make qsort happy */
static int
}
/* 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, namebuf;
isc_region_t r;
char namestr[1024];
if (ret != ISC_R_SUCCESS)
return ret;
isc_buffer_usedregion(&namebuf, &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 (ret != ISC_R_SUCCESS)
return (ret);
if (dns_name_iswildcard(name))
if (ret != ISC_R_SUCCESS)
return (ret);
goto cleanup_name;
if (ret != ISC_R_SUCCESS)
goto cleanup_signature;
isc_buffer_usedregion(&b, &r);
/* Digest the SIG rdata */
if (ret != ISC_R_SUCCESS)
goto cleanup_signature;
dns_name_toregion(name, &r);
/* create an envelope for each rdata: <name|type|class|ttl> */
if (ret != ISC_R_SUCCESS)
goto cleanup_signature;
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 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_struct;
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_VERIFYFINALFAILURE)
return (ret);
}
unsigned int *nkeys)
{
unsigned int count = 0;
*nkeys = 0;
if (!is_zone_key(pubkey))
goto next;
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))
NULL));
/* 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;
}
/* XXXBEW ensure that sig.signer refers to this key */
/* if this is a response, digest the query */
if (is_response(msg))
NULL));
/* 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);
}