Commit 289ae548 authored by Mark Andrews's avatar Mark Andrews

2105. [func] GSS-TSIG support (RFC 3645).

parent 6292befa
2105. [func] GSS-TSIG support (RFC 3645).
2104. [port] Fix Solaris SMF error message.
2103. [port] Add /usr/sfw to list of locations for OpenSSL
......
......@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: client.c,v 1.239 2006/07/22 01:00:04 marka Exp $ */
/* $Id: client.c,v 1.240 2006/12/04 01:52:45 marka Exp $ */
#include <config.h>
......@@ -1227,6 +1227,7 @@ ns_client_isself(dns_view_t *myview, dns_tsigkey_t *mykey,
{
dns_view_t *view;
dns_tsigkey_t *key;
dns_name_t *tsig = NULL;
isc_netaddr_t netsrc;
isc_netaddr_t netdst;
......@@ -1241,7 +1242,6 @@ ns_client_isself(dns_view_t *myview, dns_tsigkey_t *mykey,
for (view = ISC_LIST_HEAD(ns_g_server->viewlist);
view != NULL;
view = ISC_LIST_NEXT(view, link)) {
dns_name_t *tsig = NULL;
if (view->matchrecursiveonly)
continue;
......@@ -1253,14 +1253,14 @@ ns_client_isself(dns_view_t *myview, dns_tsigkey_t *mykey,
isc_boolean_t match;
isc_result_t result;
tsig = &mykey->name;
result = dns_view_gettsig(view, tsig, &key);
result = dns_view_gettsig(view, &mykey->name, &key);
if (result != ISC_R_SUCCESS)
continue;
match = dst_key_compare(mykey->key, key->key);
dns_tsigkey_detach(&key);
if (!match)
continue;
tsig = dns_tsigkey_identity(mykey);
}
if (allowed(&netsrc, tsig, view->matchclients) &&
......@@ -1590,11 +1590,12 @@ client_request(isc_task_t *task, isc_event_t *event) {
client->message->rdclass == dns_rdataclass_any)
{
dns_name_t *tsig = NULL;
sigresult = dns_message_rechecksig(client->message,
view);
if (sigresult == ISC_R_SUCCESS)
tsig = client->message->tsigname;
tsig = dns_tsigkey_identity(client->message->tsigkey);
if (allowed(&netaddr, tsig, view->matchclients) &&
allowed(&destaddr, tsig, view->matchdestinations) &&
!((client->message->flags & DNS_MESSAGEFLAG_RD)
......@@ -1672,12 +1673,28 @@ client_request(isc_task_t *task, isc_event_t *event) {
/* There is a signature, but it is bad. */
if (dns_message_gettsig(client->message, &name) != NULL) {
char namebuf[DNS_NAME_FORMATSIZE];
char cnamebuf[DNS_NAME_FORMATSIZE];
dns_name_format(name, namebuf, sizeof(namebuf));
ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
NS_LOGMODULE_CLIENT, ISC_LOG_ERROR,
"request has invalid signature: "
"TSIG %s: %s (%s)", namebuf,
isc_result_totext(result), tsigrcode);
if (client->message->tsigkey->generated) {
dns_name_format(client->message->tsigkey->creator,
cnamebuf, sizeof(cnamebuf));
ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
NS_LOGMODULE_CLIENT,
ISC_LOG_ERROR,
"request has invalid signature: "
"TSIG %s (%s): %s (%s)", namebuf,
cnamebuf,
isc_result_totext(result),
tsigrcode);
} else {
ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
NS_LOGMODULE_CLIENT,
ISC_LOG_ERROR,
"request has invalid signature: "
"TSIG %s: %s (%s)", namebuf,
isc_result_totext(result),
tsigrcode);
}
} else {
ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
NS_LOGMODULE_CLIENT, ISC_LOG_ERROR,
......
......@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: control.c,v 1.28 2006/03/10 00:23:21 marka Exp $ */
/* $Id: control.c,v 1.29 2006/12/04 01:52:45 marka Exp $ */
/*! \file */
......@@ -158,6 +158,10 @@ ns_control_docommand(isccc_sexpr_t *message, isc_buffer_t *text) {
result = ns_server_flushname(ns_g_server, command);
} else if (command_compare(command, NS_COMMAND_STATUS)) {
result = ns_server_status(ns_g_server, text);
} else if (command_compare(command, NS_COMMAND_TSIGLIST)) {
result = ns_server_tsiglist(ns_g_server, text);
} else if (command_compare(command, NS_COMMAND_TSIGDELETE)) {
result = ns_server_tsigdelete(ns_g_server, command, text);
} else if (command_compare(command, NS_COMMAND_FREEZE)) {
result = ns_server_freeze(ns_g_server, ISC_TRUE, command);
} else if (command_compare(command, NS_COMMAND_UNFREEZE) ||
......
......@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: control.h,v 1.22 2006/03/09 23:39:00 marka Exp $ */
/* $Id: control.h,v 1.23 2006/12/04 01:52:45 marka Exp $ */
#ifndef NAMED_CONTROL_H
#define NAMED_CONTROL_H 1
......@@ -47,6 +47,8 @@
#define NS_COMMAND_FLUSH "flush"
#define NS_COMMAND_FLUSHNAME "flushname"
#define NS_COMMAND_STATUS "status"
#define NS_COMMAND_TSIGLIST "tsig-list"
#define NS_COMMAND_TSIGDELETE "tsig-delete"
#define NS_COMMAND_FREEZE "freeze"
#define NS_COMMAND_UNFREEZE "unfreeze"
#define NS_COMMAND_THAW "thaw"
......
......@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: server.h,v 1.83 2006/03/09 23:39:00 marka Exp $ */
/* $Id: server.h,v 1.84 2006/12/04 01:52:45 marka Exp $ */
#ifndef NAMED_SERVER_H
#define NAMED_SERVER_H 1
......@@ -203,6 +203,18 @@ ns_server_flushname(ns_server_t *server, char *args);
isc_result_t
ns_server_status(ns_server_t *server, isc_buffer_t *text);
/*%
* Report a list of dynamic and static tsig keys, per view.
*/
isc_result_t
ns_server_tsiglist(ns_server_t *server, isc_buffer_t *text);
/*%
* Delete a specific key (with optional view).
*/
isc_result_t
ns_server_tsigdelete(ns_server_t *server, char *command, isc_buffer_t *text);
/*%
* Enable or disable updates for a zone.
*/
......
......@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: notify.c,v 1.33 2005/04/29 00:22:29 marka Exp $ */
/* $Id: notify.c,v 1.34 2006/12/04 01:52:45 marka Exp $ */
#include <config.h>
......@@ -25,6 +25,7 @@
#include <dns/message.h>
#include <dns/rdataset.h>
#include <dns/result.h>
#include <dns/tsig.h>
#include <dns/view.h>
#include <dns/zone.h>
#include <dns/zt.h>
......@@ -80,7 +81,7 @@ ns_notify_start(ns_client_t *client) {
dns_zone_t *zone = NULL;
char namebuf[DNS_NAME_FORMATSIZE];
char tsigbuf[DNS_NAME_FORMATSIZE + sizeof(": TSIG ''")];
dns_name_t *tsigname;
dns_tsigkey_t *tsigkey;
/*
* Interpret the question section.
......@@ -119,10 +120,20 @@ ns_notify_start(ns_client_t *client) {
goto formerr;
}
tsigname = NULL;
if (dns_message_gettsig(request, &tsigname) != NULL) {
dns_name_format(tsigname, namebuf, sizeof(namebuf));
snprintf(tsigbuf, sizeof(tsigbuf), ": TSIG '%s'", namebuf);
tsigkey = dns_message_gettsigkey(request);
if (tsigkey != NULL) {
dns_name_format(&tsigkey->name, namebuf, sizeof(namebuf));
if (tsigkey->generated) {
char cnamebuf[DNS_NAME_FORMATSIZE];
dns_name_format(tsigkey->creator, cnamebuf,
sizeof(cnamebuf));
snprintf(tsigbuf, sizeof(tsigbuf), ": TSIG '%s' (%s)",
namebuf, cnamebuf);
} else {
snprintf(tsigbuf, sizeof(tsigbuf), ": TSIG '%s'",
namebuf);
}
} else
tsigbuf[0] = '\0';
dns_name_format(zonename, namebuf, sizeof(namebuf));
......
......@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: server.c,v 1.466 2006/07/24 05:51:22 marka Exp $ */
/* $Id: server.c,v 1.467 2006/12/04 01:52:45 marka Exp $ */
/*! \file */
......@@ -60,6 +60,7 @@
#include <dns/order.h>
#include <dns/peer.h>
#include <dns/portlist.h>
#include <dns/rbt.h>
#include <dns/rdataclass.h>
#include <dns/rdataset.h>
#include <dns/rdatastruct.h>
......@@ -68,6 +69,7 @@
#include <dns/secalg.h>
#include <dns/stats.h>
#include <dns/tkey.h>
#include <dns/tsig.h>
#include <dns/view.h>
#include <dns/zone.h>
#include <dns/zt.h>
......@@ -4687,6 +4689,235 @@ ns_server_status(ns_server_t *server, isc_buffer_t *text) {
return (ISC_R_SUCCESS);
}
static isc_result_t
delete_keynames(dns_tsig_keyring_t *ring, char *target,
unsigned int *foundkeys)
{
char namestr[DNS_NAME_FORMATSIZE];
isc_result_t result;
dns_rbtnodechain_t chain;
dns_name_t foundname;
dns_fixedname_t fixedorigin;
dns_name_t *origin;
dns_rbtnode_t *node;
dns_tsigkey_t *tkey;
dns_name_init(&foundname, NULL);
dns_fixedname_init(&fixedorigin);
origin = dns_fixedname_name(&fixedorigin);
again:
dns_rbtnodechain_init(&chain, ring->mctx);
result = dns_rbtnodechain_first(&chain, ring->keys, &foundname,
origin);
if (result == ISC_R_NOTFOUND) {
dns_rbtnodechain_invalidate(&chain);
return (ISC_R_SUCCESS);
}
if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
dns_rbtnodechain_invalidate(&chain);
return (result);
}
for (;;) {
node = NULL;
dns_rbtnodechain_current(&chain, &foundname, origin, &node);
tkey = node->data;
if (tkey != NULL) {
if (!tkey->generated)
goto nextkey;
dns_name_format(&tkey->name, namestr, sizeof(namestr));
if (strcmp(namestr, target) == 0) {
(*foundkeys)++;
dns_rbtnodechain_invalidate(&chain);
(void)dns_rbt_deletename(ring->keys,
&tkey->name,
ISC_FALSE);
goto again;
}
}
nextkey:
result = dns_rbtnodechain_next(&chain, &foundname, origin);
if (result == ISC_R_NOMORE)
break;
if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
dns_rbtnodechain_invalidate(&chain);
return (result);
}
}
return (ISC_R_SUCCESS);
}
isc_result_t
ns_server_tsigdelete(ns_server_t *server, char *command, isc_buffer_t *text) {
isc_result_t result;
unsigned int n;
dns_view_t *view;
unsigned int foundkeys = 0;
char *target;
char *viewname;
(void)next_token(&command, " \t"); /* skip command name */
target = next_token(&command, " \t");
if (target == NULL)
return (ISC_R_UNEXPECTEDEND);
viewname = next_token(&command, " \t");
result = isc_task_beginexclusive(server->task);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
for (view = ISC_LIST_HEAD(server->viewlist);
view != NULL;
view = ISC_LIST_NEXT(view, link)) {
if (viewname == NULL || strcmp(view->name, viewname) == 0) {
RWLOCK(&view->dynamickeys->lock, isc_rwlocktype_write);
result = delete_keynames(view->dynamickeys, target,
&foundkeys);
RWUNLOCK(&view->dynamickeys->lock,
isc_rwlocktype_write);
if (result != ISC_R_SUCCESS) {
isc_task_endexclusive(server->task);
return (result);
}
}
}
isc_task_endexclusive(server->task);
n = snprintf((char *)isc_buffer_used(text),
isc_buffer_availablelength(text),
"%d tsig keys deleted.\n", foundkeys);
if (n >= isc_buffer_availablelength(text)) {
isc_task_endexclusive(server->task);
return (ISC_R_NOSPACE);
}
isc_buffer_add(text, n);
return (ISC_R_SUCCESS);
}
static isc_result_t
list_keynames(dns_view_t *view, dns_tsig_keyring_t *ring, isc_buffer_t *text,
unsigned int *foundkeys)
{
char namestr[DNS_NAME_FORMATSIZE];
char creatorstr[DNS_NAME_FORMATSIZE];
isc_result_t result;
dns_rbtnodechain_t chain;
dns_name_t foundname;
dns_fixedname_t fixedorigin;
dns_name_t *origin;
dns_rbtnode_t *node;
dns_tsigkey_t *tkey;
unsigned int n;
const char *viewname;
if (view != NULL)
viewname = view->name;
else
viewname = "(global)";
dns_name_init(&foundname, NULL);
dns_fixedname_init(&fixedorigin);
origin = dns_fixedname_name(&fixedorigin);
dns_rbtnodechain_init(&chain, ring->mctx);
result = dns_rbtnodechain_first(&chain, ring->keys, &foundname,
origin);
if (result == ISC_R_NOTFOUND) {
dns_rbtnodechain_invalidate(&chain);
return (ISC_R_SUCCESS);
}
if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
dns_rbtnodechain_invalidate(&chain);
return (result);
}
for (;;) {
node = NULL;
dns_rbtnodechain_current(&chain, &foundname, origin, &node);
tkey = node->data;
if (tkey != NULL) {
(*foundkeys)++;
dns_name_format(&tkey->name, namestr, sizeof(namestr));
if (tkey->generated) {
dns_name_format(tkey->creator, creatorstr,
sizeof(creatorstr));
n = snprintf((char *)isc_buffer_used(text),
isc_buffer_availablelength(text),
"view \"%s\"; type \"dynamic\"; key \"%s\"; creator \"%s\";\n",
viewname, namestr, creatorstr);
} else {
n = snprintf((char *)isc_buffer_used(text),
isc_buffer_availablelength(text),
"view \"%s\"; type \"static\"; key \"%s\";\n",
viewname, namestr);
}
if (n >= isc_buffer_availablelength(text)) {
dns_rbtnodechain_invalidate(&chain);
return (ISC_R_NOSPACE);
}
isc_buffer_add(text, n);
}
result = dns_rbtnodechain_next(&chain, &foundname, origin);
if (result == ISC_R_NOMORE)
break;
if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
dns_rbtnodechain_invalidate(&chain);
return (result);
}
}
return (ISC_R_SUCCESS);
}
isc_result_t
ns_server_tsiglist(ns_server_t *server, isc_buffer_t *text) {
isc_result_t result;
unsigned int n;
dns_view_t *view;
unsigned int foundkeys = 0;
result = isc_task_beginexclusive(server->task);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
for (view = ISC_LIST_HEAD(server->viewlist);
view != NULL;
view = ISC_LIST_NEXT(view, link)) {
RWLOCK(&view->statickeys->lock, isc_rwlocktype_read);
result = list_keynames(view, view->statickeys, text,
&foundkeys);
RWUNLOCK(&view->statickeys->lock, isc_rwlocktype_read);
if (result != ISC_R_SUCCESS) {
isc_task_endexclusive(server->task);
return (result);
}
RWLOCK(&view->dynamickeys->lock, isc_rwlocktype_read);
result = list_keynames(view, view->dynamickeys, text,
&foundkeys);
RWUNLOCK(&view->dynamickeys->lock, isc_rwlocktype_read);
if (result != ISC_R_SUCCESS) {
isc_task_endexclusive(server->task);
return (result);
}
}
isc_task_endexclusive(server->task);
if (foundkeys == 0) {
n = snprintf((char *)isc_buffer_used(text),
isc_buffer_availablelength(text),
"no tsig keys found.\n");
if (n >= isc_buffer_availablelength(text)) {
isc_task_endexclusive(server->task);
return (ISC_R_NOSPACE);
}
isc_buffer_add(text, n);
}
return (ISC_R_SUCCESS);
}
/*
* Act on a "freeze" or "thaw" command from the command channel.
*/
......
......@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: tkeyconf.c,v 1.26 2006/03/02 00:37:23 marka Exp $ */
/* $Id: tkeyconf.c,v 1.27 2006/12/04 01:52:45 marka Exp $ */
/*! \file */
......@@ -42,6 +42,13 @@
goto failure; \
} while (0)
#include<named/log.h>
#define LOG(msg) \
isc_log_write(ns_g_lctx, \
NS_LOGCATEGORY_GENERAL, \
NS_LOGMODULE_SERVER, \
ISC_LOG_ERROR, \
"%s", msg)
isc_result_t
ns_tkeyctx_fromconfig(const cfg_obj_t *options, isc_mem_t *mctx,
......@@ -100,6 +107,7 @@ ns_tkeyctx_fromconfig(const cfg_obj_t *options, isc_mem_t *mctx,
result = cfg_map_get(options, "tkey-gssapi-credential", &obj);
if (result == ISC_R_SUCCESS) {
s = cfg_obj_asstring(obj);
isc_buffer_init(&b, s, strlen(s));
isc_buffer_add(&b, strlen(s));
dns_fixedname_init(&fname);
......
......@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: update.c,v 1.129 2006/03/06 01:27:51 marka Exp $ */
/* $Id: update.c,v 1.130 2006/12/04 01:52:45 marka Exp $ */
#include <config.h>
......@@ -55,9 +55,9 @@
*/
/*
XXX TODO:
- document strict minimality
*/
* XXX TODO:
* - document strict minimality
*/
/**************************************************************************/
......@@ -69,7 +69,7 @@
/*%
* Log level for low-level debug tracing.
*/
#define LOGLEVEL_DEBUG ISC_LOG_DEBUG(8)
#define LOGLEVEL_DEBUG ISC_LOG_DEBUG(8)
/*%
* Check an operation for failure. These macros all assume that
......@@ -77,8 +77,8 @@
* label.
*/
#define CHECK(op) \
do { result = (op); \
if (result != ISC_R_SUCCESS) goto failure; \
do { result = (op); \
if (result != ISC_R_SUCCESS) goto failure; \
} while (0)
/*%
......@@ -112,9 +112,9 @@
case DNS_R_NXRRSET: \
_what = "unsuccessful"; \
} \
update_log(client, zone, LOGLEVEL_PROTOCOL, \
"update %s: %s (%s)", _what, \
msg, isc_result_totext(result)); \
update_log(client, zone, LOGLEVEL_PROTOCOL, \
"update %s: %s (%s)", _what, \
msg, isc_result_totext(result)); \
if (result != ISC_R_SUCCESS) goto failure; \
} while (0)
......@@ -132,7 +132,7 @@
if (isc_log_wouldlog(ns_g_lctx, LOGLEVEL_PROTOCOL)) { \
char _nbuf[DNS_NAME_FORMATSIZE]; \
dns_name_format(name, _nbuf, sizeof(_nbuf)); \
update_log(client, zone, LOGLEVEL_PROTOCOL, \
update_log(client, zone, LOGLEVEL_PROTOCOL, \
"update %s: %s: %s (%s)", _what, _nbuf, \
msg, isc_result_totext(result)); \
} \
......@@ -155,7 +155,7 @@
char _tbuf[DNS_RDATATYPE_FORMATSIZE]; \
dns_name_format(name, _nbuf, sizeof(_nbuf)); \
dns_rdatatype_format(type, _tbuf, sizeof(_tbuf)); \
update_log(client, zone, LOGLEVEL_PROTOCOL, \
update_log(client, zone, LOGLEVEL_PROTOCOL, \
"update %s: %s/%s: %s (%s)", \
_what, _nbuf, _tbuf, msg, \
isc_result_totext(result)); \
......@@ -171,8 +171,8 @@
do { \
result = (code); \
update_log(client, zone, LOGLEVEL_PROTOCOL, \
"error: %s: %s", \
msg, isc_result_totext(result)); \
"error: %s: %s", \
msg, isc_result_totext(result)); \
if (result != ISC_R_SUCCESS) goto failure; \
} while (0)
......@@ -182,15 +182,15 @@ typedef struct rr rr_t;
struct rr {
/* dns_name_t name; */
isc_uint32_t ttl;
dns_rdata_t rdata;
isc_uint32_t ttl;
dns_rdata_t rdata;
};
typedef struct update_event update_event_t;
struct update_event {
ISC_EVENT_COMMON(update_event_t);
dns_zone_t *zone;
dns_zone_t *zone;
isc_result_t result;
dns_message_t *answer;
};
......@@ -262,13 +262,20 @@ checkupdateacl(ns_client_t *client, dns_acl_t *acl, const char *message,
msg = "approved";
}
if (client->signer != NULL) {
dns_name_format(client->signer, namebuf, sizeof(namebuf));
ns_client_log(client, NS_LOGCATEGORY_UPDATE_SECURITY,
NS_LOGMODULE_UPDATE, ISC_LOG_INFO,
"signer \"%s\" %s", namebuf, msg);
}
dns_name_format(zonename, namebuf, sizeof(namebuf));
dns_rdataclass_format(client->view->rdclass, classbuf,
sizeof(classbuf));
ns_client_log(client, NS_LOGCATEGORY_UPDATE_SECURITY,
NS_LOGMODULE_UPDATE, level, "%s '%s/%s' %s",
message, namebuf, classbuf, msg);
NS_LOGMODULE_UPDATE, level, "%s '%s/%s' %s",
message, namebuf, classbuf, msg);
return (result);
}
......@@ -277,12 +284,11 @@ checkupdateacl(ns_client_t *client, dns_acl_t *acl, const char *message,
* update in 'diff'.
*
* Ensures:
* \li '*tuple' == NULL. Either the tuple is freed, or its
* ownership has been transferred to the diff.
* \li '*tuple' == NULL. Either the tuple is freed, or its
* ownership has been transferred to the diff.
*/
static isc_result_t
do_one_tuple(dns_difftuple_t **tuple,
dns_db_t *db, dns_dbversion_t *ver,
do_one_tuple(dns_difftuple_t **tuple, dns_db_t *db, dns_dbversion_t *ver,
dns_diff_t *diff)