mirror of
https://github.com/isc-projects/bind9.git
synced 2026-02-23 01:40:23 -05:00
When fatal is called we may be holding memory allocated by OpenSSL. This may result in the reference count for the FIPS provider not going to zero and the shared library not being unloaded during OPENSSL_cleanup. When the shared library is ultimately unloaded, when all remaining dynamically loaded libraries are freed, we have already destroyed the memory context we where using to track memory leaks / late frees resulting in INSIST being called. Disable triggering the INSIST when fatal has being called.
195 lines
4.7 KiB
C
195 lines
4.7 KiB
C
/*
|
|
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
|
*
|
|
* SPDX-License-Identifier: MPL-2.0
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
|
*
|
|
* See the COPYRIGHT file distributed with this work for additional
|
|
* information regarding copyright ownership.
|
|
*/
|
|
|
|
#include <stdarg.h>
|
|
#include <stdbool.h>
|
|
#include <stdlib.h>
|
|
|
|
#include <isc/attributes.h>
|
|
#include <isc/base32.h>
|
|
#include <isc/buffer.h>
|
|
#include <isc/commandline.h>
|
|
#include <isc/file.h>
|
|
#include <isc/hex.h>
|
|
#include <isc/iterated_hash.h>
|
|
#include <isc/result.h>
|
|
#include <isc/string.h>
|
|
#include <isc/tls.h>
|
|
#include <isc/types.h>
|
|
#include <isc/util.h>
|
|
|
|
#include <dns/fixedname.h>
|
|
#include <dns/name.h>
|
|
#include <dns/nsec3.h>
|
|
#include <dns/types.h>
|
|
|
|
const char *program = "nsec3hash";
|
|
|
|
noreturn static void
|
|
fatal(const char *format, ...);
|
|
|
|
static void
|
|
fatal(const char *format, ...) {
|
|
va_list args;
|
|
|
|
fprintf(stderr, "%s: ", program);
|
|
va_start(args, format);
|
|
vfprintf(stderr, format, args);
|
|
va_end(args);
|
|
fprintf(stderr, "\n");
|
|
isc__tls_setfatalmode();
|
|
exit(1);
|
|
}
|
|
|
|
static void
|
|
check_result(isc_result_t result, const char *message) {
|
|
if (result != ISC_R_SUCCESS) {
|
|
fatal("%s: %s", message, isc_result_totext(result));
|
|
}
|
|
}
|
|
|
|
static void
|
|
usage(void) {
|
|
fprintf(stderr, "Usage: %s salt algorithm iterations domain\n",
|
|
program);
|
|
fprintf(stderr, " %s -r algorithm flags iterations salt domain\n",
|
|
program);
|
|
exit(1);
|
|
}
|
|
|
|
typedef void
|
|
nsec3printer(unsigned int algo, unsigned int flags, unsigned int iters,
|
|
const char *saltstr, const char *domain, const char *digest);
|
|
|
|
static void
|
|
nsec3hash(nsec3printer *nsec3print, const char *algostr, const char *flagstr,
|
|
const char *iterstr, const char *saltstr, const char *domain) {
|
|
dns_fixedname_t fixed;
|
|
dns_name_t *name;
|
|
isc_buffer_t buffer;
|
|
isc_region_t region;
|
|
isc_result_t result;
|
|
unsigned char hash[NSEC3_MAX_HASH_LENGTH];
|
|
unsigned char salt[DNS_NSEC3_SALTSIZE];
|
|
unsigned char text[1024];
|
|
unsigned int hash_alg;
|
|
unsigned int flags;
|
|
unsigned int length;
|
|
unsigned int iterations;
|
|
unsigned int salt_length;
|
|
const char dash[] = "-";
|
|
|
|
if (strcmp(saltstr, "-") == 0) {
|
|
salt_length = 0;
|
|
salt[0] = 0;
|
|
} else {
|
|
isc_buffer_init(&buffer, salt, sizeof(salt));
|
|
result = isc_hex_decodestring(saltstr, &buffer);
|
|
check_result(result, "isc_hex_decodestring(salt)");
|
|
salt_length = isc_buffer_usedlength(&buffer);
|
|
if (salt_length > DNS_NSEC3_SALTSIZE) {
|
|
fatal("salt too long");
|
|
}
|
|
if (salt_length == 0) {
|
|
saltstr = dash;
|
|
}
|
|
}
|
|
hash_alg = atoi(algostr);
|
|
if (hash_alg > 255U) {
|
|
fatal("hash algorithm too large");
|
|
}
|
|
flags = flagstr == NULL ? 0 : atoi(flagstr);
|
|
if (flags > 255U) {
|
|
fatal("flags too large");
|
|
}
|
|
iterations = atoi(iterstr);
|
|
if (iterations > 0xffffU) {
|
|
fatal("iterations to large");
|
|
}
|
|
|
|
name = dns_fixedname_initname(&fixed);
|
|
isc_buffer_constinit(&buffer, domain, strlen(domain));
|
|
isc_buffer_add(&buffer, strlen(domain));
|
|
result = dns_name_fromtext(name, &buffer, dns_rootname, 0, NULL);
|
|
check_result(result, "dns_name_fromtext() failed");
|
|
|
|
dns_name_downcase(name, name, NULL);
|
|
length = isc_iterated_hash(hash, hash_alg, iterations, salt,
|
|
salt_length, name->ndata, name->length);
|
|
if (length == 0) {
|
|
fatal("isc_iterated_hash failed");
|
|
}
|
|
region.base = hash;
|
|
region.length = length;
|
|
isc_buffer_init(&buffer, text, sizeof(text));
|
|
isc_base32hexnp_totext(®ion, 1, "", &buffer);
|
|
isc_buffer_putuint8(&buffer, '\0');
|
|
|
|
nsec3print(hash_alg, flags, iterations, saltstr, domain, (char *)text);
|
|
}
|
|
|
|
static void
|
|
nsec3hash_print(unsigned int algo, unsigned int flags, unsigned int iters,
|
|
const char *saltstr, const char *domain, const char *digest) {
|
|
UNUSED(flags);
|
|
UNUSED(domain);
|
|
|
|
fprintf(stdout, "%s (salt=%s, hash=%u, iterations=%u)\n", digest,
|
|
saltstr, algo, iters);
|
|
}
|
|
|
|
static void
|
|
nsec3hash_rdata_print(unsigned int algo, unsigned int flags, unsigned int iters,
|
|
const char *saltstr, const char *domain,
|
|
const char *digest) {
|
|
fprintf(stdout, "%s NSEC3 %u %u %u %s %s\n", domain, algo, flags, iters,
|
|
saltstr, digest);
|
|
}
|
|
|
|
int
|
|
main(int argc, char *argv[]) {
|
|
bool rdata_format = false;
|
|
int ch;
|
|
|
|
while ((ch = isc_commandline_parse(argc, argv, "-r")) != -1) {
|
|
switch (ch) {
|
|
case 'r':
|
|
rdata_format = true;
|
|
break;
|
|
case '-':
|
|
isc_commandline_index -= 1;
|
|
goto skip;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
skip:
|
|
argc -= isc_commandline_index;
|
|
argv += isc_commandline_index;
|
|
|
|
if (rdata_format) {
|
|
if (argc != 5) {
|
|
usage();
|
|
}
|
|
nsec3hash(nsec3hash_rdata_print, argv[0], argv[1], argv[2],
|
|
argv[3], argv[4]);
|
|
} else {
|
|
if (argc != 4) {
|
|
usage();
|
|
}
|
|
nsec3hash(nsec3hash_print, argv[1], NULL, argv[2], argv[0],
|
|
argv[3]);
|
|
}
|
|
return (0);
|
|
}
|