Commit 0b09763c authored by Mark Andrews's avatar Mark Andrews

1328. [func] DS (delegation signer) support.

parent 6a3c86ff
1328. [func] DS (delegation signer) support.
1327. [bug] nsupdate: allow white space base64 key data.
1326. [bug] Badly encoded LOC record when the size, horizontal
......
......@@ -13,7 +13,7 @@
# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
# $Id: Makefile.in,v 1.21 2001/11/06 20:05:00 bwelling Exp $
# $Id: Makefile.in,v 1.22 2002/06/17 04:01:03 marka Exp $
srcdir = @srcdir@
VPATH = @srcdir@
......@@ -39,26 +39,15 @@ DEPLIBS = ${DNSDEPLIBS} ${ISCDEPLIBS}
LIBS = ${DNSLIBS} ${ISCLIBS} @LIBS@
# Alphabetically
TARGETS = dnssec-keygen \
dnssec-makekeyset \
dnssec-signkey \
dnssec-signzone
TARGETS = dnssec-keygen dnssec-signzone
OBJS = dnssectool.@O@
SRCS = dnssec-keygen.c dnssec-makekeyset.c \
dnssec-signkey.c dnssec-signzone.c \
dnssectool.c
SRCS = dnssec-keygen.c dnssec-signzone.c dnssectool.c
MANPAGES = dnssec-keygen.8 \
dnssec-makekeyset.8 \
dnssec-signkey.8 \
dnssec-signzone.8
MANPAGES = dnssec-keygen.8 dnssec-signzone.8
HTMLPAGES = dnssec-keygen.html \
dnssec-makekeyset.html \
dnssec-signkey.html \
dnssec-signzone.html
HTMLPAGES = dnssec-keygen.html dnssec-signzone.html
MANOBJS = ${MANPAGES} ${HTMLPAGES}
......@@ -67,12 +56,6 @@ MANOBJS = ${MANPAGES} ${HTMLPAGES}
dnssec-keygen: dnssec-keygen.@O@ ${OBJS} ${DEPLIBS}
${LIBTOOL} ${PURIFY} ${CC} ${CFLAGS} -o $@ dnssec-keygen.@O@ ${OBJS} ${LIBS}
dnssec-makekeyset: dnssec-makekeyset.@O@ ${OBJS} ${DEPLIBS}
${LIBTOOL} ${PURIFY} ${CC} ${CFLAGS} -o $@ dnssec-makekeyset.@O@ ${OBJS} ${LIBS}
dnssec-signkey: dnssec-signkey.@O@ ${OBJS} ${DEPLIBS}
${LIBTOOL} ${PURIFY} ${CC} ${CFLAGS} -o $@ dnssec-signkey.@O@ ${OBJS} ${LIBS}
dnssec-signzone.@O@: dnssec-signzone.c
${LIBTOOL} ${PURIFY} ${CC} ${ALL_CFLAGS} -DVERSION=\"${VERSION}\" -c $<
......
This diff is collapsed.
......@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: query.c,v 1.219 2002/03/28 04:03:50 marka Exp $ */
/* $Id: query.c,v 1.220 2002/06/17 04:01:08 marka Exp $ */
#include <config.h>
......@@ -2045,6 +2045,70 @@ query_addbestns(ns_client_t *client) {
}
}
static void
query_addds(ns_client_t *client, dns_db_t *db, dns_dbnode_t *node) {
dns_name_t *rname;
dns_rdataset_t *rdataset, *sigrdataset;
isc_result_t result;
CTRACE("query_addds");
rname = NULL;
rdataset = NULL;
sigrdataset = NULL;
/*
* We'll need some resources...
*/
rdataset = query_newrdataset(client);
sigrdataset = query_newrdataset(client);
if (rdataset == NULL || sigrdataset == NULL)
return;
/*
* Look for the DS record, which may or may not be present.
*/
result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ds, 0,
client->now, rdataset, sigrdataset);
/*
* If we didn't find it, look for an NXT. */
if (result == ISC_R_NOTFOUND)
result = dns_db_findrdataset(db, node, NULL,
dns_rdatatype_nxt, 0, client->now,
rdataset, sigrdataset);
if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
goto cleanup;
if (!dns_rdataset_isassociated(rdataset) ||
!dns_rdataset_isassociated(sigrdataset))
goto cleanup;
/*
* We've already added the NS record, so if the name's not there,
* we have other problems. Use this name rather than calling
* query_addrrset().
*/
result = dns_message_firstname(client->message, DNS_SECTION_AUTHORITY);
if (result != ISC_R_SUCCESS)
goto cleanup;
rname = NULL;
dns_message_currentname(client->message, DNS_SECTION_AUTHORITY,
&rname);
result = dns_message_findtype(rname, dns_rdatatype_ns, 0, NULL);
if (result != ISC_R_SUCCESS)
goto cleanup;
ISC_LIST_APPEND(rname->list, rdataset, link);
ISC_LIST_APPEND(rname->list, sigrdataset, link);
rdataset = NULL;
sigrdataset = NULL;
cleanup:
if (rdataset != NULL)
query_putrdataset(client, &rdataset);
if (sigrdataset != NULL)
query_putrdataset(client, &sigrdataset);
}
static void
query_resume(isc_task_t *task, isc_event_t *event) {
dns_fetchevent_t *devent = (dns_fetchevent_t *)event;
......@@ -2206,98 +2270,6 @@ query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qdomain,
return (result);
}
static inline isc_result_t
query_findparentkey(ns_client_t *client, dns_name_t *name,
dns_zone_t **zonep, dns_db_t **dbp,
dns_dbversion_t **versionp, dns_dbnode_t **nodep,
dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
{
dns_db_t *pdb;
dns_dbnode_t *pnode;
dns_dbversion_t *pversion;
dns_rdataset_t prdataset, psigrdataset;
dns_rdataset_t *psigrdatasetp;
isc_result_t result;
dns_zone_t *pzone;
isc_boolean_t is_zone;
dns_fixedname_t pfoundname;
/*
* 'name' is at a zone cut. Try to find a KEY for 'name' in
* the deepest ancestor zone of 'name' (if any). If it exists,
* update *zonep, *dbp, *nodep, rdataset, and sigrdataset and
* return ISC_R_SUCCESS. If not, leave them alone and return a
* non-success status.
*/
pzone = NULL;
pdb = NULL;
pnode = NULL;
pversion = NULL;
dns_rdataset_init(&prdataset);
if (sigrdataset != NULL)
dns_rdataset_init(&psigrdataset);
is_zone = ISC_FALSE;
dns_fixedname_init(&pfoundname);
result = query_getdb(client, name, DNS_GETDB_NOEXACT,
&pzone, &pdb, &pversion, &is_zone);
if (result != ISC_R_SUCCESS)
goto cleanup;
if (!is_zone) {
result = ISC_R_FAILURE;
goto cleanup;
}
if (sigrdataset != NULL)
psigrdatasetp = &psigrdataset;
else
psigrdatasetp = NULL;
result = dns_db_find(pdb, name, pversion, dns_rdatatype_key,
client->query.dboptions,
client->now, &pnode,
dns_fixedname_name(&pfoundname),
&prdataset, psigrdatasetp);
if (result == ISC_R_SUCCESS) {
if (dns_rdataset_isassociated(rdataset))
dns_rdataset_disassociate(rdataset);
dns_rdataset_clone(&prdataset, rdataset);
if (sigrdataset != NULL) {
if (dns_rdataset_isassociated(sigrdataset))
dns_rdataset_disassociate(sigrdataset);
if (dns_rdataset_isassociated(&psigrdataset))
dns_rdataset_clone(&psigrdataset, sigrdataset);
}
if (*nodep != NULL)
dns_db_detachnode(*dbp, nodep);
*nodep = pnode;
pnode = NULL;
*versionp = pversion;
if (*dbp != NULL)
dns_db_detach(dbp);
*dbp = pdb;
pdb = NULL;
if (*zonep != NULL)
dns_zone_detach(zonep);
*zonep = pzone;
pzone = NULL;
}
cleanup:
if (dns_rdataset_isassociated(&prdataset))
dns_rdataset_disassociate(&prdataset);
if (sigrdataset != NULL && dns_rdataset_isassociated(&psigrdataset))
dns_rdataset_disassociate(&psigrdataset);
if (pnode != NULL)
dns_db_detachnode(pdb, &pnode);
if (pdb != NULL)
dns_db_detach(&pdb);
if (pzone != NULL)
dns_zone_detach(&pzone);
return (result);
}
#define MAX_RESTARTS 16
#define QUERY_ERROR(r) \
......@@ -2419,6 +2391,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
dns_zone_t *zone;
dns_rdata_cname_t cname;
dns_rdata_dname_t dname;
unsigned int options;
CTRACE("query_find");
......@@ -2508,7 +2481,11 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
/*
* First we must find the right database.
*/
result = query_getdb(client, client->query.qname, 0, &zone, &db,
options = 0;
if (dns_rdatatype_atparent(qtype) &&
!dns_name_equal(client->query.qname, dns_rootname))
options |= DNS_GETDB_NOEXACT;
result = query_getdb(client, client->query.qname, options, &zone, &db,
&version, &is_zone);
if (result != ISC_R_SUCCESS) {
if (result == DNS_R_REFUSED)
......@@ -2560,63 +2537,6 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
client->query.dboptions, client->now,
&node, fname, rdataset, sigrdataset);
/*
* We interrupt our normal query processing to bring you this special
* case...
*
* RFC 2535 (DNSSEC), section 2.3.4, discusses various special
* cases that can occur at delegation points.
*
* One of these cases is that the NULL KEY for an unsecure zone
* may occur in the delegating zone instead of in the delegated zone.
* If we're authoritative for both zones, we need to look for the
* key in the delegator if we didn't find it in the delegatee. If
* we didn't do this, a client doing DNSSEC validation could fail
* because it couldn't get the NULL KEY.
*/
if (type == dns_rdatatype_key &&
is_zone &&
result == DNS_R_NXRRSET &&
!dns_db_issecure(db) &&
dns_name_equal(client->query.qname, dns_db_origin(db))) {
/*
* We're looking for a KEY at the top of an unsecure zone,
* and we didn't find it.
*/
result = query_findparentkey(client, client->query.qname,
&zone, &db, &version, &node,
rdataset, sigrdataset);
if (result == ISC_R_SUCCESS) {
/*
* We found the parent KEY.
*
* zone, db, version, node, rdataset, and sigrdataset
* have all been updated to refer to the parent's
* data. We will resume query processing as if
* we had looked for the KEY in the parent zone in
* the first place.
*
* We need to set fname correctly. We do this here
* instead of in query_findparentkey() because
* dns_name_copy() can fail (though it shouldn't
* ever do so since we should have enough space).
*/
result = dns_name_copy(client->query.qname,
fname, NULL);
if (result != ISC_R_SUCCESS) {
QUERY_ERROR(DNS_R_SERVFAIL);
goto cleanup;
}
} else {
/*
* We couldn't find the KEY in a parent zone.
* Continue with processing of the original
* results of dns_db_find().
*/
result = DNS_R_NXRRSET;
}
}
resume:
CTRACE("query_find: resume");
switch (result) {
......@@ -2730,6 +2650,8 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
&rdataset, sigrdatasetp,
dbuf, DNS_SECTION_AUTHORITY);
client->query.gluedb = NULL;
if (WANTDNSSEC(client) && dns_db_issecure(db))
query_addds(client, db, node);
} else {
/*
* We might have a better answer or delegation
......@@ -2789,6 +2711,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
/*
* Recurse!
*/
/* XXXBEW look at this? */
if (type == dns_rdatatype_key)
result = query_recurse(client, qtype,
NULL, NULL);
......@@ -2826,6 +2749,9 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
client->query.gluedb = NULL;
client->query.attributes &=
~NS_QUERYATTR_CACHEGLUEOK;
if (WANTDNSSEC(client) &&
!dns_rdataset_isassociated(sigrdataset))
query_addds(client, db, node);
}
}
goto cleanup;
......@@ -2857,8 +2783,8 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
/*
* Add NXT record if we found one.
*/
if (dns_rdataset_isassociated(rdataset)) {
if (WANTDNSSEC(client))
if (WANTDNSSEC(client)) {
if (dns_rdataset_isassociated(rdataset))
query_addrrset(client, &fname, &rdataset,
&sigrdataset,
NULL, DNS_SECTION_AUTHORITY);
......
......@@ -15,7 +15,7 @@
# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
# $Id: conf.sh.in,v 1.23 2001/08/01 19:00:58 gson Exp $
# $Id: conf.sh.in,v 1.24 2002/06/17 04:01:10 marka Exp $
#
# Common configuration data for system tests, to be sourced into
......@@ -37,8 +37,6 @@ RNDC=$TOP/bin/rndc/rndc
NSUPDATE=$TOP/bin/nsupdate/nsupdate
KEYGEN=$TOP/bin/dnssec/dnssec-keygen
SIGNER=$TOP/bin/dnssec/dnssec-signzone
KEYSIGNER=$TOP/bin/dnssec/dnssec-signkey
KEYSETTOOL=$TOP/bin/dnssec/dnssec-makekeyset
# The "stress" test is not run by default since it creates enough
# load on the machine to make it unusable to other users.
......
......@@ -15,7 +15,7 @@
# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
# $Id: sign.sh,v 1.13 2001/09/17 17:42:04 bwelling Exp $
# $Id: sign.sh,v 1.14 2002/06/17 04:01:12 marka Exp $
SYSTEMTESTTOP=../..
. $SYSTEMTESTTOP/conf.sh
......@@ -26,17 +26,11 @@ zone=.
infile=root.db.in
zonefile=root.db
keyname=`$KEYGEN -r $RANDFILE -a RSA -b 768 -n zone $zone`
(cd ../ns2 && sh sign.sh )
cp ../ns2/keyset-example. .
$KEYSIGNER -r $RANDFILE keyset-example. $keyname > /dev/null
cat signedkey-example. >> ../ns2/example.db.signed
$KEYSETTOOL -r $RANDFILE -t 3600 $keyname > /dev/null
keyname=`$KEYGEN -r $RANDFILE -a RSA -b 768 -n zone $zone`
cat $infile $keyname.key > $zonefile
......
......@@ -15,7 +15,7 @@
# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
# $Id: sign.sh,v 1.19 2002/02/20 03:33:55 marka Exp $
# $Id: sign.sh,v 1.20 2002/06/17 04:01:14 marka Exp $
SYSTEMTESTTOP=../..
. $SYSTEMTESTTOP/conf.sh
......@@ -26,29 +26,21 @@ zone=example.
infile=example.db.in
zonefile=example.db
keyname=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone`
# Have the child generate a zone key and pass it to us,
# sign it, and pass it back
# Have the child generate a zone key and pass it to us.
( cd ../ns3 && sh sign.sh )
for subdomain in secure bogus dynamic
do
cp ../ns3/keyset-$subdomain.example. .
$KEYSIGNER -r $RANDFILE keyset-$subdomain.example. $keyname > /dev/null
# This will leave two copies of the child's zone key in the signed db file;
# that shouldn't cause any problems.
cat signedkey-$subdomain.example. >>../ns3/$subdomain.example.db.signed
done
$KEYSETTOOL -r $RANDFILE -t 3600 $keyname > /dev/null
keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone`
keyname2=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone`
cat $infile $keyname.key >$zonefile
cat $infile $keyname1.key $keyname2.key >$zonefile
$SIGNER -r $RANDFILE -o $zone $zonefile > /dev/null
$SIGNER -r $RANDFILE -o $zone -k $keyname1 $zonefile $keyname2 > /dev/null
# Sign the privately secure file
......
......@@ -15,7 +15,7 @@
# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
# $Id: sign.sh,v 1.16 2002/02/20 03:33:59 marka Exp $
# $Id: sign.sh,v 1.17 2002/06/17 04:01:15 marka Exp $
RANDFILE=../random.data
......@@ -25,8 +25,6 @@ zonefile=secure.example.db
keyname=`$KEYGEN -r $RANDFILE -a RSASHA1 -b 768 -n zone $zone`
$KEYSETTOOL -r $RANDFILE -t 3600 $keyname.key > /dev/null
cat $infile $keyname.key >$zonefile
$SIGNER -r $RANDFILE -o $zone $zonefile > /dev/null
......@@ -37,8 +35,6 @@ zonefile=bogus.example.db
keyname=`$KEYGEN -r $RANDFILE -a RSA -b 768 -n zone $zone`
$KEYSETTOOL -r $RANDFILE -t 3600 $keyname.key > /dev/null
cat $infile $keyname.key >$zonefile
$SIGNER -r $RANDFILE -o $zone $zonefile > /dev/null
......@@ -49,8 +45,6 @@ zonefile=dynamic.example.db
keyname=`$KEYGEN -r $RANDFILE -a RSA -b 768 -n zone $zone`
$KEYSETTOOL -r $RANDFILE -t 3600 $keyname.key > /dev/null
cat $infile $keyname.key >$zonefile
$SIGNER -r $RANDFILE -o $zone $zonefile > /dev/null
......@@ -61,8 +55,6 @@ zonefile=keyless.example.db
keyname=`$KEYGEN -r $RANDFILE -a RSA -b 768 -n zone $zone`
$KEYSETTOOL -r $RANDFILE -t 3600 $keyname.key > /dev/null
cat $infile $keyname.key >$zonefile
$SIGNER -r $RANDFILE -o $zone $zonefile > /dev/null
......
......@@ -15,7 +15,7 @@
# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
# $Id: tests.sh,v 1.39 2002/02/20 03:33:50 marka Exp $
# $Id: tests.sh,v 1.40 2002/06/17 04:01:11 marka Exp $
SYSTEMTESTTOP=..
. $SYSTEMTESTTOP/conf.sh
......@@ -25,7 +25,7 @@ n=0
rm -f dig.out.*
DIGOPTS="+tcp +noadd +nosea +nostat +noquest +nocmd +dnssec -p 5300"
DIGOPTS="+tcp +noadd +nosea +nostat +nocmd +dnssec -p 5300"
# Check the example. domain
......@@ -113,6 +113,14 @@ n=`expr $n + 1`
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
echo "I:checking that insecurity proofs fail with a misconfigured trusted key ($n)"
ret=0
$DIG $DIGOPTS a.insecure.example. a @10.53.0.5 > dig.out.ns5.test$n || ret=1
grep "SERVFAIL" dig.out.ns5.test$n > /dev/null || ret=1
n=`expr $n + 1`
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
echo "I:checking that validation fails when key record is missing ($n)"
ret=0
$DIG $DIGOPTS a.b.keyless.example. a @10.53.0.4 > dig.out.ns4.test$n || ret=1
......
......@@ -13,7 +13,7 @@
# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
# $Id: Makefile.in,v 1.129 2002/03/07 06:29:36 marka Exp $
# $Id: Makefile.in,v 1.130 2002/06/17 04:01:17 marka Exp $
srcdir = @srcdir@
VPATH = @srcdir@
......@@ -46,7 +46,7 @@ DSTOBJS = sec/dst/dst_api.@O@ \
OBJS = a6.@O@ acl.@O@ adb.@O@ byaddr.@O@ \
cache.@O@ callbacks.@O@ compress.@O@ \
db.@O@ dbiterator.@O@ dbtable.@O@ diff.@O@ dispatch.@O@ \
dnssec.@O@ forward.@O@ journal.@O@ keytable.@O@ \
dnssec.@O@ ds.@O@ forward.@O@ journal.@O@ keytable.@O@ \
lib.@O@ log.@O@ lookup.@O@ \
master.@O@ masterdump.@O@ message.@O@ \
name.@O@ ncache.@O@ nxt.@O@ order.@O@ peer.@O@ \
......@@ -62,7 +62,7 @@ OBJS = a6.@O@ acl.@O@ adb.@O@ byaddr.@O@ \
SRCS = a6.c acl.c adb.c byaddr.c \
cache.c callbacks.c compress.c \
db.c dbiterator.c dbtable.c diff.c dispatch.c \
dnssec.c forward.c journal.c keytable.c \
dnssec.c ds.c forward.c journal.c keytable.c \
lib.c log.c lookup.c \
master.c masterdump.c message.c \
name.c ncache.c nxt.c order.c peer.c \
......
/*
* Copyright (C) 1999-2001 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: ds.c,v 1.2 2002/06/17 04:01:18 marka Exp $ */
#include <config.h>
#include <string.h>
#include <isc/buffer.h>
#include <isc/region.h>
#include <isc/sha1.h>
#include <isc/util.h>
#include <dns/ds.h>
#include <dns/fixedname.h>
#include <dns/name.h>
#include <dns/rdata.h>
#include <dns/rdatastruct.h>
#include <dns/result.h>
#include <dst/dst.h>
isc_result_t
dns_ds_buildrdata(dns_name_t *owner, dns_rdata_t *key,
unsigned int digest_type, unsigned char *buffer,
dns_rdata_t *rdata)
{
isc_sha1_t sha1;
dns_fixedname_t fname;
dns_name_t *name;
unsigned char digest[ISC_SHA1_DIGESTLENGTH];
isc_region_t r;
isc_buffer_t b;
dns_rdata_ds_t ds;
if (digest_type != DNS_DSDIGEST_SHA1)
return (ISC_R_NOTIMPLEMENTED);
dns_fixedname_init(&fname);
name = dns_fixedname_name(&fname);
(void)dns_name_downcase(owner, name, NULL);
memset(buffer, 0, DNS_DS_BUFFERSIZE);
isc_buffer_init(&b, buffer, DNS_DS_BUFFERSIZE);
isc_sha1_init(&sha1);
dns_name_toregion(name, &r);
isc_sha1_update(&sha1, r.base, r.length);
dns_rdata_toregion(key, &r);
INSIST(r.length >= 4);
isc_sha1_update(&sha1, r.base, r.length);
isc_sha1_final(&sha1, digest);
ds.mctx = NULL;
ds.common.rdclass = key->rdclass;
ds.common.rdtype = dns_rdatatype_ds;
ds.algorithm = r.base[3];
ds.key_tag = dst_region_computeid(&r, ds.algorithm);