diff options
Diffstat (limited to 'bin/nsupdate/nsupdate.c')
-rw-r--r-- | bin/nsupdate/nsupdate.c | 208 |
1 files changed, 177 insertions, 31 deletions
diff --git a/bin/nsupdate/nsupdate.c b/bin/nsupdate/nsupdate.c index 107d85f9..f84fc54c 100644 --- a/bin/nsupdate/nsupdate.c +++ b/bin/nsupdate/nsupdate.c @@ -15,7 +15,9 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: nsupdate.c,v 1.103.2.15.2.23 2006/06/09 07:29:24 marka Exp $ */ +/* $Id: nsupdate.c,v 1.130.18.13 2006/03/02 23:19:20 marka Exp $ */ + +/*! \file */ #include <config.h> @@ -282,6 +284,74 @@ reset_system(void) { updatemsg->opcode = dns_opcode_update; } +static isc_uint16_t +parse_hmac(dns_name_t **hmac, const char *hmacstr, size_t len) { + isc_uint16_t digestbits = 0; + isc_result_t result; + char buf[20]; + + REQUIRE(hmac != NULL && *hmac == NULL); + REQUIRE(hmacstr != NULL); + + if (len >= sizeof(buf)) + fatal("unknown key type '%.*s'", (int)(len), hmacstr); + + strncpy(buf, hmacstr, len); + buf[len] = 0; + + if (strcasecmp(buf, "hmac-md5") == 0) { + *hmac = DNS_TSIG_HMACMD5_NAME; + } else if (strncasecmp(buf, "hmac-md5-", 9) == 0) { + *hmac = DNS_TSIG_HMACMD5_NAME; + result = isc_parse_uint16(&digestbits, &buf[9], 10); + if (result != ISC_R_SUCCESS || digestbits > 128) + fatal("digest-bits out of range [0..128]"); + digestbits = (digestbits +7) & ~0x7U; + } else if (strcasecmp(buf, "hmac-sha1") == 0) { + *hmac = DNS_TSIG_HMACSHA1_NAME; + } else if (strncasecmp(buf, "hmac-sha1-", 10) == 0) { + *hmac = DNS_TSIG_HMACSHA1_NAME; + result = isc_parse_uint16(&digestbits, &buf[10], 10); + if (result != ISC_R_SUCCESS || digestbits > 160) + fatal("digest-bits out of range [0..160]"); + digestbits = (digestbits +7) & ~0x7U; + } else if (strcasecmp(buf, "hmac-sha224") == 0) { + *hmac = DNS_TSIG_HMACSHA224_NAME; + } else if (strncasecmp(buf, "hmac-sha224-", 12) == 0) { + *hmac = DNS_TSIG_HMACSHA224_NAME; + result = isc_parse_uint16(&digestbits, &buf[12], 10); + if (result != ISC_R_SUCCESS || digestbits > 224) + fatal("digest-bits out of range [0..224]"); + digestbits = (digestbits +7) & ~0x7U; + } else if (strcasecmp(buf, "hmac-sha256") == 0) { + *hmac = DNS_TSIG_HMACSHA256_NAME; + } else if (strncasecmp(buf, "hmac-sha256-", 12) == 0) { + *hmac = DNS_TSIG_HMACSHA256_NAME; + result = isc_parse_uint16(&digestbits, &buf[12], 10); + if (result != ISC_R_SUCCESS || digestbits > 256) + fatal("digest-bits out of range [0..256]"); + digestbits = (digestbits +7) & ~0x7U; + } else if (strcasecmp(buf, "hmac-sha384") == 0) { + *hmac = DNS_TSIG_HMACSHA384_NAME; + } else if (strncasecmp(buf, "hmac-sha384-", 12) == 0) { + *hmac = DNS_TSIG_HMACSHA384_NAME; + result = isc_parse_uint16(&digestbits, &buf[12], 10); + if (result != ISC_R_SUCCESS || digestbits > 384) + fatal("digest-bits out of range [0..384]"); + digestbits = (digestbits +7) & ~0x7U; + } else if (strcasecmp(buf, "hmac-sha512") == 0) { + *hmac = DNS_TSIG_HMACSHA512_NAME; + } else if (strncasecmp(buf, "hmac-sha512-", 12) == 0) { + *hmac = DNS_TSIG_HMACSHA512_NAME; + result = isc_parse_uint16(&digestbits, &buf[12], 10); + if (result != ISC_R_SUCCESS || digestbits > 512) + fatal("digest-bits out of range [0..512]"); + digestbits = (digestbits +7) & ~0x7U; + } else + fatal("unknown key type '%s'", buf); + return (digestbits); +} + static void setup_keystr(void) { unsigned char *secret = NULL; @@ -290,9 +360,12 @@ setup_keystr(void) { isc_result_t result; isc_buffer_t keynamesrc; char *secretstr; - char *s; + char *s, *n; dns_fixedname_t fkeyname; dns_name_t *keyname; + char *name; + dns_name_t *hmacname = NULL; + isc_uint16_t digestbits = 0; dns_fixedname_init(&fkeyname); keyname = dns_fixedname_name(&fkeyname); @@ -300,12 +373,24 @@ setup_keystr(void) { debug("Creating key..."); s = strchr(keystr, ':'); - if (s == NULL || s == keystr || *s == 0) - fatal("key option must specify keyname:secret"); + if (s == NULL || s == keystr || s[1] == 0) + fatal("key option must specify [hmac:]keyname:secret"); secretstr = s + 1; + n = strchr(secretstr, ':'); + if (n != NULL) { + if (n == secretstr || n[1] == 0) + fatal("key option must specify [hmac:]keyname:secret"); + name = secretstr; + secretstr = n + 1; + digestbits = parse_hmac(&hmacname, keystr, s - keystr); + } else { + hmacname = DNS_TSIG_HMACMD5_NAME; + name = keystr; + n = s; + } - isc_buffer_init(&keynamesrc, keystr, s - keystr); - isc_buffer_add(&keynamesrc, s - keystr); + isc_buffer_init(&keynamesrc, name, n - name); + isc_buffer_add(&keynamesrc, n - name); debug("namefromtext"); result = dns_name_fromtext(keyname, &keynamesrc, dns_rootname, @@ -328,12 +413,13 @@ setup_keystr(void) { secretlen = isc_buffer_usedlength(&secretbuf); debug("keycreate"); - result = dns_tsigkey_create(keyname, dns_tsig_hmacmd5_name, - secret, secretlen, ISC_TRUE, NULL, - 0, 0, mctx, NULL, &tsigkey); + result = dns_tsigkey_create(keyname, hmacname, secret, secretlen, + ISC_TRUE, 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)); + else + dst_key_setbits(tsigkey->key, digestbits); failure: if (secret != NULL) isc_mem_free(mctx, secret); @@ -343,6 +429,7 @@ static void setup_keyfile(void) { dst_key_t *dstkey = NULL; isc_result_t result; + dns_name_t *hmacname = NULL; debug("Creating key..."); @@ -354,11 +441,31 @@ setup_keyfile(void) { keyfile, isc_result_totext(result)); return; } - if (dst_key_alg(dstkey) == DST_ALG_HMACMD5) { + switch (dst_key_alg(dstkey)) { + case DST_ALG_HMACMD5: + hmacname = DNS_TSIG_HMACMD5_NAME; + break; + case DST_ALG_HMACSHA1: + hmacname = DNS_TSIG_HMACSHA1_NAME; + break; + case DST_ALG_HMACSHA224: + hmacname = DNS_TSIG_HMACSHA224_NAME; + break; + case DST_ALG_HMACSHA256: + hmacname = DNS_TSIG_HMACSHA256_NAME; + break; + case DST_ALG_HMACSHA384: + hmacname = DNS_TSIG_HMACSHA384_NAME; + break; + case DST_ALG_HMACSHA512: + hmacname = DNS_TSIG_HMACSHA512_NAME; + break; + } + if (hmacname != NULL) { result = dns_tsigkey_createfromkey(dst_key_name(dstkey), - dns_tsig_hmacmd5_name, - dstkey, ISC_FALSE, NULL, - 0, 0, mctx, NULL, &tsigkey); + hmacname, dstkey, ISC_FALSE, + NULL, 0, 0, mctx, NULL, + &tsigkey); if (result != ISC_R_SUCCESS) { fprintf(stderr, "could not create key from %s: %s\n", keyfile, isc_result_totext(result)); @@ -998,6 +1105,9 @@ evaluate_key(char *cmdline) { int secretlen; unsigned char *secret = NULL; isc_buffer_t secretbuf; + dns_name_t *hmacname = NULL; + isc_uint16_t digestbits = 0; + char *n; namestr = nsu_strsep(&cmdline, " \t\r\n"); if (*namestr == 0) { @@ -1008,6 +1118,13 @@ evaluate_key(char *cmdline) { dns_fixedname_init(&fkeyname); keyname = dns_fixedname_name(&fkeyname); + n = strchr(namestr, ':'); + if (n != NULL) { + digestbits = parse_hmac(&hmacname, namestr, n - namestr); + namestr = n + 1; + } else + hmacname = DNS_TSIG_HMACMD5_NAME; + isc_buffer_init(&b, namestr, strlen(namestr)); isc_buffer_add(&b, strlen(namestr)); result = dns_name_fromtext(keyname, &b, dns_rootname, ISC_FALSE, NULL); @@ -1038,15 +1155,16 @@ evaluate_key(char *cmdline) { if (tsigkey != NULL) dns_tsigkey_detach(&tsigkey); - result = dns_tsigkey_create(keyname, dns_tsig_hmacmd5_name, - secret, secretlen, ISC_TRUE, NULL, 0, 0, - mctx, NULL, &tsigkey); + result = dns_tsigkey_create(keyname, hmacname, secret, secretlen, + ISC_TRUE, NULL, 0, 0, mctx, NULL, + &tsigkey); isc_mem_free(mctx, secret); if (result != ISC_R_SUCCESS) { fprintf(stderr, "could not create key from %s %s: %s\n", namestr, secretstr, dns_result_totext(result)); return (STATUS_SYNTAX); } + dst_key_setbits(tsigkey->key, digestbits); return (STATUS_MORE); } @@ -1304,12 +1422,50 @@ evaluate_update(char *cmdline) { } static void +setzone(dns_name_t *zonename) { + isc_result_t result; + dns_name_t *name = NULL; + dns_rdataset_t *rdataset = NULL; + + result = dns_message_firstname(updatemsg, DNS_SECTION_ZONE); + if (result == ISC_R_SUCCESS) { + dns_message_currentname(updatemsg, DNS_SECTION_ZONE, &name); + dns_message_removename(updatemsg, name, DNS_SECTION_ZONE); + for (rdataset = ISC_LIST_HEAD(name->list); + rdataset != NULL; + rdataset = ISC_LIST_HEAD(name->list)) { + ISC_LIST_UNLINK(name->list, rdataset, link); + dns_rdataset_disassociate(rdataset); + dns_message_puttemprdataset(updatemsg, &rdataset); + } + dns_message_puttempname(updatemsg, &name); + } + + if (zonename != NULL) { + result = dns_message_gettempname(updatemsg, &name); + check_result(result, "dns_message_gettempname"); + dns_name_init(name, NULL); + dns_name_clone(zonename, name); + result = dns_message_gettemprdataset(updatemsg, &rdataset); + check_result(result, "dns_message_gettemprdataset"); + dns_rdataset_makequestion(rdataset, getzoneclass(), + dns_rdatatype_soa); + ISC_LIST_INIT(name->list); + ISC_LIST_APPEND(name->list, rdataset, link); + dns_message_addname(updatemsg, name, DNS_SECTION_ZONE); + } +} + +static void show_message(dns_message_t *msg) { isc_result_t result; isc_buffer_t *buf = NULL; int bufsz; ddebug("show_message()"); + + setzone(userzone); + bufsz = INITTEXT; do { if (bufsz > MAXTEXT) { @@ -1343,10 +1499,8 @@ get_next_command(void) { char *word; ddebug("get_next_command()"); - if (interactive) { + if (interactive) fprintf(stdout, "> "); - fflush(stdout); - } isc_app_block(); cmdline = fgets(cmdlinebuf, MAXCMD, input); isc_app_unblock(); @@ -1537,22 +1691,11 @@ send_update(dns_name_t *zonename, isc_sockaddr_t *master, { isc_result_t result; dns_request_t *request = NULL; - dns_name_t *name = NULL; - dns_rdataset_t *rdataset = NULL; unsigned int options = 0; ddebug("send_update()"); - result = dns_message_gettempname(updatemsg, &name); - check_result(result, "dns_message_gettempname"); - dns_name_init(name, NULL); - dns_name_clone(zonename, name); - result = dns_message_gettemprdataset(updatemsg, &rdataset); - check_result(result, "dns_message_gettemprdataset"); - dns_rdataset_makequestion(rdataset, getzoneclass(), dns_rdatatype_soa); - ISC_LIST_INIT(name->list); - ISC_LIST_APPEND(name->list, rdataset, link); - dns_message_addname(updatemsg, name, DNS_SECTION_ZONE); + setzone(zonename); if (usevc) options |= DNS_REQUESTOPT_TCP; @@ -1927,6 +2070,9 @@ cleanup(void) { ddebug("Destroying hash context"); isc_hash_destroy(); + ddebug("Destroying name state"); + dns_name_destroy(); + ddebug("Destroying memory context"); if (memdebugging) isc_mem_stats(mctx, stderr); |