summaryrefslogtreecommitdiffstats
path: root/bin/nsupdate/nsupdate.c
diff options
context:
space:
mode:
Diffstat (limited to 'bin/nsupdate/nsupdate.c')
-rw-r--r--bin/nsupdate/nsupdate.c88
1 files changed, 78 insertions, 10 deletions
diff --git a/bin/nsupdate/nsupdate.c b/bin/nsupdate/nsupdate.c
index 6cf4cf4..d9ee488 100644
--- a/bin/nsupdate/nsupdate.c
+++ b/bin/nsupdate/nsupdate.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000-2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: nsupdate.c,v 1.163.48.3 2009/04/30 07:12:49 marka Exp $ */
+/* $Id: nsupdate.c,v 1.163.48.15 2010-12-09 04:30:57 tbox Exp $ */
/*! \file */
@@ -38,6 +38,7 @@
#include <isc/log.h>
#include <isc/mem.h>
#include <isc/parseint.h>
+#include <isc/print.h>
#include <isc/random.h>
#include <isc/region.h>
#include <isc/sockaddr.h>
@@ -185,6 +186,7 @@ ddebug(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
#ifdef GSSAPI
static dns_fixedname_t fkname;
static isc_sockaddr_t *kserver = NULL;
+static char *realm = NULL;
static char servicename[DNS_NAME_FORMATSIZE];
static dns_name_t *keyname;
typedef struct nsu_gssinfo {
@@ -539,7 +541,8 @@ setup_keystr(void) {
debug("keycreate");
result = dns_tsigkey_create(keyname, hmacname, secret, secretlen,
- ISC_TRUE, NULL, 0, 0, mctx, NULL, &tsigkey);
+ ISC_FALSE, NULL, 0, 0, mctx, NULL,
+ &tsigkey);
if (result != ISC_R_SUCCESS)
fprintf(stderr, "could not create key from %s: %s\n",
keystr, dns_result_totext(result));
@@ -550,6 +553,19 @@ setup_keystr(void) {
isc_mem_free(mctx, secret);
}
+static int
+basenamelen(const char *file) {
+ int len = strlen(file);
+
+ if (len > 1 && file[len - 1] == '.')
+ len -= 1;
+ else if (len > 8 && strcmp(file + len - 8, ".private") == 0)
+ len -= 8;
+ else if (len > 4 && strcmp(file + len - 4, ".key") == 0)
+ len -= 4;
+ return (len);
+}
+
static void
setup_keyfile(void) {
dst_key_t *dstkey = NULL;
@@ -558,12 +574,16 @@ setup_keyfile(void) {
debug("Creating key...");
+ if (sig0key != NULL)
+ dst_key_free(&sig0key);
+
result = dst_key_fromnamedfile(keyfile,
DST_TYPE_PRIVATE | DST_TYPE_KEY, mctx,
&dstkey);
if (result != ISC_R_SUCCESS) {
- fprintf(stderr, "could not read key from %s: %s\n",
- keyfile, isc_result_totext(result));
+ fprintf(stderr, "could not read key from %.*s.{private,key}: "
+ "%s\n", basenamelen(keyfile), keyfile,
+ isc_result_totext(result));
return;
}
switch (dst_key_alg(dstkey)) {
@@ -591,14 +611,14 @@ setup_keyfile(void) {
hmacname, dstkey, ISC_FALSE,
NULL, 0, 0, mctx, NULL,
&tsigkey);
+ dst_key_free(&dstkey);
if (result != ISC_R_SUCCESS) {
fprintf(stderr, "could not create key from %s: %s\n",
keyfile, isc_result_totext(result));
- dst_key_free(&dstkey);
return;
}
} else
- sig0key = dstkey;
+ dst_key_attach(dstkey, &sig0key);
}
static void
@@ -1349,7 +1369,7 @@ evaluate_key(char *cmdline) {
if (tsigkey != NULL)
dns_tsigkey_detach(&tsigkey);
result = dns_tsigkey_create(keyname, hmacname, secret, secretlen,
- ISC_TRUE, NULL, 0, 0, mctx, NULL,
+ ISC_FALSE, NULL, 0, 0, mctx, NULL,
&tsigkey);
isc_mem_free(mctx, secret);
if (result != ISC_R_SUCCESS) {
@@ -1389,6 +1409,31 @@ evaluate_zone(char *cmdline) {
}
static isc_uint16_t
+evaluate_realm(char *cmdline) {
+#ifdef GSSAPI
+ char *word;
+ char buf[1024];
+
+ word = nsu_strsep(&cmdline, " \t\r\n");
+ if (*word == 0) {
+ if (realm != NULL)
+ isc_mem_free(mctx, realm);
+ realm = NULL;
+ return (STATUS_MORE);
+ }
+
+ snprintf(buf, sizeof(buf), "@%s", word);
+ realm = isc_mem_strdup(mctx, buf);
+ if (realm == NULL)
+ fatal("out of memory");
+ return (STATUS_MORE);
+#else
+ UNUSED(cmdline);
+ return (STATUS_SYNTAX);
+#endif
+}
+
+static isc_uint16_t
evaluate_ttl(char *cmdline) {
char *word;
isc_result_t result;
@@ -1779,6 +1824,8 @@ get_next_command(void) {
usegsstsig = ISC_FALSE;
return (evaluate_key(cmdline));
}
+ if (strcasecmp(word, "realm") == 0)
+ return (evaluate_realm(cmdline));
if (strcasecmp(word, "gsstsig") == 0) {
#ifdef GSSAPI
usegsstsig = ISC_TRUE;
@@ -1985,6 +2032,10 @@ send_update(dns_name_t *zonename, isc_sockaddr_t *master,
fprintf(stderr, "Sending update to %s\n", addrbuf);
}
+ /* Windows doesn't like the tsig name to be compressed. */
+ if (updatemsg->tsigname)
+ updatemsg->tsigname->attributes |= DNS_NAMEATTR_NOCOMPRESS;
+
result = dns_request_createvia3(requestmgr, updatemsg, srcaddr,
master, options, tsigkey, timeout,
udp_timeout, udp_retries, global_task,
@@ -2307,7 +2358,7 @@ start_gssrequest(dns_name_t *master)
servname = dns_fixedname_name(&fname);
result = isc_string_printf(servicename, sizeof(servicename),
- "DNS/%s", namestr);
+ "DNS/%s%s", namestr, realm ? realm : "");
if (result != ISC_R_SUCCESS)
fatal("isc_string_printf(servicename) failed: %s",
isc_result_totext(result));
@@ -2347,7 +2398,6 @@ start_gssrequest(dns_name_t *master)
isc_result_totext(result));
/* Build first request. */
-
context = GSS_C_NO_CONTEXT;
result = dns_tkey_buildgssquery(rmsg, keyname, servname, NULL, 0,
&context, use_win2k_gsstsig);
@@ -2585,6 +2635,7 @@ start_update(void) {
dns_name_init(name, NULL);
dns_name_clone(userzone, name);
} else {
+ dns_rdataset_t *tmprdataset;
result = dns_message_firstname(updatemsg, section);
if (result == ISC_R_NOMORE) {
section = DNS_SECTION_PREREQUISITE;
@@ -2602,6 +2653,19 @@ start_update(void) {
dns_message_currentname(updatemsg, section, &firstname);
dns_name_init(name, NULL);
dns_name_clone(firstname, name);
+ /*
+ * Looks to see if the first name references a DS record
+ * and if that name is not the root remove a label as DS
+ * records live in the parent zone so we need to start our
+ * search one label up.
+ */
+ tmprdataset = ISC_LIST_HEAD(firstname->list);
+ if (section == DNS_SECTION_UPDATE &&
+ !dns_name_equal(firstname, dns_rootname) &&
+ tmprdataset->type == dns_rdatatype_ds) {
+ unsigned int labels = dns_name_countlabels(name);
+ dns_name_getlabelsequence(name, 1, labels - 1, name);
+ }
}
ISC_LIST_INIT(name->list);
@@ -2636,6 +2700,10 @@ cleanup(void) {
isc_mem_put(mctx, kserver, sizeof(isc_sockaddr_t));
kserver = NULL;
}
+ if (realm != NULL) {
+ isc_mem_free(mctx, realm);
+ realm = NULL;
+ }
#endif
ddebug("Shutting down task manager");
OpenPOWER on IntegriCloud