diff --git a/contrib/sdb/sqlite/README.sdb_sqlite b/contrib/sdb/sqlite/README.sdb_sqlite new file mode 100644 index 0000000000..36128e1926 --- /dev/null +++ b/contrib/sdb/sqlite/README.sdb_sqlite @@ -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'. + diff --git a/contrib/sdb/sqlite/sqlitedb.c b/contrib/sdb/sqlite/sqlitedb.c new file mode 100644 index 0000000000..c9d0096401 --- /dev/null +++ b/contrib/sdb/sqlite/sqlitedb.c @@ -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 + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include +#include + +#include + +#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); +} diff --git a/contrib/sdb/sqlite/sqlitedb.h b/contrib/sdb/sqlite/sqlitedb.h new file mode 100644 index 0000000000..5d22d0e06b --- /dev/null +++ b/contrib/sdb/sqlite/sqlitedb.h @@ -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_result_t sqlitedb_init(void); + +void sqlitedb_clear(void); + diff --git a/contrib/sdb/sqlite/zone2sqlite.c b/contrib/sdb/sqlite/zone2sqlite.c new file mode 100644 index 0000000000..b6d7fd2f53 --- /dev/null +++ b/contrib/sdb/sqlite/zone2sqlite.c @@ -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 +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#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 \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); +} diff --git a/doc/draft/draft-ietf-dnsext-trustupdate-timers-05.txt b/doc/draft/draft-ietf-dnsext-trustupdate-timers-05.txt new file mode 100644 index 0000000000..02852591ec --- /dev/null +++ b/doc/draft/draft-ietf-dnsext-trustupdate-timers-05.txt @@ -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] + +