+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
* 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>
{
dns_view_t *view;
dns_tsigkey_t *key;
+ dns_name_t *tsig = NULL;
isc_netaddr_t netsrc;
isc_netaddr_t netdst;
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;
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) &&
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)
/* 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,
* 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 */
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) ||
* 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
#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"
* 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
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.
*/
* 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>
#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>
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.
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));
* 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 */
#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>
#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>
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.
*/
* 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 */
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,
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);
* 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>
*/
/*
- XXX TODO:
- - document strict minimality
-*/
+ * XXX TODO:
+ * - document strict minimality
+ */
/**************************************************************************/
/*%
* 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
* 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)
/*%
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)
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)); \
} \
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)); \
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)
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;
};
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);
}
* 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)
{
dns_diff_t temp_diff;
* update in 'diff'.
*
* Ensures:
- * \li 'updates' is empty.
+ * \li 'updates' is empty.
*/
static isc_result_t
do_diff(dns_diff_t *updates, dns_db_t *db, dns_dbversion_t *ver,
static isc_result_t
update_one_rr(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
- dns_diffop_t op, dns_name_t *name,
- dns_ttl_t ttl, dns_rdata_t *rdata)
+ dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
+ dns_rdata_t *rdata)
{
dns_difftuple_t *tuple = NULL;
isc_result_t result;
* If 'action' returns an error, abort iteration and return the error.
*/
static isc_result_t
-foreach_rrset(dns_db_t *db,
- dns_dbversion_t *ver,
- dns_name_t *name,
- rrset_func *action,
- void *action_data)
+foreach_rrset(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
+ rrset_func *action, void *action_data)
{
isc_result_t result;
dns_dbnode_t *node;
* and return the error.
*/
static isc_result_t
-foreach_node_rr(dns_db_t *db,
- dns_dbversion_t *ver,
- dns_name_t *name,
- rr_func *rr_action,
- void *rr_action_data)
+foreach_node_rr(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
+ rr_func *rr_action, void *rr_action_data)
{
foreach_node_rr_ctx_t ctx;
ctx.rr_action = rr_action;
* If 'action' returns an error, abort iteration and return the error.
*/
static isc_result_t
-foreach_rr(dns_db_t *db,
- dns_dbversion_t *ver,
- dns_name_t *name,
- dns_rdatatype_t type,
- dns_rdatatype_t covers,
- rr_func *rr_action,
+foreach_rr(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
+ dns_rdatatype_t type, dns_rdatatype_t covers, rr_func *rr_action,
void *rr_action_data)
{
* This would be more readable as "do { if ... } while(0)",
* but that form generates tons of warnings on Solaris 2.6.
*/
-#define RETURN_EXISTENCE_FLAG \
- return ((result == ISC_R_EXISTS) ? \
- (*exists = ISC_TRUE, ISC_R_SUCCESS) : \
+#define RETURN_EXISTENCE_FLAG \
+ return ((result == ISC_R_EXISTS) ? \
+ (*exists = ISC_TRUE, ISC_R_SUCCESS) : \
((result == ISC_R_SUCCESS) ? \
(*exists = ISC_FALSE, ISC_R_SUCCESS) : \
result))
* to false otherwise.
*/
static isc_result_t
-rrset_exists(dns_db_t *db, dns_dbversion_t *ver,
- dns_name_t *name, dns_rdatatype_t type, dns_rdatatype_t covers,
+rrset_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
+ dns_rdatatype_t type, dns_rdatatype_t covers,
isc_boolean_t *exists)
{
isc_result_t result;
}
typedef struct {
- dns_name_t *name, *signer;
+ dns_name_t *name;
+ dns_name_t *signer;
dns_ssutable_t *table;
} ssu_check_t;
REQUIRE(DNS_DIFF_VALID(diff));
CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_EXISTS,
- name, 0, rdata, &tuple));
+ name, 0, rdata, &tuple));
ISC_LIST_APPEND(diff->tuples, tuple, link);
failure:
return (result);
dns_rdataset_t rdataset;
dns_diff_t d_rrs; /* Database RRs with
this name and type */
- dns_diff_t u_rrs; /* Update RRs with
+ dns_diff_t u_rrs; /* Update RRs with
this name and type */
*typep = type = t->rdata.type;
* deletions in 'diff'.
*/
static isc_result_t
-delete_if(rr_predicate *predicate,
- dns_db_t *db,
- dns_dbversion_t *ver,
- dns_name_t *name,
- dns_rdatatype_t type,
- dns_rdatatype_t covers,
- dns_rdata_t *update_rr,
- dns_diff_t *diff)
+delete_if(rr_predicate *predicate, dns_db_t *db, dns_dbversion_t *ver,
+ dns_name_t *name, dns_rdatatype_t type, dns_rdatatype_t covers,
+ dns_rdata_t *update_rr, dns_diff_t *diff)
{
conditional_delete_ctx_t ctx;
ctx.predicate = predicate;
* be deleted before the update RR is added.
*/
if (replaces_p(ctx->update_rr, &rr->rdata)) {
- CHECK(dns_difftuple_create(ctx->del_diff.mctx,
- DNS_DIFFOP_DEL, ctx->name,
- rr->ttl,
- &rr->rdata,
+ CHECK(dns_difftuple_create(ctx->del_diff.mctx, DNS_DIFFOP_DEL,
+ ctx->name, rr->ttl, &rr->rdata,
&tuple));
dns_diff_append(&ctx->del_diff, &tuple);
return (ISC_R_SUCCESS);
* its TTL must be adjusted.
*/
if (rr->ttl != ctx->update_rr_ttl) {
- CHECK(dns_difftuple_create(ctx->del_diff.mctx,
- DNS_DIFFOP_DEL, ctx->name,
- rr->ttl,
- &rr->rdata,
+ CHECK(dns_difftuple_create(ctx->del_diff.mctx, DNS_DIFFOP_DEL,
+ ctx->name, rr->ttl, &rr->rdata,
&tuple));
dns_diff_append(&ctx->del_diff, &tuple);
if (!equal) {
CHECK(dns_difftuple_create(ctx->add_diff.mctx,
DNS_DIFFOP_ADD, ctx->name,
ctx->update_rr_ttl,
- &rr->rdata,
- &tuple));
+ &rr->rdata, &tuple));
dns_diff_append(&ctx->add_diff, &tuple);
}
}
*/
static void
get_current_rr(dns_message_t *msg, dns_section_t section,
- dns_rdataclass_t zoneclass,
- dns_name_t **name, dns_rdata_t *rdata, dns_rdatatype_t *covers,
- dns_ttl_t *ttl,
- dns_rdataclass_t *update_class)
+ dns_rdataclass_t zoneclass, dns_name_t **name,
+ dns_rdata_t *rdata, dns_rdatatype_t *covers,
+ dns_ttl_t *ttl, dns_rdataclass_t *update_class)
{
dns_rdataset_t *rdataset;
isc_result_t result;
*/
static isc_result_t
check_soa_increment(dns_db_t *db, dns_dbversion_t *ver,
- dns_rdata_t *update_rdata,
- isc_boolean_t *ok)
+ dns_rdata_t *update_rdata, isc_boolean_t *ok)
{
isc_uint32_t db_serial;
isc_uint32_t update_serial;
dns_name_t *name, isc_boolean_t *exists)
{
isc_result_t result;
- result = foreach_rrset(db, ver, name,
- is_non_nsec_action, NULL);
+ result = foreach_rrset(db, ver, name, is_non_nsec_action, NULL);
RETURN_EXISTENCE_FLAG;
}
result = dns_db_find(db, name, ver, dns_rdatatype_any,
DNS_DBFIND_GLUEOK | DNS_DBFIND_NOWILD,
(isc_stdtime_t) 0, NULL,
- dns_fixedname_name(&foundname),
- NULL, NULL);
+ dns_fixedname_name(&foundname), NULL, NULL);
if (result == ISC_R_SUCCESS) {
*flag = ISC_FALSE;
return (ISC_R_SUCCESS);
*/
static isc_result_t
add_placeholder_nsec(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
- dns_diff_t *diff) {
+ dns_diff_t *diff)
+{
isc_result_t result;
dns_difftuple_t *tuple = NULL;
isc_region_t r;
/* Get the rdataset to sign. */
CHECK(dns_db_findnode(db, name, ISC_FALSE, &node));
CHECK(dns_db_findrdataset(db, node, ver, type, 0,
- (isc_stdtime_t) 0,
- &rdataset, NULL));
+ (isc_stdtime_t) 0, &rdataset, NULL));
dns_db_detachnode(db, &node);
for (i = 0; i < nkeys; i++) {
CHECK(dns_db_findnode(db, dns_db_origin(db), ISC_FALSE, &node));
dns_rdataset_init(&rdataset);
CHECK(dns_db_findrdataset(db, node, newver, dns_rdatatype_soa, 0,
- (isc_stdtime_t) 0, &rdataset, NULL));
+ (isc_stdtime_t) 0, &rdataset, NULL));
CHECK(dns_rdataset_first(&rdataset));
dns_rdataset_current(&rdataset, &rdata);
CHECK(dns_rdata_tostruct(&rdata, &soa, NULL));
*/
result = dns_message_firstname(request, DNS_SECTION_ZONE);
if (result != ISC_R_SUCCESS)
- FAILC(DNS_R_FORMERR,
- "update zone section empty");
+ FAILC(DNS_R_FORMERR, "update zone section empty");
/*
* The zone section must contain exactly one "question", and
result = dns_zt_find(client->view->zonetable, zonename, 0, NULL,
&zone);
if (result != ISC_R_SUCCESS)
- FAILC(DNS_R_NOTAUTH,
- "not authoritative for update zone");
+ FAILC(DNS_R_NOTAUTH, "not authoritative for update zone");
switch(dns_zone_gettype(zone)) {
case dns_zone_master:
CHECK(send_forward_event(client, zone));
break;
default:
- FAILC(DNS_R_NOTAUTH,
- "not authoritative for update zone");
+ FAILC(DNS_R_NOTAUTH, "not authoritative for update zone");
}
return;
dns_db_t *db = NULL;
dns_dbversion_t *oldver = NULL;
dns_dbversion_t *ver = NULL;
- dns_diff_t diff; /* Pending updates. */
- dns_diff_t temp; /* Pending RR existence assertions. */
+ dns_diff_t diff; /* Pending updates. */
+ dns_diff_t temp; /* Pending RR existence assertions. */
isc_boolean_t soa_serial_changed = ISC_FALSE;
isc_mem_t *mctx = client->mctx;
dns_rdatatype_t covers;
sizeof(namestr));
dns_rdatatype_format(rdata.type, typestr,
sizeof(typestr));
- update_log(client, zone,
- LOGLEVEL_PROTOCOL,
+ update_log(client, zone, LOGLEVEL_PROTOCOL,
"adding an RR at '%s' %s",
namestr, typestr);
}
} else if (dns_name_equal(name, zonename) &&
(rdata.type == dns_rdatatype_soa ||
rdata.type == dns_rdatatype_ns)) {
- update_log(client, zone,
- LOGLEVEL_PROTOCOL,
+ update_log(client, zone, LOGLEVEL_PROTOCOL,
"attempt to delete all SOA "
"or NS records ignored");
continue;
static void
forward_fail(isc_task_t *task, isc_event_t *event) {
- ns_client_t *client = (ns_client_t *)event->ev_arg;
+ ns_client_t *client = (ns_client_t *)event->ev_arg;
UNUSED(task);
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: zoneconf.c,v 1.134 2006/06/04 23:17:06 marka Exp $ */
+/* $Id: zoneconf.c,v 1.135 2006/12/04 01:52:45 marka Exp $ */
/*% */
mtype = DNS_SSUMATCHTYPE_SELFSUB;
else if (strcasecmp(str, "selfwild") == 0)
mtype = DNS_SSUMATCHTYPE_SELFWILD;
+ else if (strcasecmp(str, "ms-self") == 0)
+ mtype = DNS_SSUMATCHTYPE_SELFMS;
+ else if (strcasecmp(str, "krb5-self") == 0)
+ mtype = DNS_SSUMATCHTYPE_SELFKRB5;
+ else if (strcasecmp(str, "ms-subdomain") == 0)
+ mtype = DNS_SSUMATCHTYPE_SUBDOMAINMS;
+ else if (strcasecmp(str, "krb5-subdomain") == 0)
+ mtype = DNS_SSUMATCHTYPE_SUBDOMAINKRB5;
else
INSIST(0);
# Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
-# 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
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
-# $Id: Makefile.in,v 1.23 2004/07/20 07:13:34 marka Exp $
+# $Id: Makefile.in,v 1.24 2006/12/04 01:52:45 marka Exp $
srcdir = @srcdir@
VPATH = @srcdir@
@BIND9_MAKE_INCLUDES@
CINCLUDES = ${LWRES_INCLUDES} ${DNS_INCLUDES} ${BIND9_INCLUDES} \
- ${ISC_INCLUDES}
+ ${ISC_INCLUDES} @DST_GSSAPI_INC@
-CDEFINES =
+CDEFINES = @USE_GSSAPI@
CWARNINGS =
LWRESLIBS = ../../lib/lwres/liblwres.@A@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: nsupdate.c,v 1.144 2006/06/09 07:26:42 marka Exp $ */
+/* $Id: nsupdate.c,v 1.145 2006/12/04 01:52:45 marka Exp $ */
/*! \file */
#include <isc/event.h>
#include <isc/hash.h>
#include <isc/lex.h>
+#include <isc/log.h>
#include <isc/mem.h>
#include <isc/parseint.h>
+#include <isc/random.h>
#include <isc/region.h>
#include <isc/sockaddr.h>
#include <isc/socket.h>
#include <dns/dnssec.h>
#include <dns/events.h>
#include <dns/fixedname.h>
+#include <dns/log.h>
#include <dns/masterdump.h>
#include <dns/message.h>
#include <dns/name.h>
#include <dns/rdatatype.h>
#include <dns/request.h>
#include <dns/result.h>
+#include <dns/tkey.h>
#include <dns/tsig.h>
#include <dst/dst.h>
#include <lwres/lwres.h>
#include <lwres/net.h>
+#ifdef GSSAPI
+#include <dst/gssapi.h>
+#endif
#include <bind9/getaddresses.h>
+
#ifdef HAVE_ADDRINFO
#ifdef HAVE_GETADDRINFO
#ifdef HAVE_GAISTRERROR
static isc_boolean_t have_ipv6 = ISC_FALSE;
static isc_boolean_t is_dst_up = ISC_FALSE;
static isc_boolean_t usevc = ISC_FALSE;
+static isc_boolean_t usegsstsig = ISC_FALSE;
+static isc_boolean_t use_win2k_gsstsig = ISC_FALSE;
+static isc_boolean_t tried_other_gsstsig = ISC_FALSE;
static isc_taskmgr_t *taskmgr = NULL;
static isc_task_t *global_task = NULL;
static isc_event_t *global_event = NULL;
+static isc_log_t *lctx = NULL;
static isc_mem_t *mctx = NULL;
static dns_dispatchmgr_t *dispatchmgr = NULL;
static dns_requestmgr_t *requestmgr = NULL;
static dns_message_t *updatemsg = NULL;
static dns_fixedname_t fuserzone;
static dns_name_t *userzone = NULL;
+static dns_name_t *zonename = NULL;
+static dns_name_t tmpzonename;
+static dns_name_t restart_master;
+static dns_tsig_keyring_t *gssring = NULL;
static dns_tsigkey_t *tsigkey = NULL;
static dst_key_t *sig0key;
static lwres_context_t *lwctx = NULL;
static int ns_total = 0;
static isc_sockaddr_t *userserver = NULL;
static isc_sockaddr_t *localaddr = NULL;
+static isc_sockaddr_t *serveraddr = NULL;
+static isc_sockaddr_t tempaddr;
static char *keystr = NULL, *keyfile = NULL;
static isc_entropy_t *entp = NULL;
static isc_boolean_t shuttingdown = ISC_FALSE;
static isc_boolean_t seenerror = ISC_FALSE;
static const dns_master_style_t *style;
static int requests = 0;
+static unsigned int logdebuglevel = 0;
static unsigned int timeout = 300;
static unsigned int udp_timeout = 3;
static unsigned int udp_retries = 3;
static void
ddebug(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
+#ifdef GSSAPI
+static dns_fixedname_t fkname;
+static isc_sockaddr_t *kserver = NULL;
+static char servicename[DNS_NAME_FORMATSIZE];
+static dns_name_t *keyname;
+typedef struct nsu_gssinfo {
+ dns_message_t *msg;
+ isc_sockaddr_t *addr;
+ gss_ctx_id_t context;
+} nsu_gssinfo_t;
+
+static void
+start_gssrequest(dns_name_t *master);
+static void
+send_gssrequest(isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
+ dns_message_t *msg, dns_request_t **request,
+ gss_ctx_id_t context);
+static void
+recvgss(isc_task_t *task, isc_event_t *event);
+#endif /* GSSAPI */
+
#define STATUS_MORE (isc_uint16_t)0
#define STATUS_SEND (isc_uint16_t)1
#define STATUS_QUIT (isc_uint16_t)2
check_result(result, "dns_message_create");
}
updatemsg->opcode = dns_opcode_update;
+ if (usegsstsig) {
+ if (tsigkey != NULL)
+ dns_tsigkey_detach(&tsigkey);
+ if (gssring != NULL)
+ dns_tsigkeyring_destroy(&gssring);
+ tried_other_gsstsig = ISC_FALSE;
+ }
}
static isc_uint16_t
lwres_result_t lwresult;
unsigned int attrs, attrmask;
int i;
+ isc_logconfig_t *logconfig = NULL;
ddebug("setup_system()");
result = isc_mem_create(0, 0, &mctx);
check_result(result, "isc_mem_create");
+ result = isc_log_create(mctx, &lctx, &logconfig);
+ check_result(result, "isc_log_create");
+
+ isc_log_setcontext(lctx);
+ dns_log_init(lctx);
+ dns_log_setcontext(lctx);
+
+ result = isc_log_usechannel(logconfig, "default_debug", NULL, NULL);
+ check_result(result, "isc_log_usechannel");
+
+ isc_log_setdebuglevel(lctx, logdebuglevel);
+
lwresult = lwres_context_create(&lwctx, mctx, mem_alloc, mem_free, 1);
if (lwresult != LWRES_R_SUCCESS)
fatal("lwres_context_create failed");
static void
parse_args(int argc, char **argv) {
int ch;
+ isc_uint32_t i;
isc_result_t result;
debug("parse_args");
- while ((ch = isc_commandline_parse(argc, argv, "dDMy:vk:r:t:u:")) != -1)
+ while ((ch = isc_commandline_parse(argc, argv, "dDMl:y:govk:r:t:u:")
+ ) != -1)
{
switch (ch) {
case 'd':
isc_mem_debugging = ISC_MEM_DEBUGTRACE |
ISC_MEM_DEBUGRECORD;
break;
+ case 'l':
+ result = isc_parse_uint32(&i, isc_commandline_argument,
+ 10);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "bad library debug value "
+ "'%s'\n", isc_commandline_argument);
+ exit(1);
+ }
+ logdebuglevel = i;
+ break;
case 'y':
keystr = isc_commandline_argument;
break;
case 'k':
keyfile = isc_commandline_argument;
break;
+ case 'g':
+ usegsstsig = ISC_TRUE;
+ use_win2k_gsstsig = ISC_FALSE;
+ break;
+ case 'o':
+ usegsstsig = ISC_TRUE;
+ use_win2k_gsstsig = ISC_TRUE;
+ break;
case 't':
result = isc_parse_uint32(&timeout,
isc_commandline_argument, 10);
fprintf(stderr, "%s: invalid argument -%c\n",
argv[0], ch);
fprintf(stderr, "usage: nsupdate [-d] "
- "[-y keyname:secret | -k keyfile] [-v] "
- "[filename]\n");
+ "[-g | -o | -y keyname:secret | -k keyfile] "
+ "[-v] [filename]\n");
exit(1);
}
}
exit(1);
}
+#ifdef GSSAPI
+ if (usegsstsig && (keyfile != NULL || keystr != NULL)) {
+ fprintf(stderr, "%s: cannot specify -g with -k or -y\n",
+ argv[0]);
+ exit(1);
+ }
+#else
+ if (usegsstsig) {
+ fprintf(stderr, "%s: cannot specify -g or -o, " \
+ "program not linked with GSS API Library\n",
+ argv[0]);
+ exit(1);
+ }
+#endif
+
if (argv[isc_commandline_index] != NULL) {
if (strcmp(argv[isc_commandline_index], "-") == 0) {
input = stdin;
}
r.base = word;
- r.length = strlen(word);
- result = dns_rdataclass_fromtext(&rdclass, &r);
+ r.length = strlen(word);
+ result = dns_rdataclass_fromtext(&rdclass, &r);
if (result != ISC_R_SUCCESS) {
fprintf(stderr, "could not parse class name: %s\n", word);
return (STATUS_SYNTAX);
}
static void
-show_message(dns_message_t *msg) {
+show_message(FILE *stream, dns_message_t *msg, const char *description) {
isc_result_t result;
isc_buffer_t *buf = NULL;
int bufsz;
isc_buffer_free(&buf);
return;
}
- printf("Outgoing update query:\n%.*s",
- (int)isc_buffer_usedlength(buf),
- (char*)isc_buffer_base(buf));
+ fprintf(stream, "%s\n%.*s", description,
+ (int)isc_buffer_usedlength(buf), (char*)isc_buffer_base(buf));
isc_buffer_free(&buf);
}
if (strcasecmp(word, "send") == 0)
return (STATUS_SEND);
if (strcasecmp(word, "show") == 0) {
- show_message(updatemsg);
+ show_message(stdout, updatemsg, "Outgoing update query:");
return (STATUS_MORE);
}
if (strcasecmp(word, "answer") == 0) {
if (answer != NULL)
- show_message(answer);
+ show_message(stdout, answer, "Answer:");
return (STATUS_MORE);
}
if (strcasecmp(word, "key") == 0)
return (evaluate_key(cmdline));
+ if (strcasecmp(word, "gsstsig") == 0) {
+#ifdef GSSAPI
+ usegsstsig = ISC_TRUE;
+ use_win2k_gsstsig = ISC_FALSE;
+#else
+ fprintf(stderr, "gsstsig not supported\n");
+#endif
+ return (STATUS_MORE);
+ }
+ if (strcasecmp(word, "oldgsstsig") == 0) {
+#ifdef GSSAPI
+ usegsstsig = ISC_TRUE;
+ use_win2k_gsstsig = ISC_TRUE;
+#else
+ fprintf(stderr, "gsstsig not supported\n");
+#endif
+ return (STATUS_MORE);
+ }
fprintf(stderr, "incorrect section name: %s\n", word);
return (STATUS_SYNTAX);
}
DNS_MESSAGEPARSE_PRESERVEORDER);
switch (result) {
case ISC_R_SUCCESS:
+ if (answer->verify_attempted)
+ ddebug("tsig verification successful");
break;
case DNS_R_CLOCKSKEW:
case DNS_R_EXPECTEDTSIG:
case DNS_R_TSIGERRORSET:
case DNS_R_TSIGVERIFYFAILURE:
case DNS_R_UNEXPECTEDTSIG:
+ case ISC_R_FAILURE:
+#if 0
+ if (usegsstsig && answer->rcode == dns_rcode_noerror) {
+ /*
+ * For MS DNS that violates RFC 2845, section 4.2
+ */
+ break;
+ }
+#endif
fprintf(stderr, "; TSIG error with server: %s\n",
isc_result_totext(result));
seenerror = ISC_TRUE;
(int)isc_buffer_usedlength(&b), buf);
}
}
- if (debugging) {
- isc_buffer_t *buf = NULL;
- int bufsz;
-
- bufsz = INITTEXT;
- do {
- if (bufsz > MAXTEXT) {
- fprintf(stderr, "could not allocate large "
- "enough buffer to display message\n");
- exit(1);
- }
- if (buf != NULL)
- isc_buffer_free(&buf);
- result = isc_buffer_allocate(mctx, &buf, bufsz);
- check_result(result, "isc_buffer_allocate");
- result = dns_message_totext(answer, style, 0, buf);
- bufsz *= 2;
- } while (result == ISC_R_NOSPACE);
- check_result(result, "dns_message_totext");
- fprintf(stderr, "\nReply from update query:\n%.*s\n",
- (int)isc_buffer_usedlength(buf),
- (char*)isc_buffer_base(buf));
- isc_buffer_free(&buf);
- }
+ if (debugging)
+ show_message(stderr, answer, "\nReply from update query:");
+
done:
dns_request_destroy(&request);
+ if (usegsstsig) {
+ dns_name_free(&tmpzonename, mctx);
+ dns_name_free(&restart_master, mctx);
+ }
isc_event_free(&event);
done_update();
}
isc_sockaddr_format(master, addrbuf, sizeof(addrbuf));
fprintf(stderr, "Sending update to %s\n", addrbuf);
}
+
result = dns_request_createvia3(requestmgr, updatemsg, srcaddr,
master, options, tsigkey, timeout,
udp_timeout, udp_retries, global_task,
check_result(result, "dns_request_createvia3");
if (debugging)
- show_message(updatemsg);
+ show_message(stdout, updatemsg, "Outgoing update query:");
requests++;
}
dns_rdata_t soarr = DNS_RDATA_INIT;
int pass = 0;
dns_name_t master;
- isc_sockaddr_t *serveraddr, tempaddr;
- dns_name_t *zonename;
nsu_requestinfo_t *reqinfo;
dns_message_t *soaquery = NULL;
isc_sockaddr_t *addr;
isc_sockaddr_format(addr, addrbuf, sizeof(addrbuf));
fprintf(stderr, "; Communication with %s failed: %s\n",
- addrbuf, isc_result_totext(eresult));
+ addrbuf, isc_result_totext(eresult));
if (userserver != NULL)
fatal("could not talk to specified name server");
else if (++ns_inuse >= lwconf->nsnext)
}
check_result(result, "dns_request_getresponse");
section = DNS_SECTION_ANSWER;
- if (debugging) {
- isc_buffer_t *buf = NULL;
- int bufsz;
- bufsz = INITTEXT;
- do {
- if (buf != NULL)
- isc_buffer_free(&buf);
- if (bufsz > MAXTEXT) {
- fprintf(stderr, "could not allocate enough "
- "space for debugging message\n");
- exit(1);
- }
- result = isc_buffer_allocate(mctx, &buf, bufsz);
- check_result(result, "isc_buffer_allocate");
- result = dns_message_totext(rcvmsg, style, 0, buf);
- } while (result == ISC_R_NOSPACE);
- check_result(result, "dns_message_totext");
- fprintf(stderr, "Reply from SOA query:\n%.*s\n",
- (int)isc_buffer_usedlength(buf),
- (char*)isc_buffer_base(buf));
- isc_buffer_free(&buf);
- }
+ if (debugging)
+ show_message(stderr, rcvmsg, "Reply from SOA query:");
if (rcvmsg->rcode != dns_rcode_noerror &&
rcvmsg->rcode != dns_rcode_nxdomain)
if (section == DNS_SECTION_ANSWER) {
dns_rdataset_t *tset = NULL;
if (dns_message_findtype(name, dns_rdatatype_cname, 0,
- &tset) == ISC_R_SUCCESS
- ||
+ &tset) == ISC_R_SUCCESS ||
dns_message_findtype(name, dns_rdatatype_dname, 0,
- &tset) == ISC_R_SUCCESS
- )
- {
+ &tset) == ISC_R_SUCCESS ) {
seencname = ISC_TRUE;
break;
}
}
dns_rdata_freestruct(&soa);
+#ifdef GSSAPI
+ if (usegsstsig) {
+ dns_name_init(&tmpzonename, NULL);
+ dns_name_dup(zonename, mctx, &tmpzonename);
+ dns_name_init(&restart_master, NULL);
+ dns_name_dup(&master, mctx, &restart_master);
+ start_gssrequest(&master);
+ } else {
+ send_update(zonename, serveraddr, localaddr);
+ setzoneclass(dns_rdataclass_none);
+ }
+#else
send_update(zonename, serveraddr, localaddr);
setzoneclass(dns_rdataclass_none);
+#endif
dns_message_destroy(&soaquery);
dns_request_destroy(&request);
if (userserver != NULL)
sendrequest(localaddr, userserver, soaquery, &request);
else
- sendrequest(localaddr, &servers[ns_inuse], soaquery,
- &request);
+ sendrequest(localaddr, &servers[ns_inuse], soaquery, &request);
goto out;
}
requests++;
}
+#ifdef GSSAPI
+static void
+start_gssrequest(dns_name_t *master)
+{
+ gss_ctx_id_t context;
+ isc_buffer_t buf;
+ isc_result_t result;
+ isc_uint32_t val = 0;
+ dns_message_t *rmsg;
+ dns_request_t *request = NULL;
+ dns_name_t *servname;
+ dns_fixedname_t fname;
+ char namestr[DNS_NAME_FORMATSIZE];
+ char keystr[DNS_NAME_FORMATSIZE];
+
+ debug("start_gssrequest");
+ usevc = ISC_TRUE;
+
+ if (gssring != NULL)
+ dns_tsigkeyring_destroy(&gssring);
+ gssring = NULL;
+ result = dns_tsigkeyring_create(mctx, &gssring);
+
+ dns_name_format(master, namestr, sizeof(namestr));
+ if (kserver == NULL) {
+ kserver = isc_mem_get(mctx, sizeof(isc_sockaddr_t));
+ if (kserver == NULL)
+ fatal("out of memory");
+ }
+ if (userserver == NULL)
+ get_address(namestr, DNSDEFAULTPORT, kserver);
+ else
+ (void)memcpy(kserver, userserver, sizeof(isc_sockaddr_t));
+
+ dns_fixedname_init(&fname);
+ servname = dns_fixedname_name(&fname);
+
+ sprintf(servicename,"DNS/%s", namestr);
+ isc_buffer_init(&buf, servicename, strlen(servicename));
+ isc_buffer_add(&buf, strlen(servicename));
+ result = dns_name_fromtext(servname, &buf, dns_rootname,
+ ISC_FALSE, NULL);
+
+ dns_fixedname_init(&fkname);
+ keyname = dns_fixedname_name(&fkname);
+
+ isc_random_get(&val);
+ sprintf(keystr, "%u.sig-%s", val, namestr);
+ isc_buffer_init(&buf, keystr, strlen(keystr));
+ isc_buffer_add(&buf, strlen(keystr));
+
+ result = dns_name_fromtext(keyname, &buf, dns_rootname,
+ ISC_FALSE, NULL);
+ INSIST(result == ISC_R_SUCCESS);
+
+ /* Windows doesn't recognize name compression in the key name. */
+ keyname->attributes |= DNS_NAMEATTR_NOCOMPRESS;
+
+ rmsg = NULL;
+ result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &rmsg);
+ INSIST(result == ISC_R_SUCCESS);
+
+ /* Build first request. */
+
+ context = GSS_C_NO_CONTEXT;
+ result = dns_tkey_buildgssquery(rmsg, keyname, servname, NULL, 0,
+ &context, use_win2k_gsstsig);
+ if (result == ISC_R_FAILURE)
+ fatal("Check your Kerberos ticket, it may have expired.");
+ INSIST(result == ISC_R_SUCCESS);
+
+ send_gssrequest(localaddr, kserver, rmsg, &request, context);
+}
+
+static void
+send_gssrequest(isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
+ dns_message_t *msg, dns_request_t **request,
+ gss_ctx_id_t context)
+{
+ isc_result_t result;
+ nsu_gssinfo_t *reqinfo;
+ unsigned int options = 0;
+
+ debug("send_gssrequest");
+ reqinfo = isc_mem_get(mctx, sizeof(nsu_gssinfo_t));
+ if (reqinfo == NULL)
+ fatal("out of memory");
+ reqinfo->msg = msg;
+ reqinfo->addr = destaddr;
+ reqinfo->context = context;
+
+ options |= DNS_REQUESTOPT_TCP;
+ result = dns_request_createvia3(requestmgr, msg, srcaddr, destaddr,
+ options, tsigkey, FIND_TIMEOUT * 20,
+ FIND_TIMEOUT, 3, global_task, recvgss,
+ reqinfo, request);
+ check_result(result, "dns_request_createvia3");
+ if (debugging)
+ show_message(stdout, msg, "Outgoing update query:");
+ requests++;
+}
+
+static void
+recvgss(isc_task_t *task, isc_event_t *event) {
+ dns_requestevent_t *reqev = NULL;
+ dns_request_t *request = NULL;
+ isc_result_t result, eresult;
+ dns_message_t *rcvmsg = NULL;
+ nsu_gssinfo_t *reqinfo;
+ dns_message_t *tsigquery = NULL;
+ isc_sockaddr_t *addr;
+ gss_ctx_id_t context;
+ isc_buffer_t buf;
+ dns_name_t *servname;
+ dns_fixedname_t fname;
+
+ UNUSED(task);
+
+ ddebug("recvgss()");
+
+ requests--;
+
+ REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE);
+ reqev = (dns_requestevent_t *)event;
+ request = reqev->request;
+ eresult = reqev->result;
+ reqinfo = reqev->ev_arg;
+ tsigquery = reqinfo->msg;
+ context = reqinfo->context;
+ addr = reqinfo->addr;
+
+ if (shuttingdown) {
+ dns_request_destroy(&request);
+ dns_message_destroy(&tsigquery);
+ isc_mem_put(mctx, reqinfo, sizeof(nsu_gssinfo_t));
+ isc_event_free(&event);
+ maybeshutdown();
+ return;
+ }
+
+ if (eresult != ISC_R_SUCCESS) {
+ char addrbuf[ISC_SOCKADDR_FORMATSIZE];
+
+ isc_sockaddr_format(addr, addrbuf, sizeof(addrbuf));
+ fprintf(stderr, "; Communication with %s failed: %s\n",
+ addrbuf, isc_result_totext(eresult));
+ if (userserver != NULL)
+ fatal("could not talk to specified name server");
+ else if (++ns_inuse >= lwconf->nsnext)
+ fatal("could not talk to any default name server");
+ ddebug("Destroying request [%p]", request);
+ dns_request_destroy(&request);
+ dns_message_renderreset(tsigquery);
+ sendrequest(localaddr, &servers[ns_inuse], tsigquery,
+ &request);
+ isc_mem_put(mctx, reqinfo, sizeof(nsu_gssinfo_t));
+ isc_event_free(&event);
+ return;
+ }
+ isc_mem_put(mctx, reqinfo, sizeof(nsu_gssinfo_t));
+
+ isc_event_free(&event);
+ reqev = NULL;
+
+ ddebug("recvgss creating rcvmsg");
+ result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &rcvmsg);
+ check_result(result, "dns_message_create");
+
+ result = dns_request_getresponse(request, rcvmsg,
+ DNS_MESSAGEPARSE_PRESERVEORDER);
+ check_result(result, "dns_request_getresponse");
+
+ if (debugging)
+ show_message(stderr, rcvmsg,
+ "recvmsg reply from GSS-TSIG query");
+
+ if (rcvmsg->rcode == dns_rcode_formerr && !tried_other_gsstsig) {
+ ddebug("recvgss trying %s GSS-TSIG",
+ use_win2k_gsstsig ? "Standard" : "Win2k");
+ if (use_win2k_gsstsig)
+ use_win2k_gsstsig = ISC_FALSE;
+ else
+ use_win2k_gsstsig = ISC_TRUE;
+ tried_other_gsstsig = ISC_TRUE;
+ start_gssrequest(&restart_master);
+ goto done;
+ }
+
+ if (rcvmsg->rcode != dns_rcode_noerror &&
+ rcvmsg->rcode != dns_rcode_nxdomain)
+ fatal("response to GSS-TSIG query was unsuccessful");
+
+
+ dns_fixedname_init(&fname);
+ servname = dns_fixedname_name(&fname);
+ isc_buffer_init(&buf, servicename, strlen(servicename));
+ isc_buffer_add(&buf, strlen(servicename));
+ result = dns_name_fromtext(servname, &buf, dns_rootname,
+ ISC_FALSE, NULL);
+ check_result(result, "dns_name_fromtext");
+
+ tsigkey = NULL;
+ result = dns_tkey_gssnegotiate(tsigquery, rcvmsg, servname,
+ &context, &tsigkey, gssring,
+ use_win2k_gsstsig);
+ switch (result) {
+
+ case DNS_R_CONTINUE:
+ send_gssrequest(localaddr, kserver, tsigquery, &request,
+ context);
+ break;
+
+ case ISC_R_SUCCESS:
+ /*
+ * XXXSRA Waaay too much fun here. There's no good
+ * reason why we need a TSIG here (the people who put
+ * it into the spec admitted at the time that it was
+ * not a security issue), and Windows clients don't
+ * seem to work if named complies with the spec and
+ * includes the gratuitous TSIG. So we're in the
+ * bizzare situation of having to choose between
+ * complying with a useless requirement in the spec
+ * and interoperating. This is nuts. If we can
+ * confirm this behavior, we should ask the WG to
+ * consider removing the requirement for the
+ * gratuitous TSIG here. For the moment, we ignore
+ * the TSIG -- this too is a spec violation, but it's
+ * the least insane thing to do.
+ */
+#if 0
+ /*
+ * Verify the signature.
+ */
+ rcvmsg->state = DNS_SECTION_ANY;
+ dns_message_setquerytsig(rcvmsg, NULL);
+ result = dns_message_settsigkey(rcvmsg, tsigkey);
+ check_result(result, "dns_message_settsigkey");
+ result = dns_message_checksig(rcvmsg, NULL);
+ ddebug("tsig verification: %s", dns_result_totext(result));
+ check_result(result, "dns_message_checksig");
+#endif /* 0 */
+
+ send_update(&tmpzonename, serveraddr, localaddr);
+ setzoneclass(dns_rdataclass_none);
+ break;
+
+ default:
+ fatal("dns_tkey_negotiategss: %s", isc_result_totext(result));
+ }
+
+ done:
+ dns_request_destroy(&request);
+ dns_message_destroy(&tsigquery);
+
+ dns_message_destroy(&rcvmsg);
+ ddebug("Out of recvgss");
+}
+#endif
+
static void
start_update(void) {
isc_result_t result;
return;
}
- if (userzone != NULL && userserver != NULL) {
+ if (userzone != NULL && userserver != NULL && ! usegsstsig) {
send_update(userzone, userserver, localaddr);
setzoneclass(dns_rdataclass_none);
return;
if (answer != NULL)
dns_message_destroy(&answer);
+
+#ifdef GSSAPI
+ if (usegsstsig) {
+ if (tsigkey != NULL) {
+ ddebug("detach tsigkey x%p", tsigkey);
+ dns_tsigkey_detach(&tsigkey);
+ }
+ ddebug("Destroying GSS-TSIG keyring");
+ if (gssring != NULL)
+ dns_tsigkeyring_destroy(&gssring);
+ }
+ if (kserver != NULL)
+ isc_mem_put(mctx, kserver, sizeof(isc_sockaddr_t));
+#endif
+
ddebug("Shutting down task manager");
isc_taskmgr_destroy(&taskmgr);
ddebug("Destroying name state");
dns_name_destroy();
+ ddebug("Removing log context");
+ isc_log_destroy(&lctx);
+
ddebug("Destroying memory context");
if (memdebugging)
isc_mem_stats(mctx, stderr);
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: rndc.c,v 1.113 2006/08/04 02:55:37 marka Exp $ */
+/* $Id: rndc.c,v 1.114 2006/12/04 01:52:45 marka Exp $ */
/*! \file */
r.base = databuf;
isccc_ccmsg_init(mctx, sock, &ccmsg);
- isccc_ccmsg_setmaxsize(&ccmsg, 1024);
+ isccc_ccmsg_setmaxsize(&ccmsg, 1024 * 1024);
DO("schedule recv", isccc_ccmsg_readmessage(&ccmsg, task,
rndc_recvnonce, NULL));
Makefile
dst_test
t_dst
+gsstest
.libs
randomfile
*.lo
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
-# $Id: Makefile.in,v 1.36 2004/07/20 07:13:36 marka Exp $
+# $Id: Makefile.in,v 1.37 2006/12/04 01:52:45 marka Exp $
srcdir = @srcdir@
VPATH = @srcdir@
@BIND9_MAKE_INCLUDES@
-CINCLUDES = ${TEST_INCLUDES} ${DNS_INCLUDES} ${ISC_INCLUDES}
+CINCLUDES = ${TEST_INCLUDES} ${DNS_INCLUDES} ${ISC_INCLUDES} \
+ @DST_GSSAPI_INC@
CDEFINES =
CWARNINGS =
TLIB = ../../../lib/tests/libt_api.@A@
-TARGETS = dst_test@EXEEXT@ t_dst@EXEEXT@
+TARGETS = dst_test@EXEEXT@ t_dst@EXEEXT@ gsstest@EXEEXT@
-SRCS = dst_test.c t_dst.c
+SRCS = dst_test.c t_dst.c gsstest.c
@BIND9_MAKE_RULES@
t_dst@EXEEXT@: t_dst.@O@ ${DEPLIBS} ${TLIB}
${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ t_dst.@O@ ${TLIB} ${LIBS}
+gsstest@EXEEXT@: gsstest.@O@ ${DEPLIBS} ${TLIB}
+ ${LIBTOOL} ${PURIFY} ${CC} ${CFLAGS} -o $@ gsstest.@O@ ${TLIB} ${LIBS}
+
test: t_dst@EXEEXT@
../genrandom@EXEEXT@ 100 randomfile
-@ ./t_dst@EXEEXT@ -b @srcdir@ -q 1800 -a
--- /dev/null
+/*
+ * Copyright (C) 2001 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
+ * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: gsstest.c,v 1.2 2006/12/04 01:52:45 marka Exp $ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <isc/app.h>
+#include <isc/base64.h>
+#include <isc/entropy.h>
+#include <isc/log.h>
+#include <isc/mem.h>
+#include <isc/sockaddr.h>
+#include <isc/socket.h>
+#include <isc/task.h>
+#include <isc/timer.h>
+#include <isc/util.h>
+
+#include <dns/dispatch.h>
+#include <dns/fixedname.h>
+#include <dns/keyvalues.h>
+#include <dns/log.h>
+#include <dns/message.h>
+#include <dns/name.h>
+#include <dns/request.h>
+#include <dns/result.h>
+#include <dns/tkey.h>
+#include <dns/tsig.h>
+#include <dns/view.h>
+
+#include <dns/dnssec.h>
+#include <dns/events.h>
+#include <dns/masterdump.h>
+#include <dns/rdataset.h>
+#include <dns/resolver.h>
+#include <dns/types.h>
+
+#include <dst/result.h>
+
+#ifdef GSSAPI
+#include ISC_PLATFORM_GSSAPIHEADER
+
+struct dst_context {
+ unsigned int magic;
+ dst_key_t *key;
+ isc_mem_t *mctx;
+ void *opaque;
+};
+
+#define CHECK(str, x) { \
+ if ((x) != ISC_R_SUCCESS) { \
+ fprintf(stderr, "I:%d:%s: %s\n", __LINE__, (str), isc_result_totext(x)); \
+ goto end; \
+ } \
+}
+
+static char contextname[512];
+static char gssid[512];
+static char serveraddress[512];
+static dns_fixedname_t servername, gssname;
+
+static isc_mem_t *mctx;
+static dns_requestmgr_t *requestmgr;
+static isc_sockaddr_t address;
+
+static dns_tsig_keyring_t *ring;
+static dns_tsigkey_t *tsigkey = NULL;
+static gss_ctx_id_t gssctx;
+static gss_ctx_id_t *gssctxp = &gssctx;
+
+#define RUNCHECK(x) RUNTIME_CHECK((x) == ISC_R_SUCCESS)
+
+#define PORT 53
+#define TIMEOUT 30
+
+static void initctx1(isc_task_t *task, isc_event_t *event);
+static void sendquery(isc_task_t *task, isc_event_t *event);
+static void setup();
+
+static void
+console(isc_task_t *task, isc_event_t *event)
+{
+ char buf[32];
+ isc_event_t *ev = NULL;
+
+ isc_event_free(&event);
+
+ while(1) {
+ printf("\nCommand => ");
+ scanf("%s", buf);
+
+ if(strcmp(buf, "quit") == 0) {
+ isc_app_shutdown();
+ return;
+ }
+
+ if(strcmp(buf, "initctx") == 0) {
+ ev = isc_event_allocate(mctx, (void *)1, 1, initctx1,
+ NULL, sizeof(*event));
+ isc_task_send(task, &ev);
+ return;
+ }
+
+ if(strcmp(buf, "query") == 0) {
+ ev = isc_event_allocate(mctx, (void *)1, 1, sendquery,
+ NULL, sizeof(*event));
+ isc_task_send(task, &ev);
+ return;
+ }
+
+ printf("Unknown command\n");
+ }
+}
+
+static void
+recvresponse(isc_task_t *task, isc_event_t *event) {
+ dns_requestevent_t *reqev = (dns_requestevent_t *)event;
+ isc_result_t result, result2;
+ dns_message_t *query, *response = NULL;
+ isc_buffer_t outtoken;
+ isc_buffer_t outbuf;
+ char output[10 * 1024];
+
+ unsigned char array[DNS_NAME_MAXTEXT + 1];
+ isc_buffer_init(&outtoken, array, sizeof(array));
+
+ UNUSED(task);
+
+ REQUIRE(reqev != NULL);
+
+ if (reqev->result != ISC_R_SUCCESS) {
+ fprintf(stderr, "I:request event result: %s\n",
+ isc_result_totext(reqev->result));
+ goto end;
+ }
+
+ query = reqev->ev_arg;
+
+ response = NULL;
+ result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &response);
+ CHECK("dns_message_create", result);
+
+ printf("\nReceived Response:\n");
+
+ result2 = dns_request_getresponse(reqev->request, response,
+ DNS_MESSAGEPARSE_PRESERVEORDER);
+ isc_buffer_init(&outbuf, output, sizeof(output));
+ result = dns_message_totext(response, &dns_master_style_debug, 0,
+ &outbuf);
+ CHECK("dns_message_totext", result);
+ printf("%.*s\n", (int)isc_buffer_usedlength(&outbuf),
+ (char *)isc_buffer_base(&outbuf));
+
+ CHECK("dns_request_getresponse", result2);
+
+ if (response)
+ dns_message_destroy(&response);
+
+end:
+ if (query)
+ dns_message_destroy(&query);
+
+ if (reqev->request)
+ dns_request_destroy(&reqev->request);
+
+ isc_event_free(&event);
+
+ event = isc_event_allocate(mctx, (void *)1, 1, console, NULL,
+ sizeof(*event));
+ isc_task_send(task, &event);
+ return;
+}
+
+
+static void
+sendquery(isc_task_t *task, isc_event_t *event)
+{
+ dns_request_t *request = NULL;
+ dns_message_t *message = NULL;
+ dns_name_t *qname = NULL;
+ dns_rdataset_t *qrdataset = NULL;
+ isc_result_t result;
+ dns_fixedname_t queryname;
+ isc_buffer_t buf;
+ isc_buffer_t outbuf;
+ char output[10 * 1024];
+
+ static char host[256];
+
+ isc_event_free(&event);
+
+ printf("Query => ");
+ scanf("%s", host);
+
+ dns_fixedname_init(&queryname);
+ isc_buffer_init(&buf, host, strlen(host));
+ isc_buffer_add(&buf, strlen(host));
+ result = dns_name_fromtext(dns_fixedname_name(&queryname), &buf,
+ dns_rootname, ISC_FALSE, NULL);
+ CHECK("dns_name_fromtext", result);
+
+ result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &message);
+
+ message->opcode = dns_opcode_query;
+ message->rdclass = dns_rdataclass_in;
+ message->id = (unsigned short)(random() & 0xFFFF);
+
+ result = dns_message_gettempname(message, &qname);
+ if (result != ISC_R_SUCCESS)
+ goto end;
+
+ result = dns_message_gettemprdataset(message, &qrdataset);
+ if (result != ISC_R_SUCCESS)
+ goto end;
+
+ dns_name_init(qname, NULL);
+ dns_name_clone(dns_fixedname_name(&queryname), qname);
+ dns_rdataset_init(qrdataset);
+ dns_rdataset_makequestion(qrdataset, dns_rdataclass_in,
+ dns_rdatatype_a);
+ ISC_LIST_APPEND(qname->list, qrdataset, link);
+ dns_message_addname(message, qname, DNS_SECTION_QUESTION);
+
+ result = dns_request_create(requestmgr, message, &address, 0, tsigkey,
+ TIMEOUT, task, recvresponse,
+ message, &request);
+ CHECK("dns_request_create", result);
+
+ printf("Submitting query:\n");
+ isc_buffer_init(&outbuf, output, sizeof(output));
+ result = dns_message_totext(message, &dns_master_style_debug, 0,
+ &outbuf);
+ CHECK("dns_message_totext", result);
+ printf("%.*s\n", (int)isc_buffer_usedlength(&outbuf),
+ (char *)isc_buffer_base(&outbuf));
+
+ return;
+
+ end:
+ if (qname != NULL)
+ dns_message_puttempname(message, &qname);
+ if (qrdataset != NULL)
+ dns_message_puttemprdataset(message, &qrdataset);
+ if (message != NULL)
+ dns_message_destroy(&message);
+}
+
+static void
+initctx2(isc_task_t *task, isc_event_t *event) {
+ dns_requestevent_t *reqev = (dns_requestevent_t *)event;
+ isc_result_t result;
+ dns_message_t *query, *response = NULL;
+ isc_buffer_t outtoken;
+ unsigned char array[DNS_NAME_MAXTEXT + 1];
+ dns_rdataset_t *rdataset;
+ dns_rdatatype_t qtype;
+ dns_name_t *question_name;
+
+ UNUSED(task);
+
+ REQUIRE(reqev != NULL);
+
+ if (reqev->result != ISC_R_SUCCESS) {
+ fprintf(stderr, "I:request event result: %s\n",
+ isc_result_totext(reqev->result));
+ goto end;
+ }
+
+ query = reqev->ev_arg;
+
+ response = NULL;
+ result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &response);
+ CHECK("dns_message_create", result);
+
+ result = dns_request_getresponse(reqev->request, response,
+ DNS_MESSAGEPARSE_PRESERVEORDER);
+ CHECK("dns_request_getresponse", result);
+
+ if (response->rcode != dns_rcode_noerror) {
+ result = ISC_RESULTCLASS_DNSRCODE + response->rcode;
+ fprintf(stderr, "I:response rcode: %s\n",
+ isc_result_totext(result));
+ goto end;
+ }
+
+ printf("Received token from server, calling gss_init_sec_context()\n");
+ isc_buffer_init(&outtoken, array, DNS_NAME_MAXTEXT + 1);
+ result = dns_tkey_processgssresponse(query, response,
+ dns_fixedname_name(&gssname),
+ &gssctx, &outtoken,
+ &tsigkey, ring);
+ gssctx = *gssctxp;
+ CHECK("dns_tkey_processgssresponse", result);
+ printf("Context accepted\n");
+
+ question_name = NULL;
+ dns_message_currentname(response, DNS_SECTION_ANSWER, &question_name);
+ rdataset = ISC_LIST_HEAD(question_name->list);
+ INSIST(rdataset != NULL);
+ qtype = rdataset->type;
+ if(qtype == dns_rdatatype_tkey) {
+ printf("Received TKEY response from server\n");
+ printf("Context completed\n");
+ } else {
+ printf("Did not receive TKEY response from server\n");
+ printf("Context not completed\n");
+ dns_tsigkey_detach(&tsigkey);
+ tsigkey = NULL;
+ }
+
+ if(response)
+ dns_message_destroy(&response);
+
+end:
+ if(query)
+ dns_message_destroy(&query);
+
+ if(reqev->request)
+ dns_request_destroy(&reqev->request);
+
+ isc_event_free(&event);
+
+ event = isc_event_allocate(mctx, (void *)1, 1, console, NULL,
+ sizeof(*event));
+ isc_task_send(task, &event);
+ return;
+}
+
+static void
+initctx1(isc_task_t *task, isc_event_t *event) {
+ isc_result_t result;
+ isc_buffer_t buf;
+ dns_message_t *query;
+ dns_request_t *request;
+
+ isc_event_free(&event);
+
+ printf("Initctx - GSS name => ");
+ scanf("%s", gssid);
+
+ sprintf(contextname, "gsstest.context.%d.", (int)time(NULL));
+
+ printf("Initctx - context name we're using: %s\n", contextname);
+
+ printf("Negotiating GSSAPI context: ");
+ printf(gssid);
+ printf("\n");
+
+ /*
+ * Setup a GSSAPI context with the server
+ */
+ dns_fixedname_init(&servername);
+ isc_buffer_init(&buf, contextname, strlen(contextname));
+ isc_buffer_add(&buf, strlen(contextname));
+ result = dns_name_fromtext(dns_fixedname_name(&servername), &buf,
+ dns_rootname, ISC_FALSE, NULL);
+ CHECK("dns_name_fromtext", result);
+
+ /* Make name happen */
+ dns_fixedname_init(&gssname);
+ isc_buffer_init(&buf, gssid, strlen(gssid));
+ isc_buffer_add(&buf, strlen(gssid));
+ result = dns_name_fromtext(dns_fixedname_name(&gssname), &buf,
+ dns_rootname, ISC_FALSE, NULL);
+ CHECK("dns_name_fromtext", result);
+
+ query = NULL;
+ result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &query);
+ CHECK("dns_message_create", result);
+
+ printf("Calling gss_init_sec_context()\n");
+ gssctx = GSS_C_NO_CONTEXT;
+ result = dns_tkey_buildgssquery(query, dns_fixedname_name(&servername),
+ dns_fixedname_name(&gssname),
+ NULL, 36000, &gssctx, ISC_TRUE);
+ CHECK("dns_tkey_buildgssquery", result);
+
+ printf("Sending context token to server\n");
+ request = NULL;
+ result = dns_request_create(requestmgr, query, &address, 0, NULL,
+ TIMEOUT, task, initctx2, query, &request);
+ CHECK("dns_request_create", result);
+
+ return;
+end:
+ event = isc_event_allocate(mctx, (void *)1, 1, console, NULL,
+ sizeof(*event));
+ isc_task_send(task, &event);return;
+}
+
+static void
+setup(void)
+{
+ struct in_addr inaddr;
+
+ while (1) {
+ printf("Server IP => ");
+ scanf("%s", serveraddress);
+
+ if(strcmp(serveraddress, "quit") == 0) {
+ isc_app_shutdown();
+ return;
+ }
+
+ if (inet_pton(AF_INET, serveraddress, &inaddr) == 1) {
+ isc_sockaddr_fromin(&address, &inaddr, PORT);
+ return;
+ }
+
+ };
+}
+
+int
+main(int argc, char *argv[]) {
+ isc_taskmgr_t *taskmgr;
+ isc_timermgr_t *timermgr;
+ isc_socketmgr_t *socketmgr;
+ isc_socket_t *sock;
+ unsigned int attrs, attrmask;
+ isc_sockaddr_t bind_any;
+ dns_dispatchmgr_t *dispatchmgr;
+ dns_dispatch_t *dispatchv4;
+ dns_view_t *view;
+ isc_entropy_t *ectx;
+ isc_task_t *task;
+ isc_log_t *lctx = NULL;
+ isc_logconfig_t *lcfg = NULL;
+ isc_logdestination_t destination;
+
+ UNUSED(argv);
+ UNUSED(argc);
+
+ RUNCHECK(isc_app_start());
+
+ dns_result_register();
+
+ mctx = NULL;
+ RUNCHECK(isc_mem_create(0, 0, &mctx));
+
+ RUNCHECK(isc_log_create(mctx, &lctx, &lcfg));
+ isc_log_setcontext(lctx);
+ dns_log_init(lctx);
+ dns_log_setcontext(lctx);
+
+ /*
+ * Create and install the default channel.
+ */
+ destination.file.stream = stderr;
+ destination.file.name = NULL;
+ destination.file.versions = ISC_LOG_ROLLNEVER;
+ destination.file.maximum_size = 0;
+ RUNCHECK(isc_log_createchannel(lcfg, "_default",
+ ISC_LOG_TOFILEDESC,
+ ISC_LOG_DYNAMIC,
+ &destination, ISC_LOG_PRINTTIME));
+ RUNCHECK(isc_log_usechannel(lcfg, "_default", NULL, NULL));
+
+ isc_log_setdebuglevel(lctx, 9);
+
+ ectx = NULL;
+ RUNCHECK(isc_entropy_create(mctx, &ectx));
+ RUNCHECK(isc_entropy_createfilesource(ectx, "/dev/urandom"));
+
+ RUNCHECK(dst_lib_init(mctx, ectx, ISC_ENTROPY_GOODONLY));
+
+ taskmgr = NULL;
+ RUNCHECK(isc_taskmgr_create(mctx, 1, 0, &taskmgr));
+ task = NULL;
+ RUNCHECK(isc_task_create(taskmgr, 0, &task));
+ timermgr = NULL;
+ RUNCHECK(isc_timermgr_create(mctx, &timermgr));
+ socketmgr = NULL;
+ RUNCHECK(isc_socketmgr_create(mctx, &socketmgr));
+ dispatchmgr = NULL;
+ RUNCHECK(dns_dispatchmgr_create(mctx, ectx, &dispatchmgr));
+ isc_sockaddr_any(&bind_any);
+ attrs = DNS_DISPATCHATTR_UDP |
+ DNS_DISPATCHATTR_MAKEQUERY |
+ DNS_DISPATCHATTR_IPV4;
+ attrmask = DNS_DISPATCHATTR_UDP |
+ DNS_DISPATCHATTR_TCP |
+ DNS_DISPATCHATTR_IPV4 |
+ DNS_DISPATCHATTR_IPV6;
+ dispatchv4 = NULL;
+ RUNCHECK(dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr,
+ &bind_any, 4096, 4, 2, 3, 5,
+ attrs, attrmask, &dispatchv4));
+ requestmgr = NULL;
+ RUNCHECK(dns_requestmgr_create(mctx, timermgr, socketmgr, taskmgr,
+ dispatchmgr, dispatchv4, NULL,
+ &requestmgr));
+
+ ring = NULL;
+ RUNCHECK(dns_tsigkeyring_create(mctx, &ring));
+
+ view = NULL;
+ RUNCHECK(dns_view_create(mctx, 0, "_test", &view));
+ dns_view_setkeyring(view, ring);
+
+ sock = NULL;
+ RUNCHECK(isc_socket_create(socketmgr, PF_INET, isc_sockettype_udp,
+ &sock));
+
+ setup();
+
+ RUNCHECK(isc_app_onrun(mctx, task, console, NULL));
+
+ (void)isc_app_run();
+
+ if (tsigkey)
+ dns_tsigkey_detach(&tsigkey);
+
+ dns_requestmgr_shutdown(requestmgr);
+ dns_requestmgr_detach(&requestmgr);
+
+ dns_dispatch_detach(&dispatchv4);
+ dns_dispatchmgr_destroy(&dispatchmgr);
+
+ isc_timermgr_destroy(&timermgr);
+
+ isc_task_detach(&task);
+ isc_taskmgr_destroy(&taskmgr);
+
+ isc_socket_detach(&sock);
+ isc_socketmgr_destroy(&socketmgr);
+
+ isc_mem_stats(mctx, stdout);
+
+ dns_view_detach(&view);
+
+ dst_lib_destroy();
+ isc_entropy_detach(&ectx);
+
+ isc_mem_stats(mctx, stdout);
+ isc_mem_destroy(&mctx);
+
+ isc_app_finish();
+
+ return (0);
+}
+#else
+int
+main(int argc, char *argv[]) {
+ UNUSED(argc);
+ UNUSED(argv);
+ fprintf(stderr, "R:GSSAPIONLY\n");
+ return (0);
+}
+#endif
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: config.h.in,v 1.82 2006/08/10 01:57:41 marka Exp $ */
+/* $Id: config.h.in,v 1.83 2006/12/04 01:54:53 marka Exp $ */
/*! \file */
/* Define to 1 if you have the <fcntl.h> header file. */
#undef HAVE_FCNTL_H
+/* Define to 1 if you have the <gssapi/gssapi.h> header file. */
+#undef HAVE_GSSAPI_GSSAPI_H
+
+/* Define to 1 if you have the <gssapi.h> header file. */
+#undef HAVE_GSSAPI_H
+
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
#
-# $Id: configure,v 1.406 2006/11/10 17:55:20 marka Exp $
+# $Id: configure,v 1.407 2006/12/04 01:54:53 marka Exp $
#
# Portions Copyright (C) 1996-2001 Nominum, Inc.
#
# 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.
-# From configure.in Revision: 1.418 .
+# From configure.in Revision: 1.419 .
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.59.
#
# include <unistd.h>
#endif"
-ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS subdirs build build_cpu build_vendor build_os host host_cpu host_vendor host_os SET_MAKE RANLIB ac_ct_RANLIB INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA LN_S STD_CINCLUDES STD_CDEFINES STD_CWARNINGS CCOPT AR ARFLAGS LN ETAGS PERL CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CPP EGREP ISC_SOCKADDR_LEN_T ISC_PLATFORM_HAVELONGLONG ISC_PLATFORM_HAVELIFCONF ISC_PLATFORM_NEEDSYSSELECTH LWRES_PLATFORM_NEEDSYSSELECTH USE_OPENSSL DST_OPENSSL_INC USE_GSSAPI DST_GSSAPI_INC DNS_CRYPTO_LIBS ALWAYS_DEFINES ISC_PLATFORM_USETHREADS ISC_THREAD_DIR MKDEPCC MKDEPCFLAGS MKDEPPROG IRIX_DNSSEC_WARNINGS_HACK purify_path PURIFY ECHO ac_ct_AR STRIP ac_ct_STRIP CXX CXXFLAGS ac_ct_CXX CXXCPP F77 FFLAGS ac_ct_F77 LIBTOOL O A SA LIBTOOL_MKDEP_SED LIBTOOL_MODE_COMPILE LIBTOOL_MODE_INSTALL LIBTOOL_MODE_LINK LIBTOOL_ALLOW_UNDEFINED LIBTOOL_IN_MAIN LIBBIND ISC_PLATFORM_HAVEIPV6 LWRES_PLATFORM_HAVEIPV6 ISC_PLATFORM_NEEDNETINETIN6H LWRES_PLATFORM_NEEDNETINETIN6H ISC_PLATFORM_NEEDNETINET6IN6H LWRES_PLATFORM_NEEDNETINET6IN6H ISC_PLATFORM_HAVEINADDR6 LWRES_PLATFORM_HAVEINADDR6 ISC_PLATFORM_NEEDIN6ADDRANY LWRES_PLATFORM_NEEDIN6ADDRANY ISC_PLATFORM_NEEDIN6ADDRLOOPBACK LWRES_PLATFORM_NEEDIN6ADDRLOOPBACK ISC_PLATFORM_HAVEIN6PKTINFO ISC_PLATFORM_FIXIN6ISADDR ISC_IPV6_H ISC_IPV6_O ISC_ISCIPV6_O ISC_IPV6_C LWRES_HAVE_SIN6_SCOPE_ID ISC_PLATFORM_HAVESCOPEID ISC_PLATFORM_HAVEIF_LADDRREQ ISC_PLATFORM_HAVEIF_LADDRCONF ISC_PLATFORM_NEEDNTOP ISC_PLATFORM_NEEDPTON ISC_PLATFORM_NEEDATON ISC_PLATFORM_HAVESALEN LWRES_PLATFORM_HAVESALEN ISC_PLATFORM_MSGHDRFLAVOR ISC_PLATFORM_NEEDPORTT ISC_LWRES_NEEDADDRINFO ISC_LWRES_NEEDRRSETINFO ISC_LWRES_SETHOSTENTINT ISC_LWRES_ENDHOSTENTINT ISC_LWRES_GETNETBYADDRINADDR ISC_LWRES_SETNETENTINT ISC_LWRES_ENDNETENTINT ISC_LWRES_GETHOSTBYADDRVOID ISC_LWRES_NEEDHERRNO ISC_LWRES_GETIPNODEPROTO ISC_LWRES_GETADDRINFOPROTO ISC_LWRES_GETNAMEINFOPROTO ISC_PLATFORM_NEEDSTRSEP ISC_PLATFORM_NEEDMEMMOVE ISC_PLATFORM_NEEDSTRTOUL LWRES_PLATFORM_NEEDSTRTOUL GENRANDOMLIB ISC_PLATFORM_NEEDSTRLCPY ISC_PLATFORM_NEEDSTRLCAT ISC_PLATFORM_NEEDSPRINTF LWRES_PLATFORM_NEEDSPRINTF ISC_PLATFORM_NEEDVSNPRINTF LWRES_PLATFORM_NEEDVSNPRINTF ISC_EXTRA_OBJS ISC_EXTRA_SRCS ISC_PLATFORM_QUADFORMAT LWRES_PLATFORM_QUADFORMAT ISC_PLATFORM_HAVESYSUNH ISC_PLATFORM_RLIMITTYPE ISC_PLATFORM_USEDECLSPEC LWRES_PLATFORM_USEDECLSPEC ISC_PLATFORM_BRACEPTHREADONCEINIT ISC_PLATFORM_HAVEIFNAMETOINDEX ISC_PLATFORM_HAVEXADD ISC_PLATFORM_HAVECMPXCHG ISC_PLATFORM_HAVEATOMICSTORE ISC_PLATFORM_USEGCCASM ISC_PLATFORM_USEOSFASM ISC_PLATFORM_USESTDASM ISC_ARCH_DIR LATEX PDFLATEX W3M XSLTPROC XMLLINT XSLT_DOCBOOK_STYLE_HTML XSLT_DOCBOOK_STYLE_XHTML XSLT_DOCBOOK_STYLE_MAN XSLT_DOCBOOK_CHUNK_HTML XSLT_DOCBOOK_CHUNK_XHTML XSLT_DOCBOOK_CHUNKTOC_HTML XSLT_DOCBOOK_CHUNKTOC_XHTML XSLT_DOCBOOK_MAKETOC_HTML XSLT_DOCBOOK_MAKETOC_XHTML XSLT_DB2LATEX_STYLE XSLT_DB2LATEX_ADMONITIONS IDNLIBS BIND9_TOP_BUILDDIR BIND9_ISC_BUILDINCLUDE BIND9_ISCCC_BUILDINCLUDE BIND9_ISCCFG_BUILDINCLUDE BIND9_DNS_BUILDINCLUDE BIND9_LWRES_BUILDINCLUDE BIND9_BIND9_BUILDINCLUDE BIND9_VERSION PG_CONFIG USE_DLZ DLZ_DRIVER_INCLUDES DLZ_DRIVER_LIBS DLZ_DRIVER_SRCS DLZ_DRIVER_OBJS BUILD_CC BUILD_CFLAGS BUILD_CPPFLAGS BUILD_LDFLAGS BUILD_LIBS LIBOBJS LTLIBOBJS'
+ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS subdirs build build_cpu build_vendor build_os host host_cpu host_vendor host_os SET_MAKE RANLIB ac_ct_RANLIB INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA LN_S STD_CINCLUDES STD_CDEFINES STD_CWARNINGS CCOPT AR ARFLAGS LN ETAGS PERL CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CPP EGREP ISC_SOCKADDR_LEN_T ISC_PLATFORM_HAVELONGLONG ISC_PLATFORM_HAVELIFCONF ISC_PLATFORM_NEEDSYSSELECTH LWRES_PLATFORM_NEEDSYSSELECTH USE_OPENSSL DST_OPENSSL_INC ISC_PLATFORM_HAVEGSSAPI ISC_PLATFORM_GSSAPIHEADER USE_GSSAPI DST_GSSAPI_INC DNS_GSSAPI_LIBS DNS_CRYPTO_LIBS ALWAYS_DEFINES ISC_PLATFORM_USETHREADS ISC_THREAD_DIR MKDEPCC MKDEPCFLAGS MKDEPPROG IRIX_DNSSEC_WARNINGS_HACK purify_path PURIFY ECHO ac_ct_AR STRIP ac_ct_STRIP CXX CXXFLAGS ac_ct_CXX CXXCPP F77 FFLAGS ac_ct_F77 LIBTOOL O A SA LIBTOOL_MKDEP_SED LIBTOOL_MODE_COMPILE LIBTOOL_MODE_INSTALL LIBTOOL_MODE_LINK LIBTOOL_ALLOW_UNDEFINED LIBTOOL_IN_MAIN LIBBIND ISC_PLATFORM_HAVEIPV6 LWRES_PLATFORM_HAVEIPV6 ISC_PLATFORM_NEEDNETINETIN6H LWRES_PLATFORM_NEEDNETINETIN6H ISC_PLATFORM_NEEDNETINET6IN6H LWRES_PLATFORM_NEEDNETINET6IN6H ISC_PLATFORM_HAVEINADDR6 LWRES_PLATFORM_HAVEINADDR6 ISC_PLATFORM_NEEDIN6ADDRANY LWRES_PLATFORM_NEEDIN6ADDRANY ISC_PLATFORM_NEEDIN6ADDRLOOPBACK LWRES_PLATFORM_NEEDIN6ADDRLOOPBACK ISC_PLATFORM_HAVEIN6PKTINFO ISC_PLATFORM_FIXIN6ISADDR ISC_IPV6_H ISC_IPV6_O ISC_ISCIPV6_O ISC_IPV6_C LWRES_HAVE_SIN6_SCOPE_ID ISC_PLATFORM_HAVESCOPEID ISC_PLATFORM_HAVEIF_LADDRREQ ISC_PLATFORM_HAVEIF_LADDRCONF ISC_PLATFORM_NEEDNTOP ISC_PLATFORM_NEEDPTON ISC_PLATFORM_NEEDATON ISC_PLATFORM_HAVESALEN LWRES_PLATFORM_HAVESALEN ISC_PLATFORM_MSGHDRFLAVOR ISC_PLATFORM_NEEDPORTT ISC_LWRES_NEEDADDRINFO ISC_LWRES_NEEDRRSETINFO ISC_LWRES_SETHOSTENTINT ISC_LWRES_ENDHOSTENTINT ISC_LWRES_GETNETBYADDRINADDR ISC_LWRES_SETNETENTINT ISC_LWRES_ENDNETENTINT ISC_LWRES_GETHOSTBYADDRVOID ISC_LWRES_NEEDHERRNO ISC_LWRES_GETIPNODEPROTO ISC_LWRES_GETADDRINFOPROTO ISC_LWRES_GETNAMEINFOPROTO ISC_PLATFORM_NEEDSTRSEP ISC_PLATFORM_NEEDMEMMOVE ISC_PLATFORM_NEEDSTRTOUL LWRES_PLATFORM_NEEDSTRTOUL GENRANDOMLIB ISC_PLATFORM_NEEDSTRLCPY ISC_PLATFORM_NEEDSTRLCAT ISC_PLATFORM_NEEDSPRINTF LWRES_PLATFORM_NEEDSPRINTF ISC_PLATFORM_NEEDVSNPRINTF LWRES_PLATFORM_NEEDVSNPRINTF ISC_EXTRA_OBJS ISC_EXTRA_SRCS USE_ISC_SPNEGO DST_EXTRA_OBJS DST_EXTRA_SRCS ISC_PLATFORM_QUADFORMAT LWRES_PLATFORM_QUADFORMAT ISC_PLATFORM_HAVESYSUNH ISC_PLATFORM_RLIMITTYPE ISC_PLATFORM_USEDECLSPEC LWRES_PLATFORM_USEDECLSPEC ISC_PLATFORM_BRACEPTHREADONCEINIT ISC_PLATFORM_HAVEIFNAMETOINDEX ISC_PLATFORM_HAVEXADD ISC_PLATFORM_HAVECMPXCHG ISC_PLATFORM_HAVEATOMICSTORE ISC_PLATFORM_USEGCCASM ISC_PLATFORM_USEOSFASM ISC_PLATFORM_USESTDASM ISC_ARCH_DIR LATEX PDFLATEX W3M XSLTPROC XMLLINT XSLT_DOCBOOK_STYLE_HTML XSLT_DOCBOOK_STYLE_XHTML XSLT_DOCBOOK_STYLE_MAN XSLT_DOCBOOK_CHUNK_HTML XSLT_DOCBOOK_CHUNK_XHTML XSLT_DOCBOOK_CHUNKTOC_HTML XSLT_DOCBOOK_CHUNKTOC_XHTML XSLT_DOCBOOK_MAKETOC_HTML XSLT_DOCBOOK_MAKETOC_XHTML XSLT_DB2LATEX_STYLE XSLT_DB2LATEX_ADMONITIONS IDNLIBS BIND9_TOP_BUILDDIR BIND9_ISC_BUILDINCLUDE BIND9_ISCCC_BUILDINCLUDE BIND9_ISCCFG_BUILDINCLUDE BIND9_DNS_BUILDINCLUDE BIND9_LWRES_BUILDINCLUDE BIND9_BIND9_BUILDINCLUDE BIND9_VERSION PG_CONFIG USE_DLZ DLZ_DRIVER_INCLUDES DLZ_DRIVER_LIBS DLZ_DRIVER_SRCS DLZ_DRIVER_OBJS BUILD_CC BUILD_CFLAGS BUILD_CPPFLAGS BUILD_LDFLAGS BUILD_LIBS LIBOBJS LTLIBOBJS'
ac_subst_files='BIND9_MAKE_INCLUDES BIND9_MAKE_RULES LIBISC_API LIBISCCC_API LIBISCCFG_API LIBDNS_API LIBBIND9_API LIBLWRES_API DLZ_DRIVER_RULES'
# Initialize some variables set by options.
--enable-libbind build libbind default=no
--enable-ipv6 use IPv6 default=autodetect
--enable-getifaddrs Enable the use of getifaddrs() [yes|no|glibc].
- glibc: Use getifaddrs() in glibc if you know it supports IPv6.
+ glibc: Use getifaddrs() in glibc if you know it supports IPv6.
+ --disable-isc-spnego use SPNEGO from GSSAPI library
--disable-linux-caps disable linux capabilities
--enable-atomic enable machine specific atomic operations
- [default=autodetect]
+ [default=autodetect]
Optional Packages:
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
--without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
--with-openssl=PATH Build with OpenSSL yes|no|path.
- (Required for DNSSEC)
+ (Required for DNSSEC)
+ --with-gssapi=PATH Specify path for system-supplied GSSAPI
--with-randomdev=PATH Specify path for random device
--with-ptl2 on NetBSD, use the ptl2 thread library (experimental)
--with-purify=PATH use Rational purify
# ./configure --prefix=/usr/local
#
case "$prefix" in
- NONE)
- case "$sysconfdir" in
- '${prefix}/etc')
- sysconfdir=/etc
- ;;
- esac
- case "$localstatedir" in
- '${prefix}/var')
- localstatedir=/var
- ;;
- esac
- ;;
+ NONE)
+ case "$sysconfdir" in
+ '${prefix}/etc')
+ sysconfdir=/etc
+ ;;
+ esac
+ case "$localstatedir" in
+ '${prefix}/var')
+ localstatedir=/var
+ ;;
+ esac
+ ;;
esac
#
#
case "$INSTALL" in
/*)
- ;;
- *)
- #
- # Not all systems have dirname.
- #
+ ;;
+ *)
+ #
+ # Not all systems have dirname.
+ #
- ac_dir="`echo $INSTALL | sed 's%/[^/]*$%%'`"
+ ac_dir="`echo $INSTALL | sed 's%/[^/]*$%%'`"
- ac_prog="`echo $INSTALL | sed 's%.*/%%'`"
- test "$ac_dir" = "$ac_prog" && ac_dir=.
- test -d "$ac_dir" && ac_dir="`(cd \"$ac_dir\" && pwd)`"
- INSTALL="$ac_dir/$ac_prog"
- ;;
+ ac_prog="`echo $INSTALL | sed 's%.*/%%'`"
+ test "$ac_dir" = "$ac_prog" && ac_dir=.
+ test -d "$ac_dir" && ac_dir="`(cd \"$ac_dir\" && pwd)`"
+ INSTALL="$ac_dir/$ac_prog"
+ ;;
esac
#
CC="cc"
;;
*-solaris*)
- # Use Sun's cc if it is available, but watch
- # out for /usr/ucb/cc; it will never be the right
- # compiler to use.
- #
- # If setting CC here fails, the AC_PROG_CC done
- # below might still find gcc.
+ # Use Sun's cc if it is available, but watch
+ # out for /usr/ucb/cc; it will never be the right
+ # compiler to use.
+ #
+ # If setting CC here fails, the AC_PROG_CC done
+ # below might still find gcc.
IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
for ac_dir in $PATH; do
test -z "$ac_dir" && ac_dir=.
echo "$as_me:$LINENO: result: yes" >&5
echo "${ECHO_T}yes" >&6
- cat >>confdefs.h <<\_ACEOF
+ cat >>confdefs.h <<\_ACEOF
#define inline
_ACEOF
echo "${ECHO_T}no" >&6
case $ac_cv_header_sys_select_h in
yes)
- ISC_PLATFORM_NEEDSYSSELECTH="#define ISC_PLATFORM_NEEDSYSSELECTH 1"
+ ISC_PLATFORM_NEEDSYSSELECTH="#define ISC_PLATFORM_NEEDSYSSELECTH 1"
LWRES_PLATFORM_NEEDSYSSELECTH="#define LWRES_PLATFORM_NEEDSYSSELECTH 1"
;;
no)
no)
case $ac_cv_header_sys_select_h in
yes)
- ISC_PLATFORM_NEEDSYSSELECTH="#define ISC_PLATFORM_NEEDSYSSELECTH 1"
+ ISC_PLATFORM_NEEDSYSSELECTH="#define ISC_PLATFORM_NEEDSYSSELECTH 1"
LWRES_PLATFORM_NEEDSYSSELECTH="#define LWRES_PLATFORM_NEEDSYSSELECTH 1"
;;
no)
*)
if test "$use_openssl" = "yes"
then
- # User did not specify a path - guess it
+ # User did not specify a path - guess it
for d in $openssldirs
do
if test -f $d/include/openssl/opensslv.h
then
- use_openssl=$d
+ use_openssl=$d
break
fi
done
if test "$use_openssl" = "yes"
then
- echo "$as_me:$LINENO: result: not found" >&5
+ echo "$as_me:$LINENO: result: not found" >&5
echo "${ECHO_T}not found" >&6
{ { echo "$as_me:$LINENO: error: OpenSSL was not found in any of $openssldirs; use --with-openssl=/path" >&5
echo "$as_me: error: OpenSSL was not found in any of $openssldirs; use --with-openssl=/path" >&2;}
;;
esac
fi
- echo "$as_me:$LINENO: result: using openssl from $use_openssl/lib and $use_openssl/include" >&5
-echo "${ECHO_T}using openssl from $use_openssl/lib and $use_openssl/include" >&6
+ echo "$as_me:$LINENO: result: using OpenSSL from $use_openssl/lib and $use_openssl/include" >&5
+echo "${ECHO_T}using OpenSSL from $use_openssl/lib and $use_openssl/include" >&6
saved_cflags="$CFLAGS"
saved_libs="$LIBS"
#include <stdio.h>
#include <openssl/opensslv.h>
int main() {
- if ((OPENSSL_VERSION_NUMBER >= 0x009070cfL &&
+ if ((OPENSSL_VERSION_NUMBER >= 0x009070cfL &&
OPENSSL_VERSION_NUMBER < 0x00908000L) ||
OPENSSL_VERSION_NUMBER >= 0x0090804fL)
- return (0);
+ return (0);
printf("\n\nFound OPENSSL_VERSION_NUMBER %#010x\n",
OPENSSL_VERSION_NUMBER);
printf("Require OPENSSL_VERSION_NUMBER 0x009070cf or greater (0.9.7l)\n"
"Require OPENSSL_VERSION_NUMBER 0x0090804f or greater (0.9.8d)\n\n");
- return (1);
+ return (1);
}
_ACEOF
( exit $ac_status )
echo "$as_me:$LINENO: result: not compatible" >&5
echo "${ECHO_T}not compatible" >&6
- OPENSSL_WARNING=yes
+ OPENSSL_WARNING=yes
fi
rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
DNS_CRYPTO_LIBS="$DNS_CRYPTO_LIBS $DNS_OPENSSL_LIBS"
-#
-# was --with-gssapi specified?
-#
-#AC_MSG_CHECKING(for GSSAPI library)
-#AC_ARG_WITH(gssapi,
-#[ --with-gssapi=PATH Specify path for system-supplied GSSAPI],
-# use_gssapi="$withval", use_gssapi="no")
-#
-#case "$use_gssapi" in
-# no)
-# USE_GSSAPI=''
-# DST_GSSAPI_INC=''
-# DNS_GSSAPI_LIBS=''
-# AC_MSG_RESULT(not specified)
-# ;;
-# yes)
-# AC_MSG_ERROR([--with-gssapi must specify a path])
-# ;;
-# *)
-# USE_GSSAPI='-DGSSAPI'
-# DST_GSSAPI_INC="-I$use_gssapi/include"
-# DNS_GSSAPI_LIBS="-L$use_gssapi/lib -lgssapi_krb5"
-# AC_MSG_RESULT(using gssapi from $use_gssapi/lib and $use_gssapi/include)
-# ;;
-#esac
-
-USE_GSSAPI=''
-DST_GSSAPI_INC=''
-DNS_GSSAPI_LIBS=''
-
-
-
-DNS_CRYPTO_LIBS="$DNS_CRYPTO_LIBS $DNS_GSSAPI_LIBS"
+echo "$as_me:$LINENO: checking for GSSAPI library" >&5
+echo $ECHO_N "checking for GSSAPI library... $ECHO_C" >&6
+
+# Check whether --with-gssapi or --without-gssapi was given.
+if test "${with_gssapi+set}" = set; then
+ withval="$with_gssapi"
+ use_gssapi="$withval"
+else
+ use_gssapi="no"
+fi;
+
+gssapidirs="/usr/local /usr/pkg /usr/kerberos /usr"
+if test "$use_gssapi" = "yes"
+then
+ for d in $gssapidirs
+ do
+ if test -f $d/include/gssapi/gssapi.h -o -f $d/gssapi.h
+ then
+ use_gssapi=$d
+ break
+ fi
+ done
+fi
+
+case "$use_gssapi" in
+ no)
+ echo "$as_me:$LINENO: result: disabled" >&5
+echo "${ECHO_T}disabled" >&6
+ USE_GSSAPI=''
+ ;;
+ yes)
+ { { echo "$as_me:$LINENO: error: --with-gssapi must specify a path" >&5
+echo "$as_me: error: --with-gssapi must specify a path" >&2;}
+ { (exit 1); exit 1; }; }
+ ;;
+ *)
+ echo "$as_me:$LINENO: result: looking in $use_gssapi/lib" >&5
+echo "${ECHO_T}looking in $use_gssapi/lib" >&6
+ USE_GSSAPI='-DGSSAPI'
+ saved_cppflags="$CPPFLAGS"
+ CPPFLAGS="-I$use_gssapi/include $CPPFLAGS"
+
+
+for ac_header in gssapi.h gssapi/gssapi.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+else
+ # Is the header compilable?
+echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+ (
+ cat <<\_ASBOX
+## ------------------------------------------ ##
+## Report this to the AC_PACKAGE_NAME lists. ##
+## ------------------------------------------ ##
+_ASBOX
+ ) |
+ sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ eval "$as_ac_Header=\$ac_header_preproc"
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+ ISC_PLATFORM_GSSAPIHEADER="#define ISC_PLATFORM_GSSAPIHEADER <$ac_header>"
+fi
+
+done
+
+
+ if test "$ISC_PLATFORM_GSSAPIHEADER" = ""; then
+ { { echo "$as_me:$LINENO: error: gssapi.h not found" >&5
+echo "$as_me: error: gssapi.h not found" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+
+ CPPFLAGS="$saved_cppflags"
+
+ #
+ # XXXDCL This probably doesn't work right on all systems.
+ # It will need to be worked on as problems become evident.
+ #
+ # Essentially the problems here relate to two different
+ # areas. The first area is building with either KTH
+ # or MIT Kerberos, particularly when both are present on
+ # the machine. The other is static versus dynamic linking.
+ #
+ # On the KTH vs MIT issue, Both have libkrb5 that can mess
+ # up the works if one implementation ends up trying to
+ # use the other's krb. This is unfortunately a situation
+ # that very easily arises.
+ #
+ # Dynamic linking when the dependency information is built
+ # into MIT's libgssapi_krb5 or KTH's libgssapi magically makes
+ # all such problems go away, but when that setup is not
+ # present, because either the dynamic libraries lack
+ # dependencies or static linking is being done, then the
+ # problems start to show up.
+ saved_libs="$LIBS"
+ for TRY_LIBS in \
+ "-lgssapi_krb5" \
+ "-lgssapi_krb5 -lkrb5 -lk5crypto -lcom_err" \
+ "-lgssapi_krb5 -lkrb5 -lk5crypto -lcom_err -lresolv" \
+ "-lgssapi" \
+ "-lgssapi -lkrb5 -ldes -lcrypt -lasn1 -lroken -lcom_err" \
+ "-lgssapi -lkrb5 -lcrypto -lcrypt -lasn1 -lroken -lcom_err" \
+ "-lgss"
+ do
+ # Note that this does not include $saved_libs, because
+ # on FreeBSD machines this configure script has added
+ # -L/usr/local/lib to LIBS, which can make the
+ # -lgssapi_krb5 test succeed with shared libraries even
+ # when you are trying to build with KTH in /usr/lib.
+ LIBS="-L$use_gssapi/lib $TRY_LIBS"
+ echo "$as_me:$LINENO: checking linking as $TRY_LIBS" >&5
+echo $ECHO_N "checking linking as $TRY_LIBS... $ECHO_C" >&6
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+gss_acquire_cred();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ gssapi_linked=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+gssapi_linked=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ case $gssapi_linked in
+ yes) echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; break ;;
+ no) echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6 ;;
+ esac
+ done
+
+ case $gssapi_linked in
+ no) { { echo "$as_me:$LINENO: error: could not determine proper GSSAPI linkage" >&5
+echo "$as_me: error: could not determine proper GSSAPI linkage" >&2;}
+ { (exit 1); exit 1; }; } ;;
+ esac
+
+ #
+ # XXXDCL Major kludge. Tries to cope with KTH in /usr/lib
+ # but MIT in /usr/local/lib and trying to build with KTH.
+ # /usr/local/lib can end up earlier on the link lines.
+ # Like most kludges, this one is not only inelegant it
+ # is also likely to be the wrong thing to do at least as
+ # many times as it is the right thing. Something better
+ # needs to be done.
+ #
+ if test "$use_gssapi" = "/usr" -a \
+ -f /usr/local/lib/libkrb5.a; then
+ FIX_KTH_VS_MIT=yes
+ fi
+
+ case "$FIX_KTH_VS_MIT" in
+ yes)
+ case "$enable_static_linking" in
+ yes) gssapi_lib_suffix=".a" ;;
+ *) gssapi_lib_suffix=".so" ;;
+ esac
+
+ for lib in $LIBS; do
+ case $lib in
+ -L*)
+ ;;
+ -l*)
+ new_lib=`echo $lib |
+ sed -e s%^-l%$use_gssapi/lib/lib% \
+ -e s%$%$gssapi_lib_suffix%`
+ NEW_LIBS="$NEW_LIBS $new_lib"
+ ;;
+ *)
+ { { echo "$as_me:$LINENO: error: KTH vs MIT Kerberos confusion!" >&5
+echo "$as_me: error: KTH vs MIT Kerberos confusion!" >&2;}
+ { (exit 1); exit 1; }; }
+ ;;
+ esac
+ done
+ LIBS="$NEW_LIBS"
+ ;;
+ esac
+
+ DST_GSSAPI_INC="-I$use_gssapi/include"
+ DNS_GSSAPI_LIBS="$LIBS"
+
+ echo "$as_me:$LINENO: result: using GSSAPI from $use_gssapi/lib and $use_gssapi/include" >&5
+echo "${ECHO_T}using GSSAPI from $use_gssapi/lib and $use_gssapi/include" >&6
+ LIBS="$saved_libs"
+ ;;
+esac
+
+
+
+
+
+
+
+DNS_CRYPTO_LIBS="$DNS_GSSAPI_LIBS $DNS_CRYPTO_LIBS"
#
# Applications linking with libdns also need to link with these libraries.
*-hp-hpux*)
CC="$CC -Ae -z"
# The version of the C compiler that constantly warns about
- # 'const' as well as alignment issues is unfortunately not
- # able to be discerned via the version of the operating
- # system, nor does cc have a version flag.
+ # 'const' as well as alignment issues is unfortunately not
+ # able to be discerned via the version of the operating
+ # system, nor does cc have a version flag.
case "`$CC +W 123 2>&1`" in
*Unknown?option*)
STD_CWARNINGS="+w1"
MKDEPCFLAGS="-xM"
;;
*-sco-sysv*uw*|*-*-sysv*UnixWare*|*-*-sysv*OpenUNIX*)
- # UnixWare
+ # UnixWare
CC="$CC -w"
;;
esac
;;
*-*-irix6*)
# Find out which ABI we are using.
- echo '#line 8854 "configure"' > conftest.$ac_ext
+ echo '#line 9180 "configure"' > conftest.$ac_ext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
(eval $ac_compile) 2>&5
ac_status=$?
# Provide some information about the compiler.
-echo "$as_me:9851:" \
+echo "$as_me:10177:" \
"checking for Fortran 77 compiler version" >&5
ac_compiler=`set X $ac_compile; echo $2`
{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5
-e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:10912: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:11238: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:10916: \$? = $ac_status" >&5
+ echo "$as_me:11242: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings
-e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:11155: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:11481: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:11159: \$? = $ac_status" >&5
+ echo "$as_me:11485: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings
-e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:11215: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:11541: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:11219: \$? = $ac_status" >&5
+ echo "$as_me:11545: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
-#line 13400 "configure"
+#line 13726 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
-#line 13498 "configure"
+#line 13824 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
-e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:15695: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:16021: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:15699: \$? = $ac_status" >&5
+ echo "$as_me:16025: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings
-e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:15755: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:16081: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:15759: \$? = $ac_status" >&5
+ echo "$as_me:16085: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
-#line 17116 "configure"
+#line 17442 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
-#line 17214 "configure"
+#line 17540 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
-e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:18051: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:18377: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:18055: \$? = $ac_status" >&5
+ echo "$as_me:18381: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings
-e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:18111: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:18437: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:18115: \$? = $ac_status" >&5
+ echo "$as_me:18441: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
-e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:20150: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:20476: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:20154: \$? = $ac_status" >&5
+ echo "$as_me:20480: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings
-e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:20393: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:20719: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:20397: \$? = $ac_status" >&5
+ echo "$as_me:20723: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings
-e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:20453: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:20779: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:20457: \$? = $ac_status" >&5
+ echo "$as_me:20783: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
-#line 22638 "configure"
+#line 22964 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
-#line 22736 "configure"
+#line 23062 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
#
case "$host" in
*-sco-sysv*uw*|*-*-sysv*UnixWare*|*-*-sysv*OpenUNIX*)
- # UnixWare
+ # UnixWare
ISC_PLATFORM_NEEDNETINETIN6H="#define ISC_PLATFORM_NEEDNETINETIN6H 1"
LWRES_PLATFORM_NEEDNETINETIN6H="#define LWRES_PLATFORM_NEEDNETINETIN6H 1"
- ISC_PLATFORM_FIXIN6ISADDR="#define ISC_PLATFORM_FIXIN6ISADDR 1"
+ ISC_PLATFORM_FIXIN6ISADDR="#define ISC_PLATFORM_FIXIN6ISADDR 1"
isc_netinetin6_hack="#include <netinet/in6.h>"
;;
*)
ISC_PLATFORM_NEEDNETINETIN6H="#undef ISC_PLATFORM_NEEDNETINETIN6H"
LWRES_PLATFORM_NEEDNETINETIN6H="#undef LWRES_PLATFORM_NEEDNETINETIN6H"
- ISC_PLATFORM_FIXIN6ISADDR="#undef ISC_PLATFORM_FIXIN6ISADDR"
+ ISC_PLATFORM_FIXIN6ISADDR="#undef ISC_PLATFORM_FIXIN6ISADDR"
isc_netinetin6_hack=""
;;
esac
if test "$cross_compiling" = yes; then
echo "$as_me:$LINENO: result: assuming inet_ntop needed" >&5
echo "${ECHO_T}assuming inet_ntop needed" >&6
- ISC_EXTRA_OBJS="$ISC_EXTRA_OBJS inet_ntop.$O"
- ISC_EXTRA_SRCS="$ISC_EXTRA_SRCS inet_ntop.c"
- ISC_PLATFORM_NEEDNTOP="#define ISC_PLATFORM_NEEDNTOP 1"
+ ISC_EXTRA_OBJS="$ISC_EXTRA_OBJS inet_ntop.$O"
+ ISC_EXTRA_SRCS="$ISC_EXTRA_SRCS inet_ntop.c"
+ ISC_PLATFORM_NEEDNTOP="#define ISC_PLATFORM_NEEDNTOP 1"
else
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
(exit $ac_status); }; }; then
echo "$as_me:$LINENO: result: yes" >&5
echo "${ECHO_T}yes" >&6
- ISC_PLATFORM_NEEDNTOP="#undef ISC_PLATFORM_NEEDNTOP"
+ ISC_PLATFORM_NEEDNTOP="#undef ISC_PLATFORM_NEEDNTOP"
else
echo "$as_me: program exited with status $ac_status" >&5
echo "$as_me: failed program was:" >&5
( exit $ac_status )
echo "$as_me:$LINENO: result: no" >&5
echo "${ECHO_T}no" >&6
- ISC_EXTRA_OBJS="$ISC_EXTRA_OBJS inet_ntop.$O"
- ISC_EXTRA_SRCS="$ISC_EXTRA_SRCS inet_ntop.c"
- ISC_PLATFORM_NEEDNTOP="#define ISC_PLATFORM_NEEDNTOP 1"
+ ISC_EXTRA_OBJS="$ISC_EXTRA_OBJS inet_ntop.$O"
+ ISC_EXTRA_SRCS="$ISC_EXTRA_SRCS inet_ntop.c"
+ ISC_PLATFORM_NEEDNTOP="#define ISC_PLATFORM_NEEDNTOP 1"
fi
rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
fi
(exit $ac_status); }; }; then
echo "$as_me:$LINENO: result: yes" >&5
echo "${ECHO_T}yes" >&6
- ISC_PLATFORM_NEEDPTON="#undef ISC_PLATFORM_NEEDPTON"
+ ISC_PLATFORM_NEEDPTON="#undef ISC_PLATFORM_NEEDPTON"
else
echo "$as_me: program exited with status $ac_status" >&5
echo "$as_me: failed program was:" >&5
( exit $ac_status )
echo "$as_me:$LINENO: result: no" >&5
echo "${ECHO_T}no" >&6
- ISC_EXTRA_OBJS="$ISC_EXTRA_OBJS inet_pton.$O"
- ISC_EXTRA_SRCS="$ISC_EXTRA_SRCS inet_pton.c"
- ISC_PLATFORM_NEEDPTON="#define ISC_PLATFORM_NEEDPTON 1"
+ ISC_EXTRA_OBJS="$ISC_EXTRA_OBJS inet_pton.$O"
+ ISC_EXTRA_SRCS="$ISC_EXTRA_SRCS inet_pton.c"
+ ISC_PLATFORM_NEEDPTON="#define ISC_PLATFORM_NEEDPTON 1"
fi
rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
fi
(exit $ac_status); }; }; then
echo "$as_me:$LINENO: result: yes" >&5
echo "${ECHO_T}yes" >&6
- ISC_PLATFORM_NEEDATON="#undef ISC_PLATFORM_NEEDATON"
+ ISC_PLATFORM_NEEDATON="#undef ISC_PLATFORM_NEEDATON"
else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
echo "$as_me:$LINENO: result: no" >&5
echo "${ECHO_T}no" >&6
- ISC_EXTRA_OBJS="$ISC_EXTRA_OBJS inet_aton.$O"
- ISC_EXTRA_SRCS="$ISC_EXTRA_SRCS inet_aton.c"
- ISC_PLATFORM_NEEDATON="#define ISC_PLATFORM_NEEDATON 1"
+ ISC_EXTRA_OBJS="$ISC_EXTRA_OBJS inet_aton.$O"
+ ISC_EXTRA_SRCS="$ISC_EXTRA_SRCS inet_aton.c"
+ ISC_PLATFORM_NEEDATON="#define ISC_PLATFORM_NEEDATON 1"
fi
rm -f conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
+#
+# Use our own SPNEGO implementation?
+#
+# Check whether --enable-isc-spnego or --disable-isc-spnego was given.
+if test "${enable_isc_spnego+set}" = set; then
+ enableval="$enable_isc_spnego"
+
+fi;
+
+if test -n "$USE_GSSAPI"
+then
+ case "$enable_isc_spnego" in
+ yes|'')
+ USE_ISC_SPNEGO='-DUSE_ISC_SPNEGO'
+ DST_EXTRA_OBJS="$DST_EXTRA_OBJS spnego.$O"
+ DST_EXTRA_SRCS="$DST_EXTRA_SRCS spnego.c"
+ echo "$as_me:$LINENO: result: using SPNEGO from lib/dns" >&5
+echo "${ECHO_T}using SPNEGO from lib/dns" >&6
+ ;;
+ no)
+ echo "$as_me:$LINENO: result: using SPNEGO from GSSAPI library" >&5
+echo "${ECHO_T}using SPNEGO from GSSAPI library" >&6
+ ;;
+ esac
+fi
+
+
+
+
+
+
# Determine the printf format characters to use when printing
# values of type isc_int64_t. This will normally be "ll", but where
# the compiler treats "long long" as a alias for "long" and printf
case $ac_cv_have_if_nametoindex in
no)
case "$host" in
- *-hp-hpux*)
- echo "$as_me:$LINENO: checking for if_nametoindex in -lipv6" >&5
+ *-hp-hpux*)
+ echo "$as_me:$LINENO: checking for if_nametoindex in -lipv6" >&5
echo $ECHO_N "checking for if_nametoindex in -lipv6... $ECHO_C" >&6
if test "${ac_cv_lib_ipv6_if_nametoindex+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
LIBS="-lipv6 $LIBS"
fi
- ;;
+ ;;
esac
esac
case $ac_cv_have_if_nametoindex in
BUILD_LIBS="$LIBS"
fi
+NEWFLAGS=""
+for e in $BUILD_LDFLAGS ; do
+ case $e in
+ -L*)
+ case $host_os in
+ netbsd*)
+ ee=`echo $e | sed -e 's%^-L%-Wl,-rpath,%'`
+ NEWFLAGS="$NEWFLAGS $e $ee"
+ ;;
+ freebsd*)
+ ee=`echo $e | sed -e 's%^-L%-Wl,-rpath,%'`
+ NEWFLAGS="$NEWFLAGS $e $ee"
+ ;;
+ esac
+ ;;
+ *)
+ NEWFLAGS="$NEWFLAGS $e"
+ ;;
+ esac
+done
+BUILD_LDFLAGS="$NEWFLAGS"
+
+NEWFLAGS=""
+for e in $DNS_GSSAPI_LIBS ; do
+ case $e in
+ -L*)
+ case $host_os in
+ netbsd*)
+ ee=`echo $e | sed -e 's%^-L%-Wl,-rpath,%'`
+ NEWFLAGS="$NEWFLAGS $e $ee"
+ ;;
+ freebsd*)
+ ee=`echo $e | sed -e 's%^-L%-Wl,-rpath,%'`
+ NEWFLAGS="$NEWFLAGS $e $ee"
+ ;;
+ esac
+ ;;
+ *)
+ NEWFLAGS="$NEWFLAGS $e"
+ ;;
+ esac
+done
+DNS_GSSAPI_LIBS="$NEWFLAGS"
+
+NEWFLAGS=""
+for e in $DNS_CRYPTO_LIBS ; do
+ case $e in
+ -L*)
+ case $host_os in
+ netbsd*)
+ ee=`echo $e | sed -e 's%^-L%-Wl,-rpath,%'`
+ NEWFLAGS="$NEWFLAGS $e $ee"
+ ;;
+ freebsd*)
+ ee=`echo $e | sed -e 's%^-L%-Wl,-rpath,%'`
+ NEWFLAGS="$NEWFLAGS $e $ee"
+ ;;
+ esac
+ ;;
+ *)
+ NEWFLAGS="$NEWFLAGS $e"
+ ;;
+ esac
+done
+DNS_CRYPTO_LIBS="$NEWFLAGS"
+
s,@LWRES_PLATFORM_NEEDSYSSELECTH@,$LWRES_PLATFORM_NEEDSYSSELECTH,;t t
s,@USE_OPENSSL@,$USE_OPENSSL,;t t
s,@DST_OPENSSL_INC@,$DST_OPENSSL_INC,;t t
+s,@ISC_PLATFORM_HAVEGSSAPI@,$ISC_PLATFORM_HAVEGSSAPI,;t t
+s,@ISC_PLATFORM_GSSAPIHEADER@,$ISC_PLATFORM_GSSAPIHEADER,;t t
s,@USE_GSSAPI@,$USE_GSSAPI,;t t
s,@DST_GSSAPI_INC@,$DST_GSSAPI_INC,;t t
+s,@DNS_GSSAPI_LIBS@,$DNS_GSSAPI_LIBS,;t t
s,@DNS_CRYPTO_LIBS@,$DNS_CRYPTO_LIBS,;t t
s,@ALWAYS_DEFINES@,$ALWAYS_DEFINES,;t t
s,@ISC_PLATFORM_USETHREADS@,$ISC_PLATFORM_USETHREADS,;t t
s,@LWRES_PLATFORM_NEEDVSNPRINTF@,$LWRES_PLATFORM_NEEDVSNPRINTF,;t t
s,@ISC_EXTRA_OBJS@,$ISC_EXTRA_OBJS,;t t
s,@ISC_EXTRA_SRCS@,$ISC_EXTRA_SRCS,;t t
+s,@USE_ISC_SPNEGO@,$USE_ISC_SPNEGO,;t t
+s,@DST_EXTRA_OBJS@,$DST_EXTRA_OBJS,;t t
+s,@DST_EXTRA_SRCS@,$DST_EXTRA_SRCS,;t t
s,@ISC_PLATFORM_QUADFORMAT@,$ISC_PLATFORM_QUADFORMAT,;t t
s,@LWRES_PLATFORM_QUADFORMAT@,$LWRES_PLATFORM_QUADFORMAT,;t t
s,@ISC_PLATFORM_HAVESYSUNH@,$ISC_PLATFORM_HAVESYSUNH,;t t
esyscmd([sed "s/^/# /" COPYRIGHT])dnl
AC_DIVERT_POP()dnl
-AC_REVISION($Revision: 1.418 $)
+AC_REVISION($Revision: 1.419 $)
AC_INIT(lib/dns/name.c)
AC_PREREQ(2.59)
# ./configure --prefix=/usr/local
#
case "$prefix" in
- NONE)
- case "$sysconfdir" in
- '${prefix}/etc')
- sysconfdir=/etc
- ;;
- esac
- case "$localstatedir" in
- '${prefix}/var')
- localstatedir=/var
- ;;
- esac
- ;;
+ NONE)
+ case "$sysconfdir" in
+ '${prefix}/etc')
+ sysconfdir=/etc
+ ;;
+ esac
+ case "$localstatedir" in
+ '${prefix}/var')
+ localstatedir=/var
+ ;;
+ esac
+ ;;
esac
#
#
case "$INSTALL" in
/*)
- ;;
- *)
- #
- # Not all systems have dirname.
- #
- changequote({, })
- ac_dir="`echo $INSTALL | sed 's%/[^/]*$%%'`"
- changequote([, ])
-
- ac_prog="`echo $INSTALL | sed 's%.*/%%'`"
- test "$ac_dir" = "$ac_prog" && ac_dir=.
- test -d "$ac_dir" && ac_dir="`(cd \"$ac_dir\" && pwd)`"
- INSTALL="$ac_dir/$ac_prog"
- ;;
+ ;;
+ *)
+ #
+ # Not all systems have dirname.
+ #
+ changequote({, })
+ ac_dir="`echo $INSTALL | sed 's%/[^/]*$%%'`"
+ changequote([, ])
+
+ ac_prog="`echo $INSTALL | sed 's%.*/%%'`"
+ test "$ac_dir" = "$ac_prog" && ac_dir=.
+ test -d "$ac_dir" && ac_dir="`(cd \"$ac_dir\" && pwd)`"
+ INSTALL="$ac_dir/$ac_prog"
+ ;;
esac
#
CC="cc"
;;
*-solaris*)
- # Use Sun's cc if it is available, but watch
- # out for /usr/ucb/cc; it will never be the right
- # compiler to use.
- #
- # If setting CC here fails, the AC_PROG_CC done
- # below might still find gcc.
+ # Use Sun's cc if it is available, but watch
+ # out for /usr/ucb/cc; it will never be the right
+ # compiler to use.
+ #
+ # If setting CC here fails, the AC_PROG_CC done
+ # below might still find gcc.
IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
for ac_dir in $PATH; do
test -z "$ac_dir" && ac_dir=.
],
[AC_MSG_RESULT(no)],
[AC_MSG_RESULT(yes)
- AC_DEFINE(inline, )])
+ AC_DEFINE(inline, )])
AC_TYPE_SIZE_T
AC_CHECK_TYPE(ssize_t, int)
[AC_MSG_RESULT(no)
case $ac_cv_header_sys_select_h in
yes)
- ISC_PLATFORM_NEEDSYSSELECTH="#define ISC_PLATFORM_NEEDSYSSELECTH 1"
+ ISC_PLATFORM_NEEDSYSSELECTH="#define ISC_PLATFORM_NEEDSYSSELECTH 1"
LWRES_PLATFORM_NEEDSYSSELECTH="#define LWRES_PLATFORM_NEEDSYSSELECTH 1"
;;
no)
no)
case $ac_cv_header_sys_select_h in
yes)
- ISC_PLATFORM_NEEDSYSSELECTH="#define ISC_PLATFORM_NEEDSYSSELECTH 1"
+ ISC_PLATFORM_NEEDSYSSELECTH="#define ISC_PLATFORM_NEEDSYSSELECTH 1"
LWRES_PLATFORM_NEEDSYSSELECTH="#define LWRES_PLATFORM_NEEDSYSSELECTH 1"
;;
no)
AC_MSG_CHECKING(for OpenSSL library)
AC_ARG_WITH(openssl,
[ --with-openssl[=PATH] Build with OpenSSL [yes|no|path].
- (Required for DNSSEC)],
+ (Required for DNSSEC)],
use_openssl="$withval", use_openssl="auto")
openssldirs="/usr /usr/local /usr/local/ssl /usr/pkg /usr/sfw"
*)
if test "$use_openssl" = "yes"
then
- # User did not specify a path - guess it
+ # User did not specify a path - guess it
for d in $openssldirs
do
if test -f $d/include/openssl/opensslv.h
then
- use_openssl=$d
+ use_openssl=$d
break
fi
done
if test "$use_openssl" = "yes"
then
- AC_MSG_RESULT(not found)
+ AC_MSG_RESULT(not found)
AC_MSG_ERROR(
[OpenSSL was not found in any of $openssldirs; use --with-openssl=/path])
fi
;;
esac
fi
- AC_MSG_RESULT(using openssl from $use_openssl/lib and $use_openssl/include)
+ AC_MSG_RESULT(using OpenSSL from $use_openssl/lib and $use_openssl/include)
saved_cflags="$CFLAGS"
saved_libs="$LIBS"
return (0);
}
],
- [AC_MSG_RESULT(yes)],
+ [AC_MSG_RESULT(yes)],
[AC_MSG_RESULT(no)
AC_MSG_ERROR(Could not run test program using OpenSSL from
$use_openssl/lib and $use_openssl/include.
AC_ARG_ENABLE(openssl-version-check,
[AC_HELP_STRING([--enable-openssl-version-check],
- [Check OpenSSL Version @<:@default=yes@:>@])])
+ [Check OpenSSL Version @<:@default=yes@:>@])])
case "$enable_openssl_version_check" in
yes|'')
AC_MSG_CHECKING(OpenSSL library version)
#include <stdio.h>
#include <openssl/opensslv.h>
int main() {
- if ((OPENSSL_VERSION_NUMBER >= 0x009070cfL &&
+ if ((OPENSSL_VERSION_NUMBER >= 0x009070cfL &&
OPENSSL_VERSION_NUMBER < 0x00908000L) ||
OPENSSL_VERSION_NUMBER >= 0x0090804fL)
- return (0);
+ return (0);
printf("\n\nFound OPENSSL_VERSION_NUMBER %#010x\n",
OPENSSL_VERSION_NUMBER);
printf("Require OPENSSL_VERSION_NUMBER 0x009070cf or greater (0.9.7l)\n"
"Require OPENSSL_VERSION_NUMBER 0x0090804f or greater (0.9.8d)\n\n");
- return (1);
+ return (1);
}
],
- [AC_MSG_RESULT(ok)],
+ [AC_MSG_RESULT(ok)],
[AC_MSG_RESULT(not compatible)
- OPENSSL_WARNING=yes
+ OPENSSL_WARNING=yes
],
[AC_MSG_RESULT(assuming target platform has compatible version)])
;;
AC_SUBST(DST_OPENSSL_INC)
DNS_CRYPTO_LIBS="$DNS_CRYPTO_LIBS $DNS_OPENSSL_LIBS"
-#
-# was --with-gssapi specified?
-#
-#AC_MSG_CHECKING(for GSSAPI library)
-#AC_ARG_WITH(gssapi,
-#[ --with-gssapi=PATH Specify path for system-supplied GSSAPI],
-# use_gssapi="$withval", use_gssapi="no")
-#
-#case "$use_gssapi" in
-# no)
-# USE_GSSAPI=''
-# DST_GSSAPI_INC=''
-# DNS_GSSAPI_LIBS=''
-# AC_MSG_RESULT(not specified)
-# ;;
-# yes)
-# AC_MSG_ERROR([--with-gssapi must specify a path])
-# ;;
-# *)
-# USE_GSSAPI='-DGSSAPI'
-# DST_GSSAPI_INC="-I$use_gssapi/include"
-# DNS_GSSAPI_LIBS="-L$use_gssapi/lib -lgssapi_krb5"
-# AC_MSG_RESULT(using gssapi from $use_gssapi/lib and $use_gssapi/include)
-# ;;
-#esac
-
-USE_GSSAPI=''
-DST_GSSAPI_INC=''
-DNS_GSSAPI_LIBS=''
+AC_MSG_CHECKING(for GSSAPI library)
+AC_ARG_WITH(gssapi,
+[ --with-gssapi=PATH Specify path for system-supplied GSSAPI],
+ use_gssapi="$withval", use_gssapi="no")
+
+gssapidirs="/usr/local /usr/pkg /usr/kerberos /usr"
+if test "$use_gssapi" = "yes"
+then
+ for d in $gssapidirs
+ do
+ if test -f $d/include/gssapi/gssapi.h -o -f $d/gssapi.h
+ then
+ use_gssapi=$d
+ break
+ fi
+ done
+fi
+
+case "$use_gssapi" in
+ no)
+ AC_MSG_RESULT(disabled)
+ USE_GSSAPI=''
+ ;;
+ yes)
+ AC_MSG_ERROR([--with-gssapi must specify a path])
+ ;;
+ *)
+ AC_MSG_RESULT(looking in $use_gssapi/lib)
+ USE_GSSAPI='-DGSSAPI'
+ saved_cppflags="$CPPFLAGS"
+ CPPFLAGS="-I$use_gssapi/include $CPPFLAGS"
+ AC_CHECK_HEADERS(gssapi.h gssapi/gssapi.h,
+ [ISC_PLATFORM_GSSAPIHEADER="#define ISC_PLATFORM_GSSAPIHEADER <$ac_header>"])
+
+ if test "$ISC_PLATFORM_GSSAPIHEADER" = ""; then
+ AC_MSG_ERROR([gssapi.h not found])
+ fi
+
+ CPPFLAGS="$saved_cppflags"
+
+ #
+ # XXXDCL This probably doesn't work right on all systems.
+ # It will need to be worked on as problems become evident.
+ #
+ # Essentially the problems here relate to two different
+ # areas. The first area is building with either KTH
+ # or MIT Kerberos, particularly when both are present on
+ # the machine. The other is static versus dynamic linking.
+ #
+ # On the KTH vs MIT issue, Both have libkrb5 that can mess
+ # up the works if one implementation ends up trying to
+ # use the other's krb. This is unfortunately a situation
+ # that very easily arises.
+ #
+ # Dynamic linking when the dependency information is built
+ # into MIT's libgssapi_krb5 or KTH's libgssapi magically makes
+ # all such problems go away, but when that setup is not
+ # present, because either the dynamic libraries lack
+ # dependencies or static linking is being done, then the
+ # problems start to show up.
+ saved_libs="$LIBS"
+ for TRY_LIBS in \
+ "-lgssapi_krb5" \
+ "-lgssapi_krb5 -lkrb5 -lk5crypto -lcom_err" \
+ "-lgssapi_krb5 -lkrb5 -lk5crypto -lcom_err -lresolv" \
+ "-lgssapi" \
+ "-lgssapi -lkrb5 -ldes -lcrypt -lasn1 -lroken -lcom_err" \
+ "-lgssapi -lkrb5 -lcrypto -lcrypt -lasn1 -lroken -lcom_err" \
+ "-lgss"
+ do
+ # Note that this does not include $saved_libs, because
+ # on FreeBSD machines this configure script has added
+ # -L/usr/local/lib to LIBS, which can make the
+ # -lgssapi_krb5 test succeed with shared libraries even
+ # when you are trying to build with KTH in /usr/lib.
+ LIBS="-L$use_gssapi/lib $TRY_LIBS"
+ AC_MSG_CHECKING(linking as $TRY_LIBS)
+ AC_TRY_LINK( , [gss_acquire_cred();],
+ gssapi_linked=yes, gssapi_linked=no)
+ case $gssapi_linked in
+ yes) AC_MSG_RESULT(yes); break ;;
+ no) AC_MSG_RESULT(no) ;;
+ esac
+ done
+
+ case $gssapi_linked in
+ no) AC_MSG_ERROR(could not determine proper GSSAPI linkage) ;;
+ esac
+
+ #
+ # XXXDCL Major kludge. Tries to cope with KTH in /usr/lib
+ # but MIT in /usr/local/lib and trying to build with KTH.
+ # /usr/local/lib can end up earlier on the link lines.
+ # Like most kludges, this one is not only inelegant it
+ # is also likely to be the wrong thing to do at least as
+ # many times as it is the right thing. Something better
+ # needs to be done.
+ #
+ if test "$use_gssapi" = "/usr" -a \
+ -f /usr/local/lib/libkrb5.a; then
+ FIX_KTH_VS_MIT=yes
+ fi
+
+ case "$FIX_KTH_VS_MIT" in
+ yes)
+ case "$enable_static_linking" in
+ yes) gssapi_lib_suffix=".a" ;;
+ *) gssapi_lib_suffix=".so" ;;
+ esac
+
+ for lib in $LIBS; do
+ case $lib in
+ -L*)
+ ;;
+ -l*)
+ new_lib=`echo $lib |
+ sed -e s%^-l%$use_gssapi/lib/lib% \
+ -e s%$%$gssapi_lib_suffix%`
+ NEW_LIBS="$NEW_LIBS $new_lib"
+ ;;
+ *)
+ AC_MSG_ERROR([KTH vs MIT Kerberos confusion!])
+ ;;
+ esac
+ done
+ LIBS="$NEW_LIBS"
+ ;;
+ esac
+
+ DST_GSSAPI_INC="-I$use_gssapi/include"
+ DNS_GSSAPI_LIBS="$LIBS"
+
+ AC_MSG_RESULT(using GSSAPI from $use_gssapi/lib and $use_gssapi/include)
+ LIBS="$saved_libs"
+ ;;
+esac
+
+AC_SUBST(ISC_PLATFORM_HAVEGSSAPI)
+AC_SUBST(ISC_PLATFORM_GSSAPIHEADER)
AC_SUBST(USE_GSSAPI)
AC_SUBST(DST_GSSAPI_INC)
-DNS_CRYPTO_LIBS="$DNS_CRYPTO_LIBS $DNS_GSSAPI_LIBS"
+AC_SUBST(DNS_GSSAPI_LIBS)
+DNS_CRYPTO_LIBS="$DNS_GSSAPI_LIBS $DNS_CRYPTO_LIBS"
#
# Applications linking with libdns also need to link with these libraries.
AC_CHECK_LIB(pthread, sigwait,
AC_DEFINE(HAVE_SIGWAIT),
AC_CHECK_LIB(pthread, _Psigwait,
- AC_DEFINE(HAVE_SIGWAIT),))))
+ AC_DEFINE(HAVE_SIGWAIT),))))
AC_CHECK_FUNC(pthread_attr_getstacksize,
AC_DEFINE(HAVE_PTHREAD_ATTR_GETSTACKSIZE),)
*-hp-hpux*)
CC="$CC -Ae -z"
# The version of the C compiler that constantly warns about
- # 'const' as well as alignment issues is unfortunately not
- # able to be discerned via the version of the operating
- # system, nor does cc have a version flag.
+ # 'const' as well as alignment issues is unfortunately not
+ # able to be discerned via the version of the operating
+ # system, nor does cc have a version flag.
case "`$CC +W 123 2>&1`" in
*Unknown?option*)
STD_CWARNINGS="+w1"
MKDEPCFLAGS="-xM"
;;
*-sco-sysv*uw*|*-*-sysv*UnixWare*|*-*-sysv*OpenUNIX*)
- # UnixWare
+ # UnixWare
CC="$CC -w"
;;
esac
#
case "$host" in
*-sco-sysv*uw*|*-*-sysv*UnixWare*|*-*-sysv*OpenUNIX*)
- # UnixWare
+ # UnixWare
ISC_PLATFORM_NEEDNETINETIN6H="#define ISC_PLATFORM_NEEDNETINETIN6H 1"
LWRES_PLATFORM_NEEDNETINETIN6H="#define LWRES_PLATFORM_NEEDNETINETIN6H 1"
- ISC_PLATFORM_FIXIN6ISADDR="#define ISC_PLATFORM_FIXIN6ISADDR 1"
+ ISC_PLATFORM_FIXIN6ISADDR="#define ISC_PLATFORM_FIXIN6ISADDR 1"
isc_netinetin6_hack="#include <netinet/in6.h>"
;;
*)
ISC_PLATFORM_NEEDNETINETIN6H="#undef ISC_PLATFORM_NEEDNETINETIN6H"
LWRES_PLATFORM_NEEDNETINETIN6H="#undef LWRES_PLATFORM_NEEDNETINETIN6H"
- ISC_PLATFORM_FIXIN6ISADDR="#undef ISC_PLATFORM_FIXIN6ISADDR"
+ ISC_PLATFORM_FIXIN6ISADDR="#undef ISC_PLATFORM_FIXIN6ISADDR"
isc_netinetin6_hack=""
;;
esac
#include <arpa/inet.h>
main() {
char a[16],b[64]; return(inet_ntop(AF_INET6, a, b, sizeof(b)) == (char*)0);}],
- [AC_MSG_RESULT(yes)
- ISC_PLATFORM_NEEDNTOP="#undef ISC_PLATFORM_NEEDNTOP"],
+ [AC_MSG_RESULT(yes)
+ ISC_PLATFORM_NEEDNTOP="#undef ISC_PLATFORM_NEEDNTOP"],
- [AC_MSG_RESULT(no)
- ISC_EXTRA_OBJS="$ISC_EXTRA_OBJS inet_ntop.$O"
- ISC_EXTRA_SRCS="$ISC_EXTRA_SRCS inet_ntop.c"
- ISC_PLATFORM_NEEDNTOP="#define ISC_PLATFORM_NEEDNTOP 1"],
- [AC_MSG_RESULT(assuming inet_ntop needed)
- ISC_EXTRA_OBJS="$ISC_EXTRA_OBJS inet_ntop.$O"
- ISC_EXTRA_SRCS="$ISC_EXTRA_SRCS inet_ntop.c"
- ISC_PLATFORM_NEEDNTOP="#define ISC_PLATFORM_NEEDNTOP 1"])
+ [AC_MSG_RESULT(no)
+ ISC_EXTRA_OBJS="$ISC_EXTRA_OBJS inet_ntop.$O"
+ ISC_EXTRA_SRCS="$ISC_EXTRA_SRCS inet_ntop.c"
+ ISC_PLATFORM_NEEDNTOP="#define ISC_PLATFORM_NEEDNTOP 1"],
+ [AC_MSG_RESULT(assuming inet_ntop needed)
+ ISC_EXTRA_OBJS="$ISC_EXTRA_OBJS inet_ntop.$O"
+ ISC_EXTRA_SRCS="$ISC_EXTRA_SRCS inet_ntop.c"
+ ISC_PLATFORM_NEEDNTOP="#define ISC_PLATFORM_NEEDNTOP 1"])
# On NetBSD 1.4.2 and maybe others, inet_pton() incorrectly accepts
main() { char a[16]; return (inet_pton(AF_INET, "1.2.3", a) == 1 ? 1 :
inet_pton(AF_INET, "1.2.3.04", a) == 1 ? 1 :
(inet_pton(AF_INET6, "::1.2.3.4", a) != 1)); }],
- [AC_MSG_RESULT(yes)
- ISC_PLATFORM_NEEDPTON="#undef ISC_PLATFORM_NEEDPTON"],
- [AC_MSG_RESULT(no)
- ISC_EXTRA_OBJS="$ISC_EXTRA_OBJS inet_pton.$O"
- ISC_EXTRA_SRCS="$ISC_EXTRA_SRCS inet_pton.c"
- ISC_PLATFORM_NEEDPTON="#define ISC_PLATFORM_NEEDPTON 1"],
+ [AC_MSG_RESULT(yes)
+ ISC_PLATFORM_NEEDPTON="#undef ISC_PLATFORM_NEEDPTON"],
+ [AC_MSG_RESULT(no)
+ ISC_EXTRA_OBJS="$ISC_EXTRA_OBJS inet_pton.$O"
+ ISC_EXTRA_SRCS="$ISC_EXTRA_SRCS inet_pton.c"
+ ISC_PLATFORM_NEEDPTON="#define ISC_PLATFORM_NEEDPTON 1"],
[AC_MSG_RESULT(assuming target platform has working inet_pton)
ISC_PLATFORM_NEEDPTON="#undef ISC_PLATFORM_NEEDPTON"],
- [AC_MSG_RESULT(assuming inet_pton needed)
- ISC_EXTRA_OBJS="$ISC_EXTRA_OBJS inet_pton.$O"
- ISC_EXTRA_SRCS="$ISC_EXTRA_SRCS inet_pton.c"
- ISC_PLATFORM_NEEDPTON="#define ISC_PLATFORM_NEEDPTON 1"],
- [AC_MSG_RESULT(assuming target platform has working inet_pton)
- ISC_PLATFORM_NEEDPTON="#undef ISC_PLATFORM_NEEDPTON"])
+ [AC_MSG_RESULT(assuming inet_pton needed)
+ ISC_EXTRA_OBJS="$ISC_EXTRA_OBJS inet_pton.$O"
+ ISC_EXTRA_SRCS="$ISC_EXTRA_SRCS inet_pton.c"
+ ISC_PLATFORM_NEEDPTON="#define ISC_PLATFORM_NEEDPTON 1"],
+ [AC_MSG_RESULT(assuming target platform has working inet_pton)
+ ISC_PLATFORM_NEEDPTON="#undef ISC_PLATFORM_NEEDPTON"])
AC_MSG_CHECKING([for inet_aton])
AC_TRY_LINK([
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>],
- [struct in_addr in; inet_aton(0, &in); return (0);],
- [AC_MSG_RESULT(yes)
- ISC_PLATFORM_NEEDATON="#undef ISC_PLATFORM_NEEDATON"],
+ [struct in_addr in; inet_aton(0, &in); return (0);],
+ [AC_MSG_RESULT(yes)
+ ISC_PLATFORM_NEEDATON="#undef ISC_PLATFORM_NEEDATON"],
- [AC_MSG_RESULT(no)
- ISC_EXTRA_OBJS="$ISC_EXTRA_OBJS inet_aton.$O"
- ISC_EXTRA_SRCS="$ISC_EXTRA_SRCS inet_aton.c"
- ISC_PLATFORM_NEEDATON="#define ISC_PLATFORM_NEEDATON 1"])
+ [AC_MSG_RESULT(no)
+ ISC_EXTRA_OBJS="$ISC_EXTRA_OBJS inet_aton.$O"
+ ISC_EXTRA_SRCS="$ISC_EXTRA_SRCS inet_aton.c"
+ ISC_PLATFORM_NEEDATON="#define ISC_PLATFORM_NEEDATON 1"])
AC_SUBST(ISC_PLATFORM_NEEDNTOP)
AC_SUBST(ISC_PLATFORM_NEEDPTON)
[in_port_t port = 25; return (0);],
[AC_MSG_RESULT(yes)
ISC_PLATFORM_NEEDPORTT="#undef ISC_PLATFORM_NEEDPORTT"],
- [AC_MSG_RESULT(no)
+ [AC_MSG_RESULT(no)
ISC_PLATFORM_NEEDPORTT="#define ISC_PLATFORM_NEEDPORTT 1"])
AC_SUBST(ISC_PLATFORM_NEEDPORTT)
AC_SUBST(ISC_LWRES_NEEDHERRNO)
AC_CHECK_FUNC(getipnodebyname,
- [ISC_LWRES_GETIPNODEPROTO="#undef ISC_LWRES_GETIPNODEPROTO"],
- [ISC_LWRES_GETIPNODEPROTO="#define ISC_LWRES_GETIPNODEPROTO 1"])
+ [ISC_LWRES_GETIPNODEPROTO="#undef ISC_LWRES_GETIPNODEPROTO"],
+ [ISC_LWRES_GETIPNODEPROTO="#define ISC_LWRES_GETIPNODEPROTO 1"])
AC_CHECK_FUNC(getnameinfo,
- [ISC_LWRES_GETNAMEINFOPROTO="#undef ISC_LWRES_GETNAMEINFOPROTO"],
- [ISC_LWRES_GETNAMEINFOPROTO="#define ISC_LWRES_GETNAMEINFOPROTO 1"])
+ [ISC_LWRES_GETNAMEINFOPROTO="#undef ISC_LWRES_GETNAMEINFOPROTO"],
+ [ISC_LWRES_GETNAMEINFOPROTO="#define ISC_LWRES_GETNAMEINFOPROTO 1"])
AC_CHECK_FUNC(getaddrinfo,
- [ISC_LWRES_GETADDRINFOPROTO="#undef ISC_LWRES_GETADDRINFOPROTO"
+ [ISC_LWRES_GETADDRINFOPROTO="#undef ISC_LWRES_GETADDRINFOPROTO"
AC_DEFINE(HAVE_GETADDRINFO)],
- [ISC_LWRES_GETADDRINFOPROTO="#define ISC_LWRES_GETADDRINFOPROTO 1"])
+ [ISC_LWRES_GETADDRINFOPROTO="#define ISC_LWRES_GETADDRINFOPROTO 1"])
AC_CHECK_FUNC(gai_strerror, AC_DEFINE(HAVE_GAISTRERROR))
AC_SUBST(ISC_LWRES_GETIPNODEPROTO)
AC_SUBST(ISC_LWRES_GETADDRINFOPROTO)
AC_ARG_ENABLE(getifaddrs,
[ --enable-getifaddrs Enable the use of getifaddrs() [[yes|no|glibc]].
- glibc: Use getifaddrs() in glibc if you know it supports IPv6.],
+ glibc: Use getifaddrs() in glibc if you know it supports IPv6.],
want_getifaddrs="$enableval", want_getifaddrs="yes")
case $want_getifaddrs in
AC_SUBST(ISC_EXTRA_OBJS)
AC_SUBST(ISC_EXTRA_SRCS)
+#
+# Use our own SPNEGO implementation?
+#
+AC_ARG_ENABLE(isc-spnego,
+ [ --disable-isc-spnego use SPNEGO from GSSAPI library])
+
+if test -n "$USE_GSSAPI"
+then
+ case "$enable_isc_spnego" in
+ yes|'')
+ USE_ISC_SPNEGO='-DUSE_ISC_SPNEGO'
+ DST_EXTRA_OBJS="$DST_EXTRA_OBJS spnego.$O"
+ DST_EXTRA_SRCS="$DST_EXTRA_SRCS spnego.c"
+ AC_MSG_RESULT(using SPNEGO from lib/dns)
+ ;;
+ no)
+ AC_MSG_RESULT(using SPNEGO from GSSAPI library)
+ ;;
+ esac
+fi
+
+AC_SUBST(USE_ISC_SPNEGO)
+
+AC_SUBST(DST_EXTRA_OBJS)
+AC_SUBST(DST_EXTRA_SRCS)
+
# Determine the printf format characters to use when printing
# values of type isc_int64_t. This will normally be "ll", but where
# the compiler treats "long long" as a alias for "long" and printf
case $ac_cv_have_if_nametoindex in
no)
case "$host" in
- *-hp-hpux*)
- AC_CHECK_LIB(ipv6, if_nametoindex,
+ *-hp-hpux*)
+ AC_CHECK_LIB(ipv6, if_nametoindex,
ac_cv_have_if_nametoindex=yes
LIBS="-lipv6 $LIBS",)
- ;;
+ ;;
esac
esac
case $ac_cv_have_if_nametoindex in
#
AC_ARG_ENABLE(atomic,
[ --enable-atomic enable machine specific atomic operations
- [[default=autodetect]]],
+ [[default=autodetect]]],
enable_atomic="$enableval",
enable_atomic="autodetect")
case "$enable_atomic" in
],
[arch=x86_64],
[arch=x86_32],
- [arch=x86_32])
+ [arch=x86_32])
;;
x86_64-*)
arch=x86_64
BUILD_LIBS="$LIBS"
fi
+NEWFLAGS=""
+for e in $BUILD_LDFLAGS ; do
+ case $e in
+ -L*)
+ case $host_os in
+ netbsd*)
+ ee=`echo $e | sed -e 's%^-L%-Wl,-rpath,%'`
+ NEWFLAGS="$NEWFLAGS $e $ee"
+ ;;
+ freebsd*)
+ ee=`echo $e | sed -e 's%^-L%-Wl,-rpath,%'`
+ NEWFLAGS="$NEWFLAGS $e $ee"
+ ;;
+ esac
+ ;;
+ *)
+ NEWFLAGS="$NEWFLAGS $e"
+ ;;
+ esac
+done
+BUILD_LDFLAGS="$NEWFLAGS"
+
+NEWFLAGS=""
+for e in $DNS_GSSAPI_LIBS ; do
+ case $e in
+ -L*)
+ case $host_os in
+ netbsd*)
+ ee=`echo $e | sed -e 's%^-L%-Wl,-rpath,%'`
+ NEWFLAGS="$NEWFLAGS $e $ee"
+ ;;
+ freebsd*)
+ ee=`echo $e | sed -e 's%^-L%-Wl,-rpath,%'`
+ NEWFLAGS="$NEWFLAGS $e $ee"
+ ;;
+ esac
+ ;;
+ *)
+ NEWFLAGS="$NEWFLAGS $e"
+ ;;
+ esac
+done
+DNS_GSSAPI_LIBS="$NEWFLAGS"
+
+NEWFLAGS=""
+for e in $DNS_CRYPTO_LIBS ; do
+ case $e in
+ -L*)
+ case $host_os in
+ netbsd*)
+ ee=`echo $e | sed -e 's%^-L%-Wl,-rpath,%'`
+ NEWFLAGS="$NEWFLAGS $e $ee"
+ ;;
+ freebsd*)
+ ee=`echo $e | sed -e 's%^-L%-Wl,-rpath,%'`
+ NEWFLAGS="$NEWFLAGS $e $ee"
+ ;;
+ esac
+ ;;
+ *)
+ NEWFLAGS="$NEWFLAGS $e"
+ ;;
+ esac
+done
+DNS_CRYPTO_LIBS="$NEWFLAGS"
+
AC_SUBST(BUILD_CC)
AC_SUBST(BUILD_CFLAGS)
AC_SUBST(BUILD_CPPFLAGS)
- PERFORMANCE OF THIS SOFTWARE.
-->
-<!-- File: $Id: Bv9ARM-book.xml,v 1.308 2006/09/13 00:15:37 marka Exp $ -->
+<!-- File: $Id: Bv9ARM-book.xml,v 1.309 2006/12/04 01:52:45 marka Exp $ -->
<book xmlns:xi="http://www.w3.org/2001/XInclude">
<title>BIND 9 Administrator Reference Manual</title>
</para>
<para>
- Dynamic update is enabled by
- including an <command>allow-update</command> or
- <command>update-policy</command> clause in the
- <command>zone</command> statement.
+ Dynamic update is enabled by including an
+ <command>allow-update</command> or <command>update-policy</command>
+ clause in the <command>zone</command> statement. The
+ <command>tkey-gssapi-credential</command> and
+ <command>tkey-domain</command> clauses in the
+ <command>options</command> statement enable the
+ server to negotiate keys that can be matched against those
+ in <command>update-policy</command> or
+ <command>allow-update</command>.
</para>
<para>
allow-update { key host1-host2. ;};
</programlisting>
- <para>
- This allows dynamic updates to succeed only if the request
- was signed by a key named
- "<command>host1-host2.</command>".
- </para>
<para>
- You may want to read about the more
- powerful <command>update-policy</command> statement in <xref linkend="dynamic_update_policies"/>.
- </para>
+ This allows dynamic updates to succeed only if the request
+ was signed by a key named "<command>host1-host2.</command>".
+ </para>
+
+ <para>
+ You may want to read about the more powerful
+ <command>update-policy</command> statement in
+ <xref linkend="dynamic_update_policies"/>.
+ </para>
</sect2>
<sect2>
<optional> directory <replaceable>path_name</replaceable>; </optional>
<optional> key-directory <replaceable>path_name</replaceable>; </optional>
<optional> named-xfer <replaceable>path_name</replaceable>; </optional>
+ <optional> tkey-gssapi-credential <replaceable>principal</replaceable>; </optional>
<optional> tkey-domain <replaceable>domainname</replaceable>; </optional>
<optional> tkey-dhkey <replaceable>key_name</replaceable> <replaceable>key_tag</replaceable>; </optional>
<optional> cache-file <replaceable>path_name</replaceable>; </optional>
<varlistentry>
<term><command>named-xfer</command></term>
- <listitem>
- <para>
- <emphasis>This option is obsolete.</emphasis>
- It was used in <acronym>BIND</acronym> 8 to
- specify the pathname to the <command>named-xfer</command> program.
- In <acronym>BIND</acronym> 9, no separate <command>named-xfer</command> program is
- needed; its functionality is built into the name server.
- </para>
-
- </listitem>
- </varlistentry>
+ <listitem>
+ <para>
+ <emphasis>This option is obsolete.</emphasis> It
+ was used in <acronym>BIND</acronym> 8 to specify
+ the pathname to the <command>named-xfer</command>
+ program. In <acronym>BIND</acronym> 9, no separate
+ <command>named-xfer</command> program is needed;
+ its functionality is built into the name server.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>tkey-gssapi-credential</command></term>
+ <listitem>
+ <para>
+ The security credential with which the server should
+ authenticate keys requested by the GSS-TSIG protocol.
+ Currently only Kerberos 5 authentication is available
+ and the credential is a Kerberos principal which
+ the server can aquire through the default system
+ key file, normally <filename>/etc/krb5.keytab</filename>.
+ Normally this principal is of the form
+ "<userinput>dns/</userinput><varname>server.domain</varname>".
+ To use GSS-TSIG, <command>tkey-domain</command>
+ must also be set.
+ </para>
+ </listitem>
+ </varlistentry>
<varlistentry>
<term><command>tkey-domain</command></term>
- <listitem>
- <para>
- The domain appended to the names of all
- shared keys generated with
- <command>TKEY</command>. When a client
- requests a <command>TKEY</command> exchange, it
- may or may not specify
- the desired name for the key. If present, the name of the
- shared
- key will be "<varname>client specified part</varname>" +
- "<varname>tkey-domain</varname>".
- Otherwise, the name of the shared key will be "<varname>random hex
-digits</varname>" + "<varname>tkey-domain</varname>". In most cases,
- the <command>domainname</command> should be the
- server's domain
- name.
- </para>
- </listitem>
- </varlistentry>
+ <listitem>
+ <para>
+ The domain appended to the names of all shared keys
+ generated with <command>TKEY</command>. When a
+ client requests a <command>TKEY</command> exchange,
+ it may or may not specify the desired name for the
+ key. If present, the name of the shared key will
+ will be <varname>client specified part</varname> +
+ <varname>tkey-domain</varname>. Otherwise, the
+ name of the shared key will be <varname>random hex
+ digits</varname> + <varname>tkey-domain</varname>.
+ In most cases, the <command>domainname</command>
+ should be the server's domain name, or an otherwise
+ non-existent subdomain like
+ "_tkey.<varname>domainname</varname>". If you are
+ using GSS-TSIG, this variable must be defined
+ </para>
+ </listitem>
+ </varlistentry>
<varlistentry>
<term><command>tkey-dhkey</command></term>
</sect3>
<sect3 id="dynamic_update_policies">
<title>Dynamic Update Policies</title>
- <para>
- <acronym>BIND</acronym> 9 supports two alternative
- methods of granting clients
- the right to perform dynamic updates to a zone,
- configured by the <command>allow-update</command>
- and
- <command>update-policy</command> option,
- respectively.
- </para>
- <para>
- The <command>allow-update</command> clause works the
- same
- way as in previous versions of <acronym>BIND</acronym>. It grants given clients the
- permission to update any record of any name in the zone.
- </para>
- <para>
- The <command>update-policy</command> clause is new
- in <acronym>BIND</acronym>
- 9 and allows more fine-grained control over what updates are
- allowed.
- A set of rules is specified, where each rule either grants or
- denies
- permissions for one or more names to be updated by one or more
- identities.
- If the dynamic update request message is signed (that is, it
- includes
- either a TSIG or SIG(0) record), the identity of the signer can
- be determined.
- </para>
- <para>
- Rules are specified in the <command>update-policy</command> zone
- option, and are only meaningful for master zones. When the <command>update-policy</command> statement
- is present, it is a configuration error for the <command>allow-update</command> statement
- to be present. The <command>update-policy</command>
- statement only
- examines the signer of a message; the source address is not
- relevant.
- </para>
- <para>
+ <para><acronym>BIND</acronym> 9 supports two alternative
+ methods of granting clients the right to perform
+ dynamic updates to a zone, configured by the
+ <command>allow-update</command> and
+ <command>update-policy</command> option, respectively.
+ </para>
+ <para>
+ The <command>allow-update</command> clause works the
+ same way as in previous versions of <acronym>BIND</acronym>.
+ It grants given clients the permission to update any
+ record of any name in the zone.
+ </para>
+ <para>
+ The <command>update-policy</command> clause is new
+ in <acronym>BIND</acronym> 9 and allows more fine-grained
+ control over what updates are allowed. A set of rules
+ is specified, where each rule either grants or denies
+ permissions for one or more names to be updated by
+ one or more identities. If the dynamic update request
+ message is signed (that is, it includes either a TSIG
+ or SIG(0) record), the identity of the signer can be
+ determined.
+ </para>
+ <para>
+ Rules are specified in the <command>update-policy</command>
+ zone option, and are only meaningful for master zones.
+ When the <command>update-policy</command> statement
+ is present, it is a configuration error for the
+ <command>allow-update</command> statement to be
+ present. The <command>update-policy</command> statement
+ only examines the signer of a message; the source
+ address is not relevant.
+ </para>
+
This is how a rule definition looks:
</para>
matches
the types specified in the type field.
</para>
-
- <para>
- The identity field specifies a name or a wildcard name.
- Normally, this
- is the name of the TSIG or SIG(0) key used to sign the update
- request. When a
- TKEY exchange has been used to create a shared secret, the
- identity of the
- shared secret is the same as the identity of the key used to
- authenticate the
- TKEY exchange. When the <replaceable>identity</replaceable> field specifies a
- wildcard name, it is subject to DNS wildcard expansion, so the
- rule will apply
- to multiple identities. The <replaceable>identity</replaceable> field must
- contain a fully qualified domain name.
- </para>
+ <para>
+ The identity field specifies a name or a wildcard
+ name. Normally, this is the name of the TSIG or
+ SIG(0) key used to sign the update request. When a
+ TKEY exchange has been used to create a shared secret,
+ the identity of the shared secret is the same as the
+ identity of the key used to authenticate the TKEY
+ exchange. TKEY is also the negotiation method used
+ by GSS-TSIG, which establishes an identity that is
+ the Kerberos principal of the client, such as
+ <userinput>"user@host.domain"</userinput>. When the
+ <replaceable>identity</replaceable> field specifies
+ a wildcard name, it is subject to DNS wildcard
+ expansion, so the rule will apply to multiple identities.
+ The <replaceable>identity</replaceable> field must
+ contain a fully qualified domain name.
+ </para>
<para>
The <replaceable>nametype</replaceable> field has 6
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
-# $Id: Makefile.in,v 1.154 2006/01/06 00:01:44 marka Exp $
+# $Id: Makefile.in,v 1.155 2006/12/04 01:52:46 marka Exp $
srcdir = @srcdir@
VPATH = @srcdir@
CINCLUDES = -I. -Iinclude ${DNS_INCLUDES} \
${ISC_INCLUDES} @DST_OPENSSL_INC@ @DST_GSSAPI_INC@
-CDEFINES = -DUSE_MD5 @USE_OPENSSL@ @USE_GSSAPI@
+CDEFINES = -DUSE_MD5 @USE_OPENSSL@ @USE_GSSAPI@ @USE_ISC_SPNEGO@
CWARNINGS =
ISCLIBS = ../../lib/isc/libisc.@A@
# Alphabetically
-DSTOBJS = dst_api.@O@ dst_lib.@O@ dst_parse.@O@ dst_result.@O@ \
+DSTOBJS = @DST_EXTRA_OBJS@ \
+ dst_api.@O@ dst_lib.@O@ dst_parse.@O@ dst_result.@O@ \
gssapi_link.@O@ gssapictx.@O@ hmac_link.@O@ key.@O@ \
openssl_link.@O@ openssldh_link.@O@ openssldsa_link.@O@ \
opensslrsa_link.@O@
OBJS= ${DNSOBJS} ${OTHEROBJS} ${DSTOBJS}
# Alphabetically
-DSTSRCS = dst_api.c dst_lib.c dst_parse.c \
+DSTSRCS = @DST_EXTRA_SRCS@ \
+ dst_api.c dst_lib.c dst_parse.c \
dst_result.c gssapi_link.c gssapictx.c \
hmac_link.c key.c \
openssl_link.c openssldh_link.c \
include/dns/rdatastruct.h code.h
${OBJS}: include/dns/enumtype.h include/dns/enumclass.h \
include/dns/rdatastruct.h
+
+spnego.@O@: spnego_asn1.c spnego.h
/*
* Principal Author: Brian Wellington
- * $Id: dst_api.c,v 1.7 2006/01/27 23:57:46 marka Exp $
+ * $Id: dst_api.c,v 1.8 2006/12/04 01:52:46 marka Exp $
*/
/*! \file */
static unsigned int dst_entropy_flags = 0;
static isc_boolean_t dst_initialized = ISC_FALSE;
+void gss_log(int level, const char *fmt, ...) ISC_FORMAT_PRINTF(2, 3);
+
isc_mem_t *dst__memory_pool = NULL;
/*
static void *
default_memalloc(void *arg, size_t size) {
- UNUSED(arg);
- if (size == 0U)
- size = 1;
- return (malloc(size));
+ UNUSED(arg);
+ if (size == 0U)
+ size = 1;
+ return (malloc(size));
}
static void
default_memfree(void *arg, void *ptr) {
- UNUSED(arg);
- free(ptr);
+ UNUSED(arg);
+ free(ptr);
}
isc_result_t
if (key->func->createctx == NULL)
return (DST_R_UNSUPPORTEDALG);
- if (key->opaque == NULL)
+ if (key->keydata.generic == NULL)
return (DST_R_NULLKEY);
dctx = isc_mem_get(mctx, sizeof(dst_context_t));
key = dctx->key;
CHECKALG(key->key_alg);
- if (key->opaque == NULL)
+ if (key->keydata.generic == NULL)
return (DST_R_NULLKEY);
if (key->func->sign == NULL)
return (DST_R_NOTPRIVATEKEY);
REQUIRE(sig != NULL);
CHECKALG(dctx->key->key_alg);
- if (dctx->key->opaque == NULL)
+ if (dctx->key->keydata.generic == NULL)
return (DST_R_NULLKEY);
if (dctx->key->func->verify == NULL)
return (DST_R_NOTPUBLICKEY);
CHECKALG(pub->key_alg);
CHECKALG(priv->key_alg);
- if (pub->opaque == NULL || priv->opaque == NULL)
+ if (pub->keydata.generic == NULL || priv->keydata.generic == NULL)
return (DST_R_NULLKEY);
if (pub->key_alg != priv->key_alg ||
return (result);
}
- if (!dns_name_equal(name, key->key_name) ||
- id != key->key_id ||
- alg != key->key_alg)
- {
+ if (!dns_name_equal(name, key->key_name) || id != key->key_id ||
+ alg != key->key_alg) {
dst_key_free(&key);
return (DST_R_INVALIDPRIVATEKEY);
}
return (result);
if ((type & (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC)) == DST_TYPE_PUBLIC ||
- (pubkey->key_flags & DNS_KEYFLAG_TYPEMASK) == DNS_KEYTYPE_NOKEY)
- {
+ (pubkey->key_flags & DNS_KEYFLAG_TYPEMASK) == DNS_KEYTYPE_NOKEY) {
result = computeid(pubkey);
if (result != ISC_R_SUCCESS) {
dst_key_free(&pubkey);
& 0xffff));
}
- if (key->opaque == NULL) /*%< NULL KEY */
+ if (key->keydata.generic == NULL) /*%< NULL KEY */
return (ISC_R_SUCCESS);
return (key->func->todns(key, target));
return (result);
}
+gss_ctx_id_t
+dst_key_getgssctx(const dst_key_t *key)
+{
+ REQUIRE(key != NULL);
+
+ return (key->keydata.gssctx);
+}
+
isc_result_t
-dst_key_fromgssapi(dns_name_t *name, void *opaque, isc_mem_t *mctx,
+dst_key_fromgssapi(dns_name_t *name, gss_ctx_id_t gssctx, isc_mem_t *mctx,
dst_key_t **keyp)
{
dst_key_t *key;
- REQUIRE(opaque != NULL);
+ REQUIRE(gssctx != NULL);
REQUIRE(keyp != NULL && *keyp == NULL);
key = get_key_struct(name, DST_ALG_GSSAPI, 0, DNS_KEYPROTO_DNSSEC,
0, dns_rdataclass_in, mctx);
if (key == NULL)
return (ISC_R_NOMEMORY);
- key->opaque = opaque;
+
+ key->keydata.gssctx = gssctx;
*keyp = key;
return (ISC_R_SUCCESS);
}
key = *keyp;
mctx = key->mctx;
- if (key->opaque != NULL) {
+ if (key->keydata.generic != NULL) {
INSIST(key->func->destroy != NULL);
key->func->destroy(key);
}
key->key_flags = flags;
key->key_proto = protocol;
key->mctx = mctx;
- key->opaque = NULL;
+ key->keydata.generic = NULL;
key->key_size = bits;
key->key_class = rdclass;
key->func = dst_t_func[alg];
len = 1 + 3 + 1 + 5 + strlen(suffix) + 1;
if (isc_buffer_availablelength(out) < len)
return (ISC_R_NOSPACE);
- sprintf((char *) isc_buffer_used(out), "+%03d+%05d%s", alg, id, suffix);
+ sprintf((char *) isc_buffer_used(out), "+%03d+%05d%s", alg, id,
+ suffix);
isc_buffer_add(out, len);
+
return (ISC_R_SUCCESS);
}
flags &= ~ISC_ENTROPY_GOODONLY;
return (isc_entropy_getdata(dst_entropy_pool, buf, len, NULL, flags));
}
+
+unsigned int
+dst__entropy_status(void) {
+ return (isc_entropy_status(dst_entropy_pool));
+}
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: dst_internal.h,v 1.5 2006/01/27 23:57:46 marka Exp $ */
+/* $Id: dst_internal.h,v 1.6 2006/12/04 01:52:46 marka Exp $ */
#ifndef DST_DST_INTERNAL_H
#define DST_DST_INTERNAL_H 1
#include <isc/magic.h>
#include <isc/region.h>
#include <isc/types.h>
+#include <isc/md5.h>
+#include <isc/sha1.h>
+#include <isc/hmacmd5.h>
+#include <isc/hmacsha.h>
#include <dst/dst.h>
+#ifdef OPENSSL
+#include <openssl/dh.h>
+#include <openssl/dsa.h>
+#include <openssl/err.h>
+#include <openssl/objects.h>
+#include <openssl/rsa.h>
+#endif
+
ISC_LANG_BEGINDECLS
#define KEY_MAGIC ISC_MAGIC('D','S','T','K')
typedef struct dst_func dst_func_t;
+typedef struct dst_hmacmd5_key dst_hmacmd5_key_t;
+typedef struct dst_hmacsha1_key dst_hmacsha1_key_t;
+typedef struct dst_hmacsha224_key dst_hmacsha224_key_t;
+typedef struct dst_hmacsha256_key dst_hmacsha256_key_t;
+typedef struct dst_hmacsha384_key dst_hmacsha384_key_t;
+typedef struct dst_hmacsha512_key dst_hmacsha512_key_t;
+
/*% DST Key Structure */
struct dst_key {
unsigned int magic;
isc_uint16_t key_bits; /*%< hmac digest bits */
dns_rdataclass_t key_class; /*%< class of the key record */
isc_mem_t *mctx; /*%< memory context */
- void * opaque; /*%< pointer to key in crypto pkg fmt */
+ union {
+ void *generic;
+ gss_ctx_id_t gssctx;
+#ifdef OPENSSL
+ RSA *rsa;
+ DSA *dsa;
+ DH *dh;
+#endif
+ dst_hmacmd5_key_t *hmacmd5;
+ dst_hmacsha1_key_t *hmacsha1;
+ dst_hmacsha224_key_t *hmacsha224;
+ dst_hmacsha256_key_t *hmacsha256;
+ dst_hmacsha384_key_t *hmacsha384;
+ dst_hmacsha512_key_t *hmacsha512;
+
+ } keydata; /*%< pointer to key in crypto pkg fmt */
dst_func_t * func; /*%< crypto package specific functions */
};
unsigned int magic;
dst_key_t *key;
isc_mem_t *mctx;
- void *opaque;
+ union {
+ void *generic;
+ dst_gssapi_signverifyctx_t *gssctx;
+ isc_md5_t *md5ctx;
+ isc_sha1_t *sha1ctx;
+ isc_hmacmd5_t *hmacmd5ctx;
+ isc_hmacsha1_t *hmacsha1ctx;
+ isc_hmacsha224_t *hmacsha224ctx;
+ isc_hmacsha256_t *hmacsha256ctx;
+ isc_hmacsha384_t *hmacsha384ctx;
+ isc_hmacsha512_t *hmacsha512ctx;
+ } ctxdata;
};
struct dst_func {
isc_result_t dst__entropy_getdata(void *buf, unsigned int len,
isc_boolean_t pseudo);
+/*
+ * Entropy status hook.
+ */
+unsigned int dst__entropy_status(void);
+
ISC_LANG_ENDDECLS
#endif /* DST_DST_INTERNAL_H */
*/
/*
- * $Id: gssapi_link.c,v 1.3 2005/04/29 00:22:47 marka Exp $
+ * $Id: gssapi_link.c,v 1.4 2006/12/04 01:52:46 marka Exp $
*/
-#ifdef GSSAPI
-
#include <config.h>
+#ifdef GSSAPI
+
#include <isc/buffer.h>
#include <isc/mem.h>
#include <isc/string.h>
#include "dst_internal.h"
#include "dst_parse.h"
-#include <gssapi/gssapi.h>
+#include <dst/gssapi.h>
#define INITIAL_BUFFER_SIZE 1024
#define BUFFER_EXTRA 1024
#define REGION_TO_GBUFFER(r, gb) \
do { \
- (gb).length = (r).length; \
- (gb).value = (r).base; \
+ (gb).length = (r).length; \
+ (gb).value = (r).base; \
} while (0)
-typedef struct gssapi_ctx {
- isc_buffer_t *buffer;
- gss_ctx_id_t *context_id;
-} gssapi_ctx_t;
+struct dst_gssapi_signverifyctx {
+ isc_buffer_t *buffer;
+};
+/*%
+ * Allocate a temporary "context" for use in gathering data for signing
+ * or verifying.
+ */
static isc_result_t
-gssapi_createctx(dst_key_t *key, dst_context_t *dctx) {
- gssapi_ctx_t *ctx;
+gssapi_create_signverify_ctx(dst_key_t *key, dst_context_t *dctx) {
+ dst_gssapi_signverifyctx_t *ctx;
isc_result_t result;
UNUSED(key);
- ctx = isc_mem_get(dctx->mctx, sizeof(gssapi_ctx_t));
+ ctx = isc_mem_get(dctx->mctx, sizeof(dst_gssapi_signverifyctx_t));
if (ctx == NULL)
return (ISC_R_NOMEMORY);
ctx->buffer = NULL;
result = isc_buffer_allocate(dctx->mctx, &ctx->buffer,
INITIAL_BUFFER_SIZE);
if (result != ISC_R_SUCCESS) {
- isc_mem_put(dctx->mctx, ctx, sizeof(gssapi_ctx_t));
+ isc_mem_put(dctx->mctx, ctx, sizeof(dst_gssapi_signverifyctx_t));
return (result);
}
- ctx->context_id = key->opaque;
- dctx->opaque = ctx;
+
+ dctx->ctxdata.gssctx = ctx;
+
return (ISC_R_SUCCESS);
}
+/*%
+ * Destroy the temporary sign/verify context.
+ */
static void
-gssapi_destroyctx(dst_context_t *dctx) {
- gssapi_ctx_t *ctx = dctx->opaque;
+gssapi_destroy_signverify_ctx(dst_context_t *dctx) {
+ dst_gssapi_signverifyctx_t *ctx = dctx->ctxdata.gssctx;
if (ctx != NULL) {
if (ctx->buffer != NULL)
isc_buffer_free(&ctx->buffer);
- isc_mem_put(dctx->mctx, ctx, sizeof(gssapi_ctx_t));
- dctx->opaque = NULL;
+ isc_mem_put(dctx->mctx, ctx, sizeof(dst_gssapi_signverifyctx_t));
+ dctx->ctxdata.gssctx = NULL;
}
}
+/*%
+ * Add data to our running buffer of data we will be signing or verifying.
+ * This code will see if the new data will fit in our existing buffer, and
+ * copy it in if it will. If not, it will attempt to allocate a larger
+ * buffer and copy old+new into it, and free the old buffer.
+ */
static isc_result_t
gssapi_adddata(dst_context_t *dctx, const isc_region_t *data) {
- gssapi_ctx_t *ctx = dctx->opaque;
+ dst_gssapi_signverifyctx_t *ctx = dctx->ctxdata.gssctx;
isc_buffer_t *newbuffer = NULL;
isc_region_t r;
unsigned int length;
return (result);
isc_buffer_usedregion(ctx->buffer, &r);
- (void) isc_buffer_copyregion(newbuffer, &r);
- (void) isc_buffer_copyregion(newbuffer, data);
+ (void)isc_buffer_copyregion(newbuffer, &r);
+ (void)isc_buffer_copyregion(newbuffer, data);
isc_buffer_free(&ctx->buffer);
ctx->buffer = newbuffer;
return (ISC_R_SUCCESS);
}
+/*%
+ * Sign.
+ */
static isc_result_t
gssapi_sign(dst_context_t *dctx, isc_buffer_t *sig) {
- gssapi_ctx_t *ctx = dctx->opaque;
+ dst_gssapi_signverifyctx_t *ctx = dctx->ctxdata.gssctx;
isc_region_t message;
gss_buffer_desc gmessage, gsig;
OM_uint32 minor, gret;
+ gss_ctx_id_t gssctx = dctx->key->keydata.gssctx;
+ char buf[1024];
+ /*
+ * Convert the data we wish to sign into a structure gssapi can
+ * understand.
+ */
isc_buffer_usedregion(ctx->buffer, &message);
REGION_TO_GBUFFER(message, gmessage);
- gret = gss_get_mic(&minor, ctx->context_id,
- GSS_C_QOP_DEFAULT, &gmessage, &gsig);
- if (gret != 0)
+ /*
+ * Generate the signature.
+ */
+ gret = gss_get_mic(&minor, gssctx, GSS_C_QOP_DEFAULT, &gmessage,
+ &gsig);
+
+ /*
+ * If it did not complete, we log the result and return a generic
+ * failure code.
+ */
+ if (gret != GSS_S_COMPLETE) {
+ gss_log(3, "GSS sign error: %s",
+ gss_error_tostring(gret, minor, buf, sizeof(buf)));
return (ISC_R_FAILURE);
+ }
+ /*
+ * If it will not fit in our allocated buffer, return that we need
+ * more space.
+ */
if (gsig.length > isc_buffer_availablelength(sig)) {
gss_release_buffer(&minor, &gsig);
return (ISC_R_NOSPACE);
}
+ /*
+ * Copy the output into our buffer space, and release the gssapi
+ * allocated space.
+ */
isc_buffer_putmem(sig, gsig.value, gsig.length);
-
gss_release_buffer(&minor, &gsig);
return (ISC_R_SUCCESS);
}
+/*%
+ * Verify.
+ */
static isc_result_t
gssapi_verify(dst_context_t *dctx, const isc_region_t *sig) {
- gssapi_ctx_t *ctx = dctx->opaque;
- isc_region_t message;
+ dst_gssapi_signverifyctx_t *ctx = dctx->ctxdata.gssctx;
+ isc_region_t message, r;
gss_buffer_desc gmessage, gsig;
OM_uint32 minor, gret;
-
+ gss_ctx_id_t gssctx = dctx->key->keydata.gssctx;
+ unsigned char *buf;
+ char err[1024];
+
+ /*
+ * Convert the data we wish to sign into a structure gssapi can
+ * understand.
+ */
isc_buffer_usedregion(ctx->buffer, &message);
REGION_TO_GBUFFER(message, gmessage);
- REGION_TO_GBUFFER(*sig, gsig);
-
- gret = gss_verify_mic(&minor, ctx->context_id, &gmessage, &gsig, NULL);
- if (gret != 0)
+ /*
+ * XXXMLG
+ * It seem that gss_verify_mic() modifies the signature buffer,
+ * at least on Heimdal's implementation. Copy it here to an allocated
+ * buffer.
+ */
+ buf = isc_mem_allocate(dst__memory_pool, sig->length);
+ if (buf == NULL)
return (ISC_R_FAILURE);
+ memcpy(buf, sig->base, sig->length);
+ r.base = buf;
+ r.length = sig->length;
+ REGION_TO_GBUFFER(r, gsig);
+
+ /*
+ * Verify the data.
+ */
+ gret = gss_verify_mic(&minor, gssctx, &gmessage, &gsig, NULL);
+
+ isc_mem_free(dst__memory_pool, buf);
+
+ /*
+ * Convert return codes into something useful to us.
+ */
+ if (gret != GSS_S_COMPLETE) {
+ gss_log(3, "GSS verify error: %s",
+ gss_error_tostring(gret, minor, err, sizeof(err)));
+ if (gret == GSS_S_DEFECTIVE_TOKEN ||
+ gret == GSS_S_BAD_SIG ||
+ gret == GSS_S_DUPLICATE_TOKEN ||
+ gret == GSS_S_OLD_TOKEN ||
+ gret == GSS_S_UNSEQ_TOKEN ||
+ gret == GSS_S_GAP_TOKEN ||
+ gret == GSS_S_CONTEXT_EXPIRED ||
+ gret == GSS_S_NO_CONTEXT ||
+ gret == GSS_S_FAILURE)
+ return(DST_R_VERIFYFAILURE);
+ else
+ return (ISC_R_FAILURE);
+ }
return (ISC_R_SUCCESS);
}
static isc_boolean_t
gssapi_compare(const dst_key_t *key1, const dst_key_t *key2) {
- gss_ctx_id_t gsskey1 = key1->opaque;
- gss_ctx_id_t gsskey2 = key2->opaque;
+ gss_ctx_id_t gsskey1 = key1->keydata.gssctx;
+ gss_ctx_id_t gsskey2 = key2->keydata.gssctx;
/* No idea */
return (ISC_TF(gsskey1 == gsskey2));
static isc_boolean_t
gssapi_isprivate(const dst_key_t *key) {
UNUSED(key);
- return (ISC_TRUE);
+ return (ISC_TRUE);
}
static void
gssapi_destroy(dst_key_t *key) {
- UNUSED(key);
- /* No idea */
+ REQUIRE(key != NULL);
+ dst_gssapi_deletectx(key->mctx, &key->keydata.gssctx);
+ key->keydata.gssctx = NULL;
}
static dst_func_t gssapi_functions = {
- gssapi_createctx,
- gssapi_destroyctx,
+ gssapi_create_signverify_ctx,
+ gssapi_destroy_signverify_ctx,
gssapi_adddata,
gssapi_sign,
gssapi_verify,
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: gssapictx.c,v 1.3 2005/04/29 00:22:47 marka Exp $ */
+/* $Id: gssapictx.c,v 1.4 2006/12/04 01:52:46 marka Exp $ */
#include <config.h>
#include <stdlib.h>
+#include <string.h>
#include <isc/buffer.h>
#include <isc/dir.h>
#include <dns/result.h>
#include <dns/types.h>
#include <dns/keyvalues.h>
+#include <dns/log.h>
#include <dst/gssapi.h>
#include <dst/result.h>
#include "dst_internal.h"
-#ifdef GSSAPI
+/*
+ * If we're using our own SPNEGO implementation (see configure.in),
+ * pull it in now. Otherwise, we just use whatever GSSAPI supplies.
+ */
+#if defined(GSSAPI) && defined(USE_ISC_SPNEGO)
+#include "spnego.h"
+#define gss_accept_sec_context gss_accept_sec_context_spnego
+#define gss_init_sec_context gss_init_sec_context_spnego
+#endif
-#include <gssapi/gssapi.h>
+/*
+ * Solaris8 apparently needs an explicit OID set, and Solaris10 needs
+ * one for anything but Kerberos. Supplying an explicit OID set
+ * doesn't appear to hurt anything in other implementations, so we
+ * always use one. If we're not using our own SPNEGO implementation,
+ * we include SPNEGO's OID.
+ */
+#if defined(GSSAPI)
-#define RETERR(x) do { \
- result = (x); \
- if (result != ISC_R_SUCCESS) \
- goto out; \
+static unsigned char krb5_mech_oid_bytes[] = {
+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x01, 0x02, 0x02
+};
+
+#ifndef USE_ISC_SPNEGO
+static unsigned char spnego_mech_oid_bytes[] = {
+ 0x2b, 0x06, 0x01, 0x05, 0x05, 0x02
+};
+#endif
+
+static gss_OID_desc mech_oid_set_array[] = {
+ { sizeof(krb5_mech_oid_bytes), krb5_mech_oid_bytes },
+#ifndef USE_ISC_SPNEGO
+ { sizeof(spnego_mech_oid_bytes), spnego_mech_oid_bytes },
+#endif
+};
+
+static gss_OID_set_desc mech_oid_set = {
+ sizeof(mech_oid_set_array) / sizeof(*mech_oid_set_array),
+ mech_oid_set_array
+};
+
+#endif
+
+#define REGION_TO_GBUFFER(r, gb) \
+ do { \
+ (gb).length = (r).length; \
+ (gb).value = (r).base; \
} while (0)
-#define REGION_TO_GBUFFER(r, gb) \
- do { \
- (gb).length = (r).length; \
- (gb).value = (r).base; \
+#define GBUFFER_TO_REGION(gb, r) \
+ do { \
+ (r).length = (gb).length; \
+ (r).base = (gb).value; \
} while (0)
-#define GBUFFER_TO_REGION(gb, r) \
- do { \
- (r).length = (gb).length; \
- (r).base = (gb).value; \
+
+#define RETERR(x) do { \
+ result = (x); \
+ if (result != ISC_R_SUCCESS) \
+ goto out; \
} while (0)
+#ifdef GSSAPI
static inline void
name_to_gbuffer(dns_name_t *name, isc_buffer_t *buffer,
gss_buffer_desc *gbuffer)
if (!dns_name_isabsolute(name))
namep = name;
- else {
+ else
+ {
unsigned int labels;
dns_name_init(&tname, NULL);
labels = dns_name_countlabels(name);
REGION_TO_GBUFFER(r, *gbuffer);
}
+static void
+log_cred(const gss_cred_id_t cred) {
+ OM_uint32 gret, minor, lifetime;
+ gss_name_t gname;
+ gss_buffer_desc gbuffer;
+ gss_cred_usage_t usage;
+ const char *usage_text;
+ char buf[1024];
+
+ gret = gss_inquire_cred(&minor, cred, &gname, &lifetime, &usage, NULL);
+ if (gret != GSS_S_COMPLETE) {
+ gss_log(3, "failed gss_inquire_cred: %s",
+ gss_error_tostring(gret, minor, buf, sizeof(buf)));
+ return;
+ }
+
+ gret = gss_display_name(&minor, gname, &gbuffer, NULL);
+ if (gret != GSS_S_COMPLETE)
+ gss_log(3, "failed gss_display_name: %s",
+ gss_error_tostring(gret, minor, buf, sizeof(buf)));
+ else {
+ switch (usage) {
+ case GSS_C_BOTH:
+ usage_text = "GSS_C_BOTH";
+ break;
+ case GSS_C_INITIATE:
+ usage_text = "GSS_C_INITIATE";
+ break;
+ case GSS_C_ACCEPT:
+ usage_text = "GSS_C_ACCEPT";
+ break;
+ default:
+ usage_text = "???";
+ }
+ gss_log(3, "gss cred: \"%s\", %s, %lu", (char *)gbuffer.value,
+ usage_text, (unsigned long)lifetime);
+ }
+
+ if (gret == GSS_S_COMPLETE) {
+ gret = gss_release_buffer(&minor, &gbuffer);
+ if (gret != GSS_S_COMPLETE)
+ gss_log(3, "failed gss_release_buffer: %s",
+ gss_error_tostring(gret, minor, buf,
+ sizeof(buf)));
+ }
+
+ gret = gss_release_name(&minor, &gname);
+ if (gret != GSS_S_COMPLETE)
+ gss_log(3, "failed gss_release_name: %s",
+ gss_error_tostring(gret, minor, buf, sizeof(buf)));
+}
+#endif
+
isc_result_t
-dst_gssapi_acquirecred(dns_name_t *name, isc_boolean_t initiate, void **cred) {
+dst_gssapi_acquirecred(dns_name_t *name, isc_boolean_t initiate,
+ gss_cred_id_t *cred)
+{
+#ifdef GSSAPI
isc_buffer_t namebuf;
gss_name_t gname;
gss_buffer_desc gnamebuf;
gss_OID_set mechs;
OM_uint32 lifetime;
gss_cred_usage_t usage;
+ char buf[1024];
REQUIRE(cred != NULL && *cred == NULL);
+ /*
+ * XXXSRA In theory we could use GSS_C_NT_HOSTBASED_SERVICE
+ * here when we're in the acceptor role, which would let us
+ * default the hostname and use a compiled in default service
+ * name of "DNS", giving one less thing to configure in
+ * named.conf. Unfortunately, this creates a circular
+ * dependency due to DNS-based realm lookup in at least one
+ * GSSAPI implementation (Heimdal). Oh well.
+ */
if (name != NULL) {
isc_buffer_init(&namebuf, array, sizeof(array));
name_to_gbuffer(name, &namebuf, &gnamebuf);
- gret = gss_import_name(&minor, &gnamebuf, GSS_C_NO_OID,
- &gname);
- if (gret != GSS_S_COMPLETE)
+ gret = gss_import_name(&minor, &gnamebuf,
+ GSS_C_NO_OID, &gname);
+ if (gret != GSS_S_COMPLETE) {
+ gss_log(3, "failed gss_import_name: %s",
+ gss_error_tostring(gret, minor, buf,
+ sizeof(buf)));
return (ISC_R_FAILURE);
+ }
} else
gname = NULL;
+ /* Get the credentials. */
+ if (gname != NULL)
+ gss_log(3, "acquiring credentials for %s",
+ (char *)gnamebuf.value);
+ else {
+ /* XXXDCL does this even make any sense? */
+ gss_log(3, "acquiring credentials for ?");
+ }
+
if (initiate)
usage = GSS_C_INITIATE;
else
usage = GSS_C_ACCEPT;
gret = gss_acquire_cred(&minor, gname, GSS_C_INDEFINITE,
- GSS_C_NO_OID_SET, usage,
- cred, &mechs, &lifetime);
- if (gret != GSS_S_COMPLETE)
+ &mech_oid_set,
+ usage, cred, &mechs, &lifetime);
+
+ if (gret != GSS_S_COMPLETE) {
+ gss_log(3, "failed to acquire %s credentials for %s: %s",
+ initiate ? "initiate" : "accept",
+ (char *)gnamebuf.value,
+ gss_error_tostring(gret, minor, buf, sizeof(buf)));
return (ISC_R_FAILURE);
+ }
+
+ gss_log(4, "acquired %s credentials for %s",
+ initiate ? "initiate" : "accept",
+ (char *)gnamebuf.value);
+
+ log_cred(*cred);
+
return (ISC_R_SUCCESS);
+#else
+ UNUSED(name);
+ UNUSED(initiate);
+ UNUSED(cred);
+
+ return (ISC_R_NOTIMPLEMENTED);
+#endif
+}
+
+isc_boolean_t
+dst_gssapi_identitymatchesrealmkrb5(dns_name_t *signer, dns_name_t *name,
+ dns_name_t *realm)
+{
+#ifdef GSSAPI
+ char sbuf[DNS_NAME_FORMATSIZE];
+ char nbuf[DNS_NAME_FORMATSIZE];
+ char rbuf[DNS_NAME_FORMATSIZE];
+ char *sname;
+ char *rname;
+
+ /*
+ * It is far, far easier to write the names we are looking at into
+ * a string, and do string operations on them.
+ */
+ dns_name_format(signer, sbuf, sizeof(sbuf));
+ if (name != NULL)
+ dns_name_format(name, nbuf, sizeof(nbuf));
+ dns_name_format(realm, rbuf, sizeof(rbuf));
+
+ /*
+ * Find the realm portion. This is the part after the @. If it
+ * does not exist, we don't have something we like, so we fail our
+ * compare.
+ */
+ rname = strstr(sbuf, "\\@");
+ if (rname == NULL)
+ return (isc_boolean_false);
+ *rname = '\0';
+ rname += 2;
+
+ /*
+ * Find the host portion of the signer's name. We do this by
+ * searching for the first / character. We then check to make
+ * certain the instance name is "host"
+ *
+ * This will work for
+ * host/example.com@EXAMPLE.COM
+ */
+ sname = strchr(sbuf, '/');
+ if (sname == NULL)
+ return (isc_boolean_false);
+ *sname = '\0';
+ sname++;
+ if (strcmp(sbuf, "host") != 0)
+ return (isc_boolean_false);
+
+ /*
+ * Now, we do a simple comparison between the name and the realm.
+ */
+ if (name != NULL) {
+ if ((strcasecmp(sname, nbuf) == 0)
+ && (strcmp(rname, rbuf) == 0))
+ return (isc_boolean_true);
+ } else {
+ if (strcmp(rname, rbuf) == 0)
+ return (isc_boolean_true);
+ }
+
+ return (isc_boolean_false);
+#else
+ UNUSED(signer);
+ UNUSED(name);
+ UNUSED(realm);
+ return (isc_boolean_false);
+#endif
+}
+
+isc_boolean_t
+dst_gssapi_identitymatchesrealmms(dns_name_t *signer, dns_name_t *name,
+ dns_name_t *realm)
+{
+#ifdef GSSAPI
+ char sbuf[DNS_NAME_FORMATSIZE];
+ char nbuf[DNS_NAME_FORMATSIZE];
+ char rbuf[DNS_NAME_FORMATSIZE];
+ char *sname;
+ char *nname;
+ char *rname;
+
+ /*
+ * It is far, far easier to write the names we are looking at into
+ * a string, and do string operations on them.
+ */
+ dns_name_format(signer, sbuf, sizeof(sbuf));
+ if (name != NULL)
+ dns_name_format(name, nbuf, sizeof(nbuf));
+ dns_name_format(realm, rbuf, sizeof(rbuf));
+
+ /*
+ * Find the realm portion. This is the part after the @. If it
+ * does not exist, we don't have something we like, so we fail our
+ * compare.
+ */
+ rname = strstr(sbuf, "\\@");
+ if (rname == NULL)
+ return (isc_boolean_false);
+ sname = strstr(sbuf, "\\$");
+ if (sname == NULL)
+ return (isc_boolean_false);
+
+ /*
+ * Verify that the $ and @ follow one another.
+ */
+ if (rname - sname != 2)
+ return (isc_boolean_false);
+
+ /*
+ * Find the host portion of the signer's name. Zero out the $ so
+ * it terminates the signer's name, and skip past the @ for
+ * the realm.
+ *
+ * All service principals in Microsoft format seem to be in
+ * machinename$@EXAMPLE.COM
+ * format.
+ */
+ *rname = '\0';
+ rname += 2;
+ *sname = '\0';
+ sname = sbuf;
+
+ /*
+ * Find the first . in the target name, and make it the end of
+ * the string. The rest of the name has to match the realm.
+ */
+ if (name != NULL) {
+ nname = strchr(nbuf, '.');
+ if (nname == NULL)
+ return (isc_boolean_false);
+ *nname++ = '\0';
+ }
+
+ /*
+ * Now, we do a simple comparison between the name and the realm.
+ */
+ if (name != NULL) {
+ if ((strcasecmp(sname, nbuf) == 0)
+ && (strcmp(rname, rbuf) == 0)
+ && (strcasecmp(nname, rbuf) == 0))
+ return (isc_boolean_true);
+ } else {
+ if (strcmp(rname, rbuf) == 0)
+ return (isc_boolean_true);
+ }
+
+
+ return (isc_boolean_false);
+#else
+ UNUSED(signer);
+ UNUSED(name);
+ UNUSED(realm);
+ return (isc_boolean_false);
+#endif
+}
+
+isc_result_t
+dst_gssapi_releasecred(gss_cred_id_t *cred) {
+#ifdef GSSAPI
+ OM_uint32 gret, minor;
+ char buf[1024];
+
+ REQUIRE(cred != NULL && *cred != NULL);
+
+ gret = gss_release_cred(&minor, cred);
+ if (gret != GSS_S_COMPLETE) {
+ /* Log the error, but still free the credential's memory */
+ gss_log(3, "failed releasing credential: %s",
+ gss_error_tostring(gret, minor, buf, sizeof(buf)));
+ }
+ *cred = NULL;
+
+ return(ISC_R_SUCCESS);
+#else
+ UNUSED(cred);
+
+ return (ISC_R_NOTIMPLEMENTED);
+#endif
}
isc_result_t
-dst_gssapi_initctx(dns_name_t *name, void *cred,
- isc_region_t *intoken, isc_buffer_t *outtoken,
- void **context)
+dst_gssapi_initctx(dns_name_t *name, isc_buffer_t *intoken,
+ isc_buffer_t *outtoken, gss_ctx_id_t *gssctx)
{
+#ifdef GSSAPI
isc_region_t r;
isc_buffer_t namebuf;
- gss_buffer_desc gnamebuf, gintoken, *gintokenp, gouttoken;
- OM_uint32 gret, minor, flags, ret_flags;
- gss_OID mech_type, ret_mech_type;
- OM_uint32 lifetime;
gss_name_t gname;
+ OM_uint32 gret, minor, ret_flags, flags;
+ gss_buffer_desc gintoken, *gintokenp, gouttoken;
isc_result_t result;
+ gss_buffer_desc gnamebuf;
unsigned char array[DNS_NAME_MAXTEXT + 1];
+ char buf[1024];
+ /* Client must pass us a valid gss_ctx_id_t here */
+ REQUIRE(gssctx != NULL);
+
isc_buffer_init(&namebuf, array, sizeof(array));
name_to_gbuffer(name, &namebuf, &gnamebuf);
+
+ /* Get the name as a GSS name */
gret = gss_import_name(&minor, &gnamebuf, GSS_C_NO_OID, &gname);
- if (gret != GSS_S_COMPLETE)
- return (ISC_R_FAILURE);
+ if (gret != GSS_S_COMPLETE) {
+ result = ISC_R_FAILURE;
+ goto out;
+ }
if (intoken != NULL) {
+ /* Don't call gss_release_buffer for gintoken! */
REGION_TO_GBUFFER(*intoken, gintoken);
gintokenp = &gintoken;
- } else
+ } else {
gintokenp = NULL;
+ }
- if (*context == NULL)
- *context = GSS_C_NO_CONTEXT;
flags = GSS_C_REPLAY_FLAG | GSS_C_MUTUAL_FLAG | GSS_C_DELEG_FLAG |
- GSS_C_SEQUENCE_FLAG | GSS_C_CONF_FLAG | GSS_C_INTEG_FLAG;
- mech_type = GSS_C_NO_OID;
-
- gret = gss_init_sec_context(&minor, cred, context, gname,
- mech_type, flags, 0,
- GSS_C_NO_CHANNEL_BINDINGS, gintokenp,
- &ret_mech_type, &gouttoken, &ret_flags,
- &lifetime);
- if (gret != GSS_S_COMPLETE && gret != GSS_S_CONTINUE_NEEDED)
- return (ISC_R_FAILURE);
+ GSS_C_SEQUENCE_FLAG | GSS_C_INTEG_FLAG;
+
+ gret = gss_init_sec_context(&minor, GSS_C_NO_CREDENTIAL, gssctx,
+ gname, GSS_SPNEGO_MECHANISM, flags,
+ 0, NULL, gintokenp,
+ NULL, &gouttoken, &ret_flags, NULL);
+
+ if (gret != GSS_S_COMPLETE && gret != GSS_S_CONTINUE_NEEDED) {
+ gss_log(3, "Failure initiating security context");
+ gss_log(3, "%s", gss_error_tostring(gret, minor,
+ buf, sizeof(buf)));
+ result = ISC_R_FAILURE;
+ goto out;
+ }
+
+ /*
+ * XXXSRA Not handled yet: RFC 3645 3.1.1: check ret_flags
+ * MUTUAL and INTEG flags, fail if either not set.
+ */
GBUFFER_TO_REGION(gouttoken, r);
RETERR(isc_buffer_copyregion(outtoken, &r));
+ (void)gss_release_name(&minor, &gname);
+ (void)gss_release_buffer(&minor, &gouttoken);
+
if (gret == GSS_S_COMPLETE)
- return (ISC_R_SUCCESS);
+ result = ISC_R_SUCCESS;
else
- return (DNS_R_CONTINUE);
+ result = DNS_R_CONTINUE;
out:
- return (result);
+ return (result);
+#else
+ UNUSED(name);
+ UNUSED(intoken);
+ UNUSED(outtoken);
+ UNUSED(gssctx);
+
+ return (ISC_R_NOTIMPLEMENTED);
+#endif
}
isc_result_t
-dst_gssapi_acceptctx(dns_name_t *name, void *cred,
+dst_gssapi_acceptctx(gss_cred_id_t cred,
isc_region_t *intoken, isc_buffer_t *outtoken,
- void **context)
+ gss_ctx_id_t *ctxout, dns_name_t *principal,
+ isc_mem_t *mctx)
{
+#ifdef GSSAPI
isc_region_t r;
isc_buffer_t namebuf;
gss_buffer_desc gnamebuf, gintoken, gouttoken;
- OM_uint32 gret, minor, flags;
- gss_OID mech_type;
- OM_uint32 lifetime;
- gss_cred_id_t delegated_cred;
- gss_name_t gname;
+ OM_uint32 gret, minor;
+ gss_ctx_id_t context = GSS_C_NO_CONTEXT;
+ gss_name_t gname = NULL;
isc_result_t result;
- unsigned char array[DNS_NAME_MAXTEXT + 1];
+ char buf[1024];
- isc_buffer_init(&namebuf, array, sizeof(array));
- name_to_gbuffer(name, &namebuf, &gnamebuf);
- gret = gss_import_name(&minor, &gnamebuf, GSS_C_NO_OID, &gname);
- if (gret != GSS_S_COMPLETE)
- return (ISC_R_FAILURE);
+ log_cred(cred);
REGION_TO_GBUFFER(*intoken, gintoken);
- if (*context == NULL)
- *context = GSS_C_NO_CONTEXT;
+ if (*ctxout == NULL)
+ context = GSS_C_NO_CONTEXT;
+ else
+ context = *ctxout;
+
+ gret = gss_accept_sec_context(&minor, &context, cred, &gintoken,
+ GSS_C_NO_CHANNEL_BINDINGS, &gname,
+ NULL, &gouttoken, NULL, NULL, NULL);
+
+ result = ISC_R_FAILURE;
+
+ switch (gret) {
+ case GSS_S_COMPLETE:
+ result = ISC_R_SUCCESS;
+ break;
+ case GSS_S_CONTINUE_NEEDED:
+ result = DNS_R_CONTINUE;
+ break;
+ case GSS_S_DEFECTIVE_TOKEN:
+ case GSS_S_DEFECTIVE_CREDENTIAL:
+ case GSS_S_BAD_SIG:
+ case GSS_S_DUPLICATE_TOKEN:
+ case GSS_S_OLD_TOKEN:
+ case GSS_S_NO_CRED:
+ case GSS_S_CREDENTIALS_EXPIRED:
+ case GSS_S_BAD_BINDINGS:
+ case GSS_S_NO_CONTEXT:
+ case GSS_S_BAD_MECH:
+ case GSS_S_FAILURE:
+ result = DNS_R_INVALIDTKEY;
+ /* fall through */
+ default:
+ gss_log(3, "failed gss_accept_sec_context: %s",
+ gss_error_tostring(gret, minor, buf, sizeof(buf)));
+ return (result);
+ }
- gret = gss_accept_sec_context(&minor, context, cred, &gintoken,
- GSS_C_NO_CHANNEL_BINDINGS, gname,
- &mech_type, &gouttoken, &flags,
- &lifetime, &delegated_cred);
- if (gret != GSS_S_COMPLETE)
- return (ISC_R_FAILURE);
+ INSIST(outtoken != NULL && !ISC_BUFFER_VALID(outtoken));
- GBUFFER_TO_REGION(gouttoken, r);
- RETERR(isc_buffer_copyregion(outtoken, &r));
+ if (gouttoken.length > 0) {
+ void *o = isc_mem_get(mctx, gouttoken.length);
+ if (o == NULL)
+ RETERR(ISC_R_NOMEMORY);
+ isc_buffer_init(outtoken, o, gouttoken.length);
+ GBUFFER_TO_REGION(gouttoken, r);
+ RETERR(isc_buffer_copyregion(outtoken, &r));
+ }
- return (ISC_R_SUCCESS);
+ if (gret == GSS_S_COMPLETE) {
+ gret = gss_display_name(&minor, gname, &gnamebuf, NULL);
+ if (gret != GSS_S_COMPLETE) {
+ gss_log(3, "failed gss_display_name: %s",
+ gss_error_tostring(gret, minor,
+ buf, sizeof(buf)));
+ RETERR(ISC_R_FAILURE);
+ }
+
+ /*
+ * Compensate for a bug in Solaris8's implementation
+ * of gss_display_name(). Should be harmless in any
+ * case, since principal names really should not
+ * contain null characters.
+ */
+ if (gnamebuf.length > 0 &&
+ ((char *)gnamebuf.value)[gnamebuf.length - 1] == '\0')
+ gnamebuf.length--;
+
+ gss_log(3, "gss-api source name (accept) is %.*s",
+ (int)gnamebuf.length, (char *)gnamebuf.value);
+
+ GBUFFER_TO_REGION(gnamebuf, r);
+ isc_buffer_init(&namebuf, r.base, r.length);
+ isc_buffer_add(&namebuf, r.length);
+
+ RETERR(dns_name_fromtext(principal, &namebuf, dns_rootname,
+ ISC_FALSE, NULL));
+
+ gret = gss_release_buffer(&minor, &gnamebuf);
+ if (gret != GSS_S_COMPLETE)
+ gss_log(3, "failed gss_release_buffer: %s",
+ gss_error_tostring(gret, minor, buf,
+ sizeof(buf)));
+ }
+
+ *ctxout = context;
out:
- return (result);
-}
+ if (gname != NULL) {
+ gret = gss_release_name(&minor, &gname);
+ if (gret != GSS_S_COMPLETE)
+ gss_log(3, "failed gss_release_name: %s",
+ gss_error_tostring(gret, minor, buf,
+ sizeof(buf)));
+ }
+ return (result);
#else
-
-isc_result_t
-dst_gssapi_acquirecred(dns_name_t *name, isc_boolean_t initiate, void **cred) {
- UNUSED(name);
- UNUSED(initiate);
- UNUSED(cred);
- return (ISC_R_NOTIMPLEMENTED);
-}
-
-isc_result_t
-dst_gssapi_initctx(dns_name_t *name, void *cred,
- isc_region_t *intoken, isc_buffer_t *outtoken,
- void **context)
-{
- UNUSED(name);
UNUSED(cred);
UNUSED(intoken);
UNUSED(outtoken);
- UNUSED(context);
+ UNUSED(ctxout);
+ UNUSED(principal);
+ UNUSED(mctx);
+
return (ISC_R_NOTIMPLEMENTED);
+#endif
}
isc_result_t
-dst_gssapi_acceptctx(dns_name_t *name, void *cred,
- isc_region_t *intoken, isc_buffer_t *outtoken,
- void **context)
+dst_gssapi_deletectx(isc_mem_t *mctx, gss_ctx_id_t *gssctx)
{
- UNUSED(name);
- UNUSED(cred);
- UNUSED(intoken);
- UNUSED(outtoken);
- UNUSED(context);
+#ifdef GSSAPI
+ OM_uint32 gret, minor;
+ char buf[1024];
+
+ UNUSED(mctx);
+
+ REQUIRE(gssctx != NULL && *gssctx != NULL);
+
+ /* Delete the context from the GSS provider */
+ gret = gss_delete_sec_context(&minor, gssctx, GSS_C_NO_BUFFER);
+ if (gret != GSS_S_COMPLETE) {
+ /* Log the error, but still free the context's memory */
+ gss_log(3, "Failure deleting security context %s",
+ gss_error_tostring(gret, minor, buf, sizeof(buf)));
+ }
+ return(ISC_R_SUCCESS);
+#else
+ UNUSED(mctx);
+ UNUSED(gssctx);
return (ISC_R_NOTIMPLEMENTED);
+#endif
}
+char *
+gss_error_tostring(isc_uint32_t major, isc_uint32_t minor,
+ char *buf, size_t buflen) {
+#ifdef GSSAPI
+ gss_buffer_desc msg_minor, msg_major;
+ OM_uint32 msg_ctx, minor_stat;
+
+ /* Handle major status */
+ msg_ctx = 0;
+ (void)gss_display_status(&minor_stat, major, GSS_C_GSS_CODE,
+ GSS_C_NULL_OID, &msg_ctx, &msg_major);
+
+ /* Handle minor status */
+ msg_ctx = 0;
+ (void)gss_display_status(&minor_stat, minor, GSS_C_MECH_CODE,
+ GSS_C_NULL_OID, &msg_ctx, &msg_minor);
+
+ snprintf(buf, buflen, "GSSAPI error: Major = %s, Minor = %s.",
+ (char *)msg_major.value, (char *)msg_minor.value);
+
+ (void)gss_release_buffer(&minor_stat, &msg_major);
+ (void)gss_release_buffer(&minor_stat, &msg_minor);
+ return(buf);
+#else
+ snprintf(buf, buflen, "GSSAPI error: Major = %u, Minor = %u.",
+ major, minor);
+
+ return (buf);
#endif
+}
+
+void
+gss_log(int level, const char *fmt, ...) {
+ va_list ap;
+
+ va_start(ap, fmt);
+ isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_TKEY, ISC_LOG_DEBUG(level), fmt, ap);
+ va_end(ap);
+}
/*! \file */
/*
* Principal Author: Brian Wellington
- * $Id: hmac_link.c,v 1.5 2006/01/27 23:57:46 marka Exp $
+ * $Id: hmac_link.c,v 1.6 2006/12/04 01:52:46 marka Exp $
*/
#include <config.h>
static isc_result_t hmacmd5_fromdns(dst_key_t *key, isc_buffer_t *data);
-typedef struct hmackey {
+struct dst_hmacmd5_key {
unsigned char key[HMAC_LEN];
-} HMAC_Key;
+};
static isc_result_t
getkeybits(dst_key_t *key, struct dst_private_element *element) {
static isc_result_t
hmacmd5_createctx(dst_key_t *key, dst_context_t *dctx) {
isc_hmacmd5_t *hmacmd5ctx;
- HMAC_Key *hkey = key->opaque;
+ dst_hmacmd5_key_t *hkey = key->keydata.hmacmd5;
hmacmd5ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacmd5_t));
if (hmacmd5ctx == NULL)
return (ISC_R_NOMEMORY);
isc_hmacmd5_init(hmacmd5ctx, hkey->key, HMAC_LEN);
- dctx->opaque = hmacmd5ctx;
+ dctx->ctxdata.hmacmd5ctx = hmacmd5ctx;
return (ISC_R_SUCCESS);
}
static void
hmacmd5_destroyctx(dst_context_t *dctx) {
- isc_hmacmd5_t *hmacmd5ctx = dctx->opaque;
+ isc_hmacmd5_t *hmacmd5ctx = dctx->ctxdata.hmacmd5ctx;
if (hmacmd5ctx != NULL) {
isc_hmacmd5_invalidate(hmacmd5ctx);
isc_mem_put(dctx->mctx, hmacmd5ctx, sizeof(isc_hmacmd5_t));
- dctx->opaque = NULL;
+ dctx->ctxdata.hmacmd5ctx = NULL;
}
}
static isc_result_t
hmacmd5_adddata(dst_context_t *dctx, const isc_region_t *data) {
- isc_hmacmd5_t *hmacmd5ctx = dctx->opaque;
+ isc_hmacmd5_t *hmacmd5ctx = dctx->ctxdata.hmacmd5ctx;
isc_hmacmd5_update(hmacmd5ctx, data->base, data->length);
return (ISC_R_SUCCESS);
static isc_result_t
hmacmd5_sign(dst_context_t *dctx, isc_buffer_t *sig) {
- isc_hmacmd5_t *hmacmd5ctx = dctx->opaque;
+ isc_hmacmd5_t *hmacmd5ctx = dctx->ctxdata.hmacmd5ctx;
unsigned char *digest;
if (isc_buffer_availablelength(sig) < ISC_MD5_DIGESTLENGTH)
static isc_result_t
hmacmd5_verify(dst_context_t *dctx, const isc_region_t *sig) {
- isc_hmacmd5_t *hmacmd5ctx = dctx->opaque;
+ isc_hmacmd5_t *hmacmd5ctx = dctx->ctxdata.hmacmd5ctx;
if (sig->length > ISC_MD5_DIGESTLENGTH)
return (DST_R_VERIFYFAILURE);
static isc_boolean_t
hmacmd5_compare(const dst_key_t *key1, const dst_key_t *key2) {
- HMAC_Key *hkey1, *hkey2;
+ dst_hmacmd5_key_t *hkey1, *hkey2;
- hkey1 = (HMAC_Key *)key1->opaque;
- hkey2 = (HMAC_Key *)key2->opaque;
+ hkey1 = key1->keydata.hmacmd5;
+ hkey2 = key2->keydata.hmacmd5;
if (hkey1 == NULL && hkey2 == NULL)
return (ISC_TRUE);
static void
hmacmd5_destroy(dst_key_t *key) {
- HMAC_Key *hkey = key->opaque;
- memset(hkey, 0, sizeof(HMAC_Key));
- isc_mem_put(key->mctx, hkey, sizeof(HMAC_Key));
- key->opaque = NULL;
+ dst_hmacmd5_key_t *hkey = key->keydata.hmacmd5;
+ memset(hkey, 0, sizeof(dst_hmacmd5_key_t));
+ isc_mem_put(key->mctx, hkey, sizeof(dst_hmacmd5_key_t));
+ key->keydata.hmacmd5 = NULL;
}
static isc_result_t
hmacmd5_todns(const dst_key_t *key, isc_buffer_t *data) {
- HMAC_Key *hkey;
+ dst_hmacmd5_key_t *hkey;
unsigned int bytes;
- REQUIRE(key->opaque != NULL);
+ REQUIRE(key->keydata.hmacmd5 != NULL);
- hkey = (HMAC_Key *) key->opaque;
+ hkey = key->keydata.hmacmd5;
bytes = (key->key_size + 7) / 8;
if (isc_buffer_availablelength(data) < bytes)
static isc_result_t
hmacmd5_fromdns(dst_key_t *key, isc_buffer_t *data) {
- HMAC_Key *hkey;
+ dst_hmacmd5_key_t *hkey;
int keylen;
isc_region_t r;
isc_md5_t md5ctx;
if (r.length == 0)
return (ISC_R_SUCCESS);
- hkey = (HMAC_Key *) isc_mem_get(key->mctx, sizeof(HMAC_Key));
+ hkey = isc_mem_get(key->mctx, sizeof(dst_hmacmd5_key_t));
if (hkey == NULL)
return (ISC_R_NOMEMORY);
}
key->key_size = keylen * 8;
- key->opaque = hkey;
+ key->keydata.hmacmd5 = hkey;
return (ISC_R_SUCCESS);
}
static isc_result_t
hmacmd5_tofile(const dst_key_t *key, const char *directory) {
int cnt = 0;
- HMAC_Key *hkey;
+ dst_hmacmd5_key_t *hkey;
dst_private_t priv;
int bytes = (key->key_size + 7) / 8;
unsigned char buf[2];
- if (key->opaque == NULL)
+ if (key->keydata.hmacmd5 == NULL)
return (DST_R_NULLKEY);
- hkey = (HMAC_Key *) key->opaque;
+ hkey = key->keydata.hmacmd5;
priv.elements[cnt].tag = TAG_HMACMD5_KEY;
priv.elements[cnt].length = bytes;
static isc_result_t hmacsha1_fromdns(dst_key_t *key, isc_buffer_t *data);
-typedef struct {
+struct dst_hmacsha1_key {
unsigned char key[ISC_SHA1_DIGESTLENGTH];
-} HMACSHA1_Key;
+};
static isc_result_t
hmacsha1_createctx(dst_key_t *key, dst_context_t *dctx) {
isc_hmacsha1_t *hmacsha1ctx;
- HMACSHA1_Key *hkey = key->opaque;
+ dst_hmacsha1_key_t *hkey = key->keydata.hmacsha1;
hmacsha1ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacsha1_t));
if (hmacsha1ctx == NULL)
return (ISC_R_NOMEMORY);
isc_hmacsha1_init(hmacsha1ctx, hkey->key, ISC_SHA1_DIGESTLENGTH);
- dctx->opaque = hmacsha1ctx;
+ dctx->ctxdata.hmacsha1ctx = hmacsha1ctx;
return (ISC_R_SUCCESS);
}
static void
hmacsha1_destroyctx(dst_context_t *dctx) {
- isc_hmacsha1_t *hmacsha1ctx = dctx->opaque;
+ isc_hmacsha1_t *hmacsha1ctx = dctx->ctxdata.hmacsha1ctx;
if (hmacsha1ctx != NULL) {
isc_hmacsha1_invalidate(hmacsha1ctx);
isc_mem_put(dctx->mctx, hmacsha1ctx, sizeof(isc_hmacsha1_t));
- dctx->opaque = NULL;
+ dctx->ctxdata.hmacsha1ctx = NULL;
}
}
static isc_result_t
hmacsha1_adddata(dst_context_t *dctx, const isc_region_t *data) {
- isc_hmacsha1_t *hmacsha1ctx = dctx->opaque;
+ isc_hmacsha1_t *hmacsha1ctx = dctx->ctxdata.hmacsha1ctx;
isc_hmacsha1_update(hmacsha1ctx, data->base, data->length);
return (ISC_R_SUCCESS);
static isc_result_t
hmacsha1_sign(dst_context_t *dctx, isc_buffer_t *sig) {
- isc_hmacsha1_t *hmacsha1ctx = dctx->opaque;
+ isc_hmacsha1_t *hmacsha1ctx = dctx->ctxdata.hmacsha1ctx;
unsigned char *digest;
if (isc_buffer_availablelength(sig) < ISC_SHA1_DIGESTLENGTH)
static isc_result_t
hmacsha1_verify(dst_context_t *dctx, const isc_region_t *sig) {
- isc_hmacsha1_t *hmacsha1ctx = dctx->opaque;
+ isc_hmacsha1_t *hmacsha1ctx = dctx->ctxdata.hmacsha1ctx;
if (sig->length > ISC_SHA1_DIGESTLENGTH || sig->length == 0)
return (DST_R_VERIFYFAILURE);
static isc_boolean_t
hmacsha1_compare(const dst_key_t *key1, const dst_key_t *key2) {
- HMACSHA1_Key *hkey1, *hkey2;
+ dst_hmacsha1_key_t *hkey1, *hkey2;
- hkey1 = (HMACSHA1_Key *)key1->opaque;
- hkey2 = (HMACSHA1_Key *)key2->opaque;
+ hkey1 = key1->keydata.hmacsha1;
+ hkey2 = key2->keydata.hmacsha1;
if (hkey1 == NULL && hkey2 == NULL)
return (ISC_TRUE);
static void
hmacsha1_destroy(dst_key_t *key) {
- HMACSHA1_Key *hkey = key->opaque;
- memset(hkey, 0, sizeof(HMACSHA1_Key));
- isc_mem_put(key->mctx, hkey, sizeof(HMACSHA1_Key));
- key->opaque = NULL;
+ dst_hmacsha1_key_t *hkey = key->keydata.hmacsha1;
+ memset(hkey, 0, sizeof(dst_hmacsha1_key_t));
+ isc_mem_put(key->mctx, hkey, sizeof(dst_hmacsha1_key_t));
+ key->keydata.hmacsha1 = NULL;
}
static isc_result_t
hmacsha1_todns(const dst_key_t *key, isc_buffer_t *data) {
- HMACSHA1_Key *hkey;
+ dst_hmacsha1_key_t *hkey;
unsigned int bytes;
- REQUIRE(key->opaque != NULL);
+ REQUIRE(key->keydata.hmacsha1 != NULL);
- hkey = (HMACSHA1_Key *) key->opaque;
+ hkey = key->keydata.hmacsha1;
bytes = (key->key_size + 7) / 8;
if (isc_buffer_availablelength(data) < bytes)
static isc_result_t
hmacsha1_fromdns(dst_key_t *key, isc_buffer_t *data) {
- HMACSHA1_Key *hkey;
+ dst_hmacsha1_key_t *hkey;
int keylen;
isc_region_t r;
isc_sha1_t sha1ctx;
if (r.length == 0)
return (ISC_R_SUCCESS);
- hkey = (HMACSHA1_Key *) isc_mem_get(key->mctx, sizeof(HMACSHA1_Key));
+ hkey = isc_mem_get(key->mctx, sizeof(dst_hmacsha1_key_t));
if (hkey == NULL)
return (ISC_R_NOMEMORY);
}
key->key_size = keylen * 8;
- key->opaque = hkey;
+ key->keydata.hmacsha1 = hkey;
return (ISC_R_SUCCESS);
}
static isc_result_t
hmacsha1_tofile(const dst_key_t *key, const char *directory) {
int cnt = 0;
- HMACSHA1_Key *hkey;
+ dst_hmacsha1_key_t *hkey;
dst_private_t priv;
int bytes = (key->key_size + 7) / 8;
unsigned char buf[2];
- if (key->opaque == NULL)
+ if (key->keydata.hmacsha1 == NULL)
return (DST_R_NULLKEY);
- hkey = (HMACSHA1_Key *) key->opaque;
+ hkey = key->keydata.hmacsha1;
priv.elements[cnt].tag = TAG_HMACSHA1_KEY;
priv.elements[cnt].length = bytes;
static isc_result_t hmacsha224_fromdns(dst_key_t *key, isc_buffer_t *data);
-typedef struct {
+struct dst_hmacsha224_key {
unsigned char key[ISC_SHA224_DIGESTLENGTH];
-} HMACSHA224_Key;
+};
static isc_result_t
hmacsha224_createctx(dst_key_t *key, dst_context_t *dctx) {
isc_hmacsha224_t *hmacsha224ctx;
- HMACSHA224_Key *hkey = key->opaque;
+ dst_hmacsha224_key_t *hkey = key->keydata.hmacsha224;
hmacsha224ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacsha224_t));
if (hmacsha224ctx == NULL)
return (ISC_R_NOMEMORY);
isc_hmacsha224_init(hmacsha224ctx, hkey->key, ISC_SHA224_DIGESTLENGTH);
- dctx->opaque = hmacsha224ctx;
+ dctx->ctxdata.hmacsha224ctx = hmacsha224ctx;
return (ISC_R_SUCCESS);
}
static void
hmacsha224_destroyctx(dst_context_t *dctx) {
- isc_hmacsha224_t *hmacsha224ctx = dctx->opaque;
+ isc_hmacsha224_t *hmacsha224ctx = dctx->ctxdata.hmacsha224ctx;
if (hmacsha224ctx != NULL) {
isc_hmacsha224_invalidate(hmacsha224ctx);
isc_mem_put(dctx->mctx, hmacsha224ctx, sizeof(isc_hmacsha224_t));
- dctx->opaque = NULL;
+ dctx->ctxdata.hmacsha224ctx = NULL;
}
}
static isc_result_t
hmacsha224_adddata(dst_context_t *dctx, const isc_region_t *data) {
- isc_hmacsha224_t *hmacsha224ctx = dctx->opaque;
+ isc_hmacsha224_t *hmacsha224ctx = dctx->ctxdata.hmacsha224ctx;
isc_hmacsha224_update(hmacsha224ctx, data->base, data->length);
return (ISC_R_SUCCESS);
static isc_result_t
hmacsha224_sign(dst_context_t *dctx, isc_buffer_t *sig) {
- isc_hmacsha224_t *hmacsha224ctx = dctx->opaque;
+ isc_hmacsha224_t *hmacsha224ctx = dctx->ctxdata.hmacsha224ctx;
unsigned char *digest;
if (isc_buffer_availablelength(sig) < ISC_SHA224_DIGESTLENGTH)
static isc_result_t
hmacsha224_verify(dst_context_t *dctx, const isc_region_t *sig) {
- isc_hmacsha224_t *hmacsha224ctx = dctx->opaque;
+ isc_hmacsha224_t *hmacsha224ctx = dctx->ctxdata.hmacsha224ctx;
if (sig->length > ISC_SHA224_DIGESTLENGTH || sig->length == 0)
return (DST_R_VERIFYFAILURE);
static isc_boolean_t
hmacsha224_compare(const dst_key_t *key1, const dst_key_t *key2) {
- HMACSHA224_Key *hkey1, *hkey2;
+ dst_hmacsha224_key_t *hkey1, *hkey2;
- hkey1 = (HMACSHA224_Key *)key1->opaque;
- hkey2 = (HMACSHA224_Key *)key2->opaque;
+ hkey1 = key1->keydata.hmacsha224;
+ hkey2 = key2->keydata.hmacsha224;
if (hkey1 == NULL && hkey2 == NULL)
return (ISC_TRUE);
static void
hmacsha224_destroy(dst_key_t *key) {
- HMACSHA224_Key *hkey = key->opaque;
- memset(hkey, 0, sizeof(HMACSHA224_Key));
- isc_mem_put(key->mctx, hkey, sizeof(HMACSHA224_Key));
- key->opaque = NULL;
+ dst_hmacsha224_key_t *hkey = key->keydata.hmacsha224;
+ memset(hkey, 0, sizeof(dst_hmacsha224_key_t));
+ isc_mem_put(key->mctx, hkey, sizeof(dst_hmacsha224_key_t));
+ key->keydata.hmacsha224 = NULL;
}
static isc_result_t
hmacsha224_todns(const dst_key_t *key, isc_buffer_t *data) {
- HMACSHA224_Key *hkey;
+ dst_hmacsha224_key_t *hkey;
unsigned int bytes;
- REQUIRE(key->opaque != NULL);
+ REQUIRE(key->keydata.hmacsha224 != NULL);
- hkey = (HMACSHA224_Key *) key->opaque;
+ hkey = key->keydata.hmacsha224;
bytes = (key->key_size + 7) / 8;
if (isc_buffer_availablelength(data) < bytes)
static isc_result_t
hmacsha224_fromdns(dst_key_t *key, isc_buffer_t *data) {
- HMACSHA224_Key *hkey;
+ dst_hmacsha224_key_t *hkey;
int keylen;
isc_region_t r;
isc_sha224_t sha224ctx;
if (r.length == 0)
return (ISC_R_SUCCESS);
- hkey = (HMACSHA224_Key *) isc_mem_get(key->mctx, sizeof(HMACSHA224_Key));
+ hkey = isc_mem_get(key->mctx, sizeof(dst_hmacsha224_key_t));
if (hkey == NULL)
return (ISC_R_NOMEMORY);
}
key->key_size = keylen * 8;
- key->opaque = hkey;
+ key->keydata.hmacsha224 = hkey;
return (ISC_R_SUCCESS);
}
static isc_result_t
hmacsha224_tofile(const dst_key_t *key, const char *directory) {
int cnt = 0;
- HMACSHA224_Key *hkey;
+ dst_hmacsha224_key_t *hkey;
dst_private_t priv;
int bytes = (key->key_size + 7) / 8;
unsigned char buf[2];
- if (key->opaque == NULL)
+ if (key->keydata.hmacsha224 == NULL)
return (DST_R_NULLKEY);
- hkey = (HMACSHA224_Key *) key->opaque;
+ hkey = key->keydata.hmacsha224;
priv.elements[cnt].tag = TAG_HMACSHA224_KEY;
priv.elements[cnt].length = bytes;
static isc_result_t hmacsha256_fromdns(dst_key_t *key, isc_buffer_t *data);
-typedef struct {
+struct dst_hmacsha256_key {
unsigned char key[ISC_SHA256_DIGESTLENGTH];
-} HMACSHA256_Key;
+};
static isc_result_t
hmacsha256_createctx(dst_key_t *key, dst_context_t *dctx) {
isc_hmacsha256_t *hmacsha256ctx;
- HMACSHA256_Key *hkey = key->opaque;
+ dst_hmacsha256_key_t *hkey = key->keydata.hmacsha256;
hmacsha256ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacsha256_t));
if (hmacsha256ctx == NULL)
return (ISC_R_NOMEMORY);
isc_hmacsha256_init(hmacsha256ctx, hkey->key, ISC_SHA256_DIGESTLENGTH);
- dctx->opaque = hmacsha256ctx;
+ dctx->ctxdata.hmacsha256ctx = hmacsha256ctx;
return (ISC_R_SUCCESS);
}
static void
hmacsha256_destroyctx(dst_context_t *dctx) {
- isc_hmacsha256_t *hmacsha256ctx = dctx->opaque;
+ isc_hmacsha256_t *hmacsha256ctx = dctx->ctxdata.hmacsha256ctx;
if (hmacsha256ctx != NULL) {
isc_hmacsha256_invalidate(hmacsha256ctx);
isc_mem_put(dctx->mctx, hmacsha256ctx, sizeof(isc_hmacsha256_t));
- dctx->opaque = NULL;
+ dctx->ctxdata.hmacsha256ctx = NULL;
}
}
static isc_result_t
hmacsha256_adddata(dst_context_t *dctx, const isc_region_t *data) {
- isc_hmacsha256_t *hmacsha256ctx = dctx->opaque;
+ isc_hmacsha256_t *hmacsha256ctx = dctx->ctxdata.hmacsha256ctx;
isc_hmacsha256_update(hmacsha256ctx, data->base, data->length);
return (ISC_R_SUCCESS);
static isc_result_t
hmacsha256_sign(dst_context_t *dctx, isc_buffer_t *sig) {
- isc_hmacsha256_t *hmacsha256ctx = dctx->opaque;
+ isc_hmacsha256_t *hmacsha256ctx = dctx->ctxdata.hmacsha256ctx;
unsigned char *digest;
if (isc_buffer_availablelength(sig) < ISC_SHA256_DIGESTLENGTH)
static isc_result_t
hmacsha256_verify(dst_context_t *dctx, const isc_region_t *sig) {
- isc_hmacsha256_t *hmacsha256ctx = dctx->opaque;
+ isc_hmacsha256_t *hmacsha256ctx = dctx->ctxdata.hmacsha256ctx;
if (sig->length > ISC_SHA256_DIGESTLENGTH || sig->length == 0)
return (DST_R_VERIFYFAILURE);
static isc_boolean_t
hmacsha256_compare(const dst_key_t *key1, const dst_key_t *key2) {
- HMACSHA256_Key *hkey1, *hkey2;
+ dst_hmacsha256_key_t *hkey1, *hkey2;
- hkey1 = (HMACSHA256_Key *)key1->opaque;
- hkey2 = (HMACSHA256_Key *)key2->opaque;
+ hkey1 = key1->keydata.hmacsha256;
+ hkey2 = key2->keydata.hmacsha256;
if (hkey1 == NULL && hkey2 == NULL)
return (ISC_TRUE);
static void
hmacsha256_destroy(dst_key_t *key) {
- HMACSHA256_Key *hkey = key->opaque;
- memset(hkey, 0, sizeof(HMACSHA256_Key));
- isc_mem_put(key->mctx, hkey, sizeof(HMACSHA256_Key));
- key->opaque = NULL;
+ dst_hmacsha256_key_t *hkey = key->keydata.hmacsha256;
+ memset(hkey, 0, sizeof(dst_hmacsha256_key_t));
+ isc_mem_put(key->mctx, hkey, sizeof(dst_hmacsha256_key_t));
+ key->keydata.hmacsha256 = NULL;
}
static isc_result_t
hmacsha256_todns(const dst_key_t *key, isc_buffer_t *data) {
- HMACSHA256_Key *hkey;
+ dst_hmacsha256_key_t *hkey;
unsigned int bytes;
- REQUIRE(key->opaque != NULL);
+ REQUIRE(key->keydata.hmacsha256 != NULL);
- hkey = (HMACSHA256_Key *) key->opaque;
+ hkey = key->keydata.hmacsha256;
bytes = (key->key_size + 7) / 8;
if (isc_buffer_availablelength(data) < bytes)
static isc_result_t
hmacsha256_fromdns(dst_key_t *key, isc_buffer_t *data) {
- HMACSHA256_Key *hkey;
+ dst_hmacsha256_key_t *hkey;
int keylen;
isc_region_t r;
isc_sha256_t sha256ctx;
if (r.length == 0)
return (ISC_R_SUCCESS);
- hkey = (HMACSHA256_Key *) isc_mem_get(key->mctx, sizeof(HMACSHA256_Key));
+ hkey = isc_mem_get(key->mctx, sizeof(dst_hmacsha256_key_t));
if (hkey == NULL)
return (ISC_R_NOMEMORY);
}
key->key_size = keylen * 8;
- key->opaque = hkey;
+ key->keydata.hmacsha256 = hkey;
return (ISC_R_SUCCESS);
}
static isc_result_t
hmacsha256_tofile(const dst_key_t *key, const char *directory) {
int cnt = 0;
- HMACSHA256_Key *hkey;
+ dst_hmacsha256_key_t *hkey;
dst_private_t priv;
int bytes = (key->key_size + 7) / 8;
unsigned char buf[2];
- if (key->opaque == NULL)
+ if (key->keydata.hmacsha256 == NULL)
return (DST_R_NULLKEY);
- hkey = (HMACSHA256_Key *) key->opaque;
+ hkey = key->keydata.hmacsha256;
priv.elements[cnt].tag = TAG_HMACSHA256_KEY;
priv.elements[cnt].length = bytes;
static isc_result_t hmacsha384_fromdns(dst_key_t *key, isc_buffer_t *data);
-typedef struct {
+struct dst_hmacsha384_key {
unsigned char key[ISC_SHA384_DIGESTLENGTH];
-} HMACSHA384_Key;
+};
static isc_result_t
hmacsha384_createctx(dst_key_t *key, dst_context_t *dctx) {
isc_hmacsha384_t *hmacsha384ctx;
- HMACSHA384_Key *hkey = key->opaque;
+ dst_hmacsha384_key_t *hkey = key->keydata.hmacsha384;
hmacsha384ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacsha384_t));
if (hmacsha384ctx == NULL)
return (ISC_R_NOMEMORY);
isc_hmacsha384_init(hmacsha384ctx, hkey->key, ISC_SHA384_DIGESTLENGTH);
- dctx->opaque = hmacsha384ctx;
+ dctx->ctxdata.hmacsha384ctx = hmacsha384ctx;
return (ISC_R_SUCCESS);
}
static void
hmacsha384_destroyctx(dst_context_t *dctx) {
- isc_hmacsha384_t *hmacsha384ctx = dctx->opaque;
+ isc_hmacsha384_t *hmacsha384ctx = dctx->ctxdata.hmacsha384ctx;
if (hmacsha384ctx != NULL) {
isc_hmacsha384_invalidate(hmacsha384ctx);
isc_mem_put(dctx->mctx, hmacsha384ctx, sizeof(isc_hmacsha384_t));
- dctx->opaque = NULL;
+ dctx->ctxdata.hmacsha384ctx = NULL;
}
}
static isc_result_t
hmacsha384_adddata(dst_context_t *dctx, const isc_region_t *data) {
- isc_hmacsha384_t *hmacsha384ctx = dctx->opaque;
+ isc_hmacsha384_t *hmacsha384ctx = dctx->ctxdata.hmacsha384ctx;
isc_hmacsha384_update(hmacsha384ctx, data->base, data->length);
return (ISC_R_SUCCESS);
static isc_result_t
hmacsha384_sign(dst_context_t *dctx, isc_buffer_t *sig) {
- isc_hmacsha384_t *hmacsha384ctx = dctx->opaque;
+ isc_hmacsha384_t *hmacsha384ctx = dctx->ctxdata.hmacsha384ctx;
unsigned char *digest;
if (isc_buffer_availablelength(sig) < ISC_SHA384_DIGESTLENGTH)
static isc_result_t
hmacsha384_verify(dst_context_t *dctx, const isc_region_t *sig) {
- isc_hmacsha384_t *hmacsha384ctx = dctx->opaque;
+ isc_hmacsha384_t *hmacsha384ctx = dctx->ctxdata.hmacsha384ctx;
if (sig->length > ISC_SHA384_DIGESTLENGTH || sig->length == 0)
return (DST_R_VERIFYFAILURE);
static isc_boolean_t
hmacsha384_compare(const dst_key_t *key1, const dst_key_t *key2) {
- HMACSHA384_Key *hkey1, *hkey2;
+ dst_hmacsha384_key_t *hkey1, *hkey2;
- hkey1 = (HMACSHA384_Key *)key1->opaque;
- hkey2 = (HMACSHA384_Key *)key2->opaque;
+ hkey1 = key1->keydata.hmacsha384;
+ hkey2 = key2->keydata.hmacsha384;
if (hkey1 == NULL && hkey2 == NULL)
return (ISC_TRUE);
static void
hmacsha384_destroy(dst_key_t *key) {
- HMACSHA384_Key *hkey = key->opaque;
- memset(hkey, 0, sizeof(HMACSHA384_Key));
- isc_mem_put(key->mctx, hkey, sizeof(HMACSHA384_Key));
- key->opaque = NULL;
+ dst_hmacsha384_key_t *hkey = key->keydata.hmacsha384;
+ memset(hkey, 0, sizeof(dst_hmacsha384_key_t));
+ isc_mem_put(key->mctx, hkey, sizeof(dst_hmacsha384_key_t));
+ key->keydata.hmacsha384 = NULL;
}
static isc_result_t
hmacsha384_todns(const dst_key_t *key, isc_buffer_t *data) {
- HMACSHA384_Key *hkey;
+ dst_hmacsha384_key_t *hkey;
unsigned int bytes;
- REQUIRE(key->opaque != NULL);
+ REQUIRE(key->keydata.hmacsha384 != NULL);
- hkey = (HMACSHA384_Key *) key->opaque;
+ hkey = key->keydata.hmacsha384;
bytes = (key->key_size + 7) / 8;
if (isc_buffer_availablelength(data) < bytes)
static isc_result_t
hmacsha384_fromdns(dst_key_t *key, isc_buffer_t *data) {
- HMACSHA384_Key *hkey;
+ dst_hmacsha384_key_t *hkey;
int keylen;
isc_region_t r;
isc_sha384_t sha384ctx;
if (r.length == 0)
return (ISC_R_SUCCESS);
- hkey = (HMACSHA384_Key *) isc_mem_get(key->mctx, sizeof(HMACSHA384_Key));
+ hkey = isc_mem_get(key->mctx, sizeof(dst_hmacsha384_key_t));
if (hkey == NULL)
return (ISC_R_NOMEMORY);
}
key->key_size = keylen * 8;
- key->opaque = hkey;
+ key->keydata.hmacsha384 = hkey;
return (ISC_R_SUCCESS);
}
static isc_result_t
hmacsha384_tofile(const dst_key_t *key, const char *directory) {
int cnt = 0;
- HMACSHA384_Key *hkey;
+ dst_hmacsha384_key_t *hkey;
dst_private_t priv;
int bytes = (key->key_size + 7) / 8;
unsigned char buf[2];
- if (key->opaque == NULL)
+ if (key->keydata.hmacsha384 == NULL)
return (DST_R_NULLKEY);
- hkey = (HMACSHA384_Key *) key->opaque;
+ hkey = key->keydata.hmacsha384;
priv.elements[cnt].tag = TAG_HMACSHA384_KEY;
priv.elements[cnt].length = bytes;
static isc_result_t hmacsha512_fromdns(dst_key_t *key, isc_buffer_t *data);
-typedef struct {
+struct dst_hmacsha512_key {
unsigned char key[ISC_SHA512_DIGESTLENGTH];
-} HMACSHA512_Key;
+};
static isc_result_t
hmacsha512_createctx(dst_key_t *key, dst_context_t *dctx) {
isc_hmacsha512_t *hmacsha512ctx;
- HMACSHA512_Key *hkey = key->opaque;
+ dst_hmacsha512_key_t *hkey = key->keydata.hmacsha512;
hmacsha512ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacsha512_t));
if (hmacsha512ctx == NULL)
return (ISC_R_NOMEMORY);
isc_hmacsha512_init(hmacsha512ctx, hkey->key, ISC_SHA512_DIGESTLENGTH);
- dctx->opaque = hmacsha512ctx;
+ dctx->ctxdata.hmacsha512ctx = hmacsha512ctx;
return (ISC_R_SUCCESS);
}
static void
hmacsha512_destroyctx(dst_context_t *dctx) {
- isc_hmacsha512_t *hmacsha512ctx = dctx->opaque;
+ isc_hmacsha512_t *hmacsha512ctx = dctx->ctxdata.hmacsha512ctx;
if (hmacsha512ctx != NULL) {
isc_hmacsha512_invalidate(hmacsha512ctx);
isc_mem_put(dctx->mctx, hmacsha512ctx, sizeof(isc_hmacsha512_t));
- dctx->opaque = NULL;
+ dctx->ctxdata.hmacsha512ctx = NULL;
}
}
static isc_result_t
hmacsha512_adddata(dst_context_t *dctx, const isc_region_t *data) {
- isc_hmacsha512_t *hmacsha512ctx = dctx->opaque;
+ isc_hmacsha512_t *hmacsha512ctx = dctx->ctxdata.hmacsha512ctx;
isc_hmacsha512_update(hmacsha512ctx, data->base, data->length);
return (ISC_R_SUCCESS);
static isc_result_t
hmacsha512_sign(dst_context_t *dctx, isc_buffer_t *sig) {
- isc_hmacsha512_t *hmacsha512ctx = dctx->opaque;
+ isc_hmacsha512_t *hmacsha512ctx = dctx->ctxdata.hmacsha512ctx;
unsigned char *digest;
if (isc_buffer_availablelength(sig) < ISC_SHA512_DIGESTLENGTH)
static isc_result_t
hmacsha512_verify(dst_context_t *dctx, const isc_region_t *sig) {
- isc_hmacsha512_t *hmacsha512ctx = dctx->opaque;
+ isc_hmacsha512_t *hmacsha512ctx = dctx->ctxdata.hmacsha512ctx;
if (sig->length > ISC_SHA512_DIGESTLENGTH || sig->length == 0)
return (DST_R_VERIFYFAILURE);
static isc_boolean_t
hmacsha512_compare(const dst_key_t *key1, const dst_key_t *key2) {
- HMACSHA512_Key *hkey1, *hkey2;
+ dst_hmacsha512_key_t *hkey1, *hkey2;
- hkey1 = (HMACSHA512_Key *)key1->opaque;
- hkey2 = (HMACSHA512_Key *)key2->opaque;
+ hkey1 = key1->keydata.hmacsha512;
+ hkey2 = key2->keydata.hmacsha512;
if (hkey1 == NULL && hkey2 == NULL)
return (ISC_TRUE);
static void
hmacsha512_destroy(dst_key_t *key) {
- HMACSHA512_Key *hkey = key->opaque;
- memset(hkey, 0, sizeof(HMACSHA512_Key));
- isc_mem_put(key->mctx, hkey, sizeof(HMACSHA512_Key));
- key->opaque = NULL;
+ dst_hmacsha512_key_t *hkey = key->keydata.hmacsha512;
+ memset(hkey, 0, sizeof(dst_hmacsha512_key_t));
+ isc_mem_put(key->mctx, hkey, sizeof(dst_hmacsha512_key_t));
+ key->keydata.hmacsha512 = NULL;
}
static isc_result_t
hmacsha512_todns(const dst_key_t *key, isc_buffer_t *data) {
- HMACSHA512_Key *hkey;
+ dst_hmacsha512_key_t *hkey;
unsigned int bytes;
- REQUIRE(key->opaque != NULL);
+ REQUIRE(key->keydata.hmacsha512 != NULL);
- hkey = (HMACSHA512_Key *) key->opaque;
+ hkey = key->keydata.hmacsha512;
bytes = (key->key_size + 7) / 8;
if (isc_buffer_availablelength(data) < bytes)
static isc_result_t
hmacsha512_fromdns(dst_key_t *key, isc_buffer_t *data) {
- HMACSHA512_Key *hkey;
+ dst_hmacsha512_key_t *hkey;
int keylen;
isc_region_t r;
isc_sha512_t sha512ctx;
if (r.length == 0)
return (ISC_R_SUCCESS);
- hkey = (HMACSHA512_Key *) isc_mem_get(key->mctx, sizeof(HMACSHA512_Key));
+ hkey = isc_mem_get(key->mctx, sizeof(dst_hmacsha512_key_t));
if (hkey == NULL)
return (ISC_R_NOMEMORY);
}
key->key_size = keylen * 8;
- key->opaque = hkey;
+ key->keydata.hmacsha512 = hkey;
return (ISC_R_SUCCESS);
}
static isc_result_t
hmacsha512_tofile(const dst_key_t *key, const char *directory) {
int cnt = 0;
- HMACSHA512_Key *hkey;
+ dst_hmacsha512_key_t *hkey;
dst_private_t priv;
int bytes = (key->key_size + 7) / 8;
unsigned char buf[2];
- if (key->opaque == NULL)
+ if (key->keydata.hmacsha512 == NULL)
return (DST_R_NULLKEY);
- hkey = (HMACSHA512_Key *) key->opaque;
+ hkey = key->keydata.hmacsha512;
priv.elements[cnt].tag = TAG_HMACSHA512_KEY;
priv.elements[cnt].length = bytes;
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: name.h,v 1.122 2006/03/02 00:37:23 marka Exp $ */
+/* $Id: name.h,v 1.123 2006/12/04 01:52:46 marka Exp $ */
#ifndef DNS_NAME_H
#define DNS_NAME_H 1
#define DNS_NAMEATTR_READONLY 0x0002
#define DNS_NAMEATTR_DYNAMIC 0x0004
#define DNS_NAMEATTR_DYNOFFSETS 0x0008
+#define DNS_NAMEATTR_NOCOMPRESS 0x0010
/*
* Attributes below 0x0100 reserved for name.c usage.
*/
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: ssu.h,v 1.17 2006/02/16 23:51:33 marka Exp $ */
+/* $Id: ssu.h,v 1.18 2006/12/04 01:52:46 marka Exp $ */
#ifndef DNS_SSU_H
#define DNS_SSU_H 1
ISC_LANG_BEGINDECLS
-#define DNS_SSUMATCHTYPE_NAME 0
-#define DNS_SSUMATCHTYPE_SUBDOMAIN 1
-#define DNS_SSUMATCHTYPE_WILDCARD 2
-#define DNS_SSUMATCHTYPE_SELF 3
-#define DNS_SSUMATCHTYPE_SELFSUB 4
-#define DNS_SSUMATCHTYPE_SELFWILD 5
-#define DNS_SSUMATCHTYPE_MAX 5 /* maximum defined value */
-
+#define DNS_SSUMATCHTYPE_NAME 0
+#define DNS_SSUMATCHTYPE_SUBDOMAIN 1
+#define DNS_SSUMATCHTYPE_WILDCARD 2
+#define DNS_SSUMATCHTYPE_SELF 3
+#define DNS_SSUMATCHTYPE_SELFSUB 4
+#define DNS_SSUMATCHTYPE_SELFWILD 5
+#define DNS_SSUMATCHTYPE_SELFKRB5 6
+#define DNS_SSUMATCHTYPE_SELFMS 7
+#define DNS_SSUMATCHTYPE_SUBDOMAINMS 8
+#define DNS_SSUMATCHTYPE_SUBDOMAINKRB5 9
+#define DNS_SSUMATCHTYPE_MAX 9 /* max value */
isc_result_t
dns_ssutable_create(isc_mem_t *mctx, dns_ssutable_t **table);
* at that name.
*
* Notes:
- *\li If 'matchtype' is SELF, this rule only matches if the name
- * to be updated matches the signing identity.
+ *\li If 'matchtype' is of SELF type, this rule only matches if the
+ * name to be updated matches the signing identity.
*
*\li If 'ntypes' is 0, this rule applies to all types except
* NS, SOA, RRSIG, and NSEC.
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: tkey.h,v 1.21 2005/04/29 00:23:05 marka Exp $ */
+/* $Id: tkey.h,v 1.22 2006/12/04 01:52:46 marka Exp $ */
#ifndef DNS_TKEY_H
#define DNS_TKEY_H 1
#include <dns/types.h>
#include <dst/dst.h>
+#include <dst/gssapi.h>
ISC_LANG_BEGINDECLS
struct dns_tkeyctx {
dst_key_t *dhkey;
dns_name_t *domain;
- void *gsscred;
+ gss_cred_id_t gsscred;
isc_mem_t *mctx;
isc_entropy_t *ectx;
};
isc_result_t
-dns_tkeyctx_create(isc_mem_t *mctx, isc_entropy_t *ectx, dns_tkeyctx_t **tctxp);
+dns_tkeyctx_create(isc_mem_t *mctx, isc_entropy_t *ectx,
+ dns_tkeyctx_t **tctxp);
/*%<
* Create an empty TKEY context.
*
*/
isc_result_t
-dns_tkey_buildgssquery(dns_message_t *msg, dns_name_t *name,
- dns_name_t *gname, void *cred,
- isc_uint32_t lifetime, void **context);
+dns_tkey_buildgssquery(dns_message_t *msg, dns_name_t *name, dns_name_t *gname,
+ isc_buffer_t *intoken, isc_uint32_t lifetime,
+ gss_ctx_id_t *context, isc_boolean_t win2k);
/*%<
- * XXX
+ * Builds a query containing a TKEY that will generate a GSSAPI context.
+ * The key is requested to have the specified lifetime (in seconds).
+ *
+ * Requires:
+ *\li 'msg' is a valid message
+ *\li 'name' is a valid name
+ *\li 'gname' is a valid name
+ *\li 'context' is a pointer to a valid gss_ctx_id_t
+ * (which may have the value GSS_C_NO_CONTEXT)
+ *\li 'win2k' when true says to turn on some hacks to work
+ * with the non-standard GSS-TSIG of Windows 2000
+ *
+ * Returns:
+ *\li ISC_R_SUCCESS msg was successfully updated to include the
+ * query to be sent
+ *\li other an error occurred while building the message
*/
+
isc_result_t
dns_tkey_builddeletequery(dns_message_t *msg, dns_tsigkey_t *key);
/*%<
isc_result_t
dns_tkey_processgssresponse(dns_message_t *qmsg, dns_message_t *rmsg,
- dns_name_t *gname, void *cred, void **context,
- dns_tsigkey_t **outkey, dns_tsig_keyring_t *ring);
+ dns_name_t *gname, gss_ctx_id_t *context,
+ isc_buffer_t *outtoken, dns_tsigkey_t **outkey,
+ dns_tsig_keyring_t *ring);
/*%<
* XXX
*/
*/
+isc_result_t
+dns_tkey_gssnegotiate(dns_message_t *qmsg, dns_message_t *rmsg,
+ dns_name_t *server, gss_ctx_id_t *context,
+ dns_tsigkey_t **outkey, dns_tsig_keyring_t *ring,
+ isc_boolean_t win2k);
+
+/*
+ * Client side negotiation of GSS-TSIG. Process the respsonse
+ * to a TKEY, and establish a TSIG key if negotiation was successful.
+ * Build a response to the input TKEY message. Can take multiple
+ * calls to successfully establish the context.
+ *
+ * Requires:
+ * 'qmsg' is a valid message, the original TKEY request;
+ * it will be filled with the new message to send
+ * 'rmsg' is a valid message, the incoming TKEY message
+ * 'server' is the server name
+ * 'context' is the input context handle
+ * 'outkey' receives the established key, if non-NULL;
+ * if non-NULL must point to NULL
+ * 'ring' is the keyring in which to establish the key,
+ * or NULL
+ * 'win2k' when true says to turn on some hacks to work
+ * with the non-standard GSS-TSIG of Windows 2000
+ *
+ * Returns:
+ * ISC_R_SUCCESS context was successfully established
+ * ISC_R_NOTFOUND couldn't find a needed part of the query
+ * or response
+ * DNS_R_CONTINUE additional context negotiation is required;
+ * send the new qmsg to the server
+ */
+
ISC_LANG_ENDDECLS
#endif /* DNS_TKEY_H */
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: tsig.h,v 1.47 2006/01/27 23:57:46 marka Exp $ */
+/* $Id: tsig.h,v 1.48 2006/12/04 01:52:46 marka Exp $ */
#ifndef DNS_TSIG_H
#define DNS_TSIG_H 1
struct dns_tsig_keyring {
dns_rbt_t *keys;
+ unsigned int writecount;
isc_rwlock_t lock;
isc_mem_t *mctx;
};
};
#define dns_tsigkey_identity(tsigkey) \
- ((tsigkey)->generated ? ((tsigkey)->creator) : (&((tsigkey)->name)))
+ ((tsigkey) == NULL ? NULL : \
+ (tsigkey)->generated ? ((tsigkey)->creator) : \
+ (&((tsigkey)->name)))
ISC_LANG_BEGINDECLS
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: types.h,v 1.121 2006/05/02 13:04:54 shane Exp $ */
+/* $Id: types.h,v 1.122 2006/12/04 01:52:46 marka Exp $ */
#ifndef DNS_TYPES_H
#define DNS_TYPES_H 1
typedef struct dns_zonemgr dns_zonemgr_t;
typedef struct dns_zt dns_zt_t;
+/*
+ * If we are not using GSSAPI, define the types we use as opaque types here.
+ */
+#ifndef GSSAPI
+typedef struct not_defined_gss_cred_id *gss_cred_id_t;
+typedef struct not_defined_gss_ctx *gss_ctx_id_t;
+#endif
+typedef struct dst_gssapi_signverifyctx dst_gssapi_signverifyctx_t;
+
typedef enum {
dns_fwdpolicy_none = 0,
dns_fwdpolicy_first = 1,
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: dst.h,v 1.5 2006/01/27 23:57:46 marka Exp $ */
+/* $Id: dst.h,v 1.6 2006/12/04 01:52:46 marka Exp $ */
#ifndef DST_DST_H
#define DST_DST_H 1
#include <dns/types.h>
+#include <dst/gssapi.h>
+
ISC_LANG_BEGINDECLS
/***
*\li If successful, key will contain a valid private key.
*/
+gss_ctx_id_t
+dst_key_getgssctx(const dst_key_t *key);
+/*%<
+ * Returns the opaque key data.
+ * Be cautions when using this value unless you know what you are doing.
+ *
+ * Requires:
+ *\li "key" is not NULL.
+ *
+ * Returns:
+ *\li gssctx key data, possibly NULL.
+ */
isc_result_t
-dst_key_fromgssapi(dns_name_t *name, void *opaque, isc_mem_t *mctx,
- dst_key_t **keyp);
+dst_key_fromgssapi(dns_name_t *name, gss_ctx_id_t gssctx, isc_mem_t *mctx,
+ dst_key_t **keyp);
/*%<
* Converts a GSSAPI opaque context id into a DST key.
*
* Requires:
*\li "name" is a valid absolute dns name.
- *\li "opaque" is a GSSAPI context id.
+ *\li "gssctx" is a GSSAPI context id.
*\li "mctx" is a valid memory context.
*\li "keyp" is not NULL and "*keyp" is NULL.
*
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: gssapi.h,v 1.3 2005/04/29 00:23:06 marka Exp $ */
+/* $Id: gssapi.h,v 1.4 2006/12/04 01:52:46 marka Exp $ */
#ifndef DST_GSSAPI_H
#define DST_GSSAPI_H 1
/*! \file */
+#include <isc/formatcheck.h>
#include <isc/lang.h>
-
+#include <isc/platform.h>
#include <isc/types.h>
+#include <dns/types.h>
+
+#ifdef GSSAPI
+#ifdef _WINDOWS
+/*
+ * MSVC does not like macros in #include lines.
+ */
+#include <gssapi/gssapi.h>
+#else
+#include ISC_PLATFORM_GSSAPIHEADER
+#endif
+#ifndef GSS_SPNEGO_MECHANISM
+#define GSS_SPNEGO_MECHANISM ((void*)0)
+#endif
+#endif
ISC_LANG_BEGINDECLS
***/
isc_result_t
-dst_gssapi_acquirecred(dns_name_t *name, isc_boolean_t initiate, void **cred);
+dst_gssapi_acquirecred(dns_name_t *name, isc_boolean_t initiate,
+ gss_cred_id_t *cred);
+/*
+ * Acquires GSS credentials.
+ *
+ * Requires:
+ * 'name' is a valid name, preferably one known by the GSS provider
+ * 'initiate' indicates whether the credentials are for initiating or
+ * accepting contexts
+ * 'cred' is a pointer to NULL, which will be allocated with the
+ * credential handle. Call dst_gssapi_releasecred to free
+ * the memory.
+ *
+ * Returns:
+ * ISC_R_SUCCESS msg was successfully updated to include the
+ * query to be sent
+ * other an error occurred while building the message
+ */
isc_result_t
-dst_gssapi_initctx(dns_name_t *name, void *cred,
- isc_region_t *intoken, isc_buffer_t *outtoken,
- void **context);
+dst_gssapi_releasecred(gss_cred_id_t *cred);
+/*
+ * Releases GSS credentials. Calling this function does release the
+ * memory allocated for the credential in dst_gssapi_acquirecred()
+ *
+ * Requires:
+ * 'mctx' is a valid memory context
+ * 'cred' is a pointer to the credential to be released
+ *
+ * Returns:
+ * ISC_R_SUCCESS credential was released successfully
+ * other an error occurred while releaseing
+ * the credential
+ */
+
+isc_result_t
+dst_gssapi_initctx(dns_name_t *name, isc_buffer_t *intoken,
+ isc_buffer_t *outtoken, gss_ctx_id_t *gssctx);
+/*
+ * Initiates a GSS context.
+ *
+ * Requires:
+ * 'name' is a valid name, preferably one known by the GSS
+ * provider
+ * 'intoken' is a token received from the acceptor, or NULL if
+ * there isn't one
+ * 'outtoken' is a buffer to receive the token generated by
+ * gss_init_sec_context() to be sent to the acceptor
+ * 'context' is a pointer to a valid gss_ctx_id_t
+ * (which may have the value GSS_C_NO_CONTEXT)
+ *
+ * Returns:
+ * ISC_R_SUCCESS msg was successfully updated to include the
+ * query to be sent
+ * other an error occurred while building the message
+ */
isc_result_t
-dst_gssapi_acceptctx(dns_name_t *name, void *cred,
+dst_gssapi_acceptctx(gss_cred_id_t cred,
isc_region_t *intoken, isc_buffer_t *outtoken,
- void **context);
+ gss_ctx_id_t *context, dns_name_t *principal,
+ isc_mem_t *mctx);
+/*
+ * Accepts a GSS context.
+ *
+ * Requires:
+ * 'mctx' is a valid memory context
+ * 'cred' is the acceptor's valid GSS credential handle
+ * 'intoken' is a token received from the initiator
+ * 'outtoken' is a buffer to receive the token generated by
+ * gss_accept_sec_context() to be sent to the initiator
+ * 'context' is a valid pointer to receive the generated context handle.
+ * On the initial call, it should be a pointer to NULL, which
+ * will be allocated as a gss_ctx_id_t. Subsequent calls
+ * should pass in the handle generated on the first call.
+ * Call dst_gssapi_releasecred to delete the context and free
+ * the memory.
+ *
+ * Returns:
+ * ISC_R_SUCCESS msg was successfully updated to include the
+ * query to be sent
+ * other an error occurred while building the message
+ */
+
+isc_result_t
+dst_gssapi_deletectx(isc_mem_t *mctx, gss_ctx_id_t *gssctx);
+/*
+ * Destroys a GSS context. This function deletes the context from the GSS
+ * provider and then frees the memory used by the context pointer.
+ *
+ * Requires:
+ * 'mctx' is a valid memory context
+ * 'context' is a valid GSS context
+ *
+ * Returns:
+ * ISC_R_SUCCESS
+ */
+
+
+void
+gss_log(int level, const char *fmt, ...)
+ISC_FORMAT_PRINTF(2, 3);
+/*
+ * Loging function for GSS.
+ *
+ * Requires
+ * 'level' is the log level to be used, as an integer
+ * 'fmt' is a printf format specifier
+ */
+char *
+gss_error_tostring(isc_uint32_t major, isc_uint32_t minor,
+ char *buf, size_t buflen);
/*
- * XXX
+ * Render a GSS major status/minor status pair into a string
+ *
+ * Requires:
+ * 'major' is a GSS major status code
+ * 'minor' is a GSS minor status code
+ *
+ * Returns:
+ * A string containing the text representation of the error codes.
+ * Users should copy the string if they wish to keep it.
+ */
+
+isc_boolean_t
+dst_gssapi_identitymatchesrealmkrb5(dns_name_t *signer, dns_name_t *name,
+ dns_name_t *realm);
+/*
+ * Compare a "signer" (in the format of a Kerberos-format Kerberos5
+ * printipal: host/example.com@EXAMPLE.COM) to the realm name stored
+ * in "name" (which represents the realm name).
+ *
+ */
+
+isc_boolean_t
+dst_gssapi_identitymatchesrealmms(dns_name_t *signer, dns_name_t *name,
+ dns_name_t *realm);
+/*
+ * Compare a "signer" (in the format of a Kerberos-format Kerberos5
+ * printipal: host/example.com@EXAMPLE.COM) to the realm name stored
+ * in "name" (which represents the realm name).
+ *
*/
ISC_LANG_ENDDECLS
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: message.c,v 1.232 2006/03/02 01:57:20 marka Exp $ */
+/* $Id: message.c,v 1.233 2006/12/04 01:52:46 marka Exp $ */
/*! \file */
#include <dns/tsig.h>
#include <dns/view.h>
+#ifdef SKAN_MSG_DEBUG
+static void
+hexdump(const char *msg, const char *msg2, void *base, size_t len) {
+ unsigned char *p;
+ unsigned int cnt;
+
+ p = base;
+ cnt = 0;
+
+ printf("*** %s [%s] (%u bytes @ %p)\n", msg, msg2, len, base);
+
+ while (cnt < len) {
+ if (cnt % 16 == 0)
+ printf("%p: ", p);
+ else if (cnt % 8 == 0)
+ printf(" |");
+ printf(" %02x %c", *p, (isprint(*p) ? *p : ' '));
+ p++;
+ cnt++;
+
+ if (cnt % 16 == 0)
+ printf("\n");
+ }
+
+ if (cnt % 16 != 0)
+ printf("\n");
+}
+#endif
+
#define DNS_MESSAGE_OPCODE_MASK 0x7800U
#define DNS_MESSAGE_OPCODE_SHIFT 11
#define DNS_MESSAGE_RCODE_MASK 0x000fU
return (dns_message_checksig(msg, view));
}
+#ifdef SKAN_MSG_DEBUG
+void
+dns_message_dumpsig(dns_message_t *msg, char *txt1) {
+ dns_rdata_t querytsigrdata = DNS_RDATA_INIT;
+ dns_rdata_any_tsig_t querytsig;
+
+ if (msg->tsig != NULL) {
+ dns_rdataset_first(msg->tsig);
+ dns_rdataset_current(msg->tsig, &querytsigrdata);
+ dns_rdata_tostruct(&querytsigrdata, &querytsig, NULL);
+ hexdump(txt1, "TSIG", querytsig.signature,
+ querytsig.siglen);
+ }
+
+ if (msg->querytsig != NULL) {
+ dns_rdataset_first(msg->querytsig);
+ dns_rdataset_current(msg->querytsig, &querytsigrdata);
+ dns_rdata_tostruct(&querytsigrdata, &querytsig, NULL);
+ hexdump(txt1, "QUERYTSIG", querytsig.signature,
+ querytsig.siglen);
+ }
+}
+#endif
+
isc_result_t
dns_message_checksig(dns_message_t *msg, dns_view_t *view) {
isc_buffer_t b, msgb;
if (msg->tsigkey == NULL && msg->tsig == NULL && msg->sig0 == NULL)
return (ISC_R_SUCCESS);
+
INSIST(msg->saved.base != NULL);
isc_buffer_init(&msgb, msg->saved.base, msg->saved.length);
isc_buffer_add(&msgb, msg->saved.length);
if (msg->tsigkey != NULL || msg->tsig != NULL) {
+#ifdef SKAN_MSG_DEBUG
+ dns_message_dumpsig(msg, "dns_message_checksig#1");
+#endif
if (view != NULL)
return (dns_view_checksig(view, &msgb, msg));
else
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: name.c,v 1.159 2006/02/28 02:39:51 marka Exp $ */
+/* $Id: name.c,v 1.160 2006/12/04 01:52:46 marka Exp $ */
/*! \file */
if (result != ISC_R_SUCCESS)
return (result);
- if (!thread_key_initialized) {
+ if (!thread_key_initialized) {
LOCK(&thread_key_mutex);
if (thread_key_mctx == NULL)
result = isc_mem_create2(0, 0, &thread_key_mctx, 0);
if (!thread_key_initialized &&
isc_thread_key_create(&totext_filter_proc_key,
- free_specific) != 0) {
+ free_specific) != 0) {
result = ISC_R_FAILURE;
isc_mem_detach(&thread_key_mctx);
} else
thread_key_initialized = 1;
unlock:
UNLOCK(&thread_key_mutex);
- }
+ }
return (result);
}
#endif
methods = dns_compress_getmethods(cctx);
- if ((methods & DNS_COMPRESS_GLOBAL14) != 0)
+ if ((name->attributes & DNS_NAMEATTR_NOCOMPRESS) == 0 &&
+ (methods & DNS_COMPRESS_GLOBAL14) != 0)
gf = dns_compress_findglobal(cctx, name, &gp, &go);
else
gf = ISC_FALSE;
/*
* Principal Author: Brian Wellington
- * $Id: openssl_link.c,v 1.9 2006/05/23 23:51:05 marka Exp $
+ * $Id: openssl_link.c,v 1.10 2006/12/04 01:52:46 marka Exp $
*/
#ifdef OPENSSL
#include <openssl/engine.h>
#endif
+#ifdef OVERRIDE_OPENSSL_RAND
static RAND_METHOD *rm = NULL;
+#endif
+
static isc_mutex_t *locks = NULL;
static int nlocks;
static ENGINE *e;
#endif
-
+#ifdef OVERRIDE_OPENSSL_RAND
static int
entropy_get(unsigned char *buf, int num) {
isc_result_t result;
return (result == ISC_R_SUCCESS ? num : -1);
}
+static int
+entropy_status(void) {
+ return (dst__entropy_status() > 32);
+}
+
static int
entropy_getpseudo(unsigned char *buf, int num) {
isc_result_t result;
UNUSED(num);
UNUSED(entropy);
}
+#endif
static void
lock_callback(int mode, int type, const char *file, int line) {
goto cleanup_mutexalloc;
CRYPTO_set_locking_callback(lock_callback);
CRYPTO_set_id_callback(id_callback);
+
+#ifdef OVERRIDE_OPENSSL_RAND
rm = mem_alloc(sizeof(RAND_METHOD));
if (rm == NULL) {
result = ISC_R_NOMEMORY;
rm->cleanup = NULL;
rm->add = entropy_add;
rm->pseudorand = entropy_getpseudo;
- rm->status = NULL;
+ rm->status = entropy_status;
#ifdef USE_ENGINE
e = ENGINE_new();
if (e == NULL) {
RAND_set_rand_method(rm);
#else
RAND_set_rand_method(rm);
-#endif
+#endif /* USE_ENGINER */
+#endif /* OVERRIDE_OPENSSL_RAND */
return (ISC_R_SUCCESS);
+#ifdef OVERRIDE_OPENSSL_RAND
#ifdef USE_ENGINE
cleanup_rm:
mem_free(rm);
#endif
cleanup_mutexinit:
DESTROYMUTEXBLOCK(locks, nlocks);
+#endif
cleanup_mutexalloc:
mem_free(locks);
return (result);
DESTROYMUTEXBLOCK(locks, nlocks);
mem_free(locks);
}
+#ifdef OVERRIDE_OPENSSL_RAND
if (rm != NULL) {
#if OPENSSL_VERSION_NUMBER >= 0x00907000L
RAND_cleanup();
#endif
mem_free(rm);
}
+#endif
}
isc_result_t
/*
* Principal Author: Brian Wellington
- * $Id: openssldh_link.c,v 1.6 2006/03/02 00:37:23 marka Exp $
+ * $Id: openssldh_link.c,v 1.7 2006/12/04 01:52:46 marka Exp $
*/
#ifdef OPENSSL
#include "dst_openssl.h"
#include "dst_parse.h"
-#include <openssl/dh.h>
-
#define PRIME768 "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088" \
"A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25" \
"F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A63A3620FFFFFFFFFFFFFFFF"
isc_region_t r;
unsigned int len;
- REQUIRE(pub->opaque != NULL);
- REQUIRE(priv->opaque != NULL);
+ REQUIRE(pub->keydata.dh != NULL);
+ REQUIRE(priv->keydata.dh != NULL);
- dhpub = (DH *) pub->opaque;
- dhpriv = (DH *) priv->opaque;
+ dhpub = pub->keydata.dh;
+ dhpriv = priv->keydata.dh;
len = DH_size(dhpriv);
isc_buffer_availableregion(secret, &r);
int status;
DH *dh1, *dh2;
- dh1 = (DH *) key1->opaque;
- dh2 = (DH *) key2->opaque;
+ dh1 = key1->keydata.dh;
+ dh2 = key2->keydata.dh;
if (dh1 == NULL && dh2 == NULL)
return (ISC_TRUE);
int status;
DH *dh1, *dh2;
- dh1 = (DH *) key1->opaque;
- dh2 = (DH *) key2->opaque;
+ dh1 = key1->keydata.dh;
+ dh2 = key2->keydata.dh;
if (dh1 == NULL && dh2 == NULL)
return (ISC_TRUE);
}
dh->flags &= ~DH_FLAG_CACHE_MONT_P;
- key->opaque = dh;
+ key->keydata.dh = dh;
return (ISC_R_SUCCESS);
}
static isc_boolean_t
openssldh_isprivate(const dst_key_t *key) {
- DH *dh = (DH *) key->opaque;
+ DH *dh = key->keydata.dh;
return (ISC_TF(dh != NULL && dh->priv_key != NULL));
}
static void
openssldh_destroy(dst_key_t *key) {
- DH *dh = key->opaque;
+ DH *dh = key->keydata.dh;
if (dh == NULL)
return;
if (dh->g == &bn2)
dh->g = NULL;
DH_free(dh);
- key->opaque = NULL;
+ key->keydata.dh = NULL;
}
static void
isc_region_t r;
isc_uint16_t dnslen, plen, glen, publen;
- REQUIRE(key->opaque != NULL);
+ REQUIRE(key->keydata.dh != NULL);
- dh = (DH *) key->opaque;
+ dh = key->keydata.dh;
isc_buffer_availableregion(data, &r);
isc_buffer_forward(data, plen + glen + publen + 6);
- key->opaque = (void *) dh;
+ key->keydata.dh = dh;
return (ISC_R_SUCCESS);
}
unsigned char *bufs[4];
isc_result_t result;
- if (key->opaque == NULL)
+ if (key->keydata.dh == NULL)
return (DST_R_NULLKEY);
- dh = (DH *) key->opaque;
+ dh = key->keydata.dh;
for (i = 0; i < 4; i++) {
bufs[i] = isc_mem_get(key->mctx, BN_num_bytes(dh->p));
if (dh == NULL)
DST_RET(ISC_R_NOMEMORY);
dh->flags &= ~DH_FLAG_CACHE_MONT_P;
- key->opaque = dh;
+ key->keydata.dh = dh;
for (i = 0; i < priv.nelements; i++) {
BIGNUM *bn;
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: openssldsa_link.c,v 1.5 2006/03/02 00:37:23 marka Exp $ */
+/* $Id: openssldsa_link.c,v 1.6 2006/12/04 01:52:46 marka Exp $ */
#ifdef OPENSSL
sha1ctx = isc_mem_get(dctx->mctx, sizeof(isc_sha1_t));
isc_sha1_init(sha1ctx);
- dctx->opaque = sha1ctx;
+ dctx->ctxdata.sha1ctx = sha1ctx;
return (ISC_R_SUCCESS);
}
static void
openssldsa_destroyctx(dst_context_t *dctx) {
- isc_sha1_t *sha1ctx = dctx->opaque;
+ isc_sha1_t *sha1ctx = dctx->ctxdata.sha1ctx;
if (sha1ctx != NULL) {
isc_sha1_invalidate(sha1ctx);
isc_mem_put(dctx->mctx, sha1ctx, sizeof(isc_sha1_t));
- dctx->opaque = NULL;
+ dctx->ctxdata.sha1ctx = NULL;
}
}
static isc_result_t
openssldsa_adddata(dst_context_t *dctx, const isc_region_t *data) {
- isc_sha1_t *sha1ctx = dctx->opaque;
+ isc_sha1_t *sha1ctx = dctx->ctxdata.sha1ctx;
isc_sha1_update(sha1ctx, data->base, data->length);
return (ISC_R_SUCCESS);
static isc_result_t
openssldsa_sign(dst_context_t *dctx, isc_buffer_t *sig) {
- isc_sha1_t *sha1ctx = dctx->opaque;
+ isc_sha1_t *sha1ctx = dctx->ctxdata.sha1ctx;
dst_key_t *key = dctx->key;
- DSA *dsa = key->opaque;
+ DSA *dsa = key->keydata.dsa;
DSA_SIG *dsasig;
isc_region_t r;
unsigned char digest[ISC_SHA1_DIGESTLENGTH];
static isc_result_t
openssldsa_verify(dst_context_t *dctx, const isc_region_t *sig) {
- isc_sha1_t *sha1ctx = dctx->opaque;
+ isc_sha1_t *sha1ctx = dctx->ctxdata.sha1ctx;
dst_key_t *key = dctx->key;
- DSA *dsa = key->opaque;
+ DSA *dsa = key->keydata.dsa;
DSA_SIG *dsasig;
int status = 0;
unsigned char digest[ISC_SHA1_DIGESTLENGTH];
int status;
DSA *dsa1, *dsa2;
- dsa1 = (DSA *) key1->opaque;
- dsa2 = (DSA *) key2->opaque;
+ dsa1 = key1->keydata.dsa;
+ dsa2 = key2->keydata.dsa;
if (dsa1 == NULL && dsa2 == NULL)
return (ISC_TRUE);
}
dsa->flags &= ~DSA_FLAG_CACHE_MONT_P;
- key->opaque = dsa;
+ key->keydata.dsa = dsa;
return (ISC_R_SUCCESS);
}
static isc_boolean_t
openssldsa_isprivate(const dst_key_t *key) {
- DSA *dsa = (DSA *) key->opaque;
+ DSA *dsa = key->keydata.dsa;
return (ISC_TF(dsa != NULL && dsa->priv_key != NULL));
}
static void
openssldsa_destroy(dst_key_t *key) {
- DSA *dsa = key->opaque;
+ DSA *dsa = key->keydata.dsa;
DSA_free(dsa);
- key->opaque = NULL;
+ key->keydata.dsa = NULL;
}
int dnslen;
unsigned int t, p_bytes;
- REQUIRE(key->opaque != NULL);
+ REQUIRE(key->keydata.dsa != NULL);
- dsa = (DSA *) key->opaque;
+ dsa = key->keydata.dsa;
isc_buffer_availableregion(data, &r);
isc_buffer_forward(data, 1 + ISC_SHA1_DIGESTLENGTH + 3 * p_bytes);
- key->opaque = (void *) dsa;
+ key->keydata.dsa = dsa;
return (ISC_R_SUCCESS);
}
dst_private_t priv;
unsigned char bufs[5][128];
- if (key->opaque == NULL)
+ if (key->keydata.dsa == NULL)
return (DST_R_NULLKEY);
- dsa = (DSA *) key->opaque;
+ dsa = key->keydata.dsa;
priv.elements[cnt].tag = TAG_DSA_PRIME;
priv.elements[cnt].length = BN_num_bytes(dsa->p);
if (dsa == NULL)
DST_RET(ISC_R_NOMEMORY);
dsa->flags &= ~DSA_FLAG_CACHE_MONT_P;
- key->opaque = dsa;
+ key->keydata.dsa = dsa;
for (i=0; i < priv.nelements; i++) {
BIGNUM *bn;
/*
* Principal Author: Brian Wellington
- * $Id: opensslrsa_link.c,v 1.12 2006/11/07 21:22:11 marka Exp $
+ * $Id: opensslrsa_link.c,v 1.13 2006/12/04 01:52:46 marka Exp $
*/
#ifdef OPENSSL
if (md5ctx == NULL)
return (ISC_R_NOMEMORY);
isc_md5_init(md5ctx);
- dctx->opaque = md5ctx;
+ dctx->ctxdata.md5ctx = md5ctx;
} else {
isc_sha1_t *sha1ctx;
if (sha1ctx == NULL)
return (ISC_R_NOMEMORY);
isc_sha1_init(sha1ctx);
- dctx->opaque = sha1ctx;
+ dctx->ctxdata.sha1ctx = sha1ctx;
}
return (ISC_R_SUCCESS);
dctx->key->key_alg == DST_ALG_RSASHA1);
if (dctx->key->key_alg == DST_ALG_RSAMD5) {
- isc_md5_t *md5ctx = dctx->opaque;
+ isc_md5_t *md5ctx = dctx->ctxdata.md5ctx;
if (md5ctx != NULL) {
isc_md5_invalidate(md5ctx);
isc_mem_put(dctx->mctx, md5ctx, sizeof(isc_md5_t));
+ dctx->ctxdata.md5ctx = NULL;
}
} else {
- isc_sha1_t *sha1ctx = dctx->opaque;
+ isc_sha1_t *sha1ctx = dctx->ctxdata.sha1ctx;
if (sha1ctx != NULL) {
isc_sha1_invalidate(sha1ctx);
isc_mem_put(dctx->mctx, sha1ctx, sizeof(isc_sha1_t));
+ dctx->ctxdata.sha1ctx = NULL;
}
}
- dctx->opaque = NULL;
}
static isc_result_t
dctx->key->key_alg == DST_ALG_RSASHA1);
if (dctx->key->key_alg == DST_ALG_RSAMD5) {
- isc_md5_t *md5ctx = dctx->opaque;
+ isc_md5_t *md5ctx = dctx->ctxdata.md5ctx;
isc_md5_update(md5ctx, data->base, data->length);
} else {
- isc_sha1_t *sha1ctx = dctx->opaque;
+ isc_sha1_t *sha1ctx = dctx->ctxdata.sha1ctx;
isc_sha1_update(sha1ctx, data->base, data->length);
}
return (ISC_R_SUCCESS);
static isc_result_t
opensslrsa_sign(dst_context_t *dctx, isc_buffer_t *sig) {
dst_key_t *key = dctx->key;
- RSA *rsa = key->opaque;
+ RSA *rsa = key->keydata.rsa;
isc_region_t r;
/* note: ISC_SHA1_DIGESTLENGTH > ISC_MD5_DIGESTLENGTH */
unsigned char digest[ISC_SHA1_DIGESTLENGTH];
return (ISC_R_NOSPACE);
if (dctx->key->key_alg == DST_ALG_RSAMD5) {
- isc_md5_t *md5ctx = dctx->opaque;
+ isc_md5_t *md5ctx = dctx->ctxdata.md5ctx;
isc_md5_final(md5ctx, digest);
type = NID_md5;
digestlen = ISC_MD5_DIGESTLENGTH;
} else {
- isc_sha1_t *sha1ctx = dctx->opaque;
+ isc_sha1_t *sha1ctx = dctx->ctxdata.sha1ctx;
isc_sha1_final(sha1ctx, digest);
type = NID_sha1;
digestlen = ISC_SHA1_DIGESTLENGTH;
static isc_result_t
opensslrsa_verify(dst_context_t *dctx, const isc_region_t *sig) {
dst_key_t *key = dctx->key;
- RSA *rsa = key->opaque;
+ RSA *rsa = key->keydata.rsa;
/* note: ISC_SHA1_DIGESTLENGTH > ISC_MD5_DIGESTLENGTH */
unsigned char digest[ISC_SHA1_DIGESTLENGTH];
int status = 0;
dctx->key->key_alg == DST_ALG_RSASHA1);
if (dctx->key->key_alg == DST_ALG_RSAMD5) {
- isc_md5_t *md5ctx = dctx->opaque;
+ isc_md5_t *md5ctx = dctx->ctxdata.md5ctx;
isc_md5_final(md5ctx, digest);
type = NID_md5;
digestlen = ISC_MD5_DIGESTLENGTH;
} else {
- isc_sha1_t *sha1ctx = dctx->opaque;
+ isc_sha1_t *sha1ctx = dctx->ctxdata.sha1ctx;
isc_sha1_final(sha1ctx, digest);
type = NID_sha1;
digestlen = ISC_SHA1_DIGESTLENGTH;
int status;
RSA *rsa1, *rsa2;
- rsa1 = (RSA *) key1->opaque;
- rsa2 = (RSA *) key2->opaque;
+ rsa1 = key1->keydata.rsa;
+ rsa2 = key2->keydata.rsa;
if (rsa1 == NULL && rsa2 == NULL)
return (ISC_TRUE);
if (RSA_generate_key_ex(rsa, key->key_size, e, &cb)) {
BN_free(e);
SET_FLAGS(rsa);
- key->opaque = rsa;
+ key->keydata.opaque = rsa;
return (ISC_R_SUCCESS);
}
if (rsa == NULL)
return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
SET_FLAGS(rsa);
- key->opaque = rsa;
+ key->keydata.opaque = rsa;
return (ISC_R_SUCCESS);
#endif
static isc_boolean_t
opensslrsa_isprivate(const dst_key_t *key) {
- RSA *rsa = (RSA *) key->opaque;
+ RSA *rsa = (RSA *) key->keydata.opaque;
return (ISC_TF(rsa != NULL && rsa->d != NULL));
}
static void
opensslrsa_destroy(dst_key_t *key) {
- RSA *rsa = key->opaque;
+ RSA *rsa = key->keydata.opaque;
RSA_free(rsa);
- key->opaque = NULL;
+ key->keydata.opaque = NULL;
}
unsigned int e_bytes;
unsigned int mod_bytes;
- REQUIRE(key->opaque != NULL);
+ REQUIRE(key->keydata.rsa != NULL);
- rsa = (RSA *) key->opaque;
+ rsa = key->keydata.rsa;
isc_buffer_availableregion(data, &r);
isc_buffer_forward(data, r.length);
- key->opaque = (void *) rsa;
+ key->keydata.rsa = rsa;
return (ISC_R_SUCCESS);
}
unsigned char *bufs[8];
isc_result_t result;
- if (key->opaque == NULL)
+ if (key->keydata.rsa == NULL)
return (DST_R_NULLKEY);
- rsa = (RSA *) key->opaque;
+ rsa = key->keydata.rsa;
for (i = 0; i < 8; i++) {
bufs[i] = isc_mem_get(key->mctx, BN_num_bytes(rsa->n));
if (rsa == NULL)
DST_RET(ISC_R_NOMEMORY);
SET_FLAGS(rsa);
- key->opaque = rsa;
+ key->keydata.rsa = rsa;
for (i = 0; i < priv.nelements; i++) {
BIGNUM *bn;
--- /dev/null
+-- Copyright (C) The Internet Society 2005. This version of
+-- this module is part of RFC 4178; see the RFC itself for
+-- full legal notices.
+
+-- (The above copyright notice is per RFC 3978 5.6 (a), q.v.)
+
+-- $Id: spnego.asn1,v 1.2 2006/12/04 01:52:46 marka Exp $
+
+-- This is the SPNEGO ASN.1 module from RFC 4178, tweaked
+-- to get the Heimdal ASN.1 compiler to accept it.
+
+SPNEGOASNOneSpec DEFINITIONS ::= BEGIN
+
+MechType ::= OBJECT IDENTIFIER
+
+MechTypeList ::= SEQUENCE OF MechType
+
+ContextFlags ::= BIT STRING {
+ delegFlag (0),
+ mutualFlag (1),
+ replayFlag (2),
+ sequenceFlag (3),
+ anonFlag (4),
+ confFlag (5),
+ integFlag (6)
+}
+
+NegTokenInit ::= SEQUENCE {
+ mechTypes [0] MechTypeList,
+ reqFlags [1] ContextFlags OPTIONAL,
+ mechToken [2] OCTET STRING OPTIONAL,
+ mechListMIC [3] OCTET STRING OPTIONAL
+}
+
+NegTokenResp ::= SEQUENCE {
+ negState [0] ENUMERATED {
+ accept-completed (0),
+ accept-incomplete (1),
+ reject (2),
+ request-mic (3)
+ } OPTIONAL,
+ supportedMech [1] MechType OPTIONAL,
+ responseToken [2] OCTET STRING OPTIONAL,
+ mechListMIC [3] OCTET STRING OPTIONAL
+}
+
+NegotiationToken ::= CHOICE {
+ negTokenInit [0] NegTokenInit,
+ negTokenResp [1] NegTokenResp
+}
+
+END
--- /dev/null
+/*
+ * Copyright (C) 2006 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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 ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC 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: spnego.c,v 1.2 2006/12/04 01:52:46 marka Exp $ */
+
+/*! \file
+ * \brief
+ * Portable SPNEGO implementation.
+ *
+ * This is part of a portable implementation of the SPNEGO protocol
+ * (RFCs 2478 and 4178). This implementation uses the RFC 4178 ASN.1
+ * module but is not a full implementation of the RFC 4178 protocol;
+ * at the moment, we only support GSS-TSIG with Kerberos
+ * authentication, so we only need enough of the SPNEGO protocol to
+ * support that.
+ *
+ * The files that make up this portable SPNEGO implementation are:
+ * \li spnego.c (this file)
+ * \li spnego.h (API SPNEGO exports to the rest of lib/dns)
+ * \li spnego.asn1 (SPNEGO ASN.1 module)
+ * \li spnego_asn1.c (routines generated from spngo.asn1)
+ * \li spnego_asn1.pl (perl script to generate spnego_asn1.c)
+ *
+ * Everything but the functions exported in spnego.h is static, to
+ * avoid possible conflicts with other libraries (particularly Heimdal,
+ * since much of this code comes from Heimdal by way of mod_auth_kerb).
+ *
+ * spnego_asn1.c is shipped as part of lib/dns because generating it
+ * requires both Perl and the Heimdal ASN.1 compiler. See
+ * spnego_asn1.pl for further details. We've tried to eliminate all
+ * compiler warnings from the generated code, but you may see a few
+ * when using a compiler version we haven't tested yet.
+ */
+
+/*
+ * Portions of this code were derived from mod_auth_kerb and Heimdal.
+ * These packages are available from:
+ *
+ * http://modauthkerb.sourceforge.net/
+ * http://www.pdc.kth.se/heimdal/
+ *
+ * and were released under the following licenses:
+ *
+ * ----------------------------------------------------------------
+ *
+ * Copyright (c) 2004 Masarykova universita
+ * (Masaryk University, Brno, Czech Republic)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the University nor the names of its contributors may
+ * be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ----------------------------------------------------------------
+ *
+ * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * XXXSRA We should omit this file entirely in Makefile.in via autoconf,
+ * but this will keep it from generating errors until that's written.
+ */
+
+#ifdef GSSAPI
+
+/*
+ * XXXSRA Some of the following files are almost certainly unnecessary,
+ * but using this list (borrowed from gssapictx.c) gets rid of some
+ * whacky compilation errors when building with MSVC and should be
+ * harmless in any case.
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <errno.h>
+
+#include <isc/buffer.h>
+#include <isc/dir.h>
+#include <isc/entropy.h>
+#include <isc/lex.h>
+#include <isc/mem.h>
+#include <isc/once.h>
+#include <isc/random.h>
+#include <isc/string.h>
+#include <isc/time.h>
+#include <isc/util.h>
+
+#include <dns/fixedname.h>
+#include <dns/name.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/result.h>
+#include <dns/types.h>
+#include <dns/keyvalues.h>
+#include <dns/log.h>
+
+#include <dst/gssapi.h>
+#include <dst/result.h>
+
+#include "dst_internal.h"
+
+/*
+ * The API we export
+ */
+#include "spnego.h"
+
+\f
+
+/*
+ * The isc_mem function keep track of allocation sizes, but we can't
+ * get at that information, and we need to know sizes to implement a
+ * realloc() clone. So we use a little more memory to keep track of
+ * sizes allocated here.
+ *
+ * These functions follow Harbison & Steele, 4th edition, particularly
+ * with regard to realloc()'s behavior.
+ */
+
+static void *
+spnego_malloc(size_t size, const char *file, int line)
+{
+ char *p;
+
+ if (size == 0)
+ return (NULL);
+ p = isc_mem_allocate(dst__memory_pool, size + sizeof(size_t));
+ if (p == NULL)
+ return NULL;
+ *(size_t *)p = size;
+ p += sizeof(size_t);
+#ifdef SPNEGO_ALLOC_DEBUG
+ printf("spnego_malloc(%lu) %lx %s %u\n",
+ (unsigned long) size, (unsigned long) p, file, line);
+#else
+ (void)file;
+ (void)line;
+#endif
+ return (p);
+}
+
+static void
+spnego_free(void *ptr, const char *file, int line)
+{
+ char *p = ptr;
+
+ if (p == NULL)
+ return;
+#ifdef SPNEGO_ALLOC_DEBUG
+ printf("spnego_free(%lx) %s %u\n",
+ (unsigned long) p, file, line);
+#else
+ (void)file;
+ (void)line;
+#endif
+ p -= sizeof(size_t);
+ isc_mem_free(dst__memory_pool, p);
+}
+
+static void *
+spnego_realloc(void *old_ptr, size_t new_size, const char *file, int line)
+{
+ size_t *old_size;
+ void *new_ptr;
+
+ if (old_ptr == NULL)
+ return (spnego_malloc(new_size, file, line));
+
+ if (new_size == 0) {
+ spnego_free(old_ptr, file, line);
+ return (NULL);
+ }
+
+ old_size = old_ptr;
+ old_size--;
+ if (*old_size >= new_size)
+ return (old_ptr);
+
+ new_ptr = spnego_malloc(new_size, file, line);
+ if (new_ptr == NULL)
+ return (NULL);
+
+ memcpy(new_ptr, old_ptr, *old_size);
+ spnego_free(old_ptr, file, line);
+ return (new_ptr);
+}
+
+#define malloc(x) spnego_malloc(x, __FILE__, __LINE__)
+#define free(x) spnego_free(x, __FILE__, __LINE__)
+#define realloc(x,y) spnego_realloc(x, y, __FILE__, __LINE__)
+
+\f
+/* asn1_err.h */
+/* Generated from ../../../lib/asn1/asn1_err.et */
+
+typedef enum asn1_error_number {
+ ASN1_BAD_TIMEFORMAT = 1859794432,
+ ASN1_MISSING_FIELD = 1859794433,
+ ASN1_MISPLACED_FIELD = 1859794434,
+ ASN1_TYPE_MISMATCH = 1859794435,
+ ASN1_OVERFLOW = 1859794436,
+ ASN1_OVERRUN = 1859794437,
+ ASN1_BAD_ID = 1859794438,
+ ASN1_BAD_LENGTH = 1859794439,
+ ASN1_BAD_FORMAT = 1859794440,
+ ASN1_PARSE_ERROR = 1859794441
+} asn1_error_number;
+
+#define ERROR_TABLE_BASE_asn1 1859794432
+
+\f
+
+#define __asn1_common_definitions__
+
+typedef struct octet_string {
+ size_t length;
+ void *data;
+} octet_string;
+
+typedef char *general_string;
+
+typedef char *utf8_string;
+
+typedef struct oid {
+ size_t length;
+ unsigned *components;
+} oid;
+
+\f
+/* der.h */
+
+typedef enum {
+ ASN1_C_UNIV = 0, ASN1_C_APPL = 1,
+ ASN1_C_CONTEXT = 2, ASN1_C_PRIVATE = 3
+} Der_class;
+
+typedef enum {
+ PRIM = 0, CONS = 1
+} Der_type;
+
+/* Universal tags */
+
+enum {
+ UT_Boolean = 1,
+ UT_Integer = 2,
+ UT_BitString = 3,
+ UT_OctetString = 4,
+ UT_Null = 5,
+ UT_OID = 6,
+ UT_Enumerated = 10,
+ UT_Sequence = 16,
+ UT_Set = 17,
+ UT_PrintableString = 19,
+ UT_IA5String = 22,
+ UT_UTCTime = 23,
+ UT_GeneralizedTime = 24,
+ UT_VisibleString = 26,
+ UT_GeneralString = 27
+};
+
+#define ASN1_INDEFINITE 0xdce0deed
+
+static int
+der_get_length(const unsigned char *p, size_t len,
+ size_t * val, size_t * size);
+
+static int
+der_get_octet_string(const unsigned char *p, size_t len,
+ octet_string * data, size_t * size);
+static int
+der_get_oid(const unsigned char *p, size_t len,
+ oid * data, size_t * size);
+static int
+der_get_tag(const unsigned char *p, size_t len,
+ Der_class * class, Der_type * type,
+ int *tag, size_t * size);
+
+static int
+der_match_tag(const unsigned char *p, size_t len,
+ Der_class class, Der_type type,
+ int tag, size_t * size);
+static int
+der_match_tag_and_length(const unsigned char *p, size_t len,
+ Der_class class, Der_type type, int tag,
+ size_t * length_ret, size_t * size);
+
+static int
+decode_oid(const unsigned char *p, size_t len,
+ oid * k, size_t * size);
+
+static int
+decode_enumerated(const unsigned char *p, size_t len,
+ unsigned *num, size_t *size);
+
+static int
+decode_octet_string(const unsigned char *, size_t, octet_string *, size_t *);
+
+static int
+der_put_int(unsigned char *p, size_t len, int val, size_t *);
+
+static int
+der_put_length(unsigned char *p, size_t len, size_t val, size_t *);
+
+static int
+der_put_octet_string(unsigned char *p, size_t len,
+ const octet_string * data, size_t *);
+static int
+der_put_oid(unsigned char *p, size_t len,
+ const oid * data, size_t * size);
+static int
+der_put_tag(unsigned char *p, size_t len, Der_class class, Der_type type,
+ int tag, size_t *);
+static int
+der_put_length_and_tag(unsigned char *, size_t, size_t,
+ Der_class, Der_type, int, size_t *);
+
+static int
+encode_enumerated(unsigned char *p, size_t len,
+ const unsigned *data, size_t *);
+
+static int
+encode_octet_string(unsigned char *p, size_t len,
+ const octet_string * k, size_t *);
+static int
+encode_oid(unsigned char *p, size_t len,
+ const oid * k, size_t *);
+
+static void
+free_octet_string(octet_string * k);
+
+static void
+free_oid (oid * k);
+
+static size_t
+length_len(size_t len);
+
+static int
+fix_dce(size_t reallen, size_t * len);
+
+\f
+
+/*
+ * Include stuff generated by the ASN.1 compiler.
+ */
+
+#include "spnego_asn1.c"
+
+\f
+
+static unsigned char gss_krb5_mech_oid_bytes[] = {
+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x01, 0x02, 0x02
+};
+
+static gss_OID_desc gss_krb5_mech_oid_desc = {
+ sizeof(gss_krb5_mech_oid_bytes),
+ gss_krb5_mech_oid_bytes
+};
+
+static gss_OID GSS_KRB5_MECH = &gss_krb5_mech_oid_desc;
+
+static unsigned char gss_mskrb5_mech_oid_bytes[] = {
+ 0x2a, 0x86, 0x48, 0x82, 0xf7, 0x12, 0x01, 0x02, 0x02
+};
+
+static gss_OID_desc gss_mskrb5_mech_oid_desc = {
+ sizeof(gss_mskrb5_mech_oid_bytes),
+ gss_mskrb5_mech_oid_bytes
+};
+
+static gss_OID GSS_MSKRB5_MECH = &gss_mskrb5_mech_oid_desc;
+
+static unsigned char gss_spnego_mech_oid_bytes[] = {
+ 0x2b, 0x06, 0x01, 0x05, 0x05, 0x02
+};
+
+static gss_OID_desc gss_spnego_mech_oid_desc = {
+ sizeof(gss_spnego_mech_oid_bytes),
+ gss_spnego_mech_oid_bytes
+};
+
+static gss_OID GSS_SPNEGO_MECH = &gss_spnego_mech_oid_desc;
+
+\f
+/* spnegokrb5_locl.h */
+
+static OM_uint32
+gssapi_spnego_encapsulate(OM_uint32 *,
+ unsigned char *,
+ size_t,
+ gss_buffer_t,
+ const gss_OID);
+
+static OM_uint32
+gssapi_spnego_decapsulate(OM_uint32 *,
+ gss_buffer_t,
+ unsigned char **,
+ size_t *,
+ const gss_OID);
+
+\f
+/* mod_auth_kerb.c */
+
+static int
+cmp_gss_type(gss_buffer_t token, gss_OID oid)
+{
+ unsigned char *p;
+ size_t len;
+
+ if (token->length == 0)
+ return (GSS_S_DEFECTIVE_TOKEN);
+
+ p = token->value;
+ if (*p++ != 0x60)
+ return (GSS_S_DEFECTIVE_TOKEN);
+ len = *p++;
+ if (len & 0x80) {
+ if ((len & 0x7f) > 4)
+ return (GSS_S_DEFECTIVE_TOKEN);
+ p += len & 0x7f;
+ }
+ if (*p++ != 0x06)
+ return (GSS_S_DEFECTIVE_TOKEN);
+
+ if (((OM_uint32) *p++) != oid->length)
+ return (GSS_S_DEFECTIVE_TOKEN);
+
+ return (memcmp(p, oid->elements, oid->length));
+}
+\f
+/* accept_sec_context.c */
+/*
+ * SPNEGO wrapper for Kerberos5 GSS-API kouril@ics.muni.cz, 2003 (mostly
+ * based on Heimdal code)
+ */
+
+static OM_uint32
+code_NegTokenArg(OM_uint32 * minor_status,
+ const NegTokenResp * resp,
+ unsigned char **outbuf,
+ size_t * outbuf_size)
+{
+ OM_uint32 ret;
+ u_char *buf;
+ size_t buf_size, buf_len;
+
+ buf_size = 1024;
+ buf = malloc(buf_size);
+ if (buf == NULL) {
+ *minor_status = ENOMEM;
+ return (GSS_S_FAILURE);
+ }
+ do {
+ ret = encode_NegTokenResp(buf + buf_size - 1,
+ buf_size,
+ resp, &buf_len);
+ if (ret == 0) {
+ size_t tmp;
+
+ ret = der_put_length_and_tag(buf + buf_size - buf_len - 1,
+ buf_size - buf_len,
+ buf_len,
+ ASN1_C_CONTEXT,
+ CONS,
+ 1,
+ &tmp);
+ if (ret == 0)
+ buf_len += tmp;
+ }
+ if (ret) {
+ if (ret == ASN1_OVERFLOW) {
+ u_char *tmp;
+
+ buf_size *= 2;
+ tmp = realloc(buf, buf_size);
+ if (tmp == NULL) {
+ *minor_status = ENOMEM;
+ free(buf);
+ return (GSS_S_FAILURE);
+ }
+ buf = tmp;
+ } else {
+ *minor_status = ret;
+ free(buf);
+ return (GSS_S_FAILURE);
+ }
+ }
+ } while (ret == ASN1_OVERFLOW);
+
+ *outbuf = malloc(buf_len);
+ if (*outbuf == NULL) {
+ *minor_status = ENOMEM;
+ free(buf);
+ return (GSS_S_FAILURE);
+ }
+ memcpy(*outbuf, buf + buf_size - buf_len, buf_len);
+ *outbuf_size = buf_len;
+
+ free(buf);
+
+ return (GSS_S_COMPLETE);
+}
+
+static OM_uint32
+send_reject(OM_uint32 * minor_status,
+ gss_buffer_t output_token)
+{
+ NegTokenResp resp;
+ OM_uint32 ret;
+
+ resp.negState = malloc(sizeof(*resp.negState));
+ if (resp.negState == NULL) {
+ *minor_status = ENOMEM;
+ return (GSS_S_FAILURE);
+ }
+ *(resp.negState) = reject;
+
+ resp.supportedMech = NULL;
+ resp.responseToken = NULL;
+ resp.mechListMIC = NULL;
+
+ ret = code_NegTokenArg(minor_status, &resp,
+ (unsigned char **)&output_token->value,
+ &output_token->length);
+ free_NegTokenResp(&resp);
+ if (ret)
+ return (ret);
+
+ return (GSS_S_BAD_MECH);
+}
+
+static OM_uint32
+send_accept(OM_uint32 * minor_status,
+ gss_buffer_t output_token,
+ gss_buffer_t mech_token,
+ const gss_OID pref)
+{
+ NegTokenResp resp;
+ OM_uint32 ret;
+
+ memset(&resp, 0, sizeof(resp));
+ resp.negState = malloc(sizeof(*resp.negState));
+ if (resp.negState == NULL) {
+ *minor_status = ENOMEM;
+ return (GSS_S_FAILURE);
+ }
+ *(resp.negState) = accept_completed;
+
+ resp.supportedMech = malloc(sizeof(*resp.supportedMech));
+ if (resp.supportedMech == NULL) {
+ free_NegTokenResp(&resp);
+ *minor_status = ENOMEM;
+ return (GSS_S_FAILURE);
+ }
+ ret = der_get_oid(pref->elements,
+ pref->length,
+ resp.supportedMech,
+ NULL);
+ if (ret) {
+ free_NegTokenResp(&resp);
+ *minor_status = ENOMEM;
+ return (GSS_S_FAILURE);
+ }
+ if (mech_token != NULL && mech_token->length != 0) {
+ resp.responseToken = malloc(sizeof(*resp.responseToken));
+ if (resp.responseToken == NULL) {
+ free_NegTokenResp(&resp);
+ *minor_status = ENOMEM;
+ return (GSS_S_FAILURE);
+ }
+ resp.responseToken->length = mech_token->length;
+ resp.responseToken->data = mech_token->value;
+ }
+
+ ret = code_NegTokenArg(minor_status, &resp,
+ (unsigned char **)&output_token->value,
+ &output_token->length);
+ if (resp.responseToken != NULL) {
+ free(resp.responseToken);
+ resp.responseToken = NULL;
+ }
+ free_NegTokenResp(&resp);
+ if (ret)
+ return (ret);
+
+ return (GSS_S_COMPLETE);
+}
+
+OM_uint32
+gss_accept_sec_context_spnego(OM_uint32 *minor_status,
+ gss_ctx_id_t *context_handle,
+ const gss_cred_id_t acceptor_cred_handle,
+ const gss_buffer_t input_token_buffer,
+ const gss_channel_bindings_t input_chan_bindings,
+ gss_name_t *src_name,
+ gss_OID *mech_type,
+ gss_buffer_t output_token,
+ OM_uint32 *ret_flags,
+ OM_uint32 *time_rec,
+ gss_cred_id_t *delegated_cred_handle)
+{
+ NegTokenInit init_token;
+ OM_uint32 major_status;
+ OM_uint32 minor_status2;
+ gss_buffer_desc ibuf, obuf;
+ gss_buffer_t ot = NULL;
+ gss_OID pref = GSS_KRB5_MECH;
+ unsigned char *buf;
+ size_t buf_size;
+ size_t len, taglen, ni_len;
+ int found = 0;
+ int ret;
+ unsigned i;
+
+ /*
+ * Before doing anything else, see whether this is a SPNEGO
+ * PDU. If not, dispatch to the GSSAPI library and get out.
+ */
+
+ if (cmp_gss_type(input_token_buffer, GSS_SPNEGO_MECH))
+ return (gss_accept_sec_context(minor_status,
+ context_handle,
+ acceptor_cred_handle,
+ input_token_buffer,
+ input_chan_bindings,
+ src_name,
+ mech_type,
+ output_token,
+ ret_flags,
+ time_rec,
+ delegated_cred_handle));
+
+ /*
+ * If we get here, it's SPNEGO.
+ */
+
+ memset(&init_token, 0, sizeof(init_token));
+
+ ret = gssapi_spnego_decapsulate(minor_status, input_token_buffer,
+ &buf, &buf_size, GSS_SPNEGO_MECH);
+ if (ret)
+ return (ret);
+
+ ret = der_match_tag_and_length(buf, buf_size, ASN1_C_CONTEXT, CONS,
+ 0, &len, &taglen);
+ if (ret)
+ return (ret);
+
+ ret = decode_NegTokenInit(buf + taglen, len, &init_token, &ni_len);
+ if (ret) {
+ *minor_status = EINVAL; /* XXX */
+ return (GSS_S_DEFECTIVE_TOKEN);
+ }
+
+ for (i = 0; !found && i < init_token.mechTypes.len; ++i) {
+ char mechbuf[17];
+ size_t mech_len;
+
+ ret = der_put_oid(mechbuf + sizeof(mechbuf) - 1,
+ sizeof(mechbuf),
+ &init_token.mechTypes.val[i],
+ &mech_len);
+ if (ret)
+ return (GSS_S_DEFECTIVE_TOKEN);
+ if (mech_len == GSS_KRB5_MECH->length &&
+ memcmp(GSS_KRB5_MECH->elements,
+ mechbuf + sizeof(mechbuf) - mech_len,
+ mech_len) == 0) {
+ found = 1;
+ break;
+ }
+ if (mech_len == GSS_MSKRB5_MECH->length &&
+ memcmp(GSS_MSKRB5_MECH->elements,
+ mechbuf + sizeof(mechbuf) - mech_len,
+ mech_len) == 0) {
+ found = 1;
+ if (i == 0)
+ pref = GSS_MSKRB5_MECH;
+ break;
+ }
+ }
+
+ if (!found)
+ return (send_reject(minor_status, output_token));
+
+ if (i == 0 && init_token.mechToken != NULL) {
+ ibuf.length = init_token.mechToken->length;
+ ibuf.value = init_token.mechToken->data;
+
+ major_status = gss_accept_sec_context(minor_status,
+ context_handle,
+ acceptor_cred_handle,
+ &ibuf,
+ input_chan_bindings,
+ src_name,
+ mech_type,
+ &obuf,
+ ret_flags,
+ time_rec,
+ delegated_cred_handle);
+ if (GSS_ERROR(major_status)) {
+ send_reject(&minor_status2, output_token);
+ return (major_status);
+ }
+ ot = &obuf;
+ }
+ ret = send_accept(&minor_status2, output_token, ot, pref);
+ if (ot != NULL)
+ gss_release_buffer(&minor_status2, ot);
+
+ return (ret);
+}
+\f
+/* decapsulate.c */
+
+static OM_uint32
+gssapi_verify_mech_header(u_char ** str,
+ size_t total_len,
+ const gss_OID mech)
+{
+ size_t len, len_len, mech_len, foo;
+ int e;
+ u_char *p = *str;
+
+ if (total_len < 1)
+ return (GSS_S_DEFECTIVE_TOKEN);
+ if (*p++ != 0x60)
+ return (GSS_S_DEFECTIVE_TOKEN);
+ e = der_get_length(p, total_len - 1, &len, &len_len);
+ if (e || 1 + len_len + len != total_len)
+ return (GSS_S_DEFECTIVE_TOKEN);
+ p += len_len;
+ if (*p++ != 0x06)
+ return (GSS_S_DEFECTIVE_TOKEN);
+ e = der_get_length(p, total_len - 1 - len_len - 1,
+ &mech_len, &foo);
+ if (e)
+ return (GSS_S_DEFECTIVE_TOKEN);
+ p += foo;
+ if (mech_len != mech->length)
+ return (GSS_S_BAD_MECH);
+ if (memcmp(p, mech->elements, mech->length) != 0)
+ return (GSS_S_BAD_MECH);
+ p += mech_len;
+ *str = p;
+ return (GSS_S_COMPLETE);
+}
+
+/*
+ * Remove the GSS-API wrapping from `in_token' giving `buf and buf_size' Does
+ * not copy data, so just free `in_token'.
+ */
+
+static OM_uint32
+gssapi_spnego_decapsulate(OM_uint32 *minor_status,
+ gss_buffer_t input_token_buffer,
+ unsigned char **buf,
+ size_t *buf_len,
+ const gss_OID mech)
+{
+ u_char *p;
+ OM_uint32 ret;
+
+ p = input_token_buffer->value;
+ ret = gssapi_verify_mech_header(&p,
+ input_token_buffer->length,
+ mech);
+ if (ret) {
+ *minor_status = ret;
+ return (GSS_S_FAILURE);
+ }
+ *buf_len = input_token_buffer->length -
+ (p - (u_char *) input_token_buffer->value);
+ *buf = p;
+ return (GSS_S_COMPLETE);
+}
+\f
+/* der_free.c */
+
+static void
+free_octet_string(octet_string *k)
+{
+ free(k->data);
+ k->data = NULL;
+}
+
+static void
+free_oid(oid *k)
+{
+ free(k->components);
+ k->components = NULL;
+}
+\f
+/* der_get.c */
+
+/*
+ * All decoding functions take a pointer `p' to first position in which to
+ * read, from the left, `len' which means the maximum number of characters we
+ * are able to read, `ret' were the value will be returned and `size' where
+ * the number of used bytes is stored. Either 0 or an error code is returned.
+ */
+
+static int
+der_get_unsigned(const unsigned char *p, size_t len,
+ unsigned *ret, size_t *size)
+{
+ unsigned val = 0;
+ size_t oldlen = len;
+
+ while (len--)
+ val = val * 256 + *p++;
+ *ret = val;
+ if (size)
+ *size = oldlen;
+ return (0);
+}
+
+static int
+der_get_int(const unsigned char *p, size_t len,
+ int *ret, size_t *size)
+{
+ int val = 0;
+ size_t oldlen = len;
+
+ if (len > 0) {
+ val = (signed char)*p++;
+ while (--len)
+ val = val * 256 + *p++;
+ }
+ *ret = val;
+ if (size)
+ *size = oldlen;
+ return (0);
+}
+
+static int
+der_get_length(const unsigned char *p, size_t len,
+ size_t *val, size_t *size)
+{
+ size_t v;
+
+ if (len <= 0)
+ return (ASN1_OVERRUN);
+ --len;
+ v = *p++;
+ if (v < 128) {
+ *val = v;
+ if (size)
+ *size = 1;
+ } else {
+ int e;
+ size_t l;
+ unsigned tmp;
+
+ if (v == 0x80) {
+ *val = ASN1_INDEFINITE;
+ if (size)
+ *size = 1;
+ return (0);
+ }
+ v &= 0x7F;
+ if (len < v)
+ return (ASN1_OVERRUN);
+ e = der_get_unsigned(p, v, &tmp, &l);
+ if (e)
+ return (e);
+ *val = tmp;
+ if (size)
+ *size = l + 1;
+ }
+ return (0);
+}
+
+static int
+der_get_octet_string(const unsigned char *p, size_t len,
+ octet_string *data, size_t *size)
+{
+ data->length = len;
+ data->data = malloc(len);
+ if (data->data == NULL && data->length != 0)
+ return (ENOMEM);
+ memcpy(data->data, p, len);
+ if (size)
+ *size = len;
+ return (0);
+}
+
+static int
+der_get_oid(const unsigned char *p, size_t len,
+ oid *data, size_t *size)
+{
+ int n;
+ size_t oldlen = len;
+
+ if (len < 1)
+ return (ASN1_OVERRUN);
+
+ data->components = malloc(len * sizeof(*data->components));
+ if (data->components == NULL && len != 0)
+ return (ENOMEM);
+ data->components[0] = (*p) / 40;
+ data->components[1] = (*p) % 40;
+ --len;
+ ++p;
+ for (n = 2; len > 0; ++n) {
+ unsigned u = 0;
+
+ do {
+ --len;
+ u = u * 128 + (*p++ % 128);
+ } while (len > 0 && p[-1] & 0x80);
+ data->components[n] = u;
+ }
+ if (p[-1] & 0x80) {
+ free_oid(data);
+ return (ASN1_OVERRUN);
+ }
+ data->length = n;
+ if (size)
+ *size = oldlen;
+ return (0);
+}
+
+static int
+der_get_tag(const unsigned char *p, size_t len,
+ Der_class *class, Der_type *type,
+ int *tag, size_t *size)
+{
+ if (len < 1)
+ return (ASN1_OVERRUN);
+ *class = (Der_class) (((*p) >> 6) & 0x03);
+ *type = (Der_type) (((*p) >> 5) & 0x01);
+ *tag = (*p) & 0x1F;
+ if (size)
+ *size = 1;
+ return (0);
+}
+
+static int
+der_match_tag(const unsigned char *p, size_t len,
+ Der_class class, Der_type type,
+ int tag, size_t *size)
+{
+ size_t l;
+ Der_class thisclass;
+ Der_type thistype;
+ int thistag;
+ int e;
+
+ e = der_get_tag(p, len, &thisclass, &thistype, &thistag, &l);
+ if (e)
+ return (e);
+ if (class != thisclass || type != thistype)
+ return (ASN1_BAD_ID);
+ if (tag > thistag)
+ return (ASN1_MISPLACED_FIELD);
+ if (tag < thistag)
+ return (ASN1_MISSING_FIELD);
+ if (size)
+ *size = l;
+ return (0);
+}
+
+static int
+der_match_tag_and_length(const unsigned char *p, size_t len,
+ Der_class class, Der_type type, int tag,
+ size_t *length_ret, size_t *size)
+{
+ size_t l, ret = 0;
+ int e;
+
+ e = der_match_tag(p, len, class, type, tag, &l);
+ if (e)
+ return (e);
+ p += l;
+ len -= l;
+ ret += l;
+ e = der_get_length(p, len, length_ret, &l);
+ if (e)
+ return (e);
+ p += l;
+ len -= l;
+ ret += l;
+ if (size)
+ *size = ret;
+ return (0);
+}
+
+static int
+decode_enumerated(const unsigned char *p, size_t len,
+ unsigned *num, size_t *size)
+{
+ size_t ret = 0;
+ size_t l, reallen;
+ int e;
+
+ e = der_match_tag(p, len, ASN1_C_UNIV, PRIM, UT_Enumerated, &l);
+ if (e)
+ return (e);
+ p += l;
+ len -= l;
+ ret += l;
+ e = der_get_length(p, len, &reallen, &l);
+ if (e)
+ return (e);
+ p += l;
+ len -= l;
+ ret += l;
+ e = der_get_int(p, reallen, num, &l);
+ if (e)
+ return (e);
+ p += l;
+ len -= l;
+ ret += l;
+ if (size)
+ *size = ret;
+ return (0);
+}
+
+static int
+decode_octet_string(const unsigned char *p, size_t len,
+ octet_string *k, size_t *size)
+{
+ size_t ret = 0;
+ size_t l;
+ int e;
+ size_t slen;
+
+ e = der_match_tag(p, len, ASN1_C_UNIV, PRIM, UT_OctetString, &l);
+ if (e)
+ return (e);
+ p += l;
+ len -= l;
+ ret += l;
+
+ e = der_get_length(p, len, &slen, &l);
+ if (e)
+ return (e);
+ p += l;
+ len -= l;
+ ret += l;
+ if (len < slen)
+ return (ASN1_OVERRUN);
+
+ e = der_get_octet_string(p, slen, k, &l);
+ if (e)
+ return (e);
+ p += l;
+ len -= l;
+ ret += l;
+ if (size)
+ *size = ret;
+ return (0);
+}
+
+static int
+decode_oid(const unsigned char *p, size_t len,
+ oid *k, size_t *size)
+{
+ size_t ret = 0;
+ size_t l;
+ int e;
+ size_t slen;
+
+ e = der_match_tag(p, len, ASN1_C_UNIV, PRIM, UT_OID, &l);
+ if (e)
+ return (e);
+ p += l;
+ len -= l;
+ ret += l;
+
+ e = der_get_length(p, len, &slen, &l);
+ if (e)
+ return (e);
+ p += l;
+ len -= l;
+ ret += l;
+ if (len < slen)
+ return (ASN1_OVERRUN);
+
+ e = der_get_oid(p, slen, k, &l);
+ if (e)
+ return (e);
+ p += l;
+ len -= l;
+ ret += l;
+ if (size)
+ *size = ret;
+ return (0);
+}
+
+static int
+fix_dce(size_t reallen, size_t *len)
+{
+ if (reallen == ASN1_INDEFINITE)
+ return (1);
+ if (*len < reallen)
+ return (-1);
+ *len = reallen;
+ return (0);
+}
+\f
+/* der_length.c */
+
+static size_t
+len_unsigned(unsigned val)
+{
+ size_t ret = 0;
+
+ do {
+ ++ret;
+ val /= 256;
+ } while (val);
+ return (ret);
+}
+
+static size_t
+length_len(size_t len)
+{
+ if (len < 128)
+ return (1);
+ else
+ return (len_unsigned(len) + 1);
+}
+
+\f
+/* der_put.c */
+
+/*
+ * All encoding functions take a pointer `p' to first position in which to
+ * write, from the right, `len' which means the maximum number of characters
+ * we are able to write. The function returns the number of characters
+ * written in `size' (if non-NULL). The return value is 0 or an error.
+ */
+
+static int
+der_put_unsigned(unsigned char *p, size_t len, unsigned val, size_t *size)
+{
+ unsigned char *base = p;
+
+ if (val) {
+ while (len > 0 && val) {
+ *p-- = val % 256;
+ val /= 256;
+ --len;
+ }
+ if (val != 0)
+ return (ASN1_OVERFLOW);
+ else {
+ *size = base - p;
+ return (0);
+ }
+ } else if (len < 1)
+ return (ASN1_OVERFLOW);
+ else {
+ *p = 0;
+ *size = 1;
+ return (0);
+ }
+}
+
+static int
+der_put_int(unsigned char *p, size_t len, int val, size_t *size)
+{
+ unsigned char *base = p;
+
+ if (val >= 0) {
+ do {
+ if (len < 1)
+ return (ASN1_OVERFLOW);
+ *p-- = val % 256;
+ len--;
+ val /= 256;
+ } while (val);
+ if (p[1] >= 128) {
+ if (len < 1)
+ return (ASN1_OVERFLOW);
+ *p-- = 0;
+ len--;
+ }
+ } else {
+ val = ~val;
+ do {
+ if (len < 1)
+ return (ASN1_OVERFLOW);
+ *p-- = ~(val % 256);
+ len--;
+ val /= 256;
+ } while (val);
+ if (p[1] < 128) {
+ if (len < 1)
+ return (ASN1_OVERFLOW);
+ *p-- = 0xff;
+ len--;
+ }
+ }
+ *size = base - p;
+ return (0);
+}
+
+static int
+der_put_length(unsigned char *p, size_t len, size_t val, size_t *size)
+{
+ if (len < 1)
+ return (ASN1_OVERFLOW);
+ if (val < 128) {
+ *p = val;
+ *size = 1;
+ return (0);
+ } else {
+ size_t l;
+ int e;
+
+ e = der_put_unsigned(p, len - 1, val, &l);
+ if (e)
+ return (e);
+ p -= l;
+ *p = 0x80 | l;
+ *size = l + 1;
+ return (0);
+ }
+}
+
+static int
+der_put_octet_string(unsigned char *p, size_t len,
+ const octet_string *data, size_t *size)
+{
+ if (len < data->length)
+ return (ASN1_OVERFLOW);
+ p -= data->length;
+ len -= data->length;
+ memcpy(p + 1, data->data, data->length);
+ *size = data->length;
+ return (0);
+}
+
+static int
+der_put_oid(unsigned char *p, size_t len,
+ const oid *data, size_t *size)
+{
+ unsigned char *base = p;
+ int n;
+
+ for (n = data->length - 1; n >= 2; --n) {
+ unsigned u = data->components[n];
+
+ if (len < 1)
+ return (ASN1_OVERFLOW);
+ *p-- = u % 128;
+ u /= 128;
+ --len;
+ while (u > 0) {
+ if (len < 1)
+ return (ASN1_OVERFLOW);
+ *p-- = 128 + u % 128;
+ u /= 128;
+ --len;
+ }
+ }
+ if (len < 1)
+ return (ASN1_OVERFLOW);
+ *p-- = 40 * data->components[0] + data->components[1];
+ *size = base - p;
+ return (0);
+}
+
+static int
+der_put_tag(unsigned char *p, size_t len, Der_class class, Der_type type,
+ int tag, size_t *size)
+{
+ if (len < 1)
+ return (ASN1_OVERFLOW);
+ *p = (class << 6) | (type << 5) | tag; /* XXX */
+ *size = 1;
+ return (0);
+}
+
+static int
+der_put_length_and_tag(unsigned char *p, size_t len, size_t len_val,
+ Der_class class, Der_type type, int tag, size_t *size)
+{
+ size_t ret = 0;
+ size_t l;
+ int e;
+
+ e = der_put_length(p, len, len_val, &l);
+ if (e)
+ return (e);
+ p -= l;
+ len -= l;
+ ret += l;
+ e = der_put_tag(p, len, class, type, tag, &l);
+ if (e)
+ return (e);
+ p -= l;
+ len -= l;
+ ret += l;
+ *size = ret;
+ return (0);
+}
+
+static int
+encode_enumerated(unsigned char *p, size_t len, const unsigned *data,
+ size_t *size)
+{
+ unsigned num = *data;
+ size_t ret = 0;
+ size_t l;
+ int e;
+
+ e = der_put_int(p, len, num, &l);
+ if (e)
+ return (e);
+ p -= l;
+ len -= l;
+ ret += l;
+ e = der_put_length_and_tag(p, len, l, ASN1_C_UNIV, PRIM, UT_Enumerated, &l);
+ if (e)
+ return (e);
+ p -= l;
+ len -= l;
+ ret += l;
+ *size = ret;
+ return (0);
+}
+
+static int
+encode_octet_string(unsigned char *p, size_t len,
+ const octet_string *k, size_t *size)
+{
+ size_t ret = 0;
+ size_t l;
+ int e;
+
+ e = der_put_octet_string(p, len, k, &l);
+ if (e)
+ return (e);
+ p -= l;
+ len -= l;
+ ret += l;
+ e = der_put_length_and_tag(p, len, l, ASN1_C_UNIV, PRIM, UT_OctetString, &l);
+ if (e)
+ return (e);
+ p -= l;
+ len -= l;
+ ret += l;
+ *size = ret;
+ return (0);
+}
+
+static int
+encode_oid(unsigned char *p, size_t len,
+ const oid *k, size_t *size)
+{
+ size_t ret = 0;
+ size_t l;
+ int e;
+
+ e = der_put_oid(p, len, k, &l);
+ if (e)
+ return (e);
+ p -= l;
+ len -= l;
+ ret += l;
+ e = der_put_length_and_tag(p, len, l, ASN1_C_UNIV, PRIM, UT_OID, &l);
+ if (e)
+ return (e);
+ p -= l;
+ len -= l;
+ ret += l;
+ *size = ret;
+ return (0);
+}
+
+\f
+/* encapsulate.c */
+
+static void
+gssapi_encap_length(size_t data_len,
+ size_t *len,
+ size_t *total_len,
+ const gss_OID mech)
+{
+ size_t len_len;
+
+ *len = 1 + 1 + mech->length + data_len;
+
+ len_len = length_len(*len);
+
+ *total_len = 1 + len_len + *len;
+}
+
+static u_char *
+gssapi_mech_make_header(u_char *p,
+ size_t len,
+ const gss_OID mech)
+{
+ int e;
+ size_t len_len, foo;
+
+ *p++ = 0x60;
+ len_len = length_len(len);
+ e = der_put_length(p + len_len - 1, len_len, len, &foo);
+ if (e || foo != len_len)
+ return (NULL);
+ p += len_len;
+ *p++ = 0x06;
+ *p++ = mech->length;
+ memcpy(p, mech->elements, mech->length);
+ p += mech->length;
+ return (p);
+}
+
+/*
+ * Give it a krb5_data and it will encapsulate with extra GSS-API wrappings.
+ */
+
+static OM_uint32
+gssapi_spnego_encapsulate(OM_uint32 * minor_status,
+ unsigned char *buf,
+ size_t buf_size,
+ gss_buffer_t output_token,
+ const gss_OID mech)
+{
+ size_t len, outer_len;
+ u_char *p;
+
+ gssapi_encap_length(buf_size, &len, &outer_len, mech);
+
+ output_token->length = outer_len;
+ output_token->value = malloc(outer_len);
+ if (output_token->value == NULL) {
+ *minor_status = ENOMEM;
+ return (GSS_S_FAILURE);
+ }
+ p = gssapi_mech_make_header(output_token->value, len, mech);
+ if (p == NULL)
+ return (GSS_S_FAILURE);
+ memcpy(p, buf, buf_size);
+ return (GSS_S_COMPLETE);
+}
+\f
+/* init_sec_context.c */
+/*
+ * SPNEGO wrapper for Kerberos5 GSS-API kouril@ics.muni.cz, 2003 (mostly
+ * based on Heimdal code)
+ */
+
+static int
+add_mech(MechTypeList * mech_list, gss_OID mech)
+{
+ MechType *tmp;
+ int ret;
+
+ tmp = realloc(mech_list->val, (mech_list->len + 1) * sizeof(*tmp));
+ if (tmp == NULL)
+ return (ENOMEM);
+ mech_list->val = tmp;
+
+ ret = der_get_oid(mech->elements, mech->length,
+ &mech_list->val[mech_list->len], NULL);
+ if (ret)
+ return (ret);
+
+ mech_list->len++;
+ return (0);
+}
+
+/*
+ * return the length of the mechanism in token or -1
+ * (which implies that the token was bad - GSS_S_DEFECTIVE_TOKEN
+ */
+
+static ssize_t
+gssapi_krb5_get_mech(const u_char *ptr,
+ size_t total_len,
+ const u_char **mech_ret)
+{
+ size_t len, len_len, mech_len, foo;
+ const u_char *p = ptr;
+ int e;
+
+ if (total_len < 1)
+ return (-1);
+ if (*p++ != 0x60)
+ return (-1);
+ e = der_get_length (p, total_len - 1, &len, &len_len);
+ if (e || 1 + len_len + len != total_len)
+ return (-1);
+ p += len_len;
+ if (*p++ != 0x06)
+ return (-1);
+ e = der_get_length (p, total_len - 1 - len_len - 1,
+ &mech_len, &foo);
+ if (e)
+ return (-1);
+ p += foo;
+ *mech_ret = p;
+ return (mech_len);
+}
+
+static OM_uint32
+spnego_initial(OM_uint32 *minor_status,
+ const gss_cred_id_t initiator_cred_handle,
+ gss_ctx_id_t *context_handle,
+ const gss_name_t target_name,
+ const gss_OID mech_type,
+ OM_uint32 req_flags,
+ OM_uint32 time_req,
+ const gss_channel_bindings_t input_chan_bindings,
+ const gss_buffer_t input_token,
+ gss_OID *actual_mech_type,
+ gss_buffer_t output_token,
+ OM_uint32 *ret_flags,
+ OM_uint32 *time_rec)
+{
+ NegTokenInit token_init;
+ OM_uint32 major_status, minor_status2;
+ gss_buffer_desc krb5_output_token = GSS_C_EMPTY_BUFFER;
+ unsigned char *buf = NULL;
+ size_t buf_size;
+ size_t len;
+ int ret;
+
+ (void)mech_type;
+
+ memset(&token_init, 0, sizeof(token_init));
+
+ ret = add_mech(&token_init.mechTypes, GSS_KRB5_MECH);
+ if (ret) {
+ *minor_status = ret;
+ ret = GSS_S_FAILURE;
+ goto end;
+ }
+
+ major_status = gss_init_sec_context(minor_status,
+ initiator_cred_handle,
+ context_handle,
+ target_name,
+ GSS_KRB5_MECH,
+ req_flags,
+ time_req,
+ input_chan_bindings,
+ input_token,
+ actual_mech_type,
+ &krb5_output_token,
+ ret_flags,
+ time_rec);
+ if (GSS_ERROR(major_status)) {
+ ret = major_status;
+ goto end;
+ }
+ if (krb5_output_token.length > 0) {
+ token_init.mechToken = malloc(sizeof(*token_init.mechToken));
+ if (token_init.mechToken == NULL) {
+ *minor_status = ENOMEM;
+ ret = GSS_S_FAILURE;
+ goto end;
+ }
+ token_init.mechToken->data = krb5_output_token.value;
+ token_init.mechToken->length = krb5_output_token.length;
+ }
+ /*
+ * The MS implementation of SPNEGO seems to not like the mechListMIC
+ * field, so we omit it (it's optional anyway)
+ */
+
+ buf_size = 1024;
+ buf = malloc(buf_size);
+
+ do {
+ ret = encode_NegTokenInit(buf + buf_size - 1,
+ buf_size,
+ &token_init, &len);
+ if (ret == 0) {
+ size_t tmp;
+
+ ret = der_put_length_and_tag(buf + buf_size - len - 1,
+ buf_size - len,
+ len,
+ ASN1_C_CONTEXT,
+ CONS,
+ 0,
+ &tmp);
+ if (ret == 0)
+ len += tmp;
+ }
+ if (ret) {
+ if (ret == ASN1_OVERFLOW) {
+ u_char *tmp;
+
+ buf_size *= 2;
+ tmp = realloc(buf, buf_size);
+ if (tmp == NULL) {
+ *minor_status = ENOMEM;
+ ret = GSS_S_FAILURE;
+ goto end;
+ }
+ buf = tmp;
+ } else {
+ *minor_status = ret;
+ ret = GSS_S_FAILURE;
+ goto end;
+ }
+ }
+ } while (ret == ASN1_OVERFLOW);
+
+ ret = gssapi_spnego_encapsulate(minor_status,
+ buf + buf_size - len, len,
+ output_token, GSS_SPNEGO_MECH);
+
+ ret = major_status;
+
+end:
+ if (token_init.mechToken != NULL) {
+ free(token_init.mechToken);
+ token_init.mechToken = NULL;
+ }
+ free_NegTokenInit(&token_init);
+ if (krb5_output_token.length > 0)
+ gss_release_buffer(&minor_status2, &krb5_output_token);
+ if (buf)
+ free(buf);
+
+ return (ret);
+}
+
+static OM_uint32
+spnego_reply(OM_uint32 *minor_status,
+ const gss_cred_id_t initiator_cred_handle,
+ gss_ctx_id_t *context_handle,
+ const gss_name_t target_name,
+ const gss_OID mech_type,
+ OM_uint32 req_flags,
+ OM_uint32 time_req,
+ const gss_channel_bindings_t input_chan_bindings,
+ const gss_buffer_t input_token,
+ gss_OID *actual_mech_type,
+ gss_buffer_t output_token,
+ OM_uint32 *ret_flags,
+ OM_uint32 *time_rec)
+{
+ OM_uint32 ret;
+ NegTokenResp resp;
+ unsigned char *buf;
+ size_t buf_size;
+ u_char oidbuf[17];
+ size_t oidlen;
+ gss_buffer_desc sub_token;
+ ssize_t mech_len;
+ const u_char *p;
+ size_t len, taglen;
+
+ (void)mech_type;
+
+ output_token->length = 0;
+ output_token->value = NULL;
+
+ /*
+ * SPNEGO doesn't include gss wrapping on SubsequentContextToken
+ * like the Kerberos 5 mech does. But lets check for it anyway.
+ */
+
+ mech_len = gssapi_krb5_get_mech(input_token->value,
+ input_token->length,
+ &p);
+
+ if (mech_len < 0) {
+ buf = input_token->value;
+ buf_size = input_token->length;
+ } else if ((size_t)mech_len == GSS_KRB5_MECH->length &&
+ memcmp(GSS_KRB5_MECH->elements, p, mech_len) == 0)
+ return (gss_init_sec_context(minor_status,
+ initiator_cred_handle,
+ context_handle,
+ target_name,
+ GSS_KRB5_MECH,
+ req_flags,
+ time_req,
+ input_chan_bindings,
+ input_token,
+ actual_mech_type,
+ output_token,
+ ret_flags,
+ time_rec));
+ else if ((size_t)mech_len == GSS_SPNEGO_MECH->length &&
+ memcmp(GSS_SPNEGO_MECH->elements, p, mech_len) == 0) {
+ ret = gssapi_spnego_decapsulate(minor_status,
+ input_token,
+ &buf,
+ &buf_size,
+ GSS_SPNEGO_MECH);
+ if (ret)
+ return (ret);
+ } else
+ return (GSS_S_BAD_MECH);
+
+ ret = der_match_tag_and_length(buf, buf_size,
+ ASN1_C_CONTEXT, CONS, 1, &len, &taglen);
+ if (ret)
+ return (ret);
+
+ if(len > buf_size - taglen)
+ return (ASN1_OVERRUN);
+
+ ret = decode_NegTokenResp(buf + taglen, len, &resp, NULL);
+ if (ret) {
+ *minor_status = ENOMEM;
+ return (GSS_S_FAILURE);
+ }
+
+ if (resp.negState == NULL ||
+ *(resp.negState) == reject ||
+ resp.supportedMech == NULL) {
+ free_NegTokenResp(&resp);
+ return (GSS_S_BAD_MECH);
+ }
+
+ ret = der_put_oid(oidbuf + sizeof(oidbuf) - 1,
+ sizeof(oidbuf),
+ resp.supportedMech,
+ &oidlen);
+ if (ret || oidlen != GSS_KRB5_MECH->length ||
+ memcmp(oidbuf + sizeof(oidbuf) - oidlen,
+ GSS_KRB5_MECH->elements,
+ oidlen) != 0) {
+ free_NegTokenResp(&resp);
+ return GSS_S_BAD_MECH;
+ }
+
+ if (resp.responseToken != NULL) {
+ sub_token.length = resp.responseToken->length;
+ sub_token.value = resp.responseToken->data;
+ } else {
+ sub_token.length = 0;
+ sub_token.value = NULL;
+ }
+
+ ret = gss_init_sec_context(minor_status,
+ initiator_cred_handle,
+ context_handle,
+ target_name,
+ GSS_KRB5_MECH,
+ req_flags,
+ time_req,
+ input_chan_bindings,
+ &sub_token,
+ actual_mech_type,
+ output_token,
+ ret_flags,
+ time_rec);
+ if (ret) {
+ free_NegTokenResp(&resp);
+ return (ret);
+ }
+
+ /*
+ * XXXSRA I don't think this limited implementation ever needs
+ * to check the MIC -- our preferred mechanism (Kerberos)
+ * authenticates its own messages and is the only mechanism
+ * we'll accept, so if the mechanism negotiation completes
+ * sucessfully, we don't need the MIC. See RFC 4178.
+ */
+
+ free_NegTokenResp(&resp);
+ return (ret);
+}
+
+
+
+OM_uint32
+gss_init_sec_context_spnego(OM_uint32 *minor_status,
+ const gss_cred_id_t initiator_cred_handle,
+ gss_ctx_id_t *context_handle,
+ const gss_name_t target_name,
+ const gss_OID mech_type,
+ OM_uint32 req_flags,
+ OM_uint32 time_req,
+ const gss_channel_bindings_t input_chan_bindings,
+ const gss_buffer_t input_token,
+ gss_OID *actual_mech_type,
+ gss_buffer_t output_token,
+ OM_uint32 *ret_flags,
+ OM_uint32 *time_rec)
+{
+ /* Dirty trick to suppress compiler warnings */
+
+ /* Figure out whether we're starting over or processing a reply */
+
+ if (input_token == GSS_C_NO_BUFFER || input_token->length == 0)
+ return (spnego_initial(minor_status,
+ initiator_cred_handle,
+ context_handle,
+ target_name,
+ mech_type,
+ req_flags,
+ time_req,
+ input_chan_bindings,
+ input_token,
+ actual_mech_type,
+ output_token,
+ ret_flags,
+ time_rec));
+ else
+ return (spnego_reply(minor_status,
+ initiator_cred_handle,
+ context_handle,
+ target_name,
+ mech_type,
+ req_flags,
+ time_req,
+ input_chan_bindings,
+ input_token,
+ actual_mech_type,
+ output_token,
+ ret_flags,
+ time_rec));
+}
+
+#endif /* GSSAPI */
--- /dev/null
+/*
+ * Copyright (C) 2006 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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 ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC 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: spnego.h,v 1.2 2006/12/04 01:52:46 marka Exp $ */
+
+/*! \file
+ * \brief
+ * Entry points into portable SPNEGO implementation.
+ * See spnego.c for information on the SPNEGO implementation itself.
+ */
+
+#ifndef _SPNEGO_H_
+#define _SPNEGO_H_
+
+/*%
+ * Wrapper for GSSAPI gss_init_sec_context(), using portable SPNEGO
+ * implementation instead of the one that's part of the GSSAPI
+ * library. Takes arguments identical to the standard GSSAPI
+ * function, uses standard gss_init_sec_context() to handle
+ * everything inside the SPNEGO wrapper.
+ */
+OM_uint32
+gss_init_sec_context_spnego(OM_uint32 *,
+ const gss_cred_id_t,
+ gss_ctx_id_t *,
+ const gss_name_t,
+ const gss_OID,
+ OM_uint32,
+ OM_uint32,
+ const gss_channel_bindings_t,
+ const gss_buffer_t,
+ gss_OID *,
+ gss_buffer_t,
+ OM_uint32 *,
+ OM_uint32 *);
+
+/*%
+ * Wrapper for GSSAPI gss_accept_sec_context(), using portable SPNEGO
+ * implementation instead of the one that's part of the GSSAPI
+ * library. Takes arguments identical to the standard GSSAPI
+ * function. Checks the OID of the input token to see if it's SPNEGO;
+ * if so, processes it, otherwise hands the call off to the standard
+ * gss_accept_sec_context() function.
+ */
+OM_uint32 gss_accept_sec_context_spnego(OM_uint32 *,
+ gss_ctx_id_t *,
+ const gss_cred_id_t,
+ const gss_buffer_t,
+ const gss_channel_bindings_t,
+ gss_name_t *,
+ gss_OID *,
+ gss_buffer_t,
+ OM_uint32 *,
+ OM_uint32 *,
+ gss_cred_id_t *);
+
+
+#endif
--- /dev/null
+/*
+ * Copyright (C) 2006 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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 ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC 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: spnego_asn1.c,v 1.2 2006/12/04 01:52:46 marka Exp $ */
+
+/*! \file
+ * \brief Method routines generated from SPNEGO ASN.1 module.
+ * See spnego_asn1.pl for details. Do not edit.
+ */
+
+/* Generated from spnego.asn1 */
+/* Do not edit */
+
+#ifndef __asn1_h__
+#define __asn1_h__
+
+
+#ifndef __asn1_common_definitions__
+#define __asn1_common_definitions__
+
+typedef struct octet_string {
+ size_t length;
+ void *data;
+} octet_string;
+
+typedef char *general_string;
+
+typedef char *utf8_string;
+
+typedef struct oid {
+ size_t length;
+ unsigned *components;
+} oid;
+
+#define ASN1_MALLOC_ENCODE(T, B, BL, S, L, R) \
+ do { \
+ (BL) = length_##T((S)); \
+ (B) = malloc((BL)); \
+ if((B) == NULL) { \
+ (R) = ENOMEM; \
+ } else { \
+ (R) = encode_##T(((unsigned char*)(B)) + (BL) - 1, (BL), \
+ (S), (L)); \
+ if((R) != 0) { \
+ free((B)); \
+ (B) = NULL; \
+ } \
+ } \
+ } while (0)
+
+#endif
+
+/*
+ * MechType ::= OBJECT IDENTIFIER
+ */
+
+typedef oid MechType;
+
+static int encode_MechType(unsigned char *, size_t, const MechType *, size_t *);
+static int decode_MechType(const unsigned char *, size_t, MechType *, size_t *);
+static void free_MechType(MechType *);
+/* unused declaration: length_MechType */
+/* unused declaration: copy_MechType */
+
+
+/*
+ * MechTypeList ::= SEQUENCE OF MechType
+ */
+
+typedef struct MechTypeList {
+ unsigned int len;
+ MechType *val;
+} MechTypeList;
+
+static int encode_MechTypeList(unsigned char *, size_t, const MechTypeList *, size_t *);
+static int decode_MechTypeList(const unsigned char *, size_t, MechTypeList *, size_t *);
+static void free_MechTypeList(MechTypeList *);
+/* unused declaration: length_MechTypeList */
+/* unused declaration: copy_MechTypeList */
+
+
+/*
+ * ContextFlags ::= BIT STRING { delegFlag(0), mutualFlag(1), replayFlag(2),
+ * sequenceFlag(3), anonFlag(4), confFlag(5), integFlag(6) }
+ */
+
+typedef struct ContextFlags {
+ unsigned int delegFlag:1;
+ unsigned int mutualFlag:1;
+ unsigned int replayFlag:1;
+ unsigned int sequenceFlag:1;
+ unsigned int anonFlag:1;
+ unsigned int confFlag:1;
+ unsigned int integFlag:1;
+} ContextFlags;
+
+
+static int encode_ContextFlags(unsigned char *, size_t, const ContextFlags *, size_t *);
+static int decode_ContextFlags(const unsigned char *, size_t, ContextFlags *, size_t *);
+static void free_ContextFlags(ContextFlags *);
+/* unused declaration: length_ContextFlags */
+/* unused declaration: copy_ContextFlags */
+/* unused declaration: ContextFlags2int */
+/* unused declaration: int2ContextFlags */
+/* unused declaration: asn1_ContextFlags_units */
+
+/*
+ * NegTokenInit ::= SEQUENCE { mechTypes[0] MechTypeList, reqFlags[1]
+ * ContextFlags OPTIONAL, mechToken[2] OCTET STRING OPTIONAL,
+ * mechListMIC[3] OCTET STRING OPTIONAL }
+ */
+
+typedef struct NegTokenInit {
+ MechTypeList mechTypes;
+ ContextFlags *reqFlags;
+ octet_string *mechToken;
+ octet_string *mechListMIC;
+} NegTokenInit;
+
+static int encode_NegTokenInit(unsigned char *, size_t, const NegTokenInit *, size_t *);
+static int decode_NegTokenInit(const unsigned char *, size_t, NegTokenInit *, size_t *);
+static void free_NegTokenInit(NegTokenInit *);
+/* unused declaration: length_NegTokenInit */
+/* unused declaration: copy_NegTokenInit */
+
+
+/*
+ * NegTokenResp ::= SEQUENCE { negState[0] ENUMERATED {
+ * accept-completed(0), accept-incomplete(1), reject(2), request-mic(3) }
+ * OPTIONAL, supportedMech[1] MechType OPTIONAL, responseToken[2] OCTET
+ * STRING OPTIONAL, mechListMIC[3] OCTET STRING OPTIONAL }
+ */
+
+typedef struct NegTokenResp {
+ enum {
+ accept_completed = 0,
+ accept_incomplete = 1,
+ reject = 2,
+ request_mic = 3
+ } *negState;
+
+ MechType *supportedMech;
+ octet_string *responseToken;
+ octet_string *mechListMIC;
+} NegTokenResp;
+
+static int encode_NegTokenResp(unsigned char *, size_t, const NegTokenResp *, size_t *);
+static int decode_NegTokenResp(const unsigned char *, size_t, NegTokenResp *, size_t *);
+static void free_NegTokenResp(NegTokenResp *);
+/* unused declaration: length_NegTokenResp */
+/* unused declaration: copy_NegTokenResp */
+
+
+
+
+#endif /* __asn1_h__ */
+/* Generated from spnego.asn1 */
+/* Do not edit */
+
+
+#define BACK if (e) return e; p -= l; len -= l; ret += l
+
+static int
+encode_MechType(unsigned char *p, size_t len, const MechType * data, size_t * size)
+{
+ size_t ret = 0;
+ size_t l;
+ int i, e;
+
+ i = 0;
+ e = encode_oid(p, len, data, &l);
+ BACK;
+ *size = ret;
+ return 0;
+}
+
+#define FORW if(e) goto fail; p += l; len -= l; ret += l
+
+static int
+decode_MechType(const unsigned char *p, size_t len, MechType * data, size_t * size)
+{
+ size_t ret = 0, reallen;
+ size_t l;
+ int e;
+
+ memset(data, 0, sizeof(*data));
+ reallen = 0;
+ e = decode_oid(p, len, data, &l);
+ FORW;
+ if (size)
+ *size = ret;
+ return 0;
+fail:
+ free_MechType(data);
+ return e;
+}
+
+static void
+free_MechType(MechType * data)
+{
+ free_oid(data);
+}
+
+/* unused function: length_MechType */
+
+
+/* unused function: copy_MechType */
+
+/* Generated from spnego.asn1 */
+/* Do not edit */
+
+
+#define BACK if (e) return e; p -= l; len -= l; ret += l
+
+static int
+encode_MechTypeList(unsigned char *p, size_t len, const MechTypeList * data, size_t * size)
+{
+ size_t ret = 0;
+ size_t l;
+ int i, e;
+
+ i = 0;
+ for (i = (data)->len - 1; i >= 0; --i) {
+ int oldret = ret;
+ ret = 0;
+ e = encode_MechType(p, len, &(data)->val[i], &l);
+ BACK;
+ ret += oldret;
+ }
+ e = der_put_length_and_tag(p, len, ret, ASN1_C_UNIV, CONS, UT_Sequence, &l);
+ BACK;
+ *size = ret;
+ return 0;
+}
+
+#define FORW if(e) goto fail; p += l; len -= l; ret += l
+
+static int
+decode_MechTypeList(const unsigned char *p, size_t len, MechTypeList * data, size_t * size)
+{
+ size_t ret = 0, reallen;
+ size_t l;
+ int e;
+
+ memset(data, 0, sizeof(*data));
+ reallen = 0;
+ e = der_match_tag_and_length(p, len, ASN1_C_UNIV, CONS, UT_Sequence, &reallen, &l);
+ FORW;
+ if (len < reallen)
+ return ASN1_OVERRUN;
+ len = reallen;
+ {
+ size_t origlen = len;
+ int oldret = ret;
+ ret = 0;
+ (data)->len = 0;
+ (data)->val = NULL;
+ while (ret < origlen) {
+ (data)->len++;
+ (data)->val = realloc((data)->val, sizeof(*((data)->val)) * (data)->len);
+ e = decode_MechType(p, len, &(data)->val[(data)->len - 1], &l);
+ FORW;
+ len = origlen - ret;
+ }
+ ret += oldret;
+ }
+ if (size)
+ *size = ret;
+ return 0;
+fail:
+ free_MechTypeList(data);
+ return e;
+}
+
+static void
+free_MechTypeList(MechTypeList * data)
+{
+ while ((data)->len) {
+ free_MechType(&(data)->val[(data)->len - 1]);
+ (data)->len--;
+ }
+ free((data)->val);
+ (data)->val = NULL;
+}
+
+/* unused function: length_MechTypeList */
+
+
+/* unused function: copy_MechTypeList */
+
+/* Generated from spnego.asn1 */
+/* Do not edit */
+
+
+#define BACK if (e) return e; p -= l; len -= l; ret += l
+
+static int
+encode_ContextFlags(unsigned char *p, size_t len, const ContextFlags * data, size_t * size)
+{
+ size_t ret = 0;
+ size_t l;
+ int i, e;
+
+ i = 0;
+ {
+ unsigned char c = 0;
+ *p-- = c;
+ len--;
+ ret++;
+ c = 0;
+ *p-- = c;
+ len--;
+ ret++;
+ c = 0;
+ *p-- = c;
+ len--;
+ ret++;
+ c = 0;
+ if (data->integFlag)
+ c |= 1 << 1;
+ if (data->confFlag)
+ c |= 1 << 2;
+ if (data->anonFlag)
+ c |= 1 << 3;
+ if (data->sequenceFlag)
+ c |= 1 << 4;
+ if (data->replayFlag)
+ c |= 1 << 5;
+ if (data->mutualFlag)
+ c |= 1 << 6;
+ if (data->delegFlag)
+ c |= 1 << 7;
+ *p-- = c;
+ *p-- = 0;
+ len -= 2;
+ ret += 2;
+ }
+
+ e = der_put_length_and_tag(p, len, ret, ASN1_C_UNIV, PRIM, UT_BitString, &l);
+ BACK;
+ *size = ret;
+ return 0;
+}
+
+#define FORW if(e) goto fail; p += l; len -= l; ret += l
+
+static int
+decode_ContextFlags(const unsigned char *p, size_t len, ContextFlags * data, size_t * size)
+{
+ size_t ret = 0, reallen;
+ size_t l;
+ int e;
+
+ memset(data, 0, sizeof(*data));
+ reallen = 0;
+ e = der_match_tag_and_length(p, len, ASN1_C_UNIV, PRIM, UT_BitString, &reallen, &l);
+ FORW;
+ if (len < reallen)
+ return ASN1_OVERRUN;
+ p++;
+ len--;
+ reallen--;
+ ret++;
+ data->delegFlag = (*p >> 7) & 1;
+ data->mutualFlag = (*p >> 6) & 1;
+ data->replayFlag = (*p >> 5) & 1;
+ data->sequenceFlag = (*p >> 4) & 1;
+ data->anonFlag = (*p >> 3) & 1;
+ data->confFlag = (*p >> 2) & 1;
+ data->integFlag = (*p >> 1) & 1;
+ p += reallen;
+ len -= reallen;
+ ret += reallen;
+ if (size)
+ *size = ret;
+ return 0;
+fail:
+ free_ContextFlags(data);
+ return e;
+}
+
+static void
+free_ContextFlags(ContextFlags * data)
+{
+ (void)data;
+}
+
+/* unused function: length_ContextFlags */
+
+
+/* unused function: copy_ContextFlags */
+
+
+/* unused function: ContextFlags2int */
+
+
+/* unused function: int2ContextFlags */
+
+
+/* unused variable: ContextFlags_units */
+
+/* unused function: asn1_ContextFlags_units */
+
+/* Generated from spnego.asn1 */
+/* Do not edit */
+
+
+#define BACK if (e) return e; p -= l; len -= l; ret += l
+
+static int
+encode_NegTokenInit(unsigned char *p, size_t len, const NegTokenInit * data, size_t * size)
+{
+ size_t ret = 0;
+ size_t l;
+ int i, e;
+
+ i = 0;
+ if ((data)->mechListMIC) {
+ int oldret = ret;
+ ret = 0;
+ e = encode_octet_string(p, len, (data)->mechListMIC, &l);
+ BACK;
+ e = der_put_length_and_tag(p, len, ret, ASN1_C_CONTEXT, CONS, 3, &l);
+ BACK;
+ ret += oldret;
+ }
+ if ((data)->mechToken) {
+ int oldret = ret;
+ ret = 0;
+ e = encode_octet_string(p, len, (data)->mechToken, &l);
+ BACK;
+ e = der_put_length_and_tag(p, len, ret, ASN1_C_CONTEXT, CONS, 2, &l);
+ BACK;
+ ret += oldret;
+ }
+ if ((data)->reqFlags) {
+ int oldret = ret;
+ ret = 0;
+ e = encode_ContextFlags(p, len, (data)->reqFlags, &l);
+ BACK;
+ e = der_put_length_and_tag(p, len, ret, ASN1_C_CONTEXT, CONS, 1, &l);
+ BACK;
+ ret += oldret;
+ } {
+ int oldret = ret;
+ ret = 0;
+ e = encode_MechTypeList(p, len, &(data)->mechTypes, &l);
+ BACK;
+ e = der_put_length_and_tag(p, len, ret, ASN1_C_CONTEXT, CONS, 0, &l);
+ BACK;
+ ret += oldret;
+ }
+ e = der_put_length_and_tag(p, len, ret, ASN1_C_UNIV, CONS, UT_Sequence, &l);
+ BACK;
+ *size = ret;
+ return 0;
+}
+
+#define FORW if(e) goto fail; p += l; len -= l; ret += l
+
+static int
+decode_NegTokenInit(const unsigned char *p, size_t len, NegTokenInit * data, size_t * size)
+{
+ size_t ret = 0, reallen;
+ size_t l;
+ int e;
+
+ memset(data, 0, sizeof(*data));
+ reallen = 0;
+ e = der_match_tag_and_length(p, len, ASN1_C_UNIV, CONS, UT_Sequence, &reallen, &l);
+ FORW;
+ {
+ int dce_fix;
+ if ((dce_fix = fix_dce(reallen, &len)) < 0)
+ return ASN1_BAD_FORMAT;
+ {
+ size_t newlen, oldlen;
+
+ e = der_match_tag(p, len, ASN1_C_CONTEXT, CONS, 0, &l);
+ if (e)
+ return e;
+ else {
+ p += l;
+ len -= l;
+ ret += l;
+ e = der_get_length(p, len, &newlen, &l);
+ FORW;
+ {
+ int dce_fix;
+ oldlen = len;
+ if ((dce_fix = fix_dce(newlen, &len)) < 0)
+ return ASN1_BAD_FORMAT;
+ e = decode_MechTypeList(p, len, &(data)->mechTypes, &l);
+ FORW;
+ if (dce_fix) {
+ e = der_match_tag_and_length(p, len, (Der_class) 0, (Der_type) 0, 0, &reallen, &l);
+ FORW;
+ } else
+ len = oldlen - newlen;
+ }
+ }
+ }
+ {
+ size_t newlen, oldlen;
+
+ e = der_match_tag(p, len, ASN1_C_CONTEXT, CONS, 1, &l);
+ if (e)
+ (data)->reqFlags = NULL;
+ else {
+ p += l;
+ len -= l;
+ ret += l;
+ e = der_get_length(p, len, &newlen, &l);
+ FORW;
+ {
+ int dce_fix;
+ oldlen = len;
+ if ((dce_fix = fix_dce(newlen, &len)) < 0)
+ return ASN1_BAD_FORMAT;
+ (data)->reqFlags = malloc(sizeof(*(data)->reqFlags));
+ if ((data)->reqFlags == NULL)
+ return ENOMEM;
+ e = decode_ContextFlags(p, len, (data)->reqFlags, &l);
+ FORW;
+ if (dce_fix) {
+ e = der_match_tag_and_length(p, len, (Der_class) 0, (Der_type) 0, 0, &reallen, &l);
+ FORW;
+ } else
+ len = oldlen - newlen;
+ }
+ }
+ }
+ {
+ size_t newlen, oldlen;
+
+ e = der_match_tag(p, len, ASN1_C_CONTEXT, CONS, 2, &l);
+ if (e)
+ (data)->mechToken = NULL;
+ else {
+ p += l;
+ len -= l;
+ ret += l;
+ e = der_get_length(p, len, &newlen, &l);
+ FORW;
+ {
+ int dce_fix;
+ oldlen = len;
+ if ((dce_fix = fix_dce(newlen, &len)) < 0)
+ return ASN1_BAD_FORMAT;
+ (data)->mechToken = malloc(sizeof(*(data)->mechToken));
+ if ((data)->mechToken == NULL)
+ return ENOMEM;
+ e = decode_octet_string(p, len, (data)->mechToken, &l);
+ FORW;
+ if (dce_fix) {
+ e = der_match_tag_and_length(p, len, (Der_class) 0, (Der_type) 0, 0, &reallen, &l);
+ FORW;
+ } else
+ len = oldlen - newlen;
+ }
+ }
+ }
+ {
+ size_t newlen, oldlen;
+
+ e = der_match_tag(p, len, ASN1_C_CONTEXT, CONS, 3, &l);
+ if (e)
+ (data)->mechListMIC = NULL;
+ else {
+ p += l;
+ len -= l;
+ ret += l;
+ e = der_get_length(p, len, &newlen, &l);
+ FORW;
+ {
+ int dce_fix;
+ oldlen = len;
+ if ((dce_fix = fix_dce(newlen, &len)) < 0)
+ return ASN1_BAD_FORMAT;
+ (data)->mechListMIC = malloc(sizeof(*(data)->mechListMIC));
+ if ((data)->mechListMIC == NULL)
+ return ENOMEM;
+ e = decode_octet_string(p, len, (data)->mechListMIC, &l);
+ FORW;
+ if (dce_fix) {
+ e = der_match_tag_and_length(p, len, (Der_class) 0, (Der_type) 0, 0, &reallen, &l);
+ FORW;
+ } else
+ len = oldlen - newlen;
+ }
+ }
+ }
+ if (dce_fix) {
+ e = der_match_tag_and_length(p, len, (Der_class) 0, (Der_type) 0, 0, &reallen, &l);
+ FORW;
+ }
+ }
+ if (size)
+ *size = ret;
+ return 0;
+fail:
+ free_NegTokenInit(data);
+ return e;
+}
+
+static void
+free_NegTokenInit(NegTokenInit * data)
+{
+ free_MechTypeList(&(data)->mechTypes);
+ if ((data)->reqFlags) {
+ free_ContextFlags((data)->reqFlags);
+ free((data)->reqFlags);
+ (data)->reqFlags = NULL;
+ }
+ if ((data)->mechToken) {
+ free_octet_string((data)->mechToken);
+ free((data)->mechToken);
+ (data)->mechToken = NULL;
+ }
+ if ((data)->mechListMIC) {
+ free_octet_string((data)->mechListMIC);
+ free((data)->mechListMIC);
+ (data)->mechListMIC = NULL;
+ }
+}
+
+/* unused function: length_NegTokenInit */
+
+
+/* unused function: copy_NegTokenInit */
+
+/* Generated from spnego.asn1 */
+/* Do not edit */
+
+
+#define BACK if (e) return e; p -= l; len -= l; ret += l
+
+static int
+encode_NegTokenResp(unsigned char *p, size_t len, const NegTokenResp * data, size_t * size)
+{
+ size_t ret = 0;
+ size_t l;
+ int i, e;
+
+ i = 0;
+ if ((data)->mechListMIC) {
+ int oldret = ret;
+ ret = 0;
+ e = encode_octet_string(p, len, (data)->mechListMIC, &l);
+ BACK;
+ e = der_put_length_and_tag(p, len, ret, ASN1_C_CONTEXT, CONS, 3, &l);
+ BACK;
+ ret += oldret;
+ }
+ if ((data)->responseToken) {
+ int oldret = ret;
+ ret = 0;
+ e = encode_octet_string(p, len, (data)->responseToken, &l);
+ BACK;
+ e = der_put_length_and_tag(p, len, ret, ASN1_C_CONTEXT, CONS, 2, &l);
+ BACK;
+ ret += oldret;
+ }
+ if ((data)->supportedMech) {
+ int oldret = ret;
+ ret = 0;
+ e = encode_MechType(p, len, (data)->supportedMech, &l);
+ BACK;
+ e = der_put_length_and_tag(p, len, ret, ASN1_C_CONTEXT, CONS, 1, &l);
+ BACK;
+ ret += oldret;
+ }
+ if ((data)->negState) {
+ int oldret = ret;
+ ret = 0;
+ e = encode_enumerated(p, len, (data)->negState, &l);
+ BACK;
+ e = der_put_length_and_tag(p, len, ret, ASN1_C_CONTEXT, CONS, 0, &l);
+ BACK;
+ ret += oldret;
+ }
+ e = der_put_length_and_tag(p, len, ret, ASN1_C_UNIV, CONS, UT_Sequence, &l);
+ BACK;
+ *size = ret;
+ return 0;
+}
+
+#define FORW if(e) goto fail; p += l; len -= l; ret += l
+
+static int
+decode_NegTokenResp(const unsigned char *p, size_t len, NegTokenResp * data, size_t * size)
+{
+ size_t ret = 0, reallen;
+ size_t l;
+ int e;
+
+ memset(data, 0, sizeof(*data));
+ reallen = 0;
+ e = der_match_tag_and_length(p, len, ASN1_C_UNIV, CONS, UT_Sequence, &reallen, &l);
+ FORW;
+ {
+ int dce_fix;
+ if ((dce_fix = fix_dce(reallen, &len)) < 0)
+ return ASN1_BAD_FORMAT;
+ {
+ size_t newlen, oldlen;
+
+ e = der_match_tag(p, len, ASN1_C_CONTEXT, CONS, 0, &l);
+ if (e)
+ (data)->negState = NULL;
+ else {
+ p += l;
+ len -= l;
+ ret += l;
+ e = der_get_length(p, len, &newlen, &l);
+ FORW;
+ {
+ int dce_fix;
+ oldlen = len;
+ if ((dce_fix = fix_dce(newlen, &len)) < 0)
+ return ASN1_BAD_FORMAT;
+ (data)->negState = malloc(sizeof(*(data)->negState));
+ if ((data)->negState == NULL)
+ return ENOMEM;
+ e = decode_enumerated(p, len, (data)->negState, &l);
+ FORW;
+ if (dce_fix) {
+ e = der_match_tag_and_length(p, len, (Der_class) 0, (Der_type) 0, 0, &reallen, &l);
+ FORW;
+ } else
+ len = oldlen - newlen;
+ }
+ }
+ }
+ {
+ size_t newlen, oldlen;
+
+ e = der_match_tag(p, len, ASN1_C_CONTEXT, CONS, 1, &l);
+ if (e)
+ (data)->supportedMech = NULL;
+ else {
+ p += l;
+ len -= l;
+ ret += l;
+ e = der_get_length(p, len, &newlen, &l);
+ FORW;
+ {
+ int dce_fix;
+ oldlen = len;
+ if ((dce_fix = fix_dce(newlen, &len)) < 0)
+ return ASN1_BAD_FORMAT;
+ (data)->supportedMech = malloc(sizeof(*(data)->supportedMech));
+ if ((data)->supportedMech == NULL)
+ return ENOMEM;
+ e = decode_MechType(p, len, (data)->supportedMech, &l);
+ FORW;
+ if (dce_fix) {
+ e = der_match_tag_and_length(p, len, (Der_class) 0, (Der_type) 0, 0, &reallen, &l);
+ FORW;
+ } else
+ len = oldlen - newlen;
+ }
+ }
+ }
+ {
+ size_t newlen, oldlen;
+
+ e = der_match_tag(p, len, ASN1_C_CONTEXT, CONS, 2, &l);
+ if (e)
+ (data)->responseToken = NULL;
+ else {
+ p += l;
+ len -= l;
+ ret += l;
+ e = der_get_length(p, len, &newlen, &l);
+ FORW;
+ {
+ int dce_fix;
+ oldlen = len;
+ if ((dce_fix = fix_dce(newlen, &len)) < 0)
+ return ASN1_BAD_FORMAT;
+ (data)->responseToken = malloc(sizeof(*(data)->responseToken));
+ if ((data)->responseToken == NULL)
+ return ENOMEM;
+ e = decode_octet_string(p, len, (data)->responseToken, &l);
+ FORW;
+ if (dce_fix) {
+ e = der_match_tag_and_length(p, len, (Der_class) 0, (Der_type) 0, 0, &reallen, &l);
+ FORW;
+ } else
+ len = oldlen - newlen;
+ }
+ }
+ }
+ {
+ size_t newlen, oldlen;
+
+ e = der_match_tag(p, len, ASN1_C_CONTEXT, CONS, 3, &l);
+ if (e)
+ (data)->mechListMIC = NULL;
+ else {
+ p += l;
+ len -= l;
+ ret += l;
+ e = der_get_length(p, len, &newlen, &l);
+ FORW;
+ {
+ int dce_fix;
+ oldlen = len;
+ if ((dce_fix = fix_dce(newlen, &len)) < 0)
+ return ASN1_BAD_FORMAT;
+ (data)->mechListMIC = malloc(sizeof(*(data)->mechListMIC));
+ if ((data)->mechListMIC == NULL)
+ return ENOMEM;
+ e = decode_octet_string(p, len, (data)->mechListMIC, &l);
+ FORW;
+ if (dce_fix) {
+ e = der_match_tag_and_length(p, len, (Der_class) 0, (Der_type) 0, 0, &reallen, &l);
+ FORW;
+ } else
+ len = oldlen - newlen;
+ }
+ }
+ }
+ if (dce_fix) {
+ e = der_match_tag_and_length(p, len, (Der_class) 0, (Der_type) 0, 0, &reallen, &l);
+ FORW;
+ }
+ }
+ if (size)
+ *size = ret;
+ return 0;
+fail:
+ free_NegTokenResp(data);
+ return e;
+}
+
+static void
+free_NegTokenResp(NegTokenResp * data)
+{
+ if ((data)->negState) {
+ free((data)->negState);
+ (data)->negState = NULL;
+ }
+ if ((data)->supportedMech) {
+ free_MechType((data)->supportedMech);
+ free((data)->supportedMech);
+ (data)->supportedMech = NULL;
+ }
+ if ((data)->responseToken) {
+ free_octet_string((data)->responseToken);
+ free((data)->responseToken);
+ (data)->responseToken = NULL;
+ }
+ if ((data)->mechListMIC) {
+ free_octet_string((data)->mechListMIC);
+ free((data)->mechListMIC);
+ (data)->mechListMIC = NULL;
+ }
+}
+
+/* unused function: length_NegTokenResp */
+
+
+/* unused function: copy_NegTokenResp */
+
+/* Generated from spnego.asn1 */
+/* Do not edit */
+
+
+/* CHOICE */
+/* unused variable: asn1_NegotiationToken_dummy_holder */
--- /dev/null
+#!/bin/bin/perl -w
+#
+# Copyright (C) 2006 Internet Systems Consortium, Inc. ("ISC")
+#
+# 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 ISC DISCLAIMS ALL WARRANTIES WITH
+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS. IN NO EVENT SHALL ISC 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: spnego_asn1.pl,v 1.2 2006/12/04 01:52:46 marka Exp $
+
+# Our SPNEGO implementation uses some functions generated by the
+# Heimdal ASN.1 compiler, which this script then whacks a bit to make
+# them work properly in this stripped down implementation. We don't
+# want to require our users to have a copy of the compiler, so we ship
+# the output of this script, but we need to keep the script around in
+# any case to cope with future changes to the SPNEGO ASN.1 code, so we
+# might as well supply the script for users who want it.
+
+# Overall plan: run the ASN.1 compiler, run each of its output files
+# through indent, fix up symbols and whack everything to be static.
+# We use indent for two reasons: (1) to whack the Heimdal compiler's
+# output into something closer to ISC's coding standard, and (2) to
+# make it easier for this script to parse the result.
+
+# Output from this script is C code which we expect to be #included
+# into another C file, which is why everything generated by this
+# script is marked "static". The intent is to minimize the number of
+# extern symbols exported by the SPNEGO implementation, to avoid
+# potential conflicts with the GSSAPI libraries.
+
+###
+
+# Filename of the ASN.1 specification. Hardcoded for the moment
+# since this script is intended for compiling exactly one module.
+
+my $asn1_source = $ENV{ASN1_SOURCE} || "spnego.asn1";
+
+# Heimdal ASN.1 compiler. This script was written using the version
+# from Heimdal 0.7.1. To build this, download a copy of
+# heimdal-0.7.1.tar.gz, configure and build with the default options,
+# then look for the compiler in heimdal-0.7.1/lib/asn1/asn1_compile.
+
+my $asn1_compile = $ENV{ASN1_COMPILE} || "asn1_compile";
+
+# BSD indent program. This script was written using the version of
+# indent that comes with FreeBSD 4.11-STABLE. The GNU project, as
+# usual, couldn't resist the temptation to monkey with indent's
+# command line syntax, so this probably won't work with GNU indent.
+
+my $indent = $ENV{INDENT} || "indent";
+
+###
+
+# Step 1: run the compiler. Input is the ASN.1 file. Outputs are a
+# header file (name specified on command line without the .h suffix),
+# a file called "asn1_files" listing the names of the other output
+# files, and a set of files containing C code generated by the
+# compiler for each data type that the compiler found.
+
+if (! -r $asn1_source || system($asn1_compile, $asn1_source, "asn1")) {
+ die("Couldn't compile ASN.1 source file $asn1_source\n");
+}
+
+my @files = ("asn1.h");
+
+open(F, "asn1_files")
+ or die("Couldn't open asn1_files: $!\n");
+push(@files, split)
+ while (<F>);
+close(F);
+
+unlink("asn1_files");
+
+###
+
+# Step 2: generate header block.
+
+print(q~/*
+ * Copyright (C) 2006 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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 ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC 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: spnego_asn1.pl,v 1.2 2006/12/04 01:52:46 marka Exp $ */
+
+/*! \file
+ * \brief Method routines generated from SPNEGO ASN.1 module.
+ * See spnego_asn1.pl for details. Do not edit.
+ */
+
+~);
+
+###
+
+# Step 3: read and process each generated file, then delete it.
+
+my $output;
+
+for my $file (@files) {
+
+ my $is_static = 0;
+
+ system($indent, "-di1", "-ldi1", $file) == 0
+ or die("Couldn't indent $file");
+
+ unlink("$file.BAK");
+
+ open(F, $file)
+ or die("Couldn't open $file: $!");
+
+ while (<F>) {
+
+ # Symbol name fixups
+
+ s/heim_general_string/general_string/g;
+ s/heim_octet_string/octet_string/g;
+ s/heim_oid/oid/g;
+ s/heim_utf8_string/utf8_string/g;
+
+ # Convert all externs to statics
+
+ if (/^static/) {
+ $is_static = 1;
+ }
+
+ if (!/^typedef/ &&
+ !$is_static &&
+ /^[A-Za-z_][0-9A-Za-z_]*[ \t]*($|[^:0-9A-Za-z_])/) {
+ $_ = "static " . $_;
+ $is_static = 1;
+ }
+
+ if (/[{};]/) {
+ $is_static = 0;
+ }
+
+ # Suppress file inclusion, pass anything else through
+
+ if (!/#include/) {
+ $output .= $_;
+ }
+ }
+
+ close(F);
+ unlink($file);
+}
+
+# Step 4: Delete unused stuff to avoid code bloat and compiler warnings.
+
+my @unused_functions = qw(ContextFlags2int
+ int2ContextFlags
+ asn1_ContextFlags_units
+ length_NegTokenInit
+ copy_NegTokenInit
+ length_NegTokenResp
+ copy_NegTokenResp
+ length_MechTypeList
+ length_MechType
+ copy_MechTypeList
+ length_ContextFlags
+ copy_ContextFlags
+ copy_MechType);
+
+$output =~ s<^static [^\n]+\n$_\(.+?^}></* unused function: $_ */\n>ms
+ foreach (@unused_functions);
+
+$output =~ s<^static .+$_\(.*\);$></* unused declaration: $_ */>m
+ foreach (@unused_functions);
+
+$output =~ s<^static struct units ContextFlags_units\[\].+?^};>
+ </* unused variable: ContextFlags_units */>ms;
+
+$output =~ s<^static int asn1_NegotiationToken_dummy_holder = 1;>
+ </* unused variable: asn1_NegotiationToken_dummy_holder */>ms;
+
+$output =~ s<^static void\nfree_ContextFlags\(ContextFlags \* data\)\n{\n>
+ <$&\t(void)data;\n>ms;
+
+# Step 5: Write the result.
+
+print($output);
+
/*! \file */
/*
- * $Id: ssu.c,v 1.28 2006/02/16 23:51:33 marka Exp $
+ * $Id: ssu.c,v 1.29 2006/12/04 01:52:46 marka Exp $
* Principal Author: Brian Wellington
*/
#include <dns/name.h>
#include <dns/ssu.h>
+#include <dst/gssapi.h>
+
#define SSUTABLEMAGIC ISC_MAGIC('S', 'S', 'U', 'T')
#define VALID_SSUTABLE(table) ISC_MAGIC_VALID(table, SSUTABLEMAGIC)
if (signer == NULL)
return (ISC_FALSE);
- rule = ISC_LIST_HEAD(table->rules);
- rule = ISC_LIST_NEXT(rule, link);
+
for (rule = ISC_LIST_HEAD(table->rules);
rule != NULL;
rule = ISC_LIST_NEXT(rule, link))
{
- if (dns_name_iswildcard(rule->identity)) {
- if (!dns_name_matcheswildcard(signer, rule->identity))
- continue;
- } else if (!dns_name_equal(signer, rule->identity))
- continue;
+ switch (rule->matchtype) {
+ case DNS_SSUMATCHTYPE_NAME:
+ case DNS_SSUMATCHTYPE_SUBDOMAIN:
+ case DNS_SSUMATCHTYPE_WILDCARD:
+ case DNS_SSUMATCHTYPE_SELF:
+ case DNS_SSUMATCHTYPE_SELFSUB:
+ case DNS_SSUMATCHTYPE_SELFWILD:
+ if (dns_name_iswildcard(rule->identity)) {
+ if (!dns_name_matcheswildcard(signer,
+ rule->identity))
+ continue;
+ }
+ else {
+ if (!dns_name_equal(signer, rule->identity))
+ continue;
+ }
+ break;
+ }
- if (rule->matchtype == DNS_SSUMATCHTYPE_NAME) {
+ switch (rule->matchtype) {
+ case DNS_SSUMATCHTYPE_NAME:
if (!dns_name_equal(name, rule->name))
continue;
- } else if (rule->matchtype == DNS_SSUMATCHTYPE_SUBDOMAIN) {
+ break;
+ case DNS_SSUMATCHTYPE_SUBDOMAIN:
if (!dns_name_issubdomain(name, rule->name))
continue;
- } else if (rule->matchtype == DNS_SSUMATCHTYPE_WILDCARD) {
+ break;
+ case DNS_SSUMATCHTYPE_WILDCARD:
if (!dns_name_matcheswildcard(name, rule->name))
continue;
- } else if (rule->matchtype == DNS_SSUMATCHTYPE_SELF) {
+ break;
+ case DNS_SSUMATCHTYPE_SELF:
if (!dns_name_equal(signer, name))
continue;
- } else if (rule->matchtype == DNS_SSUMATCHTYPE_SELFSUB) {
+ break;
+ case DNS_SSUMATCHTYPE_SELFSUB:
if (!dns_name_issubdomain(name, signer))
continue;
- } else if (rule->matchtype == DNS_SSUMATCHTYPE_SELFWILD) {
+ break;
+ case DNS_SSUMATCHTYPE_SELFWILD:
dns_fixedname_init(&fixed);
wildcard = dns_fixedname_name(&fixed);
result = dns_name_concatenate(dns_wildcardname, signer,
continue;
if (!dns_name_matcheswildcard(name, wildcard))
continue;
+ break;
+ case DNS_SSUMATCHTYPE_SELFKRB5:
+ if (!dst_gssapi_identitymatchesrealmkrb5(signer, name,
+ rule->identity))
+ continue;
+ break;
+ case DNS_SSUMATCHTYPE_SELFMS:
+ if (!dst_gssapi_identitymatchesrealmms(signer, name,
+ rule->identity))
+ continue;
+ break;
+ case DNS_SSUMATCHTYPE_SUBDOMAINKRB5:
+ if (!dns_name_issubdomain(name, rule->name))
+ continue;
+ if (!dst_gssapi_identitymatchesrealmkrb5(signer, NULL,
+ rule->identity))
+ continue;
+ break;
+ case DNS_SSUMATCHTYPE_SUBDOMAINMS:
+ if (!dns_name_issubdomain(name, rule->name))
+ continue;
+ if (!dst_gssapi_identitymatchesrealmms(signer, NULL,
+ rule->identity))
+ continue;
+ break;
}
if (rule->ntypes == 0) {
*/
/*
- * $Id: tkey.c,v 1.81 2005/11/30 03:33:49 marka Exp $
+ * $Id: tkey.c,v 1.82 2006/12/04 01:52:46 marka Exp $
*/
/*! \file */
#include <config.h>
va_end(ap);
}
+static void
+_dns_tkey_dumpmessage(dns_message_t *msg) {
+ isc_buffer_t outbuf;
+ unsigned char output[2048];
+ isc_result_t result;
+
+ isc_buffer_init(&outbuf, output, sizeof(output));
+ result = dns_message_totext(msg, &dns_master_style_debug, 0,
+ &outbuf);
+ /* XXXMLG ignore result */
+ fprintf(stderr, "%.*s\n", (int)isc_buffer_usedlength(&outbuf),
+ (char *)isc_buffer_base(&outbuf));
+}
+
isc_result_t
dns_tkeyctx_create(isc_mem_t *mctx, isc_entropy_t *ectx, dns_tkeyctx_t **tctxp)
{
dns_name_free(tctx->domain, mctx);
isc_mem_put(mctx, tctx->domain, sizeof(dns_name_t));
}
+ if (tctx->gsscred != NULL)
+ dst_gssapi_releasecred(&tctx->gsscred);
isc_entropy_detach(&tctx->ectx);
isc_mem_put(mctx, tctx, sizeof(dns_tkeyctx_t));
isc_mem_detach(&mctx);
*/
for (result = dns_message_firstname(msg, DNS_SECTION_ADDITIONAL);
result == ISC_R_SUCCESS && !found_key;
- result = dns_message_nextname(msg, DNS_SECTION_ADDITIONAL))
- {
+ result = dns_message_nextname(msg, DNS_SECTION_ADDITIONAL)) {
keyname = NULL;
dns_message_currentname(msg, DNS_SECTION_ADDITIONAL, &keyname);
keyset = NULL;
for (result = dns_rdataset_first(keyset);
result == ISC_R_SUCCESS && !found_key;
- result = dns_rdataset_next(keyset))
- {
+ result = dns_rdataset_next(keyset)) {
dns_rdataset_current(keyset, &keyrdata);
pubkey = NULL;
result = dns_dnssec_keyfromrdata(keyname, &keyrdata,
{
isc_result_t result = ISC_R_SUCCESS;
dst_key_t *dstkey = NULL;
- void *gssctx = NULL;
+ dns_tsigkey_t *tsigkey = NULL;
+ dns_fixedname_t principal;
isc_stdtime_t now;
isc_region_t intoken;
- unsigned char array[1024];
isc_buffer_t outtoken;
+ isc_buffer_t *outtoken_p = &outtoken;
+ gss_ctx_id_t gss_ctx = NULL;
UNUSED(namelist);
+ UNUSED(signer);
if (tctx->gsscred == NULL)
return (ISC_R_NOPERM);
if (!dns_name_equal(&tkeyin->algorithm, DNS_TSIG_GSSAPI_NAME) &&
!dns_name_equal(&tkeyin->algorithm, DNS_TSIG_GSSAPIMS_NAME)) {
tkeyout->error = dns_tsigerror_badalg;
+ tkey_log("process_gsstkey(): dns_tsigerror_badalg"); /* XXXSRA */
return (ISC_R_SUCCESS);
}
+ /*
+ * XXXDCL need to check for key expiry per 4.1.1
+ * XXXDCL need a way to check fully established, perhaps w/key_flags
+ */
+
intoken.base = tkeyin->key;
intoken.length = tkeyin->keylen;
- isc_buffer_init(&outtoken, array, sizeof(array));
- RETERR(dst_gssapi_acceptctx(name, tctx->gsscred, &intoken,
- &outtoken, &gssctx));
+ result = dns_tsigkey_find(&tsigkey, name, &tkeyin->algorithm, ring);
+ if (result == ISC_R_SUCCESS)
+ gss_ctx = dst_key_getgssctx(tsigkey->key);
- dstkey = NULL;
- RETERR(dst_key_fromgssapi(name, gssctx, msg->mctx, &dstkey));
+ memset(&outtoken, 0, sizeof(outtoken));
- result = dns_tsigkey_createfromkey(name, &tkeyin->algorithm,
- dstkey, ISC_TRUE, signer,
- tkeyin->inception, tkeyin->expire,
- msg->mctx, ring, NULL);
-#if 1
- if (result != ISC_R_SUCCESS)
- goto failure;
-#else
- if (result == ISC_R_NOTFOUND) {
- tkeyout->error = dns_tsigerror_badalg;
+ dns_fixedname_init(&principal);
+
+ result = dst_gssapi_acceptctx(tctx->gsscred, &intoken,
+ &outtoken, &gss_ctx,
+ dns_fixedname_name(&principal),
+ tctx->mctx);
+
+ if (tsigkey != NULL)
+ dns_tsigkey_detach(&tsigkey);
+
+ if (result == DNS_R_INVALIDTKEY) {
+ tkeyout->error = dns_tsigerror_badkey;
+ tkey_log("process_gsstkey(): dns_tsigerror_badkey"); /* XXXSRA */
return (ISC_R_SUCCESS);
- }
- if (result != ISC_R_SUCCESS)
+ } else if (result == ISC_R_FAILURE)
goto failure;
-#endif
+ ENSURE(result == DNS_R_CONTINUE || result == ISC_R_SUCCESS);
+ /*
+ * XXXDCL Section 4.1.3: Limit GSS_S_CONTINUE_NEEDED to 10 times.
+ */
+
+ if (tsigkey == NULL) {
+ RETERR(dst_key_fromgssapi(name, gss_ctx, msg->mctx, &dstkey));
+ RETERR(dns_tsigkey_createfromkey(name, &tkeyin->algorithm,
+ dstkey, ISC_TRUE,
+ dns_fixedname_name(&principal),
+ tkeyin->inception,
+ tkeyin->expire,
+ msg->mctx, ring, NULL));
+ }
- /* This key is good for a long time */
isc_stdtime_get(&now);
tkeyout->inception = tkeyin->inception;
tkeyout->expire = tkeyin->expire;
- tkeyout->key = isc_mem_get(msg->mctx,
- isc_buffer_usedlength(&outtoken));
- if (tkeyout->key == NULL) {
- result = ISC_R_NOMEMORY;
- goto failure;
+ if (ISC_BUFFER_VALID(outtoken_p)) {
+ tkeyout->key = isc_buffer_base(&outtoken);
+ tkeyout->keylen = isc_buffer_usedlength(&outtoken);
+ isc_buffer_invalidate(&outtoken);
+ } else {
+ tkeyout->key = isc_mem_get(msg->mctx, tkeyin->keylen);
+ if (tkeyout->key == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto failure;
+ }
+ tkeyout->keylen = tkeyin->keylen;
+ memcpy(tkeyout->key, tkeyin->key, tkeyin->keylen);
}
- tkeyout->keylen = isc_buffer_usedlength(&outtoken);
- memcpy(tkeyout->key, isc_buffer_base(&outtoken), tkeyout->keylen);
+
+ tkeyout->error = dns_rcode_noerror;
+
+ tkey_log("process_gsstkey(): dns_tsigerror_noerror"); /* XXXSRA */
return (ISC_R_SUCCESS);
- failure:
+failure:
if (dstkey != NULL)
dst_key_free(&dstkey);
+ if (ISC_BUFFER_VALID(outtoken_p))
+ isc_mem_put(tctx->mctx, isc_buffer_base(&outtoken),
+ isc_buffer_length(&outtoken));
+
+ tkey_log("process_gsstkey(): %s",
+ isc_result_totext(result)); /* XXXSRA */
+
return (result);
}
*/
if (dns_message_findname(msg, DNS_SECTION_ANSWER, qname,
dns_rdatatype_tkey, 0, &name,
- &tkeyset) != ISC_R_SUCCESS)
- {
+ &tkeyset) != ISC_R_SUCCESS) {
result = DNS_R_FORMERR;
tkey_log("dns_tkey_processquery: couldn't find a TKEY "
"matching the question");
if (tkeyin.mode != DNS_TKEYMODE_DELETE) {
dns_tsigkey_t *tsigkey = NULL;
- if (tctx->domain == NULL) {
+ if (tctx->domain == NULL && tkeyin.mode != DNS_TKEYMODE_GSSAPI) {
tkey_log("dns_tkey_processquery: tkey-domain not set");
result = DNS_R_REFUSED;
goto failure;
if (result != ISC_R_SUCCESS)
goto failure;
}
- result = dns_name_concatenate(keyname, tctx->domain,
- keyname, NULL);
- if (result != ISC_R_SUCCESS)
- goto failure;
+
+ if (tkeyin.mode == DNS_TKEYMODE_GSSAPI) {
+ /* Yup. This is a hack */
+ result = dns_name_concatenate(keyname, dns_rootname,
+ keyname, NULL);
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+ } else {
+ result = dns_name_concatenate(keyname, tctx->domain,
+ keyname, NULL);
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+ }
result = dns_tsigkey_find(&tsigkey, keyname, NULL, ring);
+
if (result == ISC_R_SUCCESS) {
tkeyout.error = dns_tsigerror_badname;
dns_tsigkey_detach(&tsigkey);
RETERR(process_gsstkey(msg, signer, keyname, &tkeyin,
tctx, &tkeyout, ring,
&namelist));
+
break;
case DNS_TKEYMODE_DELETE:
tkeyout.error = dns_rcode_noerror;
static isc_result_t
buildquery(dns_message_t *msg, dns_name_t *name,
- dns_rdata_tkey_t *tkey)
+ dns_rdata_tkey_t *tkey, isc_boolean_t win2k)
{
dns_name_t *qname = NULL, *aname = NULL;
dns_rdataset_t *question = NULL, *tkeyset = NULL;
dns_rdataset_makequestion(question, dns_rdataclass_any,
dns_rdatatype_tkey);
- RETERR(isc_buffer_allocate(msg->mctx, &dynbuf, 512));
+ RETERR(isc_buffer_allocate(msg->mctx, &dynbuf, 2048));
RETERR(dns_message_gettemprdata(msg, &rdata));
+
RETERR(dns_rdata_fromstruct(rdata, dns_rdataclass_any,
dns_rdatatype_tkey, tkey, dynbuf));
dns_message_takebuffer(msg, &dynbuf);
ISC_LIST_APPEND(aname->list, tkeyset, link);
dns_message_addname(msg, qname, DNS_SECTION_QUESTION);
- dns_message_addname(msg, aname, DNS_SECTION_ADDITIONAL);
+
+ /*
+ * Windows 2000 needs this in the answer section, not the additional
+ * section where the RFC specifies.
+ */
+ if (win2k)
+ dns_message_addname(msg, aname, DNS_SECTION_ANSWER);
+ else
+ dns_message_addname(msg, aname, DNS_SECTION_ADDITIONAL);
return (ISC_R_SUCCESS);
}
if (dynbuf != NULL)
isc_buffer_free(&dynbuf);
+ printf("buildquery error\n");
return (result);
}
tkey.other = NULL;
tkey.otherlen = 0;
- RETERR(buildquery(msg, name, &tkey));
+ RETERR(buildquery(msg, name, &tkey, ISC_FALSE));
if (nonce == NULL)
isc_mem_put(msg->mctx, r.base, 0);
}
isc_result_t
-dns_tkey_buildgssquery(dns_message_t *msg, dns_name_t *name,
- dns_name_t *gname, void *cred,
- isc_uint32_t lifetime, void **context)
+dns_tkey_buildgssquery(dns_message_t *msg, dns_name_t *name, dns_name_t *gname,
+ isc_buffer_t *intoken, isc_uint32_t lifetime,
+ gss_ctx_id_t *context, isc_boolean_t win2k)
{
dns_rdata_tkey_t tkey;
isc_result_t result;
isc_stdtime_t now;
isc_buffer_t token;
- unsigned char array[1024];
+ unsigned char array[2048];
+
+ UNUSED(intoken);
REQUIRE(msg != NULL);
REQUIRE(name != NULL);
REQUIRE(gname != NULL);
- REQUIRE(context != NULL && *context == NULL);
+ REQUIRE(context != NULL);
isc_buffer_init(&token, array, sizeof(array));
- result = dst_gssapi_initctx(gname, cred, NULL, &token, context);
+ result = dst_gssapi_initctx(gname, NULL, &token, context);
if (result != DNS_R_CONTINUE && result != ISC_R_SUCCESS)
return (result);
ISC_LINK_INIT(&tkey.common, link);
tkey.mctx = NULL;
dns_name_init(&tkey.algorithm, NULL);
- dns_name_clone(DNS_TSIG_GSSAPI_NAME, &tkey.algorithm);
+
+ if (win2k)
+ dns_name_clone(DNS_TSIG_GSSAPIMS_NAME, &tkey.algorithm);
+ else
+ dns_name_clone(DNS_TSIG_GSSAPI_NAME, &tkey.algorithm);
+
isc_stdtime_get(&now);
tkey.inception = now;
tkey.expire = now + lifetime;
tkey.other = NULL;
tkey.otherlen = 0;
- RETERR(buildquery(msg, name, &tkey));
+ RETERR(buildquery(msg, name, &tkey, win2k));
return (ISC_R_SUCCESS);
tkey.keylen = tkey.otherlen = 0;
tkey.key = tkey.other = NULL;
- return (buildquery(msg, &key->name, &tkey));
+ return (buildquery(msg, &key->name, &tkey, ISC_FALSE));
}
static isc_result_t
rtkey.mode != DNS_TKEYMODE_DIFFIEHELLMAN ||
rtkey.mode != qtkey.mode ||
!dns_name_equal(&rtkey.algorithm, &qtkey.algorithm) ||
- rmsg->rcode != dns_rcode_noerror)
- {
+ rmsg->rcode != dns_rcode_noerror) {
tkey_log("dns_tkey_processdhresponse: tkey mode invalid "
- "or error set");
+ "or error set(1)");
result = DNS_R_INVALIDTKEY;
dns_rdata_freestruct(&qtkey);
goto failure;
isc_result_t
dns_tkey_processgssresponse(dns_message_t *qmsg, dns_message_t *rmsg,
- dns_name_t *gname, void *cred, void **context,
- dns_tsigkey_t **outkey, dns_tsig_keyring_t *ring)
+ dns_name_t *gname, gss_ctx_id_t *context,
+ isc_buffer_t *outtoken, dns_tsigkey_t **outkey,
+ dns_tsig_keyring_t *ring)
{
dns_rdata_t rtkeyrdata = DNS_RDATA_INIT, qtkeyrdata = DNS_RDATA_INIT;
dns_name_t *tkeyname;
dns_rdata_tkey_t rtkey, qtkey;
- isc_buffer_t outtoken;
dst_key_t *dstkey = NULL;
- isc_region_t r;
+ isc_buffer_t intoken;
isc_result_t result;
unsigned char array[1024];
+ REQUIRE(outtoken != NULL);
REQUIRE(qmsg != NULL);
REQUIRE(rmsg != NULL);
REQUIRE(gname != NULL);
RETERR(find_tkey(rmsg, &tkeyname, &rtkeyrdata, DNS_SECTION_ANSWER));
RETERR(dns_rdata_tostruct(&rtkeyrdata, &rtkey, NULL));
- RETERR(find_tkey(qmsg, &tkeyname, &qtkeyrdata,
- DNS_SECTION_ADDITIONAL));
+ /*
+ * Win2k puts the item in the ANSWER section, while the RFC
+ * specifies it should be in the ADDITIONAL section. Check first
+ * where it should be, and then where it may be.
+ */
+ result = find_tkey(qmsg, &tkeyname, &qtkeyrdata,
+ DNS_SECTION_ADDITIONAL);
+ if (result == ISC_R_NOTFOUND)
+ result = find_tkey(qmsg, &tkeyname, &qtkeyrdata,
+ DNS_SECTION_ANSWER);
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+
RETERR(dns_rdata_tostruct(&qtkeyrdata, &qtkey, NULL));
if (rtkey.error != dns_rcode_noerror ||
rtkey.mode != DNS_TKEYMODE_GSSAPI ||
- !dns_name_equal(&rtkey.algorithm, &rtkey.algorithm))
- {
- tkey_log("dns_tkey_processdhresponse: tkey mode invalid "
- "or error set");
+ !dns_name_equal(&rtkey.algorithm, &qtkey.algorithm)) {
+ tkey_log("dns_tkey_processgssresponse: tkey mode invalid "
+ "or error set(2) %d", rtkey.error);
+ _dns_tkey_dumpmessage(qmsg);
+ _dns_tkey_dumpmessage(rmsg);
result = DNS_R_INVALIDTKEY;
goto failure;
}
- isc_buffer_init(&outtoken, array, sizeof(array));
- r.base = rtkey.key;
- r.length = rtkey.keylen;
- RETERR(dst_gssapi_initctx(gname, cred, &r, &outtoken, context));
+ isc_buffer_init(outtoken, array, sizeof(array));
+ isc_buffer_init(&intoken, rtkey.key, rtkey.keylen);
+ RETERR(dst_gssapi_initctx(gname, &intoken, outtoken, context));
dstkey = NULL;
RETERR(dst_key_fromgssapi(dns_rootname, *context, rmsg->mctx,
&dstkey));
RETERR(dns_tsigkey_createfromkey(tkeyname, DNS_TSIG_GSSAPI_NAME,
- dstkey, ISC_TRUE, NULL,
+ dstkey, ISC_FALSE, NULL,
rtkey.inception, rtkey.expire,
rmsg->mctx, ring, outkey));
return (result);
failure:
+ /*
+ * XXXSRA This probably leaks memory from rtkey and qtkey.
+ */
return (result);
}
rtkey.mode != DNS_TKEYMODE_DELETE ||
rtkey.mode != qtkey.mode ||
!dns_name_equal(&rtkey.algorithm, &qtkey.algorithm) ||
- rmsg->rcode != dns_rcode_noerror)
- {
+ rmsg->rcode != dns_rcode_noerror) {
tkey_log("dns_tkey_processdeleteresponse: tkey mode invalid "
- "or error set");
+ "or error set(3)");
result = DNS_R_INVALIDTKEY;
dns_rdata_freestruct(&qtkey);
dns_rdata_freestruct(&rtkey);
failure:
return (result);
}
+
+isc_result_t
+dns_tkey_gssnegotiate(dns_message_t *qmsg, dns_message_t *rmsg,
+ dns_name_t *server, gss_ctx_id_t *context,
+ dns_tsigkey_t **outkey, dns_tsig_keyring_t *ring,
+ isc_boolean_t win2k)
+{
+ dns_rdata_t rtkeyrdata = DNS_RDATA_INIT, qtkeyrdata = DNS_RDATA_INIT;
+ dns_name_t *tkeyname;
+ dns_rdata_tkey_t rtkey, qtkey;
+ isc_buffer_t intoken, outtoken;
+ dst_key_t *dstkey = NULL;
+ isc_result_t result;
+ unsigned char array[1024];
+
+ REQUIRE(qmsg != NULL);
+ REQUIRE(rmsg != NULL);
+ REQUIRE(server != NULL);
+ if (outkey != NULL)
+ REQUIRE(*outkey == NULL);
+
+ if (rmsg->rcode != dns_rcode_noerror)
+ return (ISC_RESULTCLASS_DNSRCODE + rmsg->rcode);
+
+ RETERR(find_tkey(rmsg, &tkeyname, &rtkeyrdata, DNS_SECTION_ANSWER));
+ RETERR(dns_rdata_tostruct(&rtkeyrdata, &rtkey, NULL));
+
+ if (win2k == ISC_TRUE)
+ RETERR(find_tkey(qmsg, &tkeyname, &qtkeyrdata,
+ DNS_SECTION_ANSWER));
+ else
+ RETERR(find_tkey(qmsg, &tkeyname, &qtkeyrdata,
+ DNS_SECTION_ADDITIONAL));
+
+ RETERR(dns_rdata_tostruct(&qtkeyrdata, &qtkey, NULL));
+
+ if (rtkey.error != dns_rcode_noerror ||
+ rtkey.mode != DNS_TKEYMODE_GSSAPI ||
+ !dns_name_equal(&rtkey.algorithm, &qtkey.algorithm))
+ {
+ tkey_log("dns_tkey_processdhresponse: tkey mode invalid "
+ "or error set(4)");
+ result = DNS_R_INVALIDTKEY;
+ goto failure;
+ }
+
+ isc_buffer_init(&intoken, rtkey.key, rtkey.keylen);
+ isc_buffer_init(&outtoken, array, sizeof(array));
+
+ result = dst_gssapi_initctx(server, &intoken, &outtoken, context);
+ if (result != DNS_R_CONTINUE && result != ISC_R_SUCCESS)
+ return (result);
+
+ dstkey = NULL;
+ RETERR(dst_key_fromgssapi(dns_rootname, *context, rmsg->mctx,
+ &dstkey));
+
+ /*
+ * XXXSRA This seems confused. If we got CONTINUE from initctx,
+ * the GSS negotiation hasn't completed yet, so we can't sign
+ * anything yet.
+ */
+
+ RETERR(dns_tsigkey_createfromkey(tkeyname,
+ (win2k
+ ? DNS_TSIG_GSSAPIMS_NAME
+ : DNS_TSIG_GSSAPI_NAME),
+ dstkey, ISC_TRUE, NULL,
+ rtkey.inception, rtkey.expire,
+ rmsg->mctx, ring, outkey));
+
+ dns_rdata_freestruct(&rtkey);
+ return (result);
+
+ failure:
+ /*
+ * XXXSRA This probably leaks memory from qtkey.
+ */
+ dns_rdata_freestruct(&rtkey);
+ return (result);
+}
*/
/*
- * $Id: tsig.c,v 1.126 2006/05/02 04:07:36 marka Exp $
+ * $Id: tsig.c,v 1.127 2006/12/04 01:52:46 marka Exp $
*/
/*! \file */
#include <config.h>
#include <isc/refcount.h>
#include <isc/string.h> /* Required for HP/UX (and others?) */
#include <isc/util.h>
+#include <isc/time.h>
#include <dns/keyvalues.h>
#include <dns/log.h>
#include <dns/message.h>
+#include <dns/fixedname.h>
#include <dns/rbt.h>
#include <dns/rdata.h>
#include <dns/rdatalist.h>
static unsigned char gsstsig_ndata[] = "\010gss-tsig";
static unsigned char gsstsig_offsets[] = { 0, 9 };
-
static dns_name_t gsstsig = {
DNS_NAME_MAGIC,
gsstsig_ndata, 10, 2,
{(void *)-1, (void *)-1},
{NULL, NULL}
};
-
LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_gssapi_name = &gsstsig;
-/* It's nice of Microsoft to conform to their own standard. */
+/*
+ * Since Microsoft doesn't follow its own standard, we will use this
+ * alternate name as a second guess.
+ */
static unsigned char gsstsigms_ndata[] = "\003gss\011microsoft\003com";
static unsigned char gsstsigms_offsets[] = { 0, 4, 14, 18 };
-
static dns_name_t gsstsigms = {
DNS_NAME_MAGIC,
gsstsigms_ndata, 19, 4,
{(void *)-1, (void *)-1},
{NULL, NULL}
};
-
LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_gssapims_name = &gsstsigms;
static unsigned char hmacsha1_ndata[] = "\011hmac-sha1";
tsig_log(dns_tsigkey_t *key, int level, const char *fmt, ...)
ISC_FORMAT_PRINTF(3, 4);
+static void
+cleanup_ring(dns_tsig_keyring_t *ring);
+static void
+tsigkey_free(dns_tsigkey_t *key);
+
static void
tsig_log(dns_tsigkey_t *key, int level, const char *fmt, ...) {
va_list ap;
char message[4096];
char namestr[DNS_NAME_FORMATSIZE];
+ char creatorstr[DNS_NAME_FORMATSIZE];
if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
return;
dns_name_format(&key->name, namestr, sizeof(namestr));
else
strcpy(namestr, "<null>");
+
+ if (key != NULL && key->generated)
+ dns_name_format(key->creator, creatorstr, sizeof(creatorstr));
+
va_start(ap, fmt);
vsnprintf(message, sizeof(message), fmt, ap);
va_end(ap);
- isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_TSIG,
- level, "tsig key '%s': %s", namestr, message);
+ if (key != NULL && key->generated)
+ isc_log_write(dns_lctx,
+ DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_TSIG,
+ level, "tsig key '%s' (%s): %s",
+ namestr, creatorstr, message);
+ else
+ isc_log_write(dns_lctx,
+ DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_TSIG,
+ level, "tsig key '%s': %s", namestr, message);
}
isc_result_t
if (ring != NULL) {
RWLOCK(&ring->lock, isc_rwlocktype_write);
+ ring->writecount++;
+
+ /*
+ * Do on the fly cleaning. Find some nodes we might not
+ * want around any more.
+ */
+ if (ring->writecount > 10) {
+ cleanup_ring(ring);
+ ring->writecount = 0;
+ }
ret = dns_rbt_addname(ring->keys, name, tkey);
if (ret != ISC_R_SUCCESS) {
RWUNLOCK(&ring->lock, isc_rwlocktype_write);
RWUNLOCK(&ring->lock, isc_rwlocktype_write);
}
- if (dstkey != NULL && dst_key_size(dstkey) < 64) {
+ /*
+ * Ignore this if it's a GSS key, since the key size is meaningless.
+ */
+ if (dstkey != NULL && dst_key_size(dstkey) < 64 &&
+ !dns_name_equal(algorithm, DNS_TSIG_GSSAPI_NAME) &&
+ !dns_name_equal(algorithm, DNS_TSIG_GSSAPIMS_NAME)) {
char namestr[DNS_NAME_FORMATSIZE];
dns_name_format(name, namestr, sizeof(namestr));
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC,
return (ret);
}
+/*
+ * Find a few nodes to destroy if possible.
+ */
+static void
+cleanup_ring(dns_tsig_keyring_t *ring)
+{
+ isc_result_t result;
+ dns_rbtnodechain_t chain;
+ dns_name_t foundname;
+ dns_fixedname_t fixedorigin;
+ dns_name_t *origin;
+ isc_stdtime_t now;
+ dns_rbtnode_t *node;
+ dns_tsigkey_t *tkey;
+
+ /*
+ * Start up a new iterator each time.
+ */
+ isc_stdtime_get(&now);
+ 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_SUCCESS && result != DNS_R_NEWORIGIN) {
+ dns_rbtnodechain_invalidate(&chain);
+ return;
+ }
+
+ for (;;) {
+ node = NULL;
+ dns_rbtnodechain_current(&chain, &foundname, origin, &node);
+ tkey = node->data;
+ if (tkey != NULL) {
+ tsig_log(tkey, 2, "tsig expire: generated=%d, refs=%d, expire=%d)", tkey->generated, isc_refcount_current(&tkey->refs), now - tkey->expire);
+ if (tkey->generated
+ && isc_refcount_current(&tkey->refs) == 1
+ && tkey->inception != tkey->expire
+ && tkey->expire < now) {
+ tsig_log(tkey, 2, "tsig expire: deleting");
+ /* delete the key */
+ dns_rbtnodechain_invalidate(&chain);
+ (void)dns_rbt_deletename(ring->keys,
+ &tkey->name,
+ ISC_FALSE);
+ goto again;
+ }
+ }
+ result = dns_rbtnodechain_next(&chain, &foundname,
+ origin);
+ if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
+ dns_rbtnodechain_invalidate(&chain);
+ return;
+ }
+
+ }
+}
+
isc_result_t
dns_tsigkey_create(dns_name_t *name, dns_name_t *algorithm,
unsigned char *secret, int length, isc_boolean_t generated,
RWUNLOCK(&key->ring->lock, isc_rwlocktype_write);
}
-static void
-buffer_putuint48(isc_buffer_t *b, isc_uint64_t val) {
- isc_uint16_t valhi;
- isc_uint32_t vallo;
-
- valhi = (isc_uint16_t)(val >> 32);
- vallo = (isc_uint32_t)(val & 0xFFFFFFFF);
- isc_buffer_putuint16(b, valhi);
- isc_buffer_putuint32(b, vallo);
-}
-
isc_result_t
dns_tsig_sign(dns_message_t *msg) {
dns_tsigkey_t *key;
tsig.otherlen = BADTIMELEN;
tsig.other = badtimedata;
isc_buffer_init(&otherbuf, tsig.other, tsig.otherlen);
- buffer_putuint48(&otherbuf, tsig.timesigned);
+ isc_buffer_putuint48(&otherbuf, tsig.timesigned);
}
if (key->key != NULL && tsig.error != dns_tsigerror_badsig) {
goto cleanup_context;
isc_buffer_putuint16(&databuf, querytsig.siglen);
if (isc_buffer_availablelength(&databuf) <
- querytsig.siglen)
- {
+ querytsig.siglen) {
ret = ISC_R_NOSPACE;
goto cleanup_context;
}
isc_buffer_clear(&databuf);
if (tsig.error == dns_tsigerror_badtime)
tsig.timesigned = querytsig.timesigned;
- buffer_putuint48(&databuf, tsig.timesigned);
+ isc_buffer_putuint48(&databuf, tsig.timesigned);
isc_buffer_putuint16(&databuf, tsig.fudge);
isc_buffer_usedregion(&databuf, &r);
ret = dst_context_adddata(ctx, &r);
REQUIRE(source != NULL);
REQUIRE(DNS_MESSAGE_VALID(msg));
tsigkey = dns_message_gettsigkey(msg);
+
REQUIRE(tsigkey == NULL || VALID_TSIG_KEY(tsigkey));
msg->verify_attempted = 1;
*/
if (is_response(msg) &&
(!dns_name_equal(keyname, &tsigkey->name) ||
- !dns_name_equal(&tsig.algorithm, &querytsig.algorithm)))
- {
+ !dns_name_equal(&tsig.algorithm, &querytsig.algorithm))) {
msg->tsigstatus = dns_tsigerror_badkey;
tsig_log(msg->tsigkey, 2,
"key name and algorithm do not match");
goto cleanup_context;
isc_buffer_clear(&databuf);
- buffer_putuint48(&databuf, tsig.timesigned);
+ isc_buffer_putuint48(&databuf, tsig.timesigned);
isc_buffer_putuint16(&databuf, tsig.fudge);
isc_buffer_putuint16(&databuf, tsig.error);
isc_buffer_putuint16(&databuf, tsig.otherlen);
msg->tsigstatus = dns_tsigerror_badsig;
ret = DNS_R_TSIGVERIFYFAILURE;
tsig_log(msg->tsigkey, 2,
- "signature failed to verify");
+ "signature failed to verify(1)");
goto cleanup_context;
} else if (ret != ISC_R_SUCCESS)
goto cleanup_context;
dst_context_destroy(&ctx);
} else if (tsig.error != dns_tsigerror_badsig &&
- tsig.error != dns_tsigerror_badkey)
- {
+ tsig.error != dns_tsigerror_badkey) {
msg->tsigstatus = dns_tsigerror_badsig;
tsig_log(msg->tsigkey, 2, "signature was empty");
return (DNS_R_TSIGVERIFYFAILURE);
* Do the key name and algorithm match that of the query?
*/
if (!dns_name_equal(keyname, &tsigkey->name) ||
- !dns_name_equal(&tsig.algorithm, &querytsig.algorithm))
- {
+ !dns_name_equal(&tsig.algorithm, &querytsig.algorithm)) {
msg->tsigstatus = dns_tsigerror_badkey;
ret = DNS_R_TSIGVERIFYFAILURE;
tsig_log(msg->tsigkey, 2,
ret = DNS_R_CLOCKSKEW;
goto cleanup_querystruct;
} else if (now + msg->timeadjust <
- tsig.timesigned - tsig.fudge)
- {
+ tsig.timesigned - tsig.fudge) {
msg->tsigstatus = dns_tsigerror_badtime;
tsig_log(msg->tsigkey, 2,
"signature is in the future");
*/
if (has_tsig) {
isc_buffer_init(&databuf, data, sizeof(data));
- buffer_putuint48(&databuf, tsig.timesigned);
+ isc_buffer_putuint48(&databuf, tsig.timesigned);
isc_buffer_putuint16(&databuf, tsig.fudge);
isc_buffer_usedregion(&databuf, &r);
ret = dst_context_adddata(msg->tsigctx, &r);
if (ret == DST_R_VERIFYFAILURE) {
msg->tsigstatus = dns_tsigerror_badsig;
tsig_log(msg->tsigkey, 2,
- "signature failed to verify");
+ "signature failed to verify(2)");
ret = DNS_R_TSIGVERIFYFAILURE;
goto cleanup_context;
}
REQUIRE(name != NULL);
REQUIRE(ring != NULL);
+ RWLOCK(&ring->lock, isc_rwlocktype_write);
+ cleanup_ring(ring);
+ RWUNLOCK(&ring->lock, isc_rwlocktype_write);
+
isc_stdtime_get(&now);
RWLOCK(&ring->lock, isc_rwlocktype_read);
key = NULL;
*/
RWUNLOCK(&ring->lock, isc_rwlocktype_read);
RWLOCK(&ring->lock, isc_rwlocktype_write);
- (void) dns_rbt_deletename(ring->keys, name, ISC_FALSE);
+ (void)dns_rbt_deletename(ring->keys, name, ISC_FALSE);
RWUNLOCK(&ring->lock, isc_rwlocktype_write);
return (ISC_R_NOTFOUND);
}
}
ring->mctx = mctx;
+ ring->writecount = 0;
*ringp = ring;
return (ISC_R_SUCCESS);
# End Source File
# Begin Source File
+SOURCE=..\spnego.c\r
+# End Source File\r
+# Begin Source File\r
+\r
SOURCE=..\hmac_link.c
# End Source File
# Begin Source File
-@erase "$(INTDIR)\forward.obj"
-@erase "$(INTDIR)\gssapi_link.obj"
-@erase "$(INTDIR)\gssapictx.obj"
+ -@erase "$(INTDIR)\spnego.obj"
-@erase "$(INTDIR)\hmac_link.obj"
-@erase "$(INTDIR)\journal.obj"
-@erase "$(INTDIR)\key.obj"
"$(INTDIR)\dst_result.obj" \
"$(INTDIR)\gssapi_link.obj" \
"$(INTDIR)\gssapictx.obj" \
+ "$(INTDIR)\spnego.obj" \
"$(INTDIR)\hmac_link.obj" \
"$(INTDIR)\key.obj" \
"$(INTDIR)\openssl_link.obj" \
-@erase "$(INTDIR)\gssapi_link.sbr"
-@erase "$(INTDIR)\gssapictx.obj"
-@erase "$(INTDIR)\gssapictx.sbr"
+ -@erase "$(INTDIR)\spnego.obj"
+ -@erase "$(INTDIR)\spnego.sbr"
-@erase "$(INTDIR)\hmac_link.obj"
-@erase "$(INTDIR)\hmac_link.sbr"
-@erase "$(INTDIR)\journal.obj"
"$(INTDIR)\dst_result.sbr" \
"$(INTDIR)\gssapi_link.sbr" \
"$(INTDIR)\gssapictx.sbr" \
+ "$(INTDIR)\spnego.sbr" \
"$(INTDIR)\hmac_link.sbr" \
"$(INTDIR)\key.sbr" \
"$(INTDIR)\openssl_link.sbr" \
"$(INTDIR)\dst_result.obj" \
"$(INTDIR)\gssapi_link.obj" \
"$(INTDIR)\gssapictx.obj" \
+ "$(INTDIR)\spnego.obj" \
"$(INTDIR)\hmac_link.obj" \
"$(INTDIR)\key.obj" \
"$(INTDIR)\openssl_link.obj" \
$(CPP) $(CPP_PROJ) $(SOURCE)
+!ENDIF
+
+SOURCE=..\spnego.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\spnego.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\spnego.obj" "$(INTDIR)\spnego.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
!ENDIF
SOURCE=..\hmac_link.c
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: buffer.c,v 1.42 2005/04/29 00:23:23 marka Exp $ */
+/* $Id: buffer.c,v 1.43 2006/12/04 01:52:46 marka Exp $ */
/*! \file */
ISC__BUFFER_PUTUINT32(b, val);
}
+isc_uint64_t
+isc_buffer_getuint48(isc_buffer_t *b) {
+ unsigned char *cp;
+ isc_uint64_t result;
+
+ /*
+ * Read an unsigned 48-bit integer in network byte order from 'b',
+ * convert it to host byte order, and return it.
+ */
+
+ REQUIRE(ISC_BUFFER_VALID(b));
+ REQUIRE(b->used - b->current >= 6);
+
+ cp = isc_buffer_current(b);
+ b->current += 6;
+ result = ((isc_int64_t)(cp[0])) << 40;
+ result |= ((isc_int64_t)(cp[1])) << 32;
+ result |= ((isc_int64_t)(cp[2])) << 24;
+ result |= ((isc_int64_t)(cp[3])) << 16;
+ result |= ((isc_int64_t)(cp[4])) << 8;
+ result |= ((isc_int64_t)(cp[5]));
+
+ return (result);
+}
+
+void
+isc__buffer_putuint48(isc_buffer_t *b, isc_uint64_t val) {
+ isc_uint16_t valhi;
+ isc_uint32_t vallo;
+
+ REQUIRE(ISC_BUFFER_VALID(b));
+ REQUIRE(b->used + 6 <= b->length);
+
+ valhi = (isc_uint16_t)(val >> 32);
+ vallo = (isc_uint32_t)(val & 0xFFFFFFFF);
+ ISC__BUFFER_PUTUINT16(b, valhi);
+ ISC__BUFFER_PUTUINT32(b, vallo);
+}
+
void
isc__buffer_putmem(isc_buffer_t *b, const unsigned char *base,
unsigned int length)
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: entropy.c,v 1.14 2005/07/12 01:00:17 marka Exp $ */
+/* $Id: entropy.c,v 1.15 2006/12/04 01:52:46 marka Exp $ */
/*! \file
* \brief
UNLOCK(&ent->lock);
}
+unsigned int
+isc_entropy_status(isc_entropy_t *ent) {
+ unsigned int estimate;
+
+ LOCK(&ent->lock);
+ estimate = ent->pool.entropy;
+ UNLOCK(&ent->lock);
+
+ return estimate;
+}
+
void
isc_entropy_attach(isc_entropy_t *ent, isc_entropy_t **entp) {
REQUIRE(VALID_ENTROPY(ent));
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: buffer.h,v 1.45 2005/04/29 00:23:34 marka Exp $ */
+/* $Id: buffer.h,v 1.46 2006/12/04 01:52:46 marka Exp $ */
#ifndef ISC_BUFFER_H
#define ISC_BUFFER_H 1
*\li The used pointer in 'b' is advanced by 4.
*/
+isc_uint64_t
+isc_buffer_getuint48(isc_buffer_t *b);
+/*!<
+ * \brief Read an unsigned 48-bit integer in network byte order from 'b',
+ * convert it to host byte order, and return it.
+ *
+ * Requires:
+ *
+ *\li 'b' is a valid buffer.
+ *
+ *\li The length of the available region of 'b' is at least 6.
+ *
+ * Ensures:
+ *
+ *\li The current pointer in 'b' is advanced by 6.
+ *
+ * Returns:
+ *
+ *\li A 48-bit unsigned integer (stored in a 64-bit integer).
+ */
+
+void
+isc__buffer_putuint48(isc_buffer_t *b, isc_uint64_t val);
+/*!<
+ * \brief Store an unsigned 48-bit integer in host byte order from 'val'
+ * into 'b' in network byte order.
+ *
+ * Requires:
+ *\li 'b' is a valid buffer.
+ *
+ *\li The length of the unused region of 'b' is at least 6.
+ *
+ * Ensures:
+ *\li The used pointer in 'b' is advanced by 6.
+ */
+
void
isc__buffer_putmem(isc_buffer_t *b, const unsigned char *base,
unsigned int length);
#define isc_buffer_putuint32 isc__buffer_putuint32
#endif
+/*
+ * No inline method for this one (yet).
+ */
+#define isc_buffer_putuint48 isc__buffer_putuint48
+
#endif /* ISC_BUFFER_H */
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: entropy.h,v 1.27 2005/04/29 00:23:35 marka Exp $ */
+/* $Id: entropy.h,v 1.28 2006/12/04 01:52:46 marka Exp $ */
#ifndef ISC_ENTROPY_H
#define ISC_ENTROPY_H 1
* \brief Dump some (trivial) stats to the stdio stream "out".
*/
+unsigned int
+isc_entropy_status(isc_entropy_t *end);
+/*
+ * Returns the number of bits the pool currently contains. This is just
+ * an estimate.
+ */
+
isc_result_t
isc_entropy_usebestsource(isc_entropy_t *ectx, isc_entropysource_t **source,
const char *randomfile, int use_keyboard);
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: platform.h.in,v 1.39 2005/06/16 21:57:59 jinmei Exp $ */
+/* $Id: platform.h.in,v 1.40 2006/12/04 01:52:46 marka Exp $ */
#ifndef ISC_PLATFORM_H
#define ISC_PLATFORM_H 1
@ISC_PLATFORM_NEEDPORTT@
/*! \brief
- * If the system needs strsep(), ISC_PLATFORM_NEEDSTRSEP will be defined.
+ * Define if the system has struct lifconf which is a extended struct ifconf
+ * for IPv6.
*/
-@ISC_PLATFORM_NEEDSTRSEP@
-
+@ISC_PLATFORM_HAVELIFCONF@
+
/*! \brief
- * If the system needs strlcpy(), ISC_PLATFORM_NEEDSTRLCPY will be defined.
+ * Define if the system has struct if_laddrconf which is a extended struct
+ * ifconf for IPv6.
*/
-@ISC_PLATFORM_NEEDSTRLCPY@
-
+@ISC_PLATFORM_HAVEIF_LADDRCONF@
+
/*! \brief
- * If the system needs strlcat(), ISC_PLATFORM_NEEDSTRLCAT will be defined.
+ * Define if the system has struct if_laddrreq.
*/
-@ISC_PLATFORM_NEEDSTRLCAT@
+@ISC_PLATFORM_HAVEIF_LADDRREQ@
/*! \brief
* Define either ISC_PLATFORM_BSD44MSGHDR or ISC_PLATFORM_BSD43MSGHDR.
@ISC_PLATFORM_MSGHDRFLAVOR@
/*! \brief
- * Define if PTHREAD_ONCE_INIT should be surrounded by braces to
- * prevent compiler warnings (such as with gcc on Solaris 2.8).
+ * Define if the system supports if_nametoindex.
*/
-@ISC_PLATFORM_BRACEPTHREADONCEINIT@
+@ISC_PLATFORM_HAVEIFNAMETOINDEX@
/*! \brief
* Define on some UnixWare systems to fix erroneous definitions of various
*/
@ISC_PLATFORM_QUADFORMAT@
-/*! \brief
+/***
+ *** String functions.
+ ***/
+/*
+ * If the system needs strsep(), ISC_PLATFORM_NEEDSTRSEP will be defined.
+ */
+@ISC_PLATFORM_NEEDSTRSEP@
+
+/*
+ * If the system needs strlcpy(), ISC_PLATFORM_NEEDSTRLCPY will be defined.
+ */
+@ISC_PLATFORM_NEEDSTRLCPY@
+
+/*
+ * If the system needs strlcat(), ISC_PLATFORM_NEEDSTRLCAT will be defined.
+ */
+@ISC_PLATFORM_NEEDSTRLCAT@
+
+/*
+ * Define if this system needs strtoul.
+ */
+@ISC_PLATFORM_NEEDSTRTOUL@
+
+/*
+ * Define if this system needs memmove.
+ */
+@ISC_PLATFORM_NEEDMEMMOVE@
+
+/***
+ *** Miscellaneous.
+ ***/
+
+/*
* Defined if we are using threads.
*/
@ISC_PLATFORM_USETHREADS@
-
-/*! \brief
+
+/*
* Defined if unistd.h does not cause fd_set to be delared.
*/
@ISC_PLATFORM_NEEDSYSSELECTH@
-
-/*! \brief
+
+/*
+ * Defined to <gssapi.h> or <gssapi/gssapi.h> for how to include
+ * the GSSAPI header.
+ */
+@ISC_PLATFORM_GSSAPIHEADER@
+
+/*
* Type used for resource limits.
*/
@ISC_PLATFORM_RLIMITTYPE@
-
-/*! \brief
+
+/*
* Define if your compiler supports "long long int".
*/
@ISC_PLATFORM_HAVELONGLONG@
-/*! \brief
- * Define if the system has struct lifconf which is a extended struct ifconf
- * for IPv6.
- */
-@ISC_PLATFORM_HAVELIFCONF@
-
-/*! \brief
- * Define if the system has struct if_laddrconf which is a extended struct
- * ifconf for IPv6.
- */
-@ISC_PLATFORM_HAVEIF_LADDRCONF@
-
-/*! \brief
- * Define if the system has struct if_laddrreq.
+/*
+ * Define if PTHREAD_ONCE_INIT should be surrounded by braces to
+ * prevent compiler warnings (such as with gcc on Solaris 2.8).
*/
-@ISC_PLATFORM_HAVEIF_LADDRREQ@
+@ISC_PLATFORM_BRACEPTHREADONCEINIT@
-/*! \brief
+/*
* Used to control how extern data is linked; needed for Win32 platforms.
*/
@ISC_PLATFORM_USEDECLSPEC@
-/*! \brief
- * Define if the system supports if_nametoindex.
- */
-@ISC_PLATFORM_HAVEIFNAMETOINDEX@
-
-/*! \brief
- * Define if this system needs strtoul.
- */
-@ISC_PLATFORM_NEEDSTRTOUL@
-
-/*! \brief
- * Define if this system needs memmove.
- */
-@ISC_PLATFORM_NEEDMEMMOVE@
-
/*
* Define if the platform has <sys/un.h>.
*/
*/
@ISC_PLATFORM_USESTDASM@
+/***
+ *** Windows dll support.
+ ***/
+
#ifndef ISC_PLATFORM_USEDECLSPEC
#define LIBISC_EXTERNAL_DATA
#define LIBDNS_EXTERNAL_DATA
isc__buffer_putstr
isc__buffer_putuint16
isc__buffer_putuint32
+isc__buffer_putuint48
isc__buffer_putuint8
isc__buffer_region
isc__buffer_remainingregion
isc_entropy_getdata
isc_entropy_putdata
isc_entropy_stats
+isc_entropy_status
isc_entropy_stopcallbacksources
isc_entropy_usebestsource
isc_error_fatal
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: namedconf.c,v 1.70 2006/06/04 23:17:07 marka Exp $ */
+/* $Id: namedconf.c,v 1.71 2006/12/04 01:52:46 marka Exp $ */
/*! \file */
};
static const char *matchtype_enums[] = {
- "name", "subdomain", "wildcard", "self", "selfsub", "selfwild", NULL };
+ "name", "subdomain", "wildcard", "self", "selfsub", "selfwild",
+ "krb5-self", "ms-self", "krb5-subdomain", "ms-subdomain", NULL };
static cfg_type_t cfg_type_matchtype = {
"matchtype", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum, &cfg_rep_string,
&matchtype_enums
#!/bin/sh -
+##
+## Modified to handle -vpath <path> option by Michael Graff, ISC.
+## The purpose of this is to allow this script to run outside of the
+## source directory, for instance when running configure with
+## ../bind9-mainline/configure
+## and still have "make depend" work.
+##
+
## ++Copyright++ 1987
## -
## Copyright (c) 1987 Regents of the University of California.
while :
do case "$1" in
+ # -vpath allows one to select a virtual path for .c files
+ -vpath)
+ VPATH=$2;
+ shift; shift ;;
# -f allows you to select a makefile name
-f)
MAKE=$2
done
if [ $# = 0 ] ; then
- echo 'usage: mkdep [-p] [-f makefile] [flags] file ...'
+ echo 'usage: mkdep [-vpath path] [-p] [-f makefile] [flags] file ...'
exit 1
fi
# egrep '^#include[ ]*".*"' /dev/null $* |
# sed -e 's/:[^"]*"\([^"]*\)".*/: \1/' -e 's/\.c/.o/' |
+if [ X"${VPATH}" != X ] ; then
+ for arg in $* ; do
+ case "$arg" in
+ -*)
+ newargs="$newargs $arg"
+ ;;
+ *)
+ newargs="$newargs $VPATH/$arg"
+ ;;
+ esac
+ done
+else
+ newargs="$*";
+fi
+
MKDEPPROG="@MKDEPPROG@"
if [ X"${MKDEPPROG}" != X ]; then
- @SHELL@ -c "${MKDEPPROG} $*"
+ @SHELL@ -c "${MKDEPPROG} ${newargs}"
else
- @MKDEPCC@ @MKDEPCFLAGS@ $* |
+ @MKDEPCC@ @MKDEPCFLAGS@ ${newargs} |
sed "
s; \./; ;g
@LIBTOOL_MKDEP_SED@
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
-# $Id: rules.in,v 1.57 2006/01/06 00:01:44 marka Exp $
+# $Id: rules.in,v 1.58 2006/12/04 01:52:46 marka Exp $
###
### Common Makefile rules for BIND 9.
(cd $$i; ${MAKE} ${MAKEDEFS} DESTDIR="${DESTDIR}" $@) || exit 1; \
fi; \
done
- @if [ X"${SRCS}" != X -a X"${PSRCS}" != X ] ; then \
- echo ${MKDEP} ${ALL_CPPFLAGS} ${SRCS}; \
- ${MKDEP} ${ALL_CPPFLAGS} ${SRCS}; \
- echo ${MKDEP} -ap ${ALL_CPPFLAGS} ${PSRCS}; \
- ${MKDEP} -ap ${ALL_CPPFLAGS} ${PSRCS}; \
- ${DEPENDEXTRA} \
- elif [ X"${SRCS}" != X ] ; then \
- echo ${MKDEP} ${ALL_CPPFLAGS} ${SRCS}; \
- ${MKDEP} ${ALL_CPPFLAGS} ${SRCS}; \
- ${DEPENDEXTRA} \
- elif [ X"${PSRCS}" != X ] ; then \
- echo ${MKDEP} ${ALL_CPPFLAGS} ${PSRCS}; \
- ${MKDEP} -p ${ALL_CPPFLAGS} ${PSRCS}; \
- ${DEPENDEXTRA} \
+ @if [ X"${VPATH}" != X ] ; then \
+ if [ X"${SRCS}" != X -a X"${PSRCS}" != X ] ; then \
+ echo ${MKDEP} -vpath ${VPATH} ${ALL_CPPFLAGS} ${SRCS}; \
+ ${MKDEP} -vpath ${VPATH} ${ALL_CPPFLAGS} ${SRCS}; \
+ echo ${MKDEP} -vpath ${VPATH} -ap ${ALL_CPPFLAGS} ${PSRCS}; \
+ ${MKDEP} -vpath ${VPATH} -ap ${ALL_CPPFLAGS} ${PSRCS}; \
+ ${DEPENDEXTRA} \
+ elif [ X"${SRCS}" != X ] ; then \
+ echo ${MKDEP} -vpath ${VPATH} ${ALL_CPPFLAGS} ${SRCS}; \
+ ${MKDEP} -vpath ${VPATH} ${ALL_CPPFLAGS} ${SRCS}; \
+ ${DEPENDEXTRA} \
+ elif [ X"${PSRCS}" != X ] ; then \
+ echo ${MKDEP} -vpath ${VPATH} ${ALL_CPPFLAGS} ${PSRCS}; \
+ ${MKDEP} -vpath ${VPATH} -p ${ALL_CPPFLAGS} ${PSRCS}; \
+ ${DEPENDEXTRA} \
+ fi \
+ else \
+ if [ X"${SRCS}" != X -a X"${PSRCS}" != X ] ; then \
+ echo ${MKDEP} ${ALL_CPPFLAGS} ${SRCS}; \
+ ${MKDEP} ${ALL_CPPFLAGS} ${SRCS}; \
+ echo ${MKDEP} -ap ${ALL_CPPFLAGS} ${PSRCS}; \
+ ${MKDEP} -ap ${ALL_CPPFLAGS} ${PSRCS}; \
+ ${DEPENDEXTRA} \
+ elif [ X"${SRCS}" != X ] ; then \
+ echo ${MKDEP} ${ALL_CPPFLAGS} ${SRCS}; \
+ ${MKDEP} ${ALL_CPPFLAGS} ${SRCS}; \
+ ${DEPENDEXTRA} \
+ elif [ X"${PSRCS}" != X ] ; then \
+ echo ${MKDEP} ${ALL_CPPFLAGS} ${PSRCS}; \
+ ${MKDEP} -p ${ALL_CPPFLAGS} ${PSRCS}; \
+ ${DEPENDEXTRA} \
+ fi \
fi
FORCE: