This commit was manufactured by cvs2git to create branch 'v9_4'.
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
SQLite BIND SDB driver
|
||||
|
||||
The SQLite BIND SDB "driver" is intended as an alternative both to the
|
||||
pgsqldb and dirdb drivers, for situations that would like the management
|
||||
simplicity and convenience of single filesystem files, with the additional
|
||||
capability of SQL databases. It is also intended as an alternative to
|
||||
the standard dynamic DNS update capability in bind, which effectively
|
||||
requires use of DNSSEC keys for authorization and is limited to 'nsupdate'
|
||||
for updates. An sqlite database, by contrast, uses and requires only
|
||||
normal filesystem permissions, and may be updated however a typical SQLite
|
||||
database might be updated, e.g., via a web service with an SQLite backend.
|
||||
|
||||
This driver is not considered suitable for very high volume public
|
||||
nameserver use, while likely useful for smaller private nameserver
|
||||
applications, whether or not in a production environment. It should
|
||||
generally be suitable wherever SQLite is preferable over larger database
|
||||
engines, and not suitable where SQLite is not preferable.
|
||||
|
||||
Usage:
|
||||
|
||||
o Use the named_sdb process ( put ENABLE_SDB=yes in /etc/sysconfig/named )
|
||||
|
||||
o Edit your named.conf to contain a database zone, eg.:
|
||||
|
||||
zone "mydomain.net." IN {
|
||||
type master;
|
||||
database "sqlite /etc/named.d/mydomain.db mydomain";
|
||||
# ^- DB file ^-Table
|
||||
};
|
||||
|
||||
o Create the database zone table
|
||||
The table must contain the columns "name", "rdtype", and "rdata", and
|
||||
is expected to contain a properly constructed zone. The program
|
||||
"zone2sqlite" creates such a table.
|
||||
|
||||
zone2sqlite usage:
|
||||
|
||||
zone2sqlite origin zonefile dbfile dbtable
|
||||
|
||||
where
|
||||
origin : zone origin, eg "mydomain.net."
|
||||
zonefile : master zone database file, eg. mydomain.net.zone
|
||||
dbfile : name of SQLite database file
|
||||
dbtable : name of table in database
|
||||
|
||||
---
|
||||
# mydomain.net.zone:
|
||||
$TTL 1H
|
||||
@ SOA localhost. root.localhost. ( 1
|
||||
3H
|
||||
1H
|
||||
1W
|
||||
1H )
|
||||
NS localhost.
|
||||
host1 A 192.168.2.1
|
||||
host2 A 192.168.2.2
|
||||
host3 A 192.168.2.3
|
||||
host4 A 192.168.2.4
|
||||
host5 A 192.168.2.5
|
||||
host6 A 192.168.2.6
|
||||
host7 A 192.168.2.7
|
||||
---
|
||||
|
||||
# zone2sqlite mydomain.net. mydomain.net.zone mydomain.net.db mydomain
|
||||
|
||||
will create/update the 'mydomain' table in database file 'mydomain.net.db'.
|
||||
|
||||
@@ -0,0 +1,324 @@
|
||||
/*
|
||||
* Copyright (C) 2007 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: sqlitedb.c,v 1.1 2007/03/05 05:30:22 marka Exp $ */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <sqlite3.h>
|
||||
|
||||
#include <isc/mem.h>
|
||||
#include <isc/print.h>
|
||||
#include <isc/result.h>
|
||||
#include <isc/util.h>
|
||||
|
||||
#include <dns/sdb.h>
|
||||
#include <dns/result.h>
|
||||
|
||||
#include <named/globals.h>
|
||||
|
||||
#include "sqlitedb.h"
|
||||
|
||||
/*
|
||||
* A simple database driver that interfaces to a SQLite database.
|
||||
*
|
||||
* The table must contain the fields "name", "rdtype", and "rdata", and
|
||||
* is expected to contain a properly constructed zone. The program "zonetodb"
|
||||
* creates such a table.
|
||||
*/
|
||||
|
||||
static dns_sdbimplementation_t *sqlitedb = NULL;
|
||||
|
||||
typedef struct _dbinfo {
|
||||
sqlite3 *db;
|
||||
char *filename;
|
||||
char *table;
|
||||
} dbinfo_t;
|
||||
|
||||
|
||||
static isc_result_t
|
||||
db_connect(dbinfo_t *dbi)
|
||||
{
|
||||
if (sqlite3_open(dbi->filename, &dbi->db) == SQLITE_OK) {
|
||||
return (ISC_R_SUCCESS);
|
||||
} else {
|
||||
/* a connection is returned even if the open fails */
|
||||
sqlite3_close(dbi->db);
|
||||
dbi->db = NULL;
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
typedef struct _lookup_parm_t {
|
||||
int i;
|
||||
dns_sdblookup_t *lookup;
|
||||
isc_result_t result;
|
||||
} lookup_parm_t;
|
||||
|
||||
|
||||
static int
|
||||
sqlitedb_lookup_cb(void *p, int cc, char **cv, char **cn)
|
||||
{
|
||||
lookup_parm_t *parm = p;
|
||||
dns_ttl_t ttl;
|
||||
char *endp;
|
||||
|
||||
/* FIXME - check these(num/names); I'm assuming a mapping for now */
|
||||
char *ttlstr = cv[0];
|
||||
char *type = cv[1];
|
||||
char *data = cv[2];
|
||||
|
||||
UNUSED(cc);
|
||||
UNUSED(cn);
|
||||
|
||||
ttl = strtol(ttlstr, &endp, 10);
|
||||
if (*endp) {
|
||||
parm->result = DNS_R_BADTTL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
parm->result = dns_sdb_putrr(parm->lookup, type, ttl, data);
|
||||
|
||||
if (parm->result != ISC_R_SUCCESS)
|
||||
return 1;
|
||||
|
||||
(parm->i)++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static isc_result_t
|
||||
sqlitedb_lookup(const char *zone,
|
||||
const char *name, void *dbdata,
|
||||
dns_sdblookup_t *lookup)
|
||||
/*
|
||||
* synchronous absolute name lookup
|
||||
*/
|
||||
{
|
||||
dbinfo_t *dbi = (dbinfo_t *) dbdata;
|
||||
char *sql;
|
||||
lookup_parm_t parm = { 0, lookup, ISC_R_SUCCESS };
|
||||
char *errmsg = NULL;
|
||||
int result;
|
||||
|
||||
UNUSED(zone);
|
||||
|
||||
sql = sqlite3_mprintf(
|
||||
"SELECT TTL,RDTYPE,RDATA FROM \"%q\" WHERE "
|
||||
"lower(NAME) = lower('%q')",
|
||||
dbi->table, name);
|
||||
|
||||
result = sqlite3_exec(dbi->db, sql,
|
||||
&sqlitedb_lookup_cb, &parm,
|
||||
&errmsg);
|
||||
sqlite3_free(sql);
|
||||
|
||||
if (result != SQLITE_OK)
|
||||
return (ISC_R_FAILURE);
|
||||
if (parm.i == 0)
|
||||
return (ISC_R_NOTFOUND);
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
typedef struct _allnodes_parm_t {
|
||||
int i;
|
||||
dns_sdballnodes_t *allnodes;
|
||||
isc_result_t result;
|
||||
} allnodes_parm_t;
|
||||
|
||||
|
||||
static int
|
||||
sqlitedb_allnodes_cb(void *p, int cc, char **cv, char **cn)
|
||||
{
|
||||
allnodes_parm_t *parm = p;
|
||||
dns_ttl_t ttl;
|
||||
char *endp;
|
||||
|
||||
/* FIXME - check these(num/names); I'm assuming a mapping for now */
|
||||
char *ttlstr = cv[0];
|
||||
char *name = cv[1];
|
||||
char *type = cv[2];
|
||||
char *data = cv[3];
|
||||
|
||||
UNUSED(cc);
|
||||
UNUSED(cn);
|
||||
|
||||
ttl = strtol(ttlstr, &endp, 10);
|
||||
if (*endp) {
|
||||
parm->result = DNS_R_BADTTL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
parm->result = dns_sdb_putnamedrr(parm->allnodes, name, type, ttl, data);
|
||||
|
||||
if (parm->result != ISC_R_SUCCESS)
|
||||
return 1;
|
||||
|
||||
(parm->i)++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static isc_result_t
|
||||
sqlitedb_allnodes(const char *zone,
|
||||
void *dbdata,
|
||||
dns_sdballnodes_t *allnodes)
|
||||
{
|
||||
dbinfo_t *dbi = (dbinfo_t *) dbdata;
|
||||
char *sql;
|
||||
allnodes_parm_t parm = { 0, allnodes, ISC_R_SUCCESS };
|
||||
char *errmsg = NULL;
|
||||
int result;
|
||||
|
||||
UNUSED(zone);
|
||||
|
||||
sql = sqlite3_mprintf(
|
||||
"SELECT TTL,NAME,RDTYPE,RDATA FROM \"%q\" ORDER BY NAME",
|
||||
dbi->table);
|
||||
|
||||
result = sqlite3_exec(dbi->db, sql,
|
||||
&sqlitedb_allnodes_cb, &parm,
|
||||
&errmsg);
|
||||
sqlite3_free(sql);
|
||||
|
||||
if (result != SQLITE_OK)
|
||||
return (ISC_R_FAILURE);
|
||||
if (parm.i == 0)
|
||||
return (ISC_R_NOTFOUND);
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
sqlitedb_destroy(const char *zone, void *driverdata, void **dbdata)
|
||||
{
|
||||
dbinfo_t *dbi = *dbdata;
|
||||
|
||||
UNUSED(zone);
|
||||
UNUSED(driverdata);
|
||||
|
||||
if (dbi->db != NULL)
|
||||
sqlite3_close(dbi->db);
|
||||
if (dbi->table != NULL)
|
||||
isc_mem_free(ns_g_mctx, dbi->table);
|
||||
if (dbi->filename != NULL)
|
||||
isc_mem_free(ns_g_mctx, dbi->filename);
|
||||
|
||||
isc_mem_put(ns_g_mctx, dbi, sizeof(dbinfo_t));
|
||||
}
|
||||
|
||||
|
||||
#define STRDUP_OR_FAIL(target, source) \
|
||||
do { \
|
||||
target = isc_mem_strdup(ns_g_mctx, source); \
|
||||
if (target == NULL) { \
|
||||
result = ISC_R_NOMEMORY; \
|
||||
goto cleanup; \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
/*
|
||||
* Create a connection to the database and save any necessary information
|
||||
* in dbdata.
|
||||
*
|
||||
* argv[0] is the name of the database file
|
||||
* argv[1] is the name of the table
|
||||
*/
|
||||
static isc_result_t
|
||||
sqlitedb_create(const char *zone,
|
||||
int argc, char **argv,
|
||||
void *driverdata, void **dbdata)
|
||||
{
|
||||
dbinfo_t *dbi;
|
||||
isc_result_t result;
|
||||
|
||||
UNUSED(zone);
|
||||
UNUSED(driverdata);
|
||||
|
||||
if (argc < 2)
|
||||
return (ISC_R_FAILURE);
|
||||
|
||||
dbi = isc_mem_get(ns_g_mctx, sizeof(dbinfo_t));
|
||||
if (dbi == NULL)
|
||||
return (ISC_R_NOMEMORY);
|
||||
dbi->db = NULL;
|
||||
dbi->filename = NULL;
|
||||
dbi->table = NULL;
|
||||
|
||||
STRDUP_OR_FAIL(dbi->filename, argv[0]);
|
||||
STRDUP_OR_FAIL(dbi->table, argv[1]);
|
||||
|
||||
result = db_connect(dbi);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup;
|
||||
|
||||
*dbdata = dbi;
|
||||
return (ISC_R_SUCCESS);
|
||||
|
||||
cleanup:
|
||||
sqlitedb_destroy(zone, driverdata, (void **)&dbi);
|
||||
return (result);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Since the SQL database corresponds to a zone, the authority data should
|
||||
* be returned by the lookup() function. Therefore the authority() function
|
||||
* is NULL.
|
||||
*/
|
||||
static dns_sdbmethods_t sqlitedb_methods = {
|
||||
sqlitedb_lookup,
|
||||
NULL, /* authority */
|
||||
sqlitedb_allnodes,
|
||||
sqlitedb_create,
|
||||
sqlitedb_destroy
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Wrapper around dns_sdb_register().
|
||||
*/
|
||||
isc_result_t
|
||||
sqlitedb_init(void)
|
||||
{
|
||||
unsigned int flags;
|
||||
flags = 0;
|
||||
return (dns_sdb_register("sqlite", &sqlitedb_methods, NULL, flags,
|
||||
ns_g_mctx, &sqlitedb));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Wrapper around dns_sdb_unregister().
|
||||
*/
|
||||
void
|
||||
sqlitedb_clear(void)
|
||||
{
|
||||
if (sqlitedb != NULL)
|
||||
dns_sdb_unregister(&sqlitedb);
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (C) 2000-2002 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: sqlitedb.h,v 1.1 2007/03/05 05:30:22 marka Exp $ */
|
||||
|
||||
#include <isc/types.h>
|
||||
|
||||
isc_result_t sqlitedb_init(void);
|
||||
|
||||
void sqlitedb_clear(void);
|
||||
|
||||
@@ -0,0 +1,301 @@
|
||||
/*
|
||||
* Copyright (C) 2007 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: zone2sqlite.c,v 1.1 2007/03/05 05:30:22 marka Exp $ */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <isc/buffer.h>
|
||||
#include <isc/mem.h>
|
||||
#include <isc/print.h>
|
||||
#include <isc/result.h>
|
||||
|
||||
#include <dns/db.h>
|
||||
#include <dns/dbiterator.h>
|
||||
#include <dns/fixedname.h>
|
||||
#include <dns/name.h>
|
||||
#include <dns/rdata.h>
|
||||
#include <dns/rdataset.h>
|
||||
#include <dns/rdatasetiter.h>
|
||||
#include <dns/rdatatype.h>
|
||||
#include <dns/result.h>
|
||||
|
||||
#include <sqlite3.h>
|
||||
|
||||
#ifndef UNUSED
|
||||
#define UNUSED(x) (x) = (x)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Generate an SQLite table from a zone.
|
||||
*/
|
||||
|
||||
typedef struct _dbinfo {
|
||||
sqlite3 *db;
|
||||
char *filename;
|
||||
char *table;
|
||||
} dbinfo_t;
|
||||
|
||||
dbinfo_t dbi = { NULL, NULL, NULL };
|
||||
|
||||
|
||||
static void
|
||||
closeandexit(int status)
|
||||
{
|
||||
if (dbi.db) {
|
||||
sqlite3_close(dbi.db);
|
||||
dbi.db = NULL;
|
||||
}
|
||||
exit(status);
|
||||
}
|
||||
|
||||
static void
|
||||
check_result(isc_result_t result, const char *message)
|
||||
{
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
fprintf(stderr, "%s: %s\n", message,
|
||||
isc_result_totext(result));
|
||||
closeandexit(1);
|
||||
}
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
db_connect(dbinfo_t *dbi)
|
||||
{
|
||||
if (sqlite3_open(dbi->filename, &dbi->db) == SQLITE_OK) {
|
||||
return (ISC_R_SUCCESS);
|
||||
} else {
|
||||
/* a connection is returned even if the open fails */
|
||||
sqlite3_close(dbi->db);
|
||||
dbi->db = NULL;
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
add_rdata_cb(void *parm, int cc, char **cv, char **cn)
|
||||
{
|
||||
UNUSED(parm);
|
||||
UNUSED(cc);
|
||||
UNUSED(cv);
|
||||
UNUSED(cn);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
addrdata(dns_name_t *name, dns_ttl_t ttl, dns_rdata_t *rdata)
|
||||
{
|
||||
unsigned char namearray[DNS_NAME_MAXTEXT + 1];
|
||||
unsigned char typearray[20];
|
||||
unsigned char dataarray[2048];
|
||||
isc_buffer_t b;
|
||||
isc_result_t result;
|
||||
char *sql;
|
||||
char *errmsg = NULL;
|
||||
int res;
|
||||
|
||||
isc_buffer_init(&b, namearray, sizeof(namearray) - 1);
|
||||
result = dns_name_totext(name, ISC_TRUE, &b);
|
||||
check_result(result, "dns_name_totext");
|
||||
namearray[isc_buffer_usedlength(&b)] = 0;
|
||||
|
||||
isc_buffer_init(&b, typearray, sizeof(typearray) - 1);
|
||||
result = dns_rdatatype_totext(rdata->type, &b);
|
||||
check_result(result, "dns_rdatatype_totext");
|
||||
typearray[isc_buffer_usedlength(&b)] = 0;
|
||||
|
||||
isc_buffer_init(&b, dataarray, sizeof(dataarray) - 1);
|
||||
result = dns_rdata_totext(rdata, NULL, &b);
|
||||
check_result(result, "dns_rdata_totext");
|
||||
dataarray[isc_buffer_usedlength(&b)] = 0;
|
||||
|
||||
sql = sqlite3_mprintf(
|
||||
"INSERT INTO %q (NAME, TTL, RDTYPE, RDATA)"
|
||||
" VALUES ('%q', %d, '%q', '%q') ",
|
||||
dbi.table,
|
||||
namearray, ttl, typearray, dataarray);
|
||||
printf("%s\n", sql);
|
||||
res = sqlite3_exec(dbi.db, sql, add_rdata_cb, NULL, &errmsg);
|
||||
sqlite3_free(sql);
|
||||
|
||||
if (result != SQLITE_OK) {
|
||||
fprintf(stderr, "INSERT failed: %s\n", errmsg);
|
||||
closeandexit(1);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
char *sql;
|
||||
int res;
|
||||
char *errmsg = NULL;
|
||||
char *porigin, *zonefile;
|
||||
dns_fixedname_t forigin, fname;
|
||||
dns_name_t *origin, *name;
|
||||
dns_db_t *db = NULL;
|
||||
dns_dbiterator_t *dbiter;
|
||||
dns_dbnode_t *node;
|
||||
dns_rdatasetiter_t *rdsiter;
|
||||
dns_rdataset_t rdataset;
|
||||
dns_rdata_t rdata = DNS_RDATA_INIT;
|
||||
isc_mem_t *mctx = NULL;
|
||||
isc_buffer_t b;
|
||||
isc_result_t result;
|
||||
|
||||
if (argc != 5) {
|
||||
printf("usage: %s <zone> <zonefile> <dbfile> <dbtable>\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
porigin = argv[1];
|
||||
zonefile = argv[2];
|
||||
|
||||
dbi.filename = argv[3];
|
||||
dbi.table = argv[4];
|
||||
|
||||
dns_result_register();
|
||||
|
||||
mctx = NULL;
|
||||
result = isc_mem_create(0, 0, &mctx);
|
||||
check_result(result, "isc_mem_create");
|
||||
|
||||
isc_buffer_init(&b, porigin, strlen(porigin));
|
||||
isc_buffer_add(&b, strlen(porigin));
|
||||
dns_fixedname_init(&forigin);
|
||||
origin = dns_fixedname_name(&forigin);
|
||||
result = dns_name_fromtext(origin, &b, dns_rootname, ISC_FALSE, NULL);
|
||||
check_result(result, "dns_name_fromtext");
|
||||
|
||||
db = NULL;
|
||||
result = dns_db_create(mctx, "rbt", origin, dns_dbtype_zone,
|
||||
dns_rdataclass_in, 0, NULL, &db);
|
||||
check_result(result, "dns_db_create");
|
||||
|
||||
result = dns_db_load(db, zonefile);
|
||||
if (result == DNS_R_SEENINCLUDE)
|
||||
result = ISC_R_SUCCESS;
|
||||
check_result(result, "dns_db_load");
|
||||
|
||||
printf("Connecting to '%s'\n", dbi.filename);
|
||||
|
||||
if ((result = db_connect(&dbi)) != ISC_R_SUCCESS) {
|
||||
fprintf(stderr, "Connection to database '%s' failed\n",
|
||||
dbi.filename);
|
||||
closeandexit(1);
|
||||
}
|
||||
|
||||
sql = sqlite3_mprintf("DROP TABLE %q ", dbi.table);
|
||||
printf("%s\n", sql);
|
||||
res = sqlite3_exec(dbi.db, sql, NULL, NULL, &errmsg);
|
||||
sqlite3_free(sql);
|
||||
#if 0
|
||||
if (res != SQLITE_OK) {
|
||||
fprintf(stderr, "DROP TABLE %s failed: %s\n",
|
||||
dbi.table, errmsg);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
sql = sqlite3_mprintf(sql, "BEGIN TRANSACTION");
|
||||
printf("%s\n", sql);
|
||||
res = sqlite3_exec(dbi.db, sql, NULL, NULL, &errmsg);
|
||||
sqlite3_free(sql);
|
||||
if (res != SQLITE_OK) {
|
||||
fprintf(stderr, "BEGIN TRANSACTION failed: %s\n", errmsg);
|
||||
closeandexit(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
sql = sqlite3_mprintf(
|
||||
"CREATE TABLE %q "
|
||||
"(NAME TEXT, TTL INTEGER, RDTYPE TEXT, RDATA TEXT) ",
|
||||
dbi.table);
|
||||
printf("%s\n", sql);
|
||||
res = sqlite3_exec(dbi.db, sql, NULL, NULL, &errmsg);
|
||||
sqlite3_free(sql);
|
||||
if (res != SQLITE_OK) {
|
||||
fprintf(stderr, "CREATE TABLE %s failed: %s\n",
|
||||
dbi.table, errmsg);
|
||||
closeandexit(1);
|
||||
}
|
||||
|
||||
dbiter = NULL;
|
||||
result = dns_db_createiterator(db, ISC_FALSE, &dbiter);
|
||||
check_result(result, "dns_db_createiterator()");
|
||||
|
||||
result = dns_dbiterator_first(dbiter);
|
||||
check_result(result, "dns_dbiterator_first");
|
||||
|
||||
dns_fixedname_init(&fname);
|
||||
name = dns_fixedname_name(&fname);
|
||||
dns_rdataset_init(&rdataset);
|
||||
dns_rdata_init(&rdata);
|
||||
|
||||
while (result == ISC_R_SUCCESS) {
|
||||
node = NULL;
|
||||
result = dns_dbiterator_current(dbiter, &node, name);
|
||||
if (result == ISC_R_NOMORE)
|
||||
break;
|
||||
check_result(result, "dns_dbiterator_current");
|
||||
|
||||
rdsiter = NULL;
|
||||
result = dns_db_allrdatasets(db, node, NULL, 0, &rdsiter);
|
||||
check_result(result, "dns_db_allrdatasets");
|
||||
|
||||
result = dns_rdatasetiter_first(rdsiter);
|
||||
|
||||
while (result == ISC_R_SUCCESS) {
|
||||
dns_rdatasetiter_current(rdsiter, &rdataset);
|
||||
result = dns_rdataset_first(&rdataset);
|
||||
check_result(result, "dns_rdataset_first");
|
||||
while (result == ISC_R_SUCCESS) {
|
||||
dns_rdataset_current(&rdataset, &rdata);
|
||||
addrdata(name, rdataset.ttl, &rdata);
|
||||
dns_rdata_reset(&rdata);
|
||||
result = dns_rdataset_next(&rdataset);
|
||||
}
|
||||
dns_rdataset_disassociate(&rdataset);
|
||||
result = dns_rdatasetiter_next(rdsiter);
|
||||
}
|
||||
dns_rdatasetiter_destroy(&rdsiter);
|
||||
dns_db_detachnode(db, &node);
|
||||
result = dns_dbiterator_next(dbiter);
|
||||
}
|
||||
|
||||
#if 0
|
||||
sql = sqlite3_mprintf(sql, "COMMIT TRANSACTION ");
|
||||
printf("%s\n", sql);
|
||||
res = sqlite3_exec(dbi.db, sql, NULL, NULL, &errmsg);
|
||||
sqlite3_free(sql);
|
||||
if (res != SQLITE_OK) {
|
||||
fprintf(stderr, "COMMIT TRANSACTION failed: %s\n", errmsg);
|
||||
closeandexit(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
dns_dbiterator_destroy(&dbiter);
|
||||
dns_db_detach(&db);
|
||||
isc_mem_destroy(&mctx);
|
||||
|
||||
closeandexit(0);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
@@ -0,0 +1,729 @@
|
||||
|
||||
|
||||
|
||||
Network Working Group M. StJohns
|
||||
Internet-Draft Nominum, Inc.
|
||||
Intended status: Informational November 29, 2006
|
||||
Expires: June 2, 2007
|
||||
|
||||
|
||||
Automated Updates of DNSSEC Trust Anchors
|
||||
draft-ietf-dnsext-trustupdate-timers-05
|
||||
|
||||
Status of this Memo
|
||||
|
||||
By submitting this Internet-Draft, each author represents that any
|
||||
applicable patent or other IPR claims of which he or she is aware
|
||||
have been or will be disclosed, and any of which he or she becomes
|
||||
aware will be disclosed, in accordance with Section 6 of BCP 79.
|
||||
|
||||
Internet-Drafts are working documents of the Internet Engineering
|
||||
Task Force (IETF), its areas, and its working groups. Note that
|
||||
other groups may also distribute working documents as Internet-
|
||||
Drafts.
|
||||
|
||||
Internet-Drafts are draft documents valid for a maximum of six months
|
||||
and may be updated, replaced, or obsoleted by other documents at any
|
||||
time. It is inappropriate to use Internet-Drafts as reference
|
||||
material or to cite them other than as "work in progress."
|
||||
|
||||
The list of current Internet-Drafts can be accessed at
|
||||
http://www.ietf.org/ietf/1id-abstracts.txt.
|
||||
|
||||
The list of Internet-Draft Shadow Directories can be accessed at
|
||||
http://www.ietf.org/shadow.html.
|
||||
|
||||
This Internet-Draft will expire on June 2, 2007.
|
||||
|
||||
Copyright Notice
|
||||
|
||||
Copyright (C) The Internet Society (2006).
|
||||
|
||||
Abstract
|
||||
|
||||
This document describes a means for automated, authenticated and
|
||||
authorized updating of DNSSEC "trust anchors". The method provides
|
||||
protection against N-1 key compromises of N keys in the trust point
|
||||
key set. Based on the trust established by the presence of a current
|
||||
anchor, other anchors may be added at the same place in the
|
||||
hierarchy, and, ultimately, supplant the existing anchor(s).
|
||||
|
||||
This mechanism will require changes to resolver management behavior
|
||||
|
||||
|
||||
|
||||
StJohns Expires June 2, 2007 [Page 1]
|
||||
|
||||
Internet-Draft trustanchor-update November 2006
|
||||
|
||||
|
||||
(but not resolver resolution behavior), and the addition of a single
|
||||
flag bit to the DNSKEY record.
|
||||
|
||||
|
||||
Table of Contents
|
||||
|
||||
1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 3
|
||||
1.1. Compliance Nomenclature . . . . . . . . . . . . . . . . . 3
|
||||
2. Theory of Operation . . . . . . . . . . . . . . . . . . . . . 4
|
||||
2.1. Revocation . . . . . . . . . . . . . . . . . . . . . . . . 4
|
||||
2.2. Add Hold-Down . . . . . . . . . . . . . . . . . . . . . . 5
|
||||
2.3. Active Refresh . . . . . . . . . . . . . . . . . . . . . . 5
|
||||
2.4. Resolver Parameters . . . . . . . . . . . . . . . . . . . 6
|
||||
2.4.1. Add Hold-Down Time . . . . . . . . . . . . . . . . . . 6
|
||||
2.4.2. Remove Hold-Down Time . . . . . . . . . . . . . . . . 6
|
||||
2.4.3. Minimum Trust Anchors per Trust Point . . . . . . . . 6
|
||||
3. Changes to DNSKEY RDATA Wire Format . . . . . . . . . . . . . 6
|
||||
4. State Table . . . . . . . . . . . . . . . . . . . . . . . . . 6
|
||||
4.1. Events . . . . . . . . . . . . . . . . . . . . . . . . . . 7
|
||||
4.2. States . . . . . . . . . . . . . . . . . . . . . . . . . . 8
|
||||
5. Trust Point Deletion . . . . . . . . . . . . . . . . . . . . . 8
|
||||
6. Scenarios - Informative . . . . . . . . . . . . . . . . . . . 9
|
||||
6.1. Adding a Trust Anchor . . . . . . . . . . . . . . . . . . 9
|
||||
6.2. Deleting a Trust Anchor . . . . . . . . . . . . . . . . . 9
|
||||
6.3. Key Roll-Over . . . . . . . . . . . . . . . . . . . . . . 10
|
||||
6.4. Active Key Compromised . . . . . . . . . . . . . . . . . . 10
|
||||
6.5. Stand-by Key Compromised . . . . . . . . . . . . . . . . . 10
|
||||
6.6. Trust Point Deletion . . . . . . . . . . . . . . . . . . . 10
|
||||
7. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 11
|
||||
8. Security Considerations . . . . . . . . . . . . . . . . . . . 11
|
||||
8.1. Key Ownership vs Acceptance Policy . . . . . . . . . . . . 11
|
||||
8.2. Multiple Key Compromise . . . . . . . . . . . . . . . . . 11
|
||||
8.3. Dynamic Updates . . . . . . . . . . . . . . . . . . . . . 11
|
||||
9. Normative References . . . . . . . . . . . . . . . . . . . . . 12
|
||||
Editorial Comments . . . . . . . . . . . . . . . . . . . . . . . .
|
||||
Author's Address . . . . . . . . . . . . . . . . . . . . . . . . . 12
|
||||
Intellectual Property and Copyright Statements . . . . . . . . . . 13
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
StJohns Expires June 2, 2007 [Page 2]
|
||||
|
||||
Internet-Draft trustanchor-update November 2006
|
||||
|
||||
|
||||
1. Introduction
|
||||
|
||||
As part of the reality of fielding DNSSEC (Domain Name System
|
||||
Security Extensions) [RFC4033] [RFC4034] [RFC4035], the community has
|
||||
come to the realization that there will not be one signed name space,
|
||||
but rather islands of signed name space each originating from
|
||||
specific points (i.e. 'trust points') in the DNS tree. Each of those
|
||||
islands will be identified by the trust point name, and validated by
|
||||
at least one associated public key. For the purpose of this document
|
||||
we'll call the association of that name and a particular key a 'trust
|
||||
anchor'. A particular trust point can have more than one key
|
||||
designated as a trust anchor.
|
||||
|
||||
For a DNSSEC-aware resolver to validate information in a DNSSEC
|
||||
protected branch of the hierarchy, it must have knowledge of a trust
|
||||
anchor applicable to that branch. It may also have more than one
|
||||
trust anchor for any given trust point. Under current rules, a chain
|
||||
of trust for DNSSEC-protected data that chains its way back to ANY
|
||||
known trust anchor is considered 'secure'.
|
||||
|
||||
Because of the probable balkanization of the DNSSEC tree due to
|
||||
signing voids at key locations, a resolver may need to know literally
|
||||
thousands of trust anchors to perform its duties. (e.g. Consider an
|
||||
unsigned ".COM".) Requiring the owner of the resolver to manually
|
||||
manage this many relationships is problematic. It's even more
|
||||
problematic when considering the eventual requirement for key
|
||||
replacement/update for a given trust anchor. The mechanism described
|
||||
herein won't help with the initial configuration of the trust anchors
|
||||
in the resolvers, but should make trust point key replacement/
|
||||
rollover more viable.
|
||||
|
||||
As mentioned above, this document describes a mechanism whereby a
|
||||
resolver can update the trust anchors for a given trust point, mainly
|
||||
without human intervention at the resolver. There are some corner
|
||||
cases discussed (e.g. multiple key compromise) that may require
|
||||
manual intervention, but they should be few and far between. This
|
||||
document DOES NOT discuss the general problem of the initial
|
||||
configuration of trust anchors for the resolver.
|
||||
|
||||
1.1. Compliance Nomenclature
|
||||
|
||||
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
|
||||
"SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
|
||||
document are to be interpreted as described in BCP 14, [RFC2119].
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
StJohns Expires June 2, 2007 [Page 3]
|
||||
|
||||
Internet-Draft trustanchor-update November 2006
|
||||
|
||||
|
||||
2. Theory of Operation
|
||||
|
||||
The general concept of this mechanism is that existing trust anchors
|
||||
can be used to authenticate new trust anchors at the same point in
|
||||
the DNS hierarchy. When a zone operator adds a new SEP key (i.e. a
|
||||
DNSKEY with the Secure Entry Point bit set) (see [RFC4034]section
|
||||
2.1.1) to a trust point DNSKEY RRSet, and when that RRSet is
|
||||
validated by an existing trust anchor, then the resolver can add the
|
||||
new key to its valid set of trust anchors for that trust point.
|
||||
|
||||
There are some issues with this approach which need to be mitigated.
|
||||
For example, a compromise of one of the existing keys could allow an
|
||||
attacker to add their own 'valid' data. This implies a need for a
|
||||
method to revoke an existing key regardless of whether or not that
|
||||
key is compromised. As another example, assuming a single key
|
||||
compromise, we need to prevent an attacker from adding a new key and
|
||||
revoking all the other old keys.
|
||||
|
||||
2.1. Revocation
|
||||
|
||||
Assume two trust anchor keys A and B. Assume that B has been
|
||||
compromised. Without a specific revocation bit, B could invalidate A
|
||||
simply by sending out a signed trust point key set which didn't
|
||||
contain A. To fix this, we add a mechanism which requires knowledge
|
||||
of the private key of a DNSKEY to revoke that DNSKEY.
|
||||
|
||||
A key is considered revoked when the resolver sees the key in a self-
|
||||
signed RRSet and the key has the REVOKE bit (see Section 7 below) set
|
||||
to '1'. Once the resolver sees the REVOKE bit, it MUST NOT use this
|
||||
key as a trust anchor or for any other purposes except validating the
|
||||
RRSIG it signed over the DNSKEY RRSet specifically for the purpose of
|
||||
validating the revocation. Unlike the 'Add' operation below,
|
||||
revocation is immediate and permanent upon receipt of a valid
|
||||
revocation at the resolver.
|
||||
|
||||
A self-signed RRSet is a DNSKEY RRSet which contains the specific
|
||||
DNSKEY and for which there is a corresponding validated RRSIG record.
|
||||
It's not a special DNSKEY RRSet, just a way of describing the
|
||||
validation requirements for that RRSet.
|
||||
|
||||
N.B. A DNSKEY with the REVOKE bit set has a different fingerprint
|
||||
than one without the bit set. This affects the matching of a DNSKEY
|
||||
to DS records in the parent, or the fingerprint stored at a resolver
|
||||
used to configure a trust point.
|
||||
|
||||
In the given example, the attacker could revoke B because it has
|
||||
knowledge of B's private key, but could not revoke A.
|
||||
|
||||
|
||||
|
||||
|
||||
StJohns Expires June 2, 2007 [Page 4]
|
||||
|
||||
Internet-Draft trustanchor-update November 2006
|
||||
|
||||
|
||||
2.2. Add Hold-Down
|
||||
|
||||
Assume two trust point keys A and B. Assume that B has been
|
||||
compromised. An attacker could generate and add a new trust anchor
|
||||
key - C (by adding C to the DNSKEY RRSet and signing it with B), and
|
||||
then invalidate the compromised key. This would result in both the
|
||||
attacker and owner being able to sign data in the zone and have it
|
||||
accepted as valid by resolvers.
|
||||
|
||||
To mitigate but not completely solve this problem, we add a hold-down
|
||||
time to the addition of the trust anchor. When the resolver sees a
|
||||
new SEP key in a validated trust point DNSKEY RRSet, the resolver
|
||||
starts an acceptance timer, and remembers all the keys that validated
|
||||
the RRSet. If the resolver ever sees the DNSKEY RRSet without the
|
||||
new key but validly signed, it stops the acceptance process for that
|
||||
key and resets the acceptance timer. If all of the keys which were
|
||||
originally used to validate this key are revoked prior to the timer
|
||||
expiring, the resolver stops the acceptance process and resets the
|
||||
timer.
|
||||
|
||||
Once the timer expires, the new key will be added as a trust anchor
|
||||
the next time the validated RRSet with the new key is seen at the
|
||||
resolver. The resolver MUST NOT treat the new key as a trust anchor
|
||||
until the hold down time expires AND it has retrieved and validated a
|
||||
DNSKEY RRSet after the hold down time which contains the new key.
|
||||
|
||||
N.B.: Once the resolver has accepted a key as a trust anchor, the key
|
||||
MUST be considered a valid trust anchor by that resolver until
|
||||
explictly revoked as described above.
|
||||
|
||||
In the given example, the zone owner can recover from a compromise by
|
||||
revoking B and adding a new key D and signing the DNSKEY RRSet with
|
||||
both A and B.
|
||||
|
||||
The reason this does not completely solve the problem has to do with
|
||||
the distributed nature of DNS. The resolver only knows what it sees.
|
||||
A determined attacker who holds one compromised key could keep a
|
||||
single resolver from realizing that key had been compromised by
|
||||
intercepting 'real' data from the originating zone and substituting
|
||||
their own (e.g. using the example, signed only by B). This is no
|
||||
worse than the current situation assuming a compromised key.
|
||||
|
||||
2.3. Active Refresh
|
||||
|
||||
A resolver which has been configured for automatic update of keys
|
||||
from a particular trust point MUST query that trust point (e.g. do a
|
||||
lookup for the DNSKEY RRSet and related RRSIG records) no less often
|
||||
than the lesser of 15 days or half the original TTL for the DNSKEY
|
||||
|
||||
|
||||
|
||||
StJohns Expires June 2, 2007 [Page 5]
|
||||
|
||||
Internet-Draft trustanchor-update November 2006
|
||||
|
||||
|
||||
RRSet or half the RRSIG expiration interval and no more often than
|
||||
once per hour. The expiration interval is the amount of time from
|
||||
when the RRSIG was last retrieved until the expiration time in the
|
||||
RRSIG.
|
||||
|
||||
If the query fails, the resolver MUST repeat the query until
|
||||
satisfied no more often than once an hour and no less often than the
|
||||
lesser of 1 day or 10% of the original TTL or 10% of the original
|
||||
expiration interval. I.e.: retryTime = MAX (1 hour, MIN (1 day, .1 *
|
||||
origTTL, .1 * expireInterval)).
|
||||
|
||||
2.4. Resolver Parameters
|
||||
|
||||
2.4.1. Add Hold-Down Time
|
||||
|
||||
The add hold-down time is 30 days or the expiration time of the
|
||||
original TTL of the first trust point DNSKEY RRSet which contained
|
||||
the new key, whichever is greater. This ensures that at least two
|
||||
validated DNSKEY RRSets which contain the new key MUST be seen by the
|
||||
resolver prior to the key's acceptance.
|
||||
|
||||
2.4.2. Remove Hold-Down Time
|
||||
|
||||
The remove hold-down time is 30 days. This parameter is solely a key
|
||||
management database bookeeping parameter. Failure to remove
|
||||
information about the state of defunct keys from the database will
|
||||
not adversely impact the security of this protocol, but may end up
|
||||
with a database cluttered with obsolete key information.
|
||||
|
||||
2.4.3. Minimum Trust Anchors per Trust Point
|
||||
|
||||
A compliant resolver MUST be able to manage at least five SEP keys
|
||||
per trust point.
|
||||
|
||||
|
||||
3. Changes to DNSKEY RDATA Wire Format
|
||||
|
||||
Bit n [msj2]of the DNSKEY Flags field is designated as the 'REVOKE'
|
||||
flag. If this bit is set to '1', AND the resolver sees an
|
||||
RRSIG(DNSKEY) signed by the associated key, then the resolver MUST
|
||||
consider this key permanently invalid for all purposes except for
|
||||
validating the revocation.
|
||||
|
||||
|
||||
4. State Table
|
||||
|
||||
The most important thing to understand is the resolver's view of any
|
||||
key at a trust point. The following state table describes that view
|
||||
|
||||
|
||||
|
||||
StJohns Expires June 2, 2007 [Page 6]
|
||||
|
||||
Internet-Draft trustanchor-update November 2006
|
||||
|
||||
|
||||
at various points in the key's lifetime. The table is a normative
|
||||
part of this specification. The initial state of the key is 'Start'.
|
||||
The resolver's view of the state of the key changes as various events
|
||||
occur.
|
||||
|
||||
This is the state of a trust point key as seen from the resolver.
|
||||
The column on the left indicates the current state. The header at
|
||||
the top shows the next state. The intersection of the two shows the
|
||||
event that will cause the state to transition from the current state
|
||||
to the next.
|
||||
|
||||
|
||||
NEXT STATE
|
||||
--------------------------------------------------
|
||||
FROM |Start |AddPend |Valid |Missing|Revoked|Removed|
|
||||
----------------------------------------------------------
|
||||
Start | |NewKey | | | | |
|
||||
----------------------------------------------------------
|
||||
AddPend |KeyRem | |AddTime| | |
|
||||
----------------------------------------------------------
|
||||
Valid | | | |KeyRem |Revbit | |
|
||||
----------------------------------------------------------
|
||||
Missing | | |KeyPres| |Revbit | |
|
||||
----------------------------------------------------------
|
||||
Revoked | | | | | |RemTime|
|
||||
----------------------------------------------------------
|
||||
Removed | | | | | | |
|
||||
----------------------------------------------------------
|
||||
|
||||
|
||||
State Table
|
||||
|
||||
4.1. Events
|
||||
NewKey The resolver sees a valid DNSKEY RRSet with a new SEP key.
|
||||
That key will become a new trust anchor for the named trust point
|
||||
after it's been present in the RRSet for at least 'add time'.
|
||||
KeyPres The key has returned to the valid DNSKEY RRSet.
|
||||
KeyRem The resolver sees a valid DNSKEY RRSet that does not contain
|
||||
this key.
|
||||
AddTime The key has been in every valid DNSKEY RRSet seen for at
|
||||
least the 'add time'.
|
||||
RemTime A revoked key has been missing from the trust point DNSKEY
|
||||
RRSet for sufficient time to be removed from the trust set.
|
||||
RevBit The key has appeared in the trust anchor DNSKEY RRSet with
|
||||
its "REVOKED" bit set, and there is an RRSig over the DNSKEY RRSet
|
||||
signed by this key.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
StJohns Expires June 2, 2007 [Page 7]
|
||||
|
||||
Internet-Draft trustanchor-update November 2006
|
||||
|
||||
|
||||
4.2. States
|
||||
Start The key doesn't yet exist as a trust anchor at the resolver.
|
||||
It may or may not exist at the zone server, but either hasn't yet
|
||||
been seen at the resolver or was seen but was absent from the last
|
||||
DNSKEY RRSet (e.g. KeyRem event).
|
||||
AddPend The key has been seen at the resolver, has its 'SEP' bit
|
||||
set, and has been included in a validated DNSKEY RRSet. There is
|
||||
a hold-down time for the key before it can be used as a trust
|
||||
anchor.
|
||||
Valid The key has been seen at the resolver and has been included in
|
||||
all validated DNSKEY RRSets from the time it was first seen up
|
||||
through the hold-down time. It is now valid for verifying RRSets
|
||||
that arrive after the hold down time. Clarification: The DNSKEY
|
||||
RRSet does not need to be continuously present at the resolver
|
||||
(e.g. its TTL might expire). If the RRSet is seen, and is
|
||||
validated (i.e. verifies against an existing trust anchor), this
|
||||
key MUST be in the RRSet otherwise a 'KeyRem' event is triggered.
|
||||
Missing This is an abnormal state. The key remains as a valid trust
|
||||
point key, but was not seen at the resolver in the last validated
|
||||
DNSKEY RRSet. This is an abnormal state because the zone operator
|
||||
should be using the REVOKE bit prior to removal.
|
||||
Revoked This is the state a key moves to once the resolver sees an
|
||||
RRSIG(DNSKEY) signed by this key where that DNSKEY RRSet contains
|
||||
this key with its REVOKE bit set to '1'. Once in this state, this
|
||||
key MUST permanently be considered invalid as a trust anchor.
|
||||
Removed After a fairly long hold-down time, information about this
|
||||
key may be purged from the resolver. A key in the removed state
|
||||
MUST NOT be considered a valid trust anchor. (Note: this state is
|
||||
more or less equivalent to the "Start" state, except that it's bad
|
||||
practice to re-introduce previously used keys - think of this as
|
||||
the holding state for all the old keys for which the resolver no
|
||||
longer needs to track state.)
|
||||
|
||||
|
||||
5. Trust Point Deletion
|
||||
|
||||
A trust point which has all of its trust anchors revoked is
|
||||
considered deleted and is treated as if the trust point was never
|
||||
configured. If there are no superior configured trust points, data
|
||||
at and below the deleted trust point are considered insecure by the
|
||||
resolver. If there ARE superior configured trust points, data at and
|
||||
below the deleted trust point are evaluated with respect to the
|
||||
superior trust point(s).
|
||||
|
||||
Alternately, a trust point which is subordinate to another configured
|
||||
trust point MAY be deleted by a resolver after 180 days where such
|
||||
subordinate trust point validly chains to a superior trust point.
|
||||
The decision to delete the subordinate trust anchor is a local
|
||||
|
||||
|
||||
|
||||
StJohns Expires June 2, 2007 [Page 8]
|
||||
|
||||
Internet-Draft trustanchor-update November 2006
|
||||
|
||||
|
||||
configuration decision. Once the subordinate trust point is deleted,
|
||||
validation of the subordinate zone is dependent on validating the
|
||||
chain of trust to the superior trust point.
|
||||
|
||||
|
||||
6. Scenarios - Informative
|
||||
|
||||
The suggested model for operation is to have one active key and one
|
||||
stand-by key at each trust point. The active key will be used to
|
||||
sign the DNSKEY RRSet. The stand-by key will not normally sign this
|
||||
RRSet, but the resolver will accept it as a trust anchor if/when it
|
||||
sees the signature on the trust point DNSKEY RRSet.
|
||||
|
||||
Since the stand-by key is not in active signing use, the associated
|
||||
private key may (and should) be provided with additional protections
|
||||
not normally available to a key that must be used frequently. E.g.
|
||||
locked in a safe, split among many parties, etc. Notionally, the
|
||||
stand-by key should be less subject to compromise than an active key,
|
||||
but that will be dependent on operational concerns not addressed
|
||||
here.
|
||||
|
||||
6.1. Adding a Trust Anchor
|
||||
|
||||
Assume an existing trust anchor key 'A'.
|
||||
1. Generate a new key pair.
|
||||
2. Create a DNSKEY record from the key pair and set the SEP and Zone
|
||||
Key bits.
|
||||
3. Add the DNSKEY to the RRSet.
|
||||
4. Sign the DNSKEY RRSet ONLY with the existing trust anchor key -
|
||||
'A'.
|
||||
5. Wait a while (i.e. for various resolvers timers to go off and for
|
||||
them to retrieve the new DNSKEY RRSet and signatures).
|
||||
6. The new trust anchor will be populated at the resolvers on the
|
||||
schedule described by the state table and update algorithm - see
|
||||
Section 2 above
|
||||
|
||||
6.2. Deleting a Trust Anchor
|
||||
|
||||
Assume existing trust anchors 'A' and 'B' and that you want to revoke
|
||||
and delete 'A'.
|
||||
1. Set the revocation bit on key 'A'.
|
||||
2. Sign the DNSKEY RRSet with both 'A' and 'B'.
|
||||
'A' is now revoked. The operator should include the revoked 'A' in
|
||||
the RRSet for at least the remove hold-down time, but then may remove
|
||||
it from the DNSKEY RRSet.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
StJohns Expires June 2, 2007 [Page 9]
|
||||
|
||||
Internet-Draft trustanchor-update November 2006
|
||||
|
||||
|
||||
6.3. Key Roll-Over
|
||||
|
||||
Assume existing keys A and B. 'A' is actively in use (i.e. has been
|
||||
signing the DNSKEY RRSet.) 'B' was the stand-by key. (i.e. has been
|
||||
in the DNSKEY RRSet and is a valid trust anchor, but wasn't being
|
||||
used to sign the RRSet.)
|
||||
1. Generate a new key pair 'C'.
|
||||
2. Add 'C' to the DNSKEY RRSet.
|
||||
3. Set the revocation bit on key 'A'.
|
||||
4. Sign the RRSet with 'A' and 'B'.
|
||||
'A' is now revoked, 'B' is now the active key, and 'C' will be the
|
||||
stand-by key once the hold-down expires. The operator should include
|
||||
the revoked 'A' in the RRSet for at least the remove hold-down time,
|
||||
but may then remove it from the DNSKEY RRSet.
|
||||
|
||||
6.4. Active Key Compromised
|
||||
|
||||
This is the same as the mechanism for Key Roll-Over (Section 6.3)
|
||||
above assuming 'A' is the active key.
|
||||
|
||||
6.5. Stand-by Key Compromised
|
||||
|
||||
Using the same assumptions and naming conventions as Key Roll-Over
|
||||
(Section 6.3) above:
|
||||
1. Generate a new key pair 'C'.
|
||||
2. Add 'C' to the DNSKEY RRSet.
|
||||
3. Set the revocation bit on key 'B'.
|
||||
4. Sign the RRSet with 'A' and 'B'.
|
||||
'B' is now revoked, 'A' remains the active key, and 'C' will be the
|
||||
stand-by key once the hold-down expires. 'B' should continue to be
|
||||
included in the RRSet for the remove hold-down time.
|
||||
|
||||
6.6. Trust Point Deletion
|
||||
|
||||
To delete a trust point which is subordinate to another configured
|
||||
trust point (e.g. example.com to .com) requires some juggling of the
|
||||
data. The specific process is:
|
||||
1. Generate a new DNSKEY and DS record and provide the DS record to
|
||||
the parent along with DS records for the old keys
|
||||
2. Once the parent has published the DSs, add the new DNSKEY to the
|
||||
RRSet and revoke ALL of the old keys at the same time while
|
||||
signing the DNSKEY RRSet with all of the old and new keys.
|
||||
3. After 30 days stop publishing the old, revoked keys and remove
|
||||
any corresponding DS records in the parent.
|
||||
Revoking the old trust point keys at the same time as adding new keys
|
||||
that chain to a superior trust prevents the resolver from adding the
|
||||
new keys as trust anchors. Adding DS records for the old keys avoids
|
||||
a race condition where either the subordinate zone becomes unsecure
|
||||
|
||||
|
||||
|
||||
StJohns Expires June 2, 2007 [Page 10]
|
||||
|
||||
Internet-Draft trustanchor-update November 2006
|
||||
|
||||
|
||||
(because the trust point was deleted) or becomes bogus (because it
|
||||
didn't chain to the superior zone).
|
||||
|
||||
|
||||
7. IANA Considerations
|
||||
|
||||
The IANA will need to assign a bit in the DNSKEY flags field (see
|
||||
section 4.3 of [RFC3755]) for the REVOKE bit. There are no other
|
||||
IANA actions required.
|
||||
|
||||
|
||||
8. Security Considerations
|
||||
|
||||
In addition to the following sections, see also Theory of Operation
|
||||
above and especially Section 2.2 for related discussions.
|
||||
|
||||
8.1. Key Ownership vs Acceptance Policy
|
||||
|
||||
The reader should note that, while the zone owner is responsible for
|
||||
creating and distributing keys, it's wholly the decision of the
|
||||
resolver owner as to whether to accept such keys for the
|
||||
authentication of the zone information. This implies the decision to
|
||||
update trust anchor keys based on trust for a current trust anchor
|
||||
key is also the resolver owner's decision.
|
||||
|
||||
The resolver owner (and resolver implementers) MAY choose to permit
|
||||
or prevent key status updates based on this mechanism for specific
|
||||
trust points. If they choose to prevent the automated updates, they
|
||||
will need to establish a mechanism for manual or other out-of-band
|
||||
updates outside the scope of this document.
|
||||
|
||||
8.2. Multiple Key Compromise
|
||||
|
||||
This scheme permits recovery as long as at least one valid trust
|
||||
anchor key remains uncompromised. E.g. if there are three keys, you
|
||||
can recover if two of them are compromised. The zone owner should
|
||||
determine their own level of comfort with respect to the number of
|
||||
active valid trust anchors in a zone and should be prepared to
|
||||
implement recovery procedures once they detect a compromise. A
|
||||
manual or other out-of-band update of all resolvers will be required
|
||||
if all trust anchor keys at a trust point are compromised.
|
||||
|
||||
8.3. Dynamic Updates
|
||||
|
||||
Allowing a resolver to update its trust anchor set based on in-band
|
||||
key information is potentially less secure than a manual process.
|
||||
However, given the nature of the DNS, the number of resolvers that
|
||||
would require update if a trust anchor key were compromised, and the
|
||||
|
||||
|
||||
|
||||
StJohns Expires June 2, 2007 [Page 11]
|
||||
|
||||
Internet-Draft trustanchor-update November 2006
|
||||
|
||||
|
||||
lack of a standard management framework for DNS, this approach is no
|
||||
worse than the existing situation.
|
||||
|
||||
|
||||
9. Normative References
|
||||
|
||||
[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
|
||||
Requirement Levels", BCP 14, RFC 2119, March 1997.
|
||||
|
||||
[RFC3755] Weiler, S., "Legacy Resolver Compatibility for Delegation
|
||||
Signer (DS)", RFC 3755, May 2004.
|
||||
|
||||
[RFC4033] Arends, R., Austein, R., Larson, M., Massey, D., and S.
|
||||
Rose, "DNS Security Introduction and Requirements",
|
||||
RFC 4033, March 2005.
|
||||
|
||||
[RFC4034] Arends, R., Austein, R., Larson, M., Massey, D., and S.
|
||||
Rose, "Resource Records for the DNS Security Extensions",
|
||||
RFC 4034, March 2005.
|
||||
|
||||
[RFC4035] Arends, R., Austein, R., Larson, M., Massey, D., and S.
|
||||
Rose, "Protocol Modifications for the DNS Security
|
||||
Extensions", RFC 4035, March 2005.
|
||||
|
||||
Editorial Comments
|
||||
|
||||
[msj2] msj: To be assigned.
|
||||
|
||||
|
||||
Author's Address
|
||||
|
||||
Michael StJohns
|
||||
Nominum, Inc.
|
||||
2385 Bay Road
|
||||
Redwood City, CA 94063
|
||||
USA
|
||||
|
||||
Phone: +1-301-528-4729
|
||||
Email: Mike.StJohns@nominum.com
|
||||
URI: www.nominum.com
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
StJohns Expires June 2, 2007 [Page 12]
|
||||
|
||||
Internet-Draft trustanchor-update November 2006
|
||||
|
||||
|
||||
Full Copyright Statement
|
||||
|
||||
Copyright (C) The Internet Society (2006).
|
||||
|
||||
This document is subject to the rights, licenses and restrictions
|
||||
contained in BCP 78, and except as set forth therein, the authors
|
||||
retain all their rights.
|
||||
|
||||
This document and the information contained herein are provided on an
|
||||
"AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
|
||||
OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
|
||||
ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
|
||||
INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
|
||||
INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
|
||||
Intellectual Property
|
||||
|
||||
The IETF takes no position regarding the validity or scope of any
|
||||
Intellectual Property Rights or other rights that might be claimed to
|
||||
pertain to the implementation or use of the technology described in
|
||||
this document or the extent to which any license under such rights
|
||||
might or might not be available; nor does it represent that it has
|
||||
made any independent effort to identify any such rights. Information
|
||||
on the procedures with respect to rights in RFC documents can be
|
||||
found in BCP 78 and BCP 79.
|
||||
|
||||
Copies of IPR disclosures made to the IETF Secretariat and any
|
||||
assurances of licenses to be made available, or the result of an
|
||||
attempt made to obtain a general license or permission for the use of
|
||||
such proprietary rights by implementers or users of this
|
||||
specification can be obtained from the IETF on-line IPR repository at
|
||||
http://www.ietf.org/ipr.
|
||||
|
||||
The IETF invites any interested party to bring to its attention any
|
||||
copyrights, patents or patent applications, or other proprietary
|
||||
rights that may cover technology that may be required to implement
|
||||
this standard. Please address the information to the IETF at
|
||||
ietf-ipr@ietf.org.
|
||||
|
||||
|
||||
Acknowledgment
|
||||
|
||||
Funding for the RFC Editor function is provided by the IETF
|
||||
Administrative Support Activity (IASA).
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
StJohns Expires June 2, 2007 [Page 13]
|
||||
|
||||
|
||||
Reference in New Issue
Block a user