1999-07-12 20:08:42 +00:00
|
|
|
/*
|
2018-03-15 18:32:45 -07:00
|
|
|
* Portions Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
2007-06-18 23:47:57 +00:00
|
|
|
*
|
2016-06-27 14:56:38 +10:00
|
|
|
* 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
|
2020-09-14 16:20:40 -07:00
|
|
|
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
2007-06-18 23:47:57 +00:00
|
|
|
*
|
2018-02-23 09:53:12 +01:00
|
|
|
* See the COPYRIGHT file distributed with this work for additional
|
|
|
|
* information regarding copyright ownership.
|
|
|
|
*
|
|
|
|
* Portions Copyright (C) Network Associates, Inc.
|
2000-08-01 01:33:37 +00:00
|
|
|
*
|
2007-08-28 07:20:43 +00:00
|
|
|
* Permission to use, copy, modify, and/or distribute this software for any
|
1999-07-12 20:08:42 +00:00
|
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
|
|
* copyright notice and this permission notice appear in all copies.
|
2000-08-01 01:33:37 +00:00
|
|
|
*
|
2004-03-05 05:14:21 +00:00
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES 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.
|
1999-07-12 20:08:42 +00:00
|
|
|
*/
|
|
|
|
|
2005-04-27 04:57:32 +00:00
|
|
|
/*! \file */
|
|
|
|
|
2018-03-28 14:19:37 +02:00
|
|
|
#include <inttypes.h>
|
2018-04-17 08:29:14 -07:00
|
|
|
#include <stdbool.h>
|
2000-05-15 23:14:42 +00:00
|
|
|
#include <stdlib.h>
|
2009-11-07 03:36:58 +00:00
|
|
|
#include <time.h>
|
2000-05-15 23:14:42 +00:00
|
|
|
|
2000-05-15 21:02:39 +00:00
|
|
|
#include <isc/buffer.h>
|
1999-10-08 22:24:06 +00:00
|
|
|
#include <isc/dir.h>
|
2020-02-12 13:59:18 +01:00
|
|
|
#include <isc/file.h>
|
2001-01-09 00:53:06 +00:00
|
|
|
#include <isc/fsaccess.h>
|
1999-07-12 20:08:42 +00:00
|
|
|
#include <isc/lex.h>
|
|
|
|
#include <isc/mem.h>
|
|
|
|
#include <isc/once.h>
|
2010-05-12 23:49:40 +00:00
|
|
|
#include <isc/platform.h>
|
2001-05-09 23:04:50 +00:00
|
|
|
#include <isc/print.h>
|
2000-03-28 03:06:38 +00:00
|
|
|
#include <isc/random.h>
|
2020-02-12 13:59:18 +01:00
|
|
|
#include <isc/refcount.h>
|
2017-09-19 16:16:45 +05:30
|
|
|
#include <isc/safe.h>
|
2000-05-08 14:38:29 +00:00
|
|
|
#include <isc/string.h>
|
2000-03-28 03:06:38 +00:00
|
|
|
#include <isc/time.h>
|
2000-04-28 01:12:23 +00:00
|
|
|
#include <isc/util.h>
|
|
|
|
|
2016-08-19 08:02:51 +10:00
|
|
|
#include <pk11/site.h>
|
|
|
|
|
2012-06-14 15:44:20 +10:00
|
|
|
#define DST_KEY_INTERNAL
|
|
|
|
|
2000-06-06 21:58:16 +00:00
|
|
|
#include <dns/fixedname.h>
|
2002-11-12 22:22:32 +00:00
|
|
|
#include <dns/keyvalues.h>
|
2000-05-24 23:13:32 +00:00
|
|
|
#include <dns/name.h>
|
1999-07-12 20:08:42 +00:00
|
|
|
#include <dns/rdata.h>
|
2000-09-12 09:54:36 +00:00
|
|
|
#include <dns/rdataclass.h>
|
2002-11-12 22:22:32 +00:00
|
|
|
#include <dns/ttl.h>
|
2000-06-02 18:57:51 +00:00
|
|
|
#include <dns/types.h>
|
1999-07-12 20:08:42 +00:00
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
#include <dst/result.h>
|
|
|
|
|
2020-03-09 16:17:26 +01:00
|
|
|
#include "dst_internal.h"
|
|
|
|
|
2002-01-21 01:07:32 +00:00
|
|
|
#define DST_AS_STR(t) ((t).value.as_textregion.base)
|
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
#define NEXTTOKEN(lex, opt, token) \
|
|
|
|
{ \
|
|
|
|
ret = isc_lex_gettoken(lex, opt, token); \
|
|
|
|
if (ret != ISC_R_SUCCESS) \
|
|
|
|
goto cleanup; \
|
|
|
|
}
|
|
|
|
|
|
|
|
#define NEXTTOKEN_OR_EOF(lex, opt, token) \
|
|
|
|
do { \
|
|
|
|
ret = isc_lex_gettoken(lex, opt, token); \
|
|
|
|
if (ret == ISC_R_EOF) \
|
|
|
|
break; \
|
|
|
|
if (ret != ISC_R_SUCCESS) \
|
|
|
|
goto cleanup; \
|
|
|
|
} while ((*token).type == isc_tokentype_eol);
|
|
|
|
|
|
|
|
#define READLINE(lex, opt, token) \
|
|
|
|
do { \
|
|
|
|
ret = isc_lex_gettoken(lex, opt, token); \
|
|
|
|
if (ret == ISC_R_EOF) \
|
|
|
|
break; \
|
|
|
|
if (ret != ISC_R_SUCCESS) \
|
|
|
|
goto cleanup; \
|
2019-09-12 11:45:10 +02:00
|
|
|
} while ((*token).type != isc_tokentype_eol)
|
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
#define BADTOKEN() \
|
|
|
|
{ \
|
|
|
|
ret = ISC_R_UNEXPECTEDTOKEN; \
|
|
|
|
goto cleanup; \
|
2019-09-12 11:45:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#define NUMERIC_NTAGS (DST_MAX_NUMERIC + 1)
|
|
|
|
static const char *numerictags[NUMERIC_NTAGS] = {
|
2020-02-12 13:59:18 +01:00
|
|
|
"Predecessor:", "Successor:", "MaxTTL:", "RollPeriod:", "Lifetime:"
|
2019-09-12 11:45:10 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
#define BOOLEAN_NTAGS (DST_MAX_BOOLEAN + 1)
|
2020-02-12 13:59:18 +01:00
|
|
|
static const char *booleantags[BOOLEAN_NTAGS] = { "KSK:", "ZSK:" };
|
2019-09-12 11:45:10 +02:00
|
|
|
|
|
|
|
#define TIMING_NTAGS (DST_MAX_TIMES + 1)
|
|
|
|
static const char *timingtags[TIMING_NTAGS] = {
|
2020-02-12 13:59:18 +01:00
|
|
|
"Generated:", "Published:", "Active:", "Revoked:",
|
|
|
|
"Retired:", "Removed:",
|
|
|
|
|
|
|
|
"DSPublish:", "SyncPublish:", "SyncDelete:",
|
|
|
|
|
Implement 'rndc dnssec -checkds'
Add a new 'rndc' command 'dnssec -checkds' that allows the user to
signal named that a new DS record has been seen published in the
parent, or that an existing DS record has been withdrawn from the
parent.
Upon the 'checkds' request, 'named' will write out the new state for
the key, updating the 'DSPublish' or 'DSRemoved' timing metadata.
This replaces the "parent-registration-delay" configuration option,
this was unreliable because it was purely time based (if the user
did not actually submit the new DS to the parent for example, this
could result in an invalid DNSSEC state).
Because we cannot rely on the parent registration delay for state
transition, we need to replace it with a different guard. Instead,
if a key wants its DS state to be moved to RUMOURED, the "DSPublish"
time must be set and must not be in the future. If a key wants its
DS state to be moved to UNRETENTIVE, the "DSRemoved" time must be set
and must not be in the future.
By default, with '-checkds' you set the time that the DS has been
published or withdrawn to now, but you can set a different time with
'-when'. If there is only one KSK for the zone, that key has its
DS state moved to RUMOURED. If there are multiple keys for the zone,
specify the right key with '-key'.
2020-07-31 08:37:51 +02:00
|
|
|
"DNSKEYChange:", "ZRRSIGChange:", "KRRSIGChange:", "DSChange:",
|
|
|
|
|
|
|
|
"DSRemoved:"
|
2019-09-12 11:57:55 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
#define KEYSTATES_NTAGS (DST_MAX_KEYSTATES + 1)
|
|
|
|
static const char *keystatestags[KEYSTATES_NTAGS] = {
|
2020-02-12 13:59:18 +01:00
|
|
|
"DNSKEYState:", "ZRRSIGState:", "KRRSIGState:", "DSState:", "GoalState:"
|
2019-09-12 11:57:55 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
#define KEYSTATES_NVALUES 4
|
|
|
|
static const char *keystates[KEYSTATES_NVALUES] = {
|
2020-02-12 13:59:18 +01:00
|
|
|
"hidden",
|
|
|
|
"rumoured",
|
|
|
|
"omnipresent",
|
|
|
|
"unretentive",
|
2019-09-12 11:45:10 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
#define STATE_ALGORITHM_STR "Algorithm:"
|
2020-02-13 14:44:37 -08:00
|
|
|
#define STATE_LENGTH_STR "Length:"
|
2020-02-12 13:59:18 +01:00
|
|
|
#define MAX_NTAGS \
|
|
|
|
(DST_MAX_NUMERIC + DST_MAX_BOOLEAN + DST_MAX_TIMES + DST_MAX_KEYSTATES)
|
2019-09-12 11:45:10 +02:00
|
|
|
|
2000-06-02 23:36:14 +00:00
|
|
|
static dst_func_t *dst_t_func[DST_MAX_ALGS];
|
2014-05-29 22:22:53 -07:00
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
static bool dst_initialized = false;
|
2000-06-02 18:57:51 +00:00
|
|
|
|
2020-02-14 08:14:03 +01:00
|
|
|
void
|
|
|
|
gss_log(int level, const char *fmt, ...) ISC_FORMAT_PRINTF(2, 3);
|
2006-12-04 01:54:53 +00:00
|
|
|
|
2000-06-08 20:38:48 +00:00
|
|
|
/*
|
|
|
|
* Static functions.
|
|
|
|
*/
|
2020-02-14 08:14:03 +01:00
|
|
|
static dst_key_t *
|
|
|
|
get_key_struct(const dns_name_t *name, unsigned int alg, unsigned int flags,
|
|
|
|
unsigned int protocol, unsigned int bits,
|
|
|
|
dns_rdataclass_t rdclass, dns_ttl_t ttl, isc_mem_t *mctx);
|
|
|
|
static isc_result_t
|
|
|
|
write_public_key(const dst_key_t *key, int type, const char *directory);
|
|
|
|
static isc_result_t
|
|
|
|
write_key_state(const dst_key_t *key, int type, const char *directory);
|
|
|
|
static isc_result_t
|
|
|
|
buildfilename(dns_name_t *name, dns_keytag_t id, unsigned int alg,
|
|
|
|
unsigned int type, const char *directory, isc_buffer_t *out);
|
|
|
|
static isc_result_t
|
|
|
|
computeid(dst_key_t *key);
|
|
|
|
static isc_result_t
|
|
|
|
frombuffer(const dns_name_t *name, unsigned int alg, unsigned int flags,
|
|
|
|
unsigned int protocol, dns_rdataclass_t rdclass,
|
|
|
|
isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp);
|
|
|
|
|
|
|
|
static isc_result_t
|
|
|
|
algorithm_status(unsigned int alg);
|
|
|
|
|
|
|
|
static isc_result_t
|
|
|
|
addsuffix(char *filename, int len, const char *dirname, const char *ofilename,
|
|
|
|
const char *suffix);
|
2020-02-12 13:59:18 +01:00
|
|
|
|
|
|
|
#define RETERR(x) \
|
|
|
|
do { \
|
|
|
|
result = (x); \
|
|
|
|
if (result != ISC_R_SUCCESS) \
|
|
|
|
goto out; \
|
2000-06-09 22:32:20 +00:00
|
|
|
} while (0)
|
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
#define CHECKALG(alg) \
|
|
|
|
do { \
|
|
|
|
isc_result_t _r; \
|
|
|
|
_r = algorithm_status(alg); \
|
|
|
|
if (_r != ISC_R_SUCCESS) \
|
2020-02-13 21:48:23 +01:00
|
|
|
return ((_r)); \
|
2020-02-12 13:59:18 +01:00
|
|
|
} while (0);
|
2001-07-10 19:05:53 +00:00
|
|
|
|
2000-06-06 21:58:16 +00:00
|
|
|
isc_result_t
|
2020-02-13 14:44:37 -08:00
|
|
|
dst_lib_init(isc_mem_t *mctx, const char *engine) {
|
2000-06-09 22:32:20 +00:00
|
|
|
isc_result_t result;
|
|
|
|
|
2009-09-01 00:22:28 +00:00
|
|
|
REQUIRE(mctx != NULL);
|
2020-03-30 13:49:55 -07:00
|
|
|
REQUIRE(!dst_initialized);
|
2000-06-09 22:32:20 +00:00
|
|
|
|
2009-11-03 19:43:54 +00:00
|
|
|
UNUSED(engine);
|
|
|
|
|
2000-06-09 22:32:20 +00:00
|
|
|
dst_result_register();
|
|
|
|
|
|
|
|
memset(dst_t_func, 0, sizeof(dst_t_func));
|
|
|
|
RETERR(dst__hmacmd5_init(&dst_t_func[DST_ALG_HMACMD5]));
|
2006-01-27 02:35:15 +00:00
|
|
|
RETERR(dst__hmacsha1_init(&dst_t_func[DST_ALG_HMACSHA1]));
|
|
|
|
RETERR(dst__hmacsha224_init(&dst_t_func[DST_ALG_HMACSHA224]));
|
|
|
|
RETERR(dst__hmacsha256_init(&dst_t_func[DST_ALG_HMACSHA256]));
|
|
|
|
RETERR(dst__hmacsha384_init(&dst_t_func[DST_ALG_HMACSHA384]));
|
|
|
|
RETERR(dst__hmacsha512_init(&dst_t_func[DST_ALG_HMACSHA512]));
|
2018-10-11 15:13:27 +00:00
|
|
|
RETERR(dst__openssl_init(mctx, engine));
|
2018-07-19 13:46:01 -04:00
|
|
|
RETERR(dst__openssldh_init(&dst_t_func[DST_ALG_DH]));
|
2018-06-12 11:26:04 +02:00
|
|
|
#if USE_OPENSSL
|
2009-10-27 22:25:37 +00:00
|
|
|
RETERR(dst__opensslrsa_init(&dst_t_func[DST_ALG_RSASHA1],
|
|
|
|
DST_ALG_RSASHA1));
|
|
|
|
RETERR(dst__opensslrsa_init(&dst_t_func[DST_ALG_NSEC3RSASHA1],
|
|
|
|
DST_ALG_NSEC3RSASHA1));
|
|
|
|
RETERR(dst__opensslrsa_init(&dst_t_func[DST_ALG_RSASHA256],
|
|
|
|
DST_ALG_RSASHA256));
|
|
|
|
RETERR(dst__opensslrsa_init(&dst_t_func[DST_ALG_RSASHA512],
|
|
|
|
DST_ALG_RSASHA512));
|
2012-05-02 23:20:17 +10:00
|
|
|
RETERR(dst__opensslecdsa_init(&dst_t_func[DST_ALG_ECDSA256]));
|
|
|
|
RETERR(dst__opensslecdsa_init(&dst_t_func[DST_ALG_ECDSA384]));
|
2017-07-31 15:26:00 +02:00
|
|
|
#ifdef HAVE_OPENSSL_ED25519
|
|
|
|
RETERR(dst__openssleddsa_init(&dst_t_func[DST_ALG_ED25519]));
|
2020-02-13 21:48:23 +01:00
|
|
|
#endif /* ifdef HAVE_OPENSSL_ED25519 */
|
2017-07-31 15:26:00 +02:00
|
|
|
#ifdef HAVE_OPENSSL_ED448
|
|
|
|
RETERR(dst__openssleddsa_init(&dst_t_func[DST_ALG_ED448]));
|
2020-02-13 21:48:23 +01:00
|
|
|
#endif /* ifdef HAVE_OPENSSL_ED448 */
|
2018-06-12 11:26:04 +02:00
|
|
|
#endif /* USE_OPENSSL */
|
|
|
|
|
|
|
|
#if USE_PKCS11
|
2014-03-12 20:52:01 -07:00
|
|
|
RETERR(dst__pkcs11_init(mctx, engine));
|
2014-01-14 15:40:56 -08:00
|
|
|
RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_RSASHA1]));
|
|
|
|
RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_NSEC3RSASHA1]));
|
|
|
|
RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_RSASHA256]));
|
|
|
|
RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_RSASHA512]));
|
|
|
|
RETERR(dst__pkcs11ecdsa_init(&dst_t_func[DST_ALG_ECDSA256]));
|
|
|
|
RETERR(dst__pkcs11ecdsa_init(&dst_t_func[DST_ALG_ECDSA384]));
|
2017-07-31 15:26:00 +02:00
|
|
|
RETERR(dst__pkcs11eddsa_init(&dst_t_func[DST_ALG_ED25519]));
|
|
|
|
RETERR(dst__pkcs11eddsa_init(&dst_t_func[DST_ALG_ED448]));
|
2018-06-12 11:26:04 +02:00
|
|
|
#endif /* USE_PKCS11 */
|
2018-08-07 16:46:53 +02:00
|
|
|
#if HAVE_GSSAPI
|
2002-12-13 02:51:41 +00:00
|
|
|
RETERR(dst__gssapi_init(&dst_t_func[DST_ALG_GSSAPI]));
|
2018-08-07 16:46:53 +02:00
|
|
|
#endif /* HAVE_GSSAPI */
|
2018-04-22 14:56:28 +02:00
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
dst_initialized = true;
|
2000-06-09 22:32:20 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
out:
|
2009-10-05 17:30:49 +00:00
|
|
|
/* avoid immediate crash! */
|
2018-04-17 08:29:14 -07:00
|
|
|
dst_initialized = true;
|
2000-06-09 22:32:20 +00:00
|
|
|
dst_lib_destroy();
|
|
|
|
return (result);
|
2000-06-06 21:58:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-02-13 14:44:37 -08:00
|
|
|
dst_lib_destroy(void) {
|
2001-11-06 20:47:59 +00:00
|
|
|
int i;
|
2020-03-30 13:47:58 -07:00
|
|
|
RUNTIME_CHECK(dst_initialized);
|
2018-04-17 08:29:14 -07:00
|
|
|
dst_initialized = false;
|
2000-06-06 21:58:16 +00:00
|
|
|
|
2020-02-13 18:16:57 +01:00
|
|
|
for (i = 0; i < DST_MAX_ALGS; i++) {
|
|
|
|
if (dst_t_func[i] != NULL && dst_t_func[i]->cleanup != NULL) {
|
2001-11-06 20:47:59 +00:00
|
|
|
dst_t_func[i]->cleanup();
|
2020-02-13 18:16:57 +01:00
|
|
|
}
|
|
|
|
}
|
2000-06-09 23:31:55 +00:00
|
|
|
dst__openssl_destroy();
|
2018-06-12 11:26:04 +02:00
|
|
|
#if USE_PKCS11
|
2020-02-12 13:59:18 +01:00
|
|
|
(void)dst__pkcs11_destroy();
|
2018-06-12 11:26:04 +02:00
|
|
|
#endif /* USE_PKCS11 */
|
2000-06-06 21:58:16 +00:00
|
|
|
}
|
1999-07-12 20:08:42 +00:00
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
bool
|
2020-02-13 14:44:37 -08:00
|
|
|
dst_algorithm_supported(unsigned int alg) {
|
2020-03-30 13:47:58 -07:00
|
|
|
REQUIRE(dst_initialized);
|
2000-06-06 21:58:16 +00:00
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (alg >= DST_MAX_ALGS || dst_t_func[alg] == NULL) {
|
2018-04-17 08:29:14 -07:00
|
|
|
return (false);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2018-04-17 08:29:14 -07:00
|
|
|
return (true);
|
1999-07-12 20:08:42 +00:00
|
|
|
}
|
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
bool
|
2020-02-13 14:44:37 -08:00
|
|
|
dst_ds_digest_supported(unsigned int digest_type) {
|
2020-02-12 13:59:18 +01:00
|
|
|
return (digest_type == DNS_DSDIGEST_SHA1 ||
|
|
|
|
digest_type == DNS_DSDIGEST_SHA256 ||
|
|
|
|
digest_type == DNS_DSDIGEST_SHA384);
|
2012-10-03 12:38:43 +10:00
|
|
|
}
|
|
|
|
|
2000-03-06 20:06:01 +00:00
|
|
|
isc_result_t
|
2020-02-12 13:59:18 +01:00
|
|
|
dst_context_create(dst_key_t *key, isc_mem_t *mctx, isc_logcategory_t *category,
|
2020-02-13 14:44:37 -08:00
|
|
|
bool useforsigning, int maxbits, dst_context_t **dctxp) {
|
2000-06-02 18:57:51 +00:00
|
|
|
dst_context_t *dctx;
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_result_t result;
|
2000-06-02 18:57:51 +00:00
|
|
|
|
2020-03-30 13:47:58 -07:00
|
|
|
REQUIRE(dst_initialized);
|
2000-06-12 07:07:53 +00:00
|
|
|
REQUIRE(VALID_KEY(key));
|
2000-06-02 18:57:51 +00:00
|
|
|
REQUIRE(mctx != NULL);
|
|
|
|
REQUIRE(dctxp != NULL && *dctxp == NULL);
|
1999-07-12 20:08:42 +00:00
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (key->func->createctx == NULL && key->func->createctx2 == NULL) {
|
2000-06-02 23:36:14 +00:00
|
|
|
return (DST_R_UNSUPPORTEDALG);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
|
|
|
if (key->keydata.generic == NULL) {
|
2000-06-12 07:07:53 +00:00
|
|
|
return (DST_R_NULLKEY);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2000-06-02 23:36:14 +00:00
|
|
|
|
2000-06-02 18:57:51 +00:00
|
|
|
dctx = isc_mem_get(mctx, sizeof(dst_context_t));
|
2016-01-04 22:05:23 -08:00
|
|
|
memset(dctx, 0, sizeof(*dctx));
|
|
|
|
dst_key_attach(key, &dctx->key);
|
|
|
|
isc_mem_attach(mctx, &dctx->mctx);
|
2012-10-24 12:58:16 -07:00
|
|
|
dctx->category = category;
|
2020-02-13 21:48:23 +01:00
|
|
|
if (useforsigning) {
|
2014-01-14 15:40:56 -08:00
|
|
|
dctx->use = DO_SIGN;
|
2020-02-13 21:48:23 +01:00
|
|
|
} else {
|
2014-01-14 15:40:56 -08:00
|
|
|
dctx->use = DO_VERIFY;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
|
|
|
if (key->func->createctx2 != NULL) {
|
2014-01-14 15:40:56 -08:00
|
|
|
result = key->func->createctx2(key, maxbits, dctx);
|
2020-02-13 21:48:23 +01:00
|
|
|
} else {
|
2014-01-14 15:40:56 -08:00
|
|
|
result = key->func->createctx(key, dctx);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2000-06-02 18:57:51 +00:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2020-02-13 21:48:23 +01:00
|
|
|
if (dctx->key != NULL) {
|
2016-01-04 22:05:23 -08:00
|
|
|
dst_key_free(&dctx->key);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-01-04 22:05:23 -08:00
|
|
|
isc_mem_putanddetach(&dctx->mctx, dctx, sizeof(dst_context_t));
|
2000-06-02 18:57:51 +00:00
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
dctx->magic = CTX_MAGIC;
|
|
|
|
*dctxp = dctx;
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
1999-07-12 20:08:42 +00:00
|
|
|
|
2000-06-02 18:57:51 +00:00
|
|
|
void
|
2020-02-13 14:44:37 -08:00
|
|
|
dst_context_destroy(dst_context_t **dctxp) {
|
2000-06-02 18:57:51 +00:00
|
|
|
dst_context_t *dctx;
|
1999-07-12 20:08:42 +00:00
|
|
|
|
2000-06-02 18:57:51 +00:00
|
|
|
REQUIRE(dctxp != NULL && VALID_CTX(*dctxp));
|
1999-07-12 20:08:42 +00:00
|
|
|
|
2000-06-02 18:57:51 +00:00
|
|
|
dctx = *dctxp;
|
2020-02-08 04:37:54 -08:00
|
|
|
*dctxp = NULL;
|
2000-06-02 23:36:14 +00:00
|
|
|
INSIST(dctx->key->func->destroyctx != NULL);
|
2000-06-02 18:57:51 +00:00
|
|
|
dctx->key->func->destroyctx(dctx);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (dctx->key != NULL) {
|
2016-01-04 22:05:23 -08:00
|
|
|
dst_key_free(&dctx->key);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2000-06-02 18:57:51 +00:00
|
|
|
dctx->magic = 0;
|
2016-01-04 22:05:23 -08:00
|
|
|
isc_mem_putanddetach(&dctx->mctx, dctx, sizeof(dst_context_t));
|
1999-07-12 20:08:42 +00:00
|
|
|
}
|
|
|
|
|
2000-06-02 18:57:51 +00:00
|
|
|
isc_result_t
|
2020-02-13 14:44:37 -08:00
|
|
|
dst_context_adddata(dst_context_t *dctx, const isc_region_t *data) {
|
2000-06-02 18:57:51 +00:00
|
|
|
REQUIRE(VALID_CTX(dctx));
|
|
|
|
REQUIRE(data != NULL);
|
2000-06-02 23:36:14 +00:00
|
|
|
INSIST(dctx->key->func->adddata != NULL);
|
1999-07-12 20:08:42 +00:00
|
|
|
|
2000-06-02 18:57:51 +00:00
|
|
|
return (dctx->key->func->adddata(dctx, data));
|
|
|
|
}
|
1999-07-12 20:08:42 +00:00
|
|
|
|
2000-03-06 20:06:01 +00:00
|
|
|
isc_result_t
|
2020-02-13 14:44:37 -08:00
|
|
|
dst_context_sign(dst_context_t *dctx, isc_buffer_t *sig) {
|
2001-11-30 02:11:04 +00:00
|
|
|
dst_key_t *key;
|
|
|
|
|
2000-06-02 18:57:51 +00:00
|
|
|
REQUIRE(VALID_CTX(dctx));
|
|
|
|
REQUIRE(sig != NULL);
|
1999-07-12 20:08:42 +00:00
|
|
|
|
2001-11-30 02:11:04 +00:00
|
|
|
key = dctx->key;
|
|
|
|
CHECKALG(key->key_alg);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (key->keydata.generic == NULL) {
|
2000-06-02 18:57:51 +00:00
|
|
|
return (DST_R_NULLKEY);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2008-03-31 14:42:51 +00:00
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (key->func->sign == NULL) {
|
2001-11-30 02:11:04 +00:00
|
|
|
return (DST_R_NOTPRIVATEKEY);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2020-03-30 13:49:55 -07:00
|
|
|
if (key->func->isprivate == NULL || !key->func->isprivate(key)) {
|
2000-06-02 18:57:51 +00:00
|
|
|
return (DST_R_NOTPRIVATEKEY);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-07-12 20:08:42 +00:00
|
|
|
|
2001-11-30 02:11:04 +00:00
|
|
|
return (key->func->sign(dctx, sig));
|
2000-06-02 18:57:51 +00:00
|
|
|
}
|
1999-07-12 20:08:42 +00:00
|
|
|
|
2000-06-02 18:57:51 +00:00
|
|
|
isc_result_t
|
2020-02-13 14:44:37 -08:00
|
|
|
dst_context_verify(dst_context_t *dctx, isc_region_t *sig) {
|
2000-06-02 18:57:51 +00:00
|
|
|
REQUIRE(VALID_CTX(dctx));
|
|
|
|
REQUIRE(sig != NULL);
|
|
|
|
|
2001-07-10 19:05:53 +00:00
|
|
|
CHECKALG(dctx->key->key_alg);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (dctx->key->keydata.generic == NULL) {
|
1999-09-01 18:56:19 +00:00
|
|
|
return (DST_R_NULLKEY);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
|
|
|
if (dctx->key->func->verify == NULL) {
|
1999-09-27 16:55:45 +00:00
|
|
|
return (DST_R_NOTPUBLICKEY);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-07-12 20:08:42 +00:00
|
|
|
|
2000-06-02 18:57:51 +00:00
|
|
|
return (dctx->key->func->verify(dctx, sig));
|
1999-07-12 20:08:42 +00:00
|
|
|
}
|
|
|
|
|
2012-06-14 15:44:20 +10:00
|
|
|
isc_result_t
|
|
|
|
dst_context_verify2(dst_context_t *dctx, unsigned int maxbits,
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_region_t *sig) {
|
2012-06-14 15:44:20 +10:00
|
|
|
REQUIRE(VALID_CTX(dctx));
|
|
|
|
REQUIRE(sig != NULL);
|
|
|
|
|
|
|
|
CHECKALG(dctx->key->key_alg);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (dctx->key->keydata.generic == NULL) {
|
2012-06-14 15:44:20 +10:00
|
|
|
return (DST_R_NULLKEY);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2020-02-13 14:44:37 -08:00
|
|
|
if (dctx->key->func->verify == NULL && dctx->key->func->verify2 == NULL)
|
|
|
|
{
|
2012-06-14 15:44:20 +10:00
|
|
|
return (DST_R_NOTPUBLICKEY);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2012-06-14 15:44:20 +10:00
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
return (dctx->key->func->verify2 != NULL
|
|
|
|
? dctx->key->func->verify2(dctx, maxbits, sig)
|
|
|
|
: dctx->key->func->verify(dctx, sig));
|
2012-06-14 15:44:20 +10:00
|
|
|
}
|
|
|
|
|
2000-03-06 20:06:01 +00:00
|
|
|
isc_result_t
|
2000-05-17 22:48:10 +00:00
|
|
|
dst_key_computesecret(const dst_key_t *pub, const dst_key_t *priv,
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_buffer_t *secret) {
|
2020-03-30 13:47:58 -07:00
|
|
|
REQUIRE(dst_initialized);
|
1999-09-27 16:55:45 +00:00
|
|
|
REQUIRE(VALID_KEY(pub) && VALID_KEY(priv));
|
|
|
|
REQUIRE(secret != NULL);
|
|
|
|
|
2001-07-10 19:05:53 +00:00
|
|
|
CHECKALG(pub->key_alg);
|
|
|
|
CHECKALG(priv->key_alg);
|
1999-09-27 16:55:45 +00:00
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (pub->keydata.generic == NULL || priv->keydata.generic == NULL) {
|
1999-09-27 16:55:45 +00:00
|
|
|
return (DST_R_NULLKEY);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-09-27 16:55:45 +00:00
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
if (pub->key_alg != priv->key_alg || pub->func->computesecret == NULL ||
|
2020-02-13 14:44:37 -08:00
|
|
|
priv->func->computesecret == NULL)
|
|
|
|
{
|
1999-09-27 16:55:45 +00:00
|
|
|
return (DST_R_KEYCANNOTCOMPUTESECRET);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-09-27 16:55:45 +00:00
|
|
|
|
2020-03-30 13:49:55 -07:00
|
|
|
if (!dst_key_isprivate(priv)) {
|
1999-09-27 16:55:45 +00:00
|
|
|
return (DST_R_NOTPRIVATEKEY);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-09-27 16:55:45 +00:00
|
|
|
|
|
|
|
return (pub->func->computesecret(pub, priv, secret));
|
|
|
|
}
|
|
|
|
|
2000-08-01 01:33:37 +00:00
|
|
|
isc_result_t
|
2020-02-13 14:44:37 -08:00
|
|
|
dst_key_tofile(const dst_key_t *key, int type, const char *directory) {
|
2000-06-02 18:57:51 +00:00
|
|
|
isc_result_t ret = ISC_R_SUCCESS;
|
1999-07-12 20:08:42 +00:00
|
|
|
|
2020-03-30 13:47:58 -07:00
|
|
|
REQUIRE(dst_initialized);
|
1999-07-12 20:08:42 +00:00
|
|
|
REQUIRE(VALID_KEY(key));
|
2019-09-11 16:29:33 +02:00
|
|
|
REQUIRE((type &
|
2020-02-12 13:59:18 +01:00
|
|
|
(DST_TYPE_PRIVATE | DST_TYPE_PUBLIC | DST_TYPE_STATE)) != 0);
|
1999-07-12 20:08:42 +00:00
|
|
|
|
2001-07-10 19:05:53 +00:00
|
|
|
CHECKALG(key->key_alg);
|
1999-07-12 20:08:42 +00:00
|
|
|
|
2019-09-11 16:29:33 +02:00
|
|
|
if (key->func->tofile == NULL) {
|
2000-06-02 23:36:14 +00:00
|
|
|
return (DST_R_UNSUPPORTEDALG);
|
2019-09-11 16:29:33 +02:00
|
|
|
}
|
2000-06-02 23:36:14 +00:00
|
|
|
|
2018-10-11 11:57:57 +02:00
|
|
|
if ((type & DST_TYPE_PUBLIC) != 0) {
|
2004-03-10 02:19:58 +00:00
|
|
|
ret = write_public_key(key, type, directory);
|
2019-09-11 16:29:33 +02:00
|
|
|
if (ret != ISC_R_SUCCESS) {
|
|
|
|
return (ret);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((type & DST_TYPE_STATE) != 0) {
|
|
|
|
ret = write_key_state(key, type, directory);
|
|
|
|
if (ret != ISC_R_SUCCESS) {
|
1999-07-12 20:08:42 +00:00
|
|
|
return (ret);
|
2019-09-11 16:29:33 +02:00
|
|
|
}
|
1999-07-12 20:08:42 +00:00
|
|
|
}
|
|
|
|
|
2018-10-11 11:57:57 +02:00
|
|
|
if (((type & DST_TYPE_PRIVATE) != 0) &&
|
2020-02-13 14:44:37 -08:00
|
|
|
(key->key_flags & DNS_KEYFLAG_TYPEMASK) != DNS_KEYTYPE_NOKEY)
|
|
|
|
{
|
2000-06-06 21:58:16 +00:00
|
|
|
return (key->func->tofile(key, directory));
|
2019-09-11 16:29:33 +02:00
|
|
|
}
|
|
|
|
return (ISC_R_SUCCESS);
|
1999-07-12 20:08:42 +00:00
|
|
|
}
|
|
|
|
|
2013-09-04 13:53:02 +10:00
|
|
|
void
|
2020-02-13 14:44:37 -08:00
|
|
|
dst_key_setexternal(dst_key_t *key, bool value) {
|
2013-09-04 13:53:02 +10:00
|
|
|
key->external = value;
|
|
|
|
}
|
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
bool
|
2020-02-13 14:44:37 -08:00
|
|
|
dst_key_isexternal(dst_key_t *key) {
|
2013-09-04 13:53:02 +10:00
|
|
|
return (key->external);
|
|
|
|
}
|
|
|
|
|
2014-06-10 19:18:34 +05:30
|
|
|
isc_result_t
|
2020-02-12 13:59:18 +01:00
|
|
|
dst_key_getfilename(dns_name_t *name, dns_keytag_t id, unsigned int alg,
|
|
|
|
int type, const char *directory, isc_mem_t *mctx,
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_buffer_t *buf) {
|
2014-06-10 19:18:34 +05:30
|
|
|
isc_result_t result;
|
|
|
|
|
2020-03-30 13:47:58 -07:00
|
|
|
REQUIRE(dst_initialized);
|
2014-06-10 19:18:34 +05:30
|
|
|
REQUIRE(dns_name_isabsolute(name));
|
2019-09-12 11:45:10 +02:00
|
|
|
REQUIRE((type &
|
2020-02-12 13:59:18 +01:00
|
|
|
(DST_TYPE_PRIVATE | DST_TYPE_PUBLIC | DST_TYPE_STATE)) != 0);
|
2014-06-10 19:18:34 +05:30
|
|
|
REQUIRE(mctx != NULL);
|
|
|
|
REQUIRE(buf != NULL);
|
|
|
|
|
|
|
|
CHECKALG(alg);
|
|
|
|
|
|
|
|
result = buildfilename(name, id, alg, type, directory, buf);
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
2020-02-13 21:48:23 +01:00
|
|
|
if (isc_buffer_availablelength(buf) > 0) {
|
2014-06-10 19:18:34 +05:30
|
|
|
isc_buffer_putuint8(buf, 0);
|
2020-02-13 21:48:23 +01:00
|
|
|
} else {
|
2014-06-10 19:18:34 +05:30
|
|
|
result = ISC_R_NOSPACE;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2014-06-10 19:18:34 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2000-03-06 20:06:01 +00:00
|
|
|
isc_result_t
|
2020-02-12 13:59:18 +01:00
|
|
|
dst_key_fromfile(dns_name_t *name, dns_keytag_t id, unsigned int alg, int type,
|
2020-02-13 14:44:37 -08:00
|
|
|
const char *directory, isc_mem_t *mctx, dst_key_t **keyp) {
|
2014-06-10 19:18:34 +05:30
|
|
|
isc_result_t result;
|
2020-02-13 14:44:37 -08:00
|
|
|
char filename[NAME_MAX];
|
2014-06-10 19:18:34 +05:30
|
|
|
isc_buffer_t buf;
|
2020-02-13 14:44:37 -08:00
|
|
|
dst_key_t *key;
|
1999-07-12 20:08:42 +00:00
|
|
|
|
2020-03-30 13:47:58 -07:00
|
|
|
REQUIRE(dst_initialized);
|
2000-05-24 23:13:32 +00:00
|
|
|
REQUIRE(dns_name_isabsolute(name));
|
2000-06-06 21:58:16 +00:00
|
|
|
REQUIRE((type & (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC)) != 0);
|
1999-07-12 20:08:42 +00:00
|
|
|
REQUIRE(mctx != NULL);
|
2000-05-19 00:20:59 +00:00
|
|
|
REQUIRE(keyp != NULL && *keyp == NULL);
|
1999-07-12 20:08:42 +00:00
|
|
|
|
2001-07-10 19:05:53 +00:00
|
|
|
CHECKALG(alg);
|
1999-07-12 20:08:42 +00:00
|
|
|
|
2014-06-10 19:18:34 +05:30
|
|
|
key = NULL;
|
|
|
|
|
2018-08-21 10:45:29 +02:00
|
|
|
isc_buffer_init(&buf, filename, NAME_MAX);
|
2014-06-10 19:18:34 +05:30
|
|
|
result = dst_key_getfilename(name, id, alg, type, NULL, mctx, &buf);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2014-06-10 19:18:34 +05:30
|
|
|
goto out;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-07-12 20:08:42 +00:00
|
|
|
|
2014-06-10 19:18:34 +05:30
|
|
|
result = dst_key_fromnamedfile(filename, directory, type, mctx, &key);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2014-06-10 19:18:34 +05:30
|
|
|
goto out;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2000-06-06 21:58:16 +00:00
|
|
|
|
2001-04-04 02:02:58 +00:00
|
|
|
result = computeid(key);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2014-06-10 19:18:34 +05:30
|
|
|
goto out;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2001-04-04 02:02:58 +00:00
|
|
|
|
2006-12-04 01:54:53 +00:00
|
|
|
if (!dns_name_equal(name, key->key_name) || id != key->key_id ||
|
2020-02-13 14:44:37 -08:00
|
|
|
alg != key->key_alg)
|
|
|
|
{
|
2014-06-10 19:18:34 +05:30
|
|
|
result = DST_R_INVALIDPRIVATEKEY;
|
|
|
|
goto out;
|
2000-06-06 21:58:16 +00:00
|
|
|
}
|
2001-04-04 02:02:58 +00:00
|
|
|
|
2000-06-06 21:58:16 +00:00
|
|
|
*keyp = key;
|
2014-06-10 19:18:34 +05:30
|
|
|
result = ISC_R_SUCCESS;
|
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
out:
|
2020-02-13 21:48:23 +01:00
|
|
|
if ((key != NULL) && (result != ISC_R_SUCCESS)) {
|
2014-06-10 19:18:34 +05:30
|
|
|
dst_key_free(&key);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2014-06-10 19:18:34 +05:30
|
|
|
|
|
|
|
return (result);
|
2000-06-06 21:58:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
isc_result_t
|
2020-02-12 13:59:18 +01:00
|
|
|
dst_key_fromnamedfile(const char *filename, const char *dirname, int type,
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_mem_t *mctx, dst_key_t **keyp) {
|
2000-06-06 21:58:16 +00:00
|
|
|
isc_result_t result;
|
2020-02-13 14:44:37 -08:00
|
|
|
dst_key_t *pubkey = NULL, *key = NULL;
|
|
|
|
char *newfilename = NULL;
|
|
|
|
int newfilenamelen = 0;
|
|
|
|
isc_lex_t *lex = NULL;
|
2000-06-06 21:58:16 +00:00
|
|
|
|
2020-03-30 13:47:58 -07:00
|
|
|
REQUIRE(dst_initialized);
|
2000-06-06 21:58:16 +00:00
|
|
|
REQUIRE(filename != NULL);
|
|
|
|
REQUIRE((type & (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC)) != 0);
|
|
|
|
REQUIRE(mctx != NULL);
|
|
|
|
REQUIRE(keyp != NULL && *keyp == NULL);
|
|
|
|
|
2009-07-19 04:18:05 +00:00
|
|
|
/* If an absolute path is specified, don't use the key directory */
|
|
|
|
#ifndef WIN32
|
2020-02-13 21:48:23 +01:00
|
|
|
if (filename[0] == '/') {
|
2009-07-19 04:18:05 +00:00
|
|
|
dirname = NULL;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
|
|
|
#else /* WIN32 */
|
|
|
|
if (filename[0] == '/' || filename[0] == '\\') {
|
2009-07-19 04:18:05 +00:00
|
|
|
dirname = NULL;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
|
|
|
#endif /* ifndef WIN32 */
|
2009-07-19 04:18:05 +00:00
|
|
|
|
2004-10-14 05:55:52 +00:00
|
|
|
newfilenamelen = strlen(filename) + 5;
|
2020-02-13 21:48:23 +01:00
|
|
|
if (dirname != NULL) {
|
2009-07-19 04:18:05 +00:00
|
|
|
newfilenamelen += strlen(dirname) + 1;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2004-10-14 05:55:52 +00:00
|
|
|
newfilename = isc_mem_get(mctx, newfilenamelen);
|
2020-02-12 13:59:18 +01:00
|
|
|
result = addsuffix(newfilename, newfilenamelen, dirname, filename,
|
|
|
|
".key");
|
2004-10-14 05:55:52 +00:00
|
|
|
INSIST(result == ISC_R_SUCCESS);
|
|
|
|
|
|
|
|
result = dst_key_read_public(newfilename, type, mctx, &pubkey);
|
|
|
|
isc_mem_put(mctx, newfilename, newfilenamelen);
|
2005-11-30 03:33:49 +00:00
|
|
|
newfilename = NULL;
|
2012-10-23 22:04:06 -07:00
|
|
|
RETERR(result);
|
2000-06-06 21:58:16 +00:00
|
|
|
|
2004-10-01 00:10:59 +00:00
|
|
|
if ((type & (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC)) == DST_TYPE_PUBLIC ||
|
2020-02-13 14:44:37 -08:00
|
|
|
(pubkey->key_flags & DNS_KEYFLAG_TYPEMASK) == DNS_KEYTYPE_NOKEY)
|
|
|
|
{
|
2001-04-04 02:02:58 +00:00
|
|
|
result = computeid(pubkey);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
dst_key_free(&pubkey);
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2000-06-06 21:58:16 +00:00
|
|
|
*keyp = pubkey;
|
|
|
|
return (ISC_R_SUCCESS);
|
1999-07-12 20:08:42 +00:00
|
|
|
}
|
2000-08-01 01:33:37 +00:00
|
|
|
|
2001-11-06 22:27:52 +00:00
|
|
|
result = algorithm_status(pubkey->key_alg);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
dst_key_free(&pubkey);
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2019-09-12 11:57:55 +02:00
|
|
|
key = get_key_struct(pubkey->key_name, pubkey->key_alg,
|
|
|
|
pubkey->key_flags, pubkey->key_proto,
|
|
|
|
pubkey->key_size, pubkey->key_class,
|
|
|
|
pubkey->key_ttl, mctx);
|
|
|
|
if (key == NULL) {
|
|
|
|
dst_key_free(&pubkey);
|
|
|
|
return (ISC_R_NOMEMORY);
|
|
|
|
}
|
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (key->func->parse == NULL) {
|
2019-09-12 11:57:55 +02:00
|
|
|
RETERR(DST_R_UNSUPPORTEDALG);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2019-09-12 11:57:55 +02:00
|
|
|
|
2019-09-12 11:45:10 +02:00
|
|
|
/*
|
|
|
|
* Read the state file, if requested by type.
|
|
|
|
*/
|
|
|
|
if ((type & DST_TYPE_STATE) != 0) {
|
|
|
|
newfilenamelen = strlen(filename) + 7;
|
|
|
|
if (dirname != NULL) {
|
|
|
|
newfilenamelen += strlen(dirname) + 1;
|
|
|
|
}
|
|
|
|
newfilename = isc_mem_get(mctx, newfilenamelen);
|
2020-02-12 13:59:18 +01:00
|
|
|
result = addsuffix(newfilename, newfilenamelen, dirname,
|
|
|
|
filename, ".state");
|
2019-09-12 11:45:10 +02:00
|
|
|
INSIST(result == ISC_R_SUCCESS);
|
|
|
|
|
2019-09-12 11:57:55 +02:00
|
|
|
result = dst_key_read_state(newfilename, mctx, &key);
|
|
|
|
if (result == ISC_R_FILENOTFOUND) {
|
|
|
|
/* Having no state is valid. */
|
|
|
|
result = ISC_R_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2019-09-12 11:45:10 +02:00
|
|
|
isc_mem_put(mctx, newfilename, newfilenamelen);
|
|
|
|
newfilename = NULL;
|
|
|
|
RETERR(result);
|
|
|
|
}
|
|
|
|
|
2002-02-27 22:12:06 +00:00
|
|
|
newfilenamelen = strlen(filename) + 9;
|
2020-02-13 21:48:23 +01:00
|
|
|
if (dirname != NULL) {
|
2009-07-19 04:18:05 +00:00
|
|
|
newfilenamelen += strlen(dirname) + 1;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2002-02-27 22:12:06 +00:00
|
|
|
newfilename = isc_mem_get(mctx, newfilenamelen);
|
2020-02-12 13:59:18 +01:00
|
|
|
result = addsuffix(newfilename, newfilenamelen, dirname, filename,
|
|
|
|
".private");
|
2002-02-27 22:12:06 +00:00
|
|
|
INSIST(result == ISC_R_SUCCESS);
|
1999-07-12 20:08:42 +00:00
|
|
|
|
2002-02-27 22:12:06 +00:00
|
|
|
RETERR(isc_lex_create(mctx, 1500, &lex));
|
|
|
|
RETERR(isc_lex_openfile(lex, newfilename));
|
|
|
|
isc_mem_put(mctx, newfilename, newfilenamelen);
|
2001-04-04 02:02:58 +00:00
|
|
|
|
2009-09-03 04:09:58 +00:00
|
|
|
RETERR(key->func->parse(key, lex, pubkey));
|
2002-02-27 22:12:06 +00:00
|
|
|
isc_lex_destroy(&lex);
|
|
|
|
|
|
|
|
RETERR(computeid(key));
|
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (pubkey->key_id != key->key_id) {
|
2002-02-27 22:12:06 +00:00
|
|
|
RETERR(DST_R_INVALIDPRIVATEKEY);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2009-09-03 04:09:58 +00:00
|
|
|
dst_key_free(&pubkey);
|
2001-04-04 02:02:58 +00:00
|
|
|
|
1999-07-12 20:08:42 +00:00
|
|
|
*keyp = key;
|
1999-10-14 18:32:49 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
2010-12-02 23:22:42 +00:00
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
out:
|
2020-02-13 21:48:23 +01:00
|
|
|
if (pubkey != NULL) {
|
2009-09-03 04:09:58 +00:00
|
|
|
dst_key_free(&pubkey);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
|
|
|
if (newfilename != NULL) {
|
2002-02-27 22:12:06 +00:00
|
|
|
isc_mem_put(mctx, newfilename, newfilenamelen);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
|
|
|
if (lex != NULL) {
|
2002-02-27 22:12:06 +00:00
|
|
|
isc_lex_destroy(&lex);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
|
|
|
if (key != NULL) {
|
2012-10-23 22:04:06 -07:00
|
|
|
dst_key_free(&key);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2002-02-27 22:12:06 +00:00
|
|
|
return (result);
|
1999-07-12 20:08:42 +00:00
|
|
|
}
|
|
|
|
|
2000-03-06 20:06:01 +00:00
|
|
|
isc_result_t
|
2020-02-13 14:44:37 -08:00
|
|
|
dst_key_todns(const dst_key_t *key, isc_buffer_t *target) {
|
2020-03-30 13:47:58 -07:00
|
|
|
REQUIRE(dst_initialized);
|
1999-07-12 20:08:42 +00:00
|
|
|
REQUIRE(VALID_KEY(key));
|
|
|
|
REQUIRE(target != NULL);
|
|
|
|
|
2001-07-10 19:05:53 +00:00
|
|
|
CHECKALG(key->key_alg);
|
1999-07-12 20:08:42 +00:00
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (key->func->todns == NULL) {
|
2000-06-02 23:36:14 +00:00
|
|
|
return (DST_R_UNSUPPORTEDALG);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2000-06-02 23:36:14 +00:00
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (isc_buffer_availablelength(target) < 4) {
|
1999-10-20 22:14:15 +00:00
|
|
|
return (ISC_R_NOSPACE);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2018-03-28 14:19:37 +02:00
|
|
|
isc_buffer_putuint16(target, (uint16_t)(key->key_flags & 0xffff));
|
|
|
|
isc_buffer_putuint8(target, (uint8_t)key->key_proto);
|
|
|
|
isc_buffer_putuint8(target, (uint8_t)key->key_alg);
|
1999-07-12 20:08:42 +00:00
|
|
|
|
2018-10-11 11:57:57 +02:00
|
|
|
if ((key->key_flags & DNS_KEYFLAG_EXTENDED) != 0) {
|
2020-02-13 21:48:23 +01:00
|
|
|
if (isc_buffer_availablelength(target) < 2) {
|
1999-10-20 22:14:15 +00:00
|
|
|
return (ISC_R_NOSPACE);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2020-02-12 13:59:18 +01:00
|
|
|
isc_buffer_putuint16(
|
|
|
|
target, (uint16_t)((key->key_flags >> 16) & 0xffff));
|
1999-07-12 20:08:42 +00:00
|
|
|
}
|
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (key->keydata.generic == NULL) { /*%< NULL KEY */
|
1999-10-14 18:32:49 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-07-12 20:08:42 +00:00
|
|
|
|
2000-06-02 18:57:51 +00:00
|
|
|
return (key->func->todns(key, target));
|
1999-07-12 20:08:42 +00:00
|
|
|
}
|
|
|
|
|
2000-03-06 20:06:01 +00:00
|
|
|
isc_result_t
|
2016-12-30 15:45:08 +11:00
|
|
|
dst_key_fromdns(const dns_name_t *name, dns_rdataclass_t rdclass,
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp) {
|
|
|
|
uint8_t alg, proto;
|
|
|
|
uint32_t flags, extflags;
|
|
|
|
dst_key_t *key = NULL;
|
2011-10-20 21:20:02 +00:00
|
|
|
dns_keytag_t id, rid;
|
2001-04-04 02:02:58 +00:00
|
|
|
isc_region_t r;
|
|
|
|
isc_result_t result;
|
1999-07-12 20:08:42 +00:00
|
|
|
|
2001-04-04 02:02:58 +00:00
|
|
|
REQUIRE(dst_initialized);
|
|
|
|
|
|
|
|
isc_buffer_remainingregion(source, &r);
|
1999-07-12 20:08:42 +00:00
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (isc_buffer_remaininglength(source) < 4) {
|
1999-09-01 18:56:19 +00:00
|
|
|
return (DST_R_INVALIDPUBLICKEY);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-07-12 20:08:42 +00:00
|
|
|
flags = isc_buffer_getuint16(source);
|
|
|
|
proto = isc_buffer_getuint8(source);
|
|
|
|
alg = isc_buffer_getuint8(source);
|
|
|
|
|
2018-10-25 10:27:49 +02:00
|
|
|
id = dst_region_computeid(&r);
|
|
|
|
rid = dst_region_computerid(&r);
|
2001-04-04 02:02:58 +00:00
|
|
|
|
2018-10-11 11:57:57 +02:00
|
|
|
if ((flags & DNS_KEYFLAG_EXTENDED) != 0) {
|
2020-02-13 21:48:23 +01:00
|
|
|
if (isc_buffer_remaininglength(source) < 2) {
|
1999-09-01 18:56:19 +00:00
|
|
|
return (DST_R_INVALIDPUBLICKEY);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-07-12 20:08:42 +00:00
|
|
|
extflags = isc_buffer_getuint16(source);
|
|
|
|
flags |= (extflags << 16);
|
|
|
|
}
|
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
result = frombuffer(name, alg, flags, proto, rdclass, source, mctx,
|
|
|
|
&key);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2001-04-04 02:02:58 +00:00
|
|
|
return (result);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2001-04-04 02:02:58 +00:00
|
|
|
key->key_id = id;
|
2011-10-20 21:20:02 +00:00
|
|
|
key->key_rid = rid;
|
2001-04-04 02:02:58 +00:00
|
|
|
|
|
|
|
*keyp = key;
|
|
|
|
return (ISC_R_SUCCESS);
|
1999-07-12 20:08:42 +00:00
|
|
|
}
|
|
|
|
|
2000-03-06 20:06:01 +00:00
|
|
|
isc_result_t
|
2020-02-12 13:59:18 +01:00
|
|
|
dst_key_frombuffer(const dns_name_t *name, unsigned int alg, unsigned int flags,
|
|
|
|
unsigned int protocol, dns_rdataclass_t rdclass,
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp) {
|
|
|
|
dst_key_t *key = NULL;
|
2001-04-04 02:02:58 +00:00
|
|
|
isc_result_t result;
|
1999-07-12 20:08:42 +00:00
|
|
|
|
2001-04-04 02:02:58 +00:00
|
|
|
REQUIRE(dst_initialized);
|
1999-07-12 20:08:42 +00:00
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
result = frombuffer(name, alg, flags, protocol, rdclass, source, mctx,
|
|
|
|
&key);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2001-04-04 02:02:58 +00:00
|
|
|
return (result);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2000-06-02 23:36:14 +00:00
|
|
|
|
2001-04-04 02:02:58 +00:00
|
|
|
result = computeid(key);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
2000-05-19 00:20:59 +00:00
|
|
|
dst_key_free(&key);
|
2001-04-04 02:02:58 +00:00
|
|
|
return (result);
|
1999-07-12 20:08:42 +00:00
|
|
|
}
|
2000-05-19 00:20:59 +00:00
|
|
|
|
|
|
|
*keyp = key;
|
1999-10-14 18:32:49 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
1999-07-12 20:08:42 +00:00
|
|
|
}
|
|
|
|
|
2000-08-01 01:33:37 +00:00
|
|
|
isc_result_t
|
2020-02-13 14:44:37 -08:00
|
|
|
dst_key_tobuffer(const dst_key_t *key, isc_buffer_t *target) {
|
2020-03-30 13:47:58 -07:00
|
|
|
REQUIRE(dst_initialized);
|
1999-07-12 20:08:42 +00:00
|
|
|
REQUIRE(VALID_KEY(key));
|
|
|
|
REQUIRE(target != NULL);
|
|
|
|
|
2001-07-10 19:05:53 +00:00
|
|
|
CHECKALG(key->key_alg);
|
1999-07-12 20:08:42 +00:00
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (key->func->todns == NULL) {
|
2000-06-02 23:36:14 +00:00
|
|
|
return (DST_R_UNSUPPORTEDALG);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2000-06-02 23:36:14 +00:00
|
|
|
|
2000-06-02 18:57:51 +00:00
|
|
|
return (key->func->todns(key, target));
|
1999-07-12 20:08:42 +00:00
|
|
|
}
|
|
|
|
|
2002-02-27 22:12:06 +00:00
|
|
|
isc_result_t
|
2020-02-13 14:44:37 -08:00
|
|
|
dst_key_privatefrombuffer(dst_key_t *key, isc_buffer_t *buffer) {
|
|
|
|
isc_lex_t *lex = NULL;
|
2002-02-27 22:12:06 +00:00
|
|
|
isc_result_t result = ISC_R_SUCCESS;
|
|
|
|
|
2020-03-30 13:47:58 -07:00
|
|
|
REQUIRE(dst_initialized);
|
2002-02-27 22:12:06 +00:00
|
|
|
REQUIRE(VALID_KEY(key));
|
|
|
|
REQUIRE(!dst_key_isprivate(key));
|
|
|
|
REQUIRE(buffer != NULL);
|
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (key->func->parse == NULL) {
|
2002-02-27 22:12:06 +00:00
|
|
|
RETERR(DST_R_UNSUPPORTEDALG);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2002-02-27 22:12:06 +00:00
|
|
|
|
|
|
|
RETERR(isc_lex_create(key->mctx, 1500, &lex));
|
|
|
|
RETERR(isc_lex_openbuffer(lex, buffer));
|
2009-09-03 04:09:58 +00:00
|
|
|
RETERR(key->func->parse(key, lex, NULL));
|
2020-02-12 13:59:18 +01:00
|
|
|
out:
|
2020-02-13 21:48:23 +01:00
|
|
|
if (lex != NULL) {
|
2002-02-27 22:12:06 +00:00
|
|
|
isc_lex_destroy(&lex);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2002-02-27 22:12:06 +00:00
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2006-12-04 01:54:53 +00:00
|
|
|
gss_ctx_id_t
|
2020-02-13 14:44:37 -08:00
|
|
|
dst_key_getgssctx(const dst_key_t *key) {
|
2006-12-04 01:54:53 +00:00
|
|
|
REQUIRE(key != NULL);
|
|
|
|
|
|
|
|
return (key->keydata.gssctx);
|
|
|
|
}
|
|
|
|
|
2000-08-17 02:04:22 +00:00
|
|
|
isc_result_t
|
2020-02-12 13:59:18 +01:00
|
|
|
dst_key_fromgssapi(const dns_name_t *name, gss_ctx_id_t gssctx, isc_mem_t *mctx,
|
2020-02-13 14:44:37 -08:00
|
|
|
dst_key_t **keyp, isc_region_t *intoken) {
|
|
|
|
dst_key_t *key;
|
2010-12-18 01:56:23 +00:00
|
|
|
isc_result_t result;
|
2000-08-17 02:04:22 +00:00
|
|
|
|
2006-12-04 01:54:53 +00:00
|
|
|
REQUIRE(gssctx != NULL);
|
2000-08-17 02:04:22 +00:00
|
|
|
REQUIRE(keyp != NULL && *keyp == NULL);
|
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
key = get_key_struct(name, DST_ALG_GSSAPI, 0, DNS_KEYPROTO_DNSSEC, 0,
|
|
|
|
dns_rdataclass_in, 0, mctx);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (key == NULL) {
|
2000-08-17 02:04:22 +00:00
|
|
|
return (ISC_R_NOMEMORY);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2006-12-04 01:54:53 +00:00
|
|
|
|
2010-12-18 01:56:23 +00:00
|
|
|
if (intoken != NULL) {
|
|
|
|
/*
|
|
|
|
* Keep the token for use by external ssu rules. They may need
|
|
|
|
* to examine the PAC in the kerberos ticket.
|
|
|
|
*/
|
2020-02-02 08:35:46 +01:00
|
|
|
isc_buffer_allocate(key->mctx, &key->key_tkeytoken,
|
|
|
|
intoken->length);
|
2010-12-18 01:56:23 +00:00
|
|
|
RETERR(isc_buffer_copyregion(key->key_tkeytoken, intoken));
|
|
|
|
}
|
|
|
|
|
2006-12-04 01:54:53 +00:00
|
|
|
key->keydata.gssctx = gssctx;
|
2000-08-17 02:04:22 +00:00
|
|
|
*keyp = key;
|
2010-12-18 01:56:23 +00:00
|
|
|
result = ISC_R_SUCCESS;
|
|
|
|
out:
|
2018-10-19 19:23:39 +11:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
dst_key_free(&key);
|
|
|
|
}
|
2020-02-13 21:48:23 +01:00
|
|
|
return (result);
|
2000-08-17 02:04:22 +00:00
|
|
|
}
|
|
|
|
|
2012-06-14 15:44:20 +10:00
|
|
|
isc_result_t
|
2016-12-30 15:45:08 +11:00
|
|
|
dst_key_buildinternal(const dns_name_t *name, unsigned int alg,
|
2012-06-14 15:44:20 +10:00
|
|
|
unsigned int bits, unsigned int flags,
|
|
|
|
unsigned int protocol, dns_rdataclass_t rdclass,
|
2020-02-13 14:44:37 -08:00
|
|
|
void *data, isc_mem_t *mctx, dst_key_t **keyp) {
|
|
|
|
dst_key_t *key;
|
2012-06-14 15:44:20 +10:00
|
|
|
isc_result_t result;
|
|
|
|
|
2020-03-30 13:47:58 -07:00
|
|
|
REQUIRE(dst_initialized);
|
2012-06-14 15:44:20 +10:00
|
|
|
REQUIRE(dns_name_isabsolute(name));
|
|
|
|
REQUIRE(mctx != NULL);
|
|
|
|
REQUIRE(keyp != NULL && *keyp == NULL);
|
|
|
|
REQUIRE(data != NULL);
|
|
|
|
|
|
|
|
CHECKALG(alg);
|
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
key = get_key_struct(name, alg, flags, protocol, bits, rdclass, 0,
|
|
|
|
mctx);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (key == NULL) {
|
2012-06-14 15:44:20 +10:00
|
|
|
return (ISC_R_NOMEMORY);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2012-06-14 15:44:20 +10:00
|
|
|
|
|
|
|
key->keydata.generic = data;
|
|
|
|
|
|
|
|
result = computeid(key);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
dst_key_free(&key);
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
|
|
|
*keyp = key;
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2008-03-31 14:42:51 +00:00
|
|
|
isc_result_t
|
2016-12-30 15:45:08 +11:00
|
|
|
dst_key_fromlabel(const dns_name_t *name, int alg, unsigned int flags,
|
2008-03-31 14:42:51 +00:00
|
|
|
unsigned int protocol, dns_rdataclass_t rdclass,
|
|
|
|
const char *engine, const char *label, const char *pin,
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_mem_t *mctx, dst_key_t **keyp) {
|
|
|
|
dst_key_t *key;
|
2008-03-31 14:42:51 +00:00
|
|
|
isc_result_t result;
|
|
|
|
|
2020-03-30 13:47:58 -07:00
|
|
|
REQUIRE(dst_initialized);
|
2008-03-31 14:42:51 +00:00
|
|
|
REQUIRE(dns_name_isabsolute(name));
|
|
|
|
REQUIRE(mctx != NULL);
|
|
|
|
REQUIRE(keyp != NULL && *keyp == NULL);
|
|
|
|
REQUIRE(label != NULL);
|
|
|
|
|
|
|
|
CHECKALG(alg);
|
|
|
|
|
2011-03-17 01:40:40 +00:00
|
|
|
key = get_key_struct(name, alg, flags, protocol, 0, rdclass, 0, mctx);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (key == NULL) {
|
2008-03-31 14:42:51 +00:00
|
|
|
return (ISC_R_NOMEMORY);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2008-03-31 14:42:51 +00:00
|
|
|
|
|
|
|
if (key->func->fromlabel == NULL) {
|
|
|
|
dst_key_free(&key);
|
|
|
|
return (DST_R_UNSUPPORTEDALG);
|
|
|
|
}
|
|
|
|
|
|
|
|
result = key->func->fromlabel(key, engine, label, pin);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
dst_key_free(&key);
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
|
|
|
result = computeid(key);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
dst_key_free(&key);
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
|
|
|
*keyp = key;
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2000-03-06 20:06:01 +00:00
|
|
|
isc_result_t
|
2020-02-12 13:59:18 +01:00
|
|
|
dst_key_generate(const dns_name_t *name, unsigned int alg, unsigned int bits,
|
|
|
|
unsigned int param, unsigned int flags, unsigned int protocol,
|
|
|
|
dns_rdataclass_t rdclass, isc_mem_t *mctx, dst_key_t **keyp,
|
2020-02-13 14:44:37 -08:00
|
|
|
void (*callback)(int)) {
|
|
|
|
dst_key_t *key;
|
2000-03-06 20:06:01 +00:00
|
|
|
isc_result_t ret;
|
1999-07-12 20:08:42 +00:00
|
|
|
|
2020-03-30 13:47:58 -07:00
|
|
|
REQUIRE(dst_initialized);
|
2000-05-24 23:13:32 +00:00
|
|
|
REQUIRE(dns_name_isabsolute(name));
|
1999-07-12 20:08:42 +00:00
|
|
|
REQUIRE(mctx != NULL);
|
2000-05-19 00:20:59 +00:00
|
|
|
REQUIRE(keyp != NULL && *keyp == NULL);
|
1999-07-12 20:08:42 +00:00
|
|
|
|
2001-07-10 19:05:53 +00:00
|
|
|
CHECKALG(alg);
|
1999-07-12 20:08:42 +00:00
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
key = get_key_struct(name, alg, flags, protocol, bits, rdclass, 0,
|
|
|
|
mctx);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (key == NULL) {
|
1999-10-20 22:14:15 +00:00
|
|
|
return (ISC_R_NOMEMORY);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-07-12 20:08:42 +00:00
|
|
|
|
2005-04-27 04:57:32 +00:00
|
|
|
if (bits == 0) { /*%< NULL KEY */
|
2000-05-19 00:20:59 +00:00
|
|
|
key->key_flags |= DNS_KEYTYPE_NOKEY;
|
|
|
|
*keyp = key;
|
1999-10-14 18:32:49 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
1999-07-12 20:08:42 +00:00
|
|
|
}
|
|
|
|
|
2000-06-02 18:57:51 +00:00
|
|
|
if (key->func->generate == NULL) {
|
|
|
|
dst_key_free(&key);
|
|
|
|
return (DST_R_UNSUPPORTEDALG);
|
|
|
|
}
|
|
|
|
|
2009-10-24 09:46:19 +00:00
|
|
|
ret = key->func->generate(key, param, callback);
|
1999-10-14 18:32:49 +00:00
|
|
|
if (ret != ISC_R_SUCCESS) {
|
2000-05-19 00:20:59 +00:00
|
|
|
dst_key_free(&key);
|
1999-07-12 20:08:42 +00:00
|
|
|
return (ret);
|
|
|
|
}
|
|
|
|
|
2001-04-04 02:02:58 +00:00
|
|
|
ret = computeid(key);
|
|
|
|
if (ret != ISC_R_SUCCESS) {
|
|
|
|
dst_key_free(&key);
|
|
|
|
return (ret);
|
|
|
|
}
|
|
|
|
|
2000-05-19 00:20:59 +00:00
|
|
|
*keyp = key;
|
1999-10-14 18:32:49 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
1999-07-12 20:08:42 +00:00
|
|
|
}
|
|
|
|
|
2019-09-11 16:29:33 +02:00
|
|
|
isc_result_t
|
2020-02-13 14:44:37 -08:00
|
|
|
dst_key_getbool(const dst_key_t *key, int type, bool *valuep) {
|
2019-09-11 16:29:33 +02:00
|
|
|
REQUIRE(VALID_KEY(key));
|
|
|
|
REQUIRE(valuep != NULL);
|
|
|
|
REQUIRE(type <= DST_MAX_BOOLEAN);
|
|
|
|
if (!key->boolset[type]) {
|
|
|
|
return (ISC_R_NOTFOUND);
|
|
|
|
}
|
|
|
|
*valuep = key->bools[type];
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-02-13 14:44:37 -08:00
|
|
|
dst_key_setbool(dst_key_t *key, int type, bool value) {
|
2019-09-11 16:29:33 +02:00
|
|
|
REQUIRE(VALID_KEY(key));
|
|
|
|
REQUIRE(type <= DST_MAX_BOOLEAN);
|
|
|
|
key->bools[type] = value;
|
|
|
|
key->boolset[type] = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-02-13 14:44:37 -08:00
|
|
|
dst_key_unsetbool(dst_key_t *key, int type) {
|
2019-09-11 16:29:33 +02:00
|
|
|
REQUIRE(VALID_KEY(key));
|
|
|
|
REQUIRE(type <= DST_MAX_BOOLEAN);
|
|
|
|
key->boolset[type] = false;
|
|
|
|
}
|
|
|
|
|
2009-10-09 06:09:21 +00:00
|
|
|
isc_result_t
|
2020-02-13 14:44:37 -08:00
|
|
|
dst_key_getnum(const dst_key_t *key, int type, uint32_t *valuep) {
|
2009-10-09 06:09:21 +00:00
|
|
|
REQUIRE(VALID_KEY(key));
|
|
|
|
REQUIRE(valuep != NULL);
|
|
|
|
REQUIRE(type <= DST_MAX_NUMERIC);
|
2019-09-11 16:29:33 +02:00
|
|
|
if (!key->numset[type]) {
|
2009-10-09 06:09:21 +00:00
|
|
|
return (ISC_R_NOTFOUND);
|
2019-09-11 16:29:33 +02:00
|
|
|
}
|
2009-10-09 06:09:21 +00:00
|
|
|
*valuep = key->nums[type];
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-02-13 14:44:37 -08:00
|
|
|
dst_key_setnum(dst_key_t *key, int type, uint32_t value) {
|
2009-10-09 06:09:21 +00:00
|
|
|
REQUIRE(VALID_KEY(key));
|
|
|
|
REQUIRE(type <= DST_MAX_NUMERIC);
|
|
|
|
key->nums[type] = value;
|
2018-04-17 08:29:14 -07:00
|
|
|
key->numset[type] = true;
|
2009-10-09 06:09:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-02-13 14:44:37 -08:00
|
|
|
dst_key_unsetnum(dst_key_t *key, int type) {
|
2009-10-09 06:09:21 +00:00
|
|
|
REQUIRE(VALID_KEY(key));
|
|
|
|
REQUIRE(type <= DST_MAX_NUMERIC);
|
2018-04-17 08:29:14 -07:00
|
|
|
key->numset[type] = false;
|
2009-10-09 06:09:21 +00:00
|
|
|
}
|
|
|
|
|
2009-07-19 04:18:05 +00:00
|
|
|
isc_result_t
|
2020-02-13 14:44:37 -08:00
|
|
|
dst_key_gettime(const dst_key_t *key, int type, isc_stdtime_t *timep) {
|
2009-07-19 04:18:05 +00:00
|
|
|
REQUIRE(VALID_KEY(key));
|
|
|
|
REQUIRE(timep != NULL);
|
|
|
|
REQUIRE(type <= DST_MAX_TIMES);
|
2019-09-11 16:29:33 +02:00
|
|
|
if (!key->timeset[type]) {
|
2009-07-19 04:18:05 +00:00
|
|
|
return (ISC_R_NOTFOUND);
|
2019-09-11 16:29:33 +02:00
|
|
|
}
|
2009-07-19 04:18:05 +00:00
|
|
|
*timep = key->times[type];
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-02-13 14:44:37 -08:00
|
|
|
dst_key_settime(dst_key_t *key, int type, isc_stdtime_t when) {
|
2009-07-19 04:18:05 +00:00
|
|
|
REQUIRE(VALID_KEY(key));
|
|
|
|
REQUIRE(type <= DST_MAX_TIMES);
|
|
|
|
key->times[type] = when;
|
2018-04-17 08:29:14 -07:00
|
|
|
key->timeset[type] = true;
|
2009-09-02 06:29:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-02-13 14:44:37 -08:00
|
|
|
dst_key_unsettime(dst_key_t *key, int type) {
|
2009-09-02 06:29:01 +00:00
|
|
|
REQUIRE(VALID_KEY(key));
|
|
|
|
REQUIRE(type <= DST_MAX_TIMES);
|
2018-04-17 08:29:14 -07:00
|
|
|
key->timeset[type] = false;
|
2009-09-02 06:29:01 +00:00
|
|
|
}
|
|
|
|
|
2019-09-11 16:29:33 +02:00
|
|
|
isc_result_t
|
2020-02-13 14:44:37 -08:00
|
|
|
dst_key_getstate(const dst_key_t *key, int type, dst_key_state_t *statep) {
|
2019-09-11 16:29:33 +02:00
|
|
|
REQUIRE(VALID_KEY(key));
|
|
|
|
REQUIRE(statep != NULL);
|
|
|
|
REQUIRE(type <= DST_MAX_KEYSTATES);
|
|
|
|
if (!key->keystateset[type]) {
|
|
|
|
return (ISC_R_NOTFOUND);
|
|
|
|
}
|
|
|
|
*statep = key->keystates[type];
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-02-13 14:44:37 -08:00
|
|
|
dst_key_setstate(dst_key_t *key, int type, dst_key_state_t state) {
|
2019-09-11 16:29:33 +02:00
|
|
|
REQUIRE(VALID_KEY(key));
|
|
|
|
REQUIRE(type <= DST_MAX_KEYSTATES);
|
|
|
|
key->keystates[type] = state;
|
|
|
|
key->keystateset[type] = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-02-13 14:44:37 -08:00
|
|
|
dst_key_unsetstate(dst_key_t *key, int type) {
|
2019-09-11 16:29:33 +02:00
|
|
|
REQUIRE(VALID_KEY(key));
|
|
|
|
REQUIRE(type <= DST_MAX_KEYSTATES);
|
|
|
|
key->keystateset[type] = false;
|
|
|
|
}
|
|
|
|
|
2009-09-02 06:29:01 +00:00
|
|
|
isc_result_t
|
2020-02-13 14:44:37 -08:00
|
|
|
dst_key_getprivateformat(const dst_key_t *key, int *majorp, int *minorp) {
|
2009-09-02 06:29:01 +00:00
|
|
|
REQUIRE(VALID_KEY(key));
|
|
|
|
REQUIRE(majorp != NULL);
|
|
|
|
REQUIRE(minorp != NULL);
|
|
|
|
*majorp = key->fmt_major;
|
|
|
|
*minorp = key->fmt_minor;
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-02-13 14:44:37 -08:00
|
|
|
dst_key_setprivateformat(dst_key_t *key, int major, int minor) {
|
2009-09-02 06:29:01 +00:00
|
|
|
REQUIRE(VALID_KEY(key));
|
|
|
|
key->fmt_major = major;
|
|
|
|
key->fmt_minor = minor;
|
2009-07-19 04:18:05 +00:00
|
|
|
}
|
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
static bool
|
2009-09-23 16:01:57 +00:00
|
|
|
comparekeys(const dst_key_t *key1, const dst_key_t *key2,
|
2018-04-17 08:29:14 -07:00
|
|
|
bool match_revoked_key,
|
2020-02-13 14:44:37 -08:00
|
|
|
bool (*compare)(const dst_key_t *key1, const dst_key_t *key2)) {
|
2020-03-30 13:47:58 -07:00
|
|
|
REQUIRE(dst_initialized);
|
1999-07-12 20:08:42 +00:00
|
|
|
REQUIRE(VALID_KEY(key1));
|
|
|
|
REQUIRE(VALID_KEY(key2));
|
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (key1 == key2) {
|
2018-04-17 08:29:14 -07:00
|
|
|
return (true);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2009-09-23 16:01:57 +00:00
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (key1->key_alg != key2->key_alg) {
|
2018-04-17 08:29:14 -07:00
|
|
|
return (false);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2009-09-23 16:01:57 +00:00
|
|
|
|
|
|
|
if (key1->key_id != key2->key_id) {
|
2020-02-13 21:48:23 +01:00
|
|
|
if (!match_revoked_key) {
|
2018-04-17 08:29:14 -07:00
|
|
|
return (false);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2009-09-23 16:01:57 +00:00
|
|
|
if ((key1->key_flags & DNS_KEYFLAG_REVOKE) ==
|
2020-02-13 14:44:37 -08:00
|
|
|
(key2->key_flags & DNS_KEYFLAG_REVOKE))
|
|
|
|
{
|
2018-04-17 08:29:14 -07:00
|
|
|
return (false);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2011-10-20 21:20:02 +00:00
|
|
|
if (key1->key_id != key2->key_rid &&
|
2020-02-13 21:48:23 +01:00
|
|
|
key1->key_rid != key2->key_id) {
|
2018-04-17 08:29:14 -07:00
|
|
|
return (false);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2009-09-23 16:01:57 +00:00
|
|
|
}
|
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (compare != NULL) {
|
2009-09-23 16:01:57 +00:00
|
|
|
return (compare(key1, key2));
|
2020-02-13 21:48:23 +01:00
|
|
|
} else {
|
2018-04-17 08:29:14 -07:00
|
|
|
return (false);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-07-12 20:08:42 +00:00
|
|
|
}
|
2000-06-02 18:57:51 +00:00
|
|
|
|
2009-09-23 16:01:57 +00:00
|
|
|
/*
|
|
|
|
* Compares only the public portion of two keys, by converting them
|
|
|
|
* both to wire format and comparing the results.
|
|
|
|
*/
|
2018-04-17 08:29:14 -07:00
|
|
|
static bool
|
2020-02-13 14:44:37 -08:00
|
|
|
pub_compare(const dst_key_t *key1, const dst_key_t *key2) {
|
|
|
|
isc_result_t result;
|
2009-10-12 05:50:52 +00:00
|
|
|
unsigned char buf1[DST_KEY_MAXSIZE], buf2[DST_KEY_MAXSIZE];
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_buffer_t b1, b2;
|
|
|
|
isc_region_t r1, r2;
|
2009-09-23 16:01:57 +00:00
|
|
|
|
2009-10-12 05:50:52 +00:00
|
|
|
isc_buffer_init(&b1, buf1, sizeof(buf1));
|
2009-09-23 16:01:57 +00:00
|
|
|
result = dst_key_todns(key1, &b1);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2018-04-17 08:29:14 -07:00
|
|
|
return (false);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2009-10-12 05:50:52 +00:00
|
|
|
/* Zero out flags. */
|
|
|
|
buf1[0] = buf1[1] = 0;
|
2020-02-13 21:48:23 +01:00
|
|
|
if ((key1->key_flags & DNS_KEYFLAG_EXTENDED) != 0) {
|
2009-10-12 20:48:12 +00:00
|
|
|
isc_buffer_subtract(&b1, 2);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2009-09-23 16:01:57 +00:00
|
|
|
|
2009-10-12 05:50:52 +00:00
|
|
|
isc_buffer_init(&b2, buf2, sizeof(buf2));
|
2009-09-23 16:01:57 +00:00
|
|
|
result = dst_key_todns(key2, &b2);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2018-04-17 08:29:14 -07:00
|
|
|
return (false);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2009-10-12 05:50:52 +00:00
|
|
|
/* Zero out flags. */
|
|
|
|
buf2[0] = buf2[1] = 0;
|
2020-02-13 21:48:23 +01:00
|
|
|
if ((key2->key_flags & DNS_KEYFLAG_EXTENDED) != 0) {
|
2009-10-12 20:48:12 +00:00
|
|
|
isc_buffer_subtract(&b2, 2);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2009-09-23 16:01:57 +00:00
|
|
|
|
|
|
|
isc_buffer_usedregion(&b1, &r1);
|
2009-10-12 09:03:06 +00:00
|
|
|
/* Remove extended flags. */
|
|
|
|
if ((key1->key_flags & DNS_KEYFLAG_EXTENDED) != 0) {
|
|
|
|
memmove(&buf1[4], &buf1[6], r1.length - 6);
|
|
|
|
r1.length -= 2;
|
|
|
|
}
|
|
|
|
|
2009-09-23 16:01:57 +00:00
|
|
|
isc_buffer_usedregion(&b2, &r2);
|
2009-10-12 09:03:06 +00:00
|
|
|
/* Remove extended flags. */
|
|
|
|
if ((key2->key_flags & DNS_KEYFLAG_EXTENDED) != 0) {
|
|
|
|
memmove(&buf2[4], &buf2[6], r2.length - 6);
|
|
|
|
r2.length -= 2;
|
|
|
|
}
|
2018-04-17 08:29:14 -07:00
|
|
|
return (isc_region_compare(&r1, &r2) == 0);
|
2009-09-23 16:01:57 +00:00
|
|
|
}
|
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
bool
|
2020-02-13 14:44:37 -08:00
|
|
|
dst_key_compare(const dst_key_t *key1, const dst_key_t *key2) {
|
2018-04-17 08:29:14 -07:00
|
|
|
return (comparekeys(key1, key2, false, key1->func->compare));
|
2009-09-23 16:01:57 +00:00
|
|
|
}
|
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
bool
|
2009-09-23 16:01:57 +00:00
|
|
|
dst_key_pubcompare(const dst_key_t *key1, const dst_key_t *key2,
|
2020-02-13 14:44:37 -08:00
|
|
|
bool match_revoked_key) {
|
2009-09-23 16:01:57 +00:00
|
|
|
return (comparekeys(key1, key2, match_revoked_key, pub_compare));
|
|
|
|
}
|
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
bool
|
2020-02-13 14:44:37 -08:00
|
|
|
dst_key_paramcompare(const dst_key_t *key1, const dst_key_t *key2) {
|
2020-03-30 13:47:58 -07:00
|
|
|
REQUIRE(dst_initialized);
|
1999-09-27 16:55:45 +00:00
|
|
|
REQUIRE(VALID_KEY(key1));
|
|
|
|
REQUIRE(VALID_KEY(key2));
|
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (key1 == key2) {
|
2018-04-17 08:29:14 -07:00
|
|
|
return (true);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-09-27 16:55:45 +00:00
|
|
|
if (key1->key_alg == key2->key_alg &&
|
|
|
|
key1->func->paramcompare != NULL &&
|
2020-03-30 13:47:58 -07:00
|
|
|
key1->func->paramcompare(key1, key2))
|
2020-02-13 14:44:37 -08:00
|
|
|
{
|
2018-04-17 08:29:14 -07:00
|
|
|
return (true);
|
2020-02-13 21:48:23 +01:00
|
|
|
} else {
|
2018-04-17 08:29:14 -07:00
|
|
|
return (false);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-09-27 16:55:45 +00:00
|
|
|
}
|
1999-07-12 20:08:42 +00:00
|
|
|
|
2010-12-09 00:54:34 +00:00
|
|
|
void
|
2020-02-13 14:44:37 -08:00
|
|
|
dst_key_attach(dst_key_t *source, dst_key_t **target) {
|
2020-03-30 13:47:58 -07:00
|
|
|
REQUIRE(dst_initialized);
|
2010-12-09 00:54:34 +00:00
|
|
|
REQUIRE(target != NULL && *target == NULL);
|
|
|
|
REQUIRE(VALID_KEY(source));
|
|
|
|
|
2018-08-17 15:16:59 +02:00
|
|
|
isc_refcount_increment(&source->refs);
|
2010-12-09 00:54:34 +00:00
|
|
|
*target = source;
|
|
|
|
}
|
|
|
|
|
1999-07-12 20:08:42 +00:00
|
|
|
void
|
2020-02-13 14:44:37 -08:00
|
|
|
dst_key_free(dst_key_t **keyp) {
|
2020-03-30 13:47:58 -07:00
|
|
|
REQUIRE(dst_initialized);
|
2000-05-19 00:20:59 +00:00
|
|
|
REQUIRE(keyp != NULL && VALID_KEY(*keyp));
|
2018-08-28 10:18:59 +02:00
|
|
|
dst_key_t *key = *keyp;
|
|
|
|
*keyp = NULL;
|
1999-08-03 19:48:10 +00:00
|
|
|
|
2018-08-17 15:16:59 +02:00
|
|
|
if (isc_refcount_decrement(&key->refs) == 1) {
|
|
|
|
isc_refcount_destroy(&key->refs);
|
2018-08-28 10:18:59 +02:00
|
|
|
isc_mem_t *mctx = key->mctx;
|
2018-08-17 15:16:59 +02:00
|
|
|
if (key->keydata.generic != NULL) {
|
|
|
|
INSIST(key->func->destroy != NULL);
|
|
|
|
key->func->destroy(key);
|
|
|
|
}
|
2020-02-13 21:48:23 +01:00
|
|
|
if (key->engine != NULL) {
|
2018-08-17 15:16:59 +02:00
|
|
|
isc_mem_free(mctx, key->engine);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
|
|
|
if (key->label != NULL) {
|
2018-08-17 15:16:59 +02:00
|
|
|
isc_mem_free(mctx, key->label);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2018-08-17 15:16:59 +02:00
|
|
|
dns_name_free(key->key_name, mctx);
|
|
|
|
isc_mem_put(mctx, key->key_name, sizeof(dns_name_t));
|
|
|
|
if (key->key_tkeytoken) {
|
|
|
|
isc_buffer_free(&key->key_tkeytoken);
|
|
|
|
}
|
|
|
|
isc_safe_memwipe(key, sizeof(*key));
|
|
|
|
isc_mem_putanddetach(&mctx, key, sizeof(*key));
|
2010-12-18 01:56:23 +00:00
|
|
|
}
|
1999-07-12 20:08:42 +00:00
|
|
|
}
|
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
bool
|
2020-02-13 14:44:37 -08:00
|
|
|
dst_key_isprivate(const dst_key_t *key) {
|
1999-09-23 20:54:38 +00:00
|
|
|
REQUIRE(VALID_KEY(key));
|
2000-06-02 23:36:14 +00:00
|
|
|
INSIST(key->func->isprivate != NULL);
|
1999-09-23 20:54:38 +00:00
|
|
|
return (key->func->isprivate(key));
|
|
|
|
}
|
|
|
|
|
2000-05-15 21:02:39 +00:00
|
|
|
isc_result_t
|
2020-02-12 13:59:18 +01:00
|
|
|
dst_key_buildfilename(const dst_key_t *key, int type, const char *directory,
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_buffer_t *out) {
|
2000-05-15 21:02:39 +00:00
|
|
|
REQUIRE(VALID_KEY(key));
|
|
|
|
REQUIRE(type == DST_TYPE_PRIVATE || type == DST_TYPE_PUBLIC ||
|
2019-09-11 16:29:33 +02:00
|
|
|
type == DST_TYPE_STATE || type == 0);
|
2000-05-15 21:02:39 +00:00
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
return (buildfilename(key->key_name, key->key_id, key->key_alg, type,
|
|
|
|
directory, out));
|
2000-05-15 23:14:42 +00:00
|
|
|
}
|
|
|
|
|
1999-10-26 19:31:52 +00:00
|
|
|
isc_result_t
|
2020-02-13 14:44:37 -08:00
|
|
|
dst_key_sigsize(const dst_key_t *key, unsigned int *n) {
|
2020-03-30 13:47:58 -07:00
|
|
|
REQUIRE(dst_initialized);
|
1999-07-12 20:08:42 +00:00
|
|
|
REQUIRE(VALID_KEY(key));
|
1999-10-26 19:31:52 +00:00
|
|
|
REQUIRE(n != NULL);
|
1999-07-12 20:08:42 +00:00
|
|
|
|
2004-02-01 23:56:19 +00:00
|
|
|
/* XXXVIX this switch statement is too sparse to gen a jump table. */
|
1999-07-12 20:08:42 +00:00
|
|
|
switch (key->key_alg) {
|
2004-02-01 23:56:19 +00:00
|
|
|
case DST_ALG_RSASHA1:
|
2008-09-24 02:46:23 +00:00
|
|
|
case DST_ALG_NSEC3RSASHA1:
|
2009-10-22 02:21:31 +00:00
|
|
|
case DST_ALG_RSASHA256:
|
|
|
|
case DST_ALG_RSASHA512:
|
2004-02-01 23:56:19 +00:00
|
|
|
*n = (key->key_size + 7) / 8;
|
|
|
|
break;
|
2012-05-02 23:20:17 +10:00
|
|
|
case DST_ALG_ECDSA256:
|
|
|
|
*n = DNS_SIG_ECDSA256SIZE;
|
|
|
|
break;
|
|
|
|
case DST_ALG_ECDSA384:
|
|
|
|
*n = DNS_SIG_ECDSA384SIZE;
|
|
|
|
break;
|
2017-07-31 15:26:00 +02:00
|
|
|
case DST_ALG_ED25519:
|
|
|
|
*n = DNS_SIG_ED25519SIZE;
|
|
|
|
break;
|
|
|
|
case DST_ALG_ED448:
|
|
|
|
*n = DNS_SIG_ED448SIZE;
|
|
|
|
break;
|
2004-02-01 23:56:19 +00:00
|
|
|
case DST_ALG_HMACMD5:
|
2018-06-01 09:31:59 +02:00
|
|
|
*n = isc_md_type_get_size(ISC_MD_MD5);
|
2004-02-01 23:56:19 +00:00
|
|
|
break;
|
2006-01-27 02:35:15 +00:00
|
|
|
case DST_ALG_HMACSHA1:
|
2018-06-01 09:31:59 +02:00
|
|
|
*n = isc_md_type_get_size(ISC_MD_SHA1);
|
2006-01-27 02:35:15 +00:00
|
|
|
break;
|
|
|
|
case DST_ALG_HMACSHA224:
|
2018-06-01 09:31:59 +02:00
|
|
|
*n = isc_md_type_get_size(ISC_MD_SHA224);
|
2006-01-27 02:35:15 +00:00
|
|
|
break;
|
|
|
|
case DST_ALG_HMACSHA256:
|
2018-06-01 09:31:59 +02:00
|
|
|
*n = isc_md_type_get_size(ISC_MD_SHA256);
|
2006-01-27 02:35:15 +00:00
|
|
|
break;
|
|
|
|
case DST_ALG_HMACSHA384:
|
2018-06-01 09:31:59 +02:00
|
|
|
*n = isc_md_type_get_size(ISC_MD_SHA384);
|
2006-01-27 02:35:15 +00:00
|
|
|
break;
|
|
|
|
case DST_ALG_HMACSHA512:
|
2018-06-01 09:31:59 +02:00
|
|
|
*n = isc_md_type_get_size(ISC_MD_SHA512);
|
2006-01-27 02:35:15 +00:00
|
|
|
break;
|
2004-02-01 23:56:19 +00:00
|
|
|
case DST_ALG_GSSAPI:
|
2005-04-27 04:57:32 +00:00
|
|
|
*n = 128; /*%< XXX */
|
2004-02-01 23:56:19 +00:00
|
|
|
break;
|
|
|
|
case DST_ALG_DH:
|
|
|
|
default:
|
|
|
|
return (DST_R_UNSUPPORTEDALG);
|
1999-10-05 15:08:52 +00:00
|
|
|
}
|
1999-10-26 19:31:52 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
1999-10-05 15:08:52 +00:00
|
|
|
}
|
|
|
|
|
1999-10-26 19:31:52 +00:00
|
|
|
isc_result_t
|
2020-02-13 14:44:37 -08:00
|
|
|
dst_key_secretsize(const dst_key_t *key, unsigned int *n) {
|
2020-03-30 13:47:58 -07:00
|
|
|
REQUIRE(dst_initialized);
|
1999-10-05 15:08:52 +00:00
|
|
|
REQUIRE(VALID_KEY(key));
|
1999-10-26 19:31:52 +00:00
|
|
|
REQUIRE(n != NULL);
|
1999-10-05 15:08:52 +00:00
|
|
|
|
2018-06-12 11:26:04 +02:00
|
|
|
if (key->key_alg == DST_ALG_DH) {
|
2004-02-01 23:56:19 +00:00
|
|
|
*n = (key->key_size + 7) / 8;
|
2018-06-12 11:26:04 +02:00
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
return (DST_R_UNSUPPORTEDALG);
|
1999-07-12 20:08:42 +00:00
|
|
|
}
|
|
|
|
|
2009-10-12 20:48:12 +00:00
|
|
|
/*%
|
|
|
|
* Set the flags on a key, then recompute the key ID
|
|
|
|
*/
|
|
|
|
isc_result_t
|
2020-02-13 14:44:37 -08:00
|
|
|
dst_key_setflags(dst_key_t *key, uint32_t flags) {
|
2009-10-12 20:48:12 +00:00
|
|
|
REQUIRE(VALID_KEY(key));
|
|
|
|
key->key_flags = flags;
|
|
|
|
return (computeid(key));
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-02-13 14:44:37 -08:00
|
|
|
dst_key_format(const dst_key_t *key, char *cp, unsigned int size) {
|
2009-10-12 20:48:12 +00:00
|
|
|
char namestr[DNS_NAME_FORMATSIZE];
|
|
|
|
char algstr[DNS_NAME_FORMATSIZE];
|
|
|
|
|
|
|
|
dns_name_format(dst_key_name(key), namestr, sizeof(namestr));
|
2020-02-12 13:59:18 +01:00
|
|
|
dns_secalg_format((dns_secalg_t)dst_key_alg(key), algstr,
|
2009-10-12 20:48:12 +00:00
|
|
|
sizeof(algstr));
|
|
|
|
snprintf(cp, size, "%s/%s/%d", namestr, algstr, dst_key_id(key));
|
|
|
|
}
|
|
|
|
|
2011-01-10 05:32:04 +00:00
|
|
|
isc_result_t
|
2020-02-13 14:44:37 -08:00
|
|
|
dst_key_dump(dst_key_t *key, isc_mem_t *mctx, char **buffer, int *length) {
|
2011-01-10 05:32:04 +00:00
|
|
|
REQUIRE(buffer != NULL && *buffer == NULL);
|
|
|
|
REQUIRE(length != NULL && *length == 0);
|
|
|
|
REQUIRE(VALID_KEY(key));
|
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (key->func->dump == NULL) {
|
2011-01-10 05:32:04 +00:00
|
|
|
return (ISC_R_NOTIMPLEMENTED);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2011-01-10 05:32:04 +00:00
|
|
|
return (key->func->dump(key, mctx, buffer, length));
|
|
|
|
}
|
|
|
|
|
|
|
|
isc_result_t
|
|
|
|
dst_key_restore(dns_name_t *name, unsigned int alg, unsigned int flags,
|
|
|
|
unsigned int protocol, dns_rdataclass_t rdclass,
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_mem_t *mctx, const char *keystr, dst_key_t **keyp) {
|
2011-01-10 05:32:04 +00:00
|
|
|
isc_result_t result;
|
2020-02-13 14:44:37 -08:00
|
|
|
dst_key_t *key;
|
2011-01-10 05:32:04 +00:00
|
|
|
|
2020-03-30 13:47:58 -07:00
|
|
|
REQUIRE(dst_initialized);
|
2011-01-11 23:47:14 +00:00
|
|
|
REQUIRE(keyp != NULL && *keyp == NULL);
|
2011-01-10 05:32:04 +00:00
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (alg >= DST_MAX_ALGS || dst_t_func[alg] == NULL) {
|
2011-01-11 23:47:14 +00:00
|
|
|
return (DST_R_UNSUPPORTEDALG);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2011-01-10 05:32:04 +00:00
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (dst_t_func[alg]->restore == NULL) {
|
2011-01-10 05:32:04 +00:00
|
|
|
return (ISC_R_NOTIMPLEMENTED);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2011-01-10 05:32:04 +00:00
|
|
|
|
2011-03-17 01:40:40 +00:00
|
|
|
key = get_key_struct(name, alg, flags, protocol, 0, rdclass, 0, mctx);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (key == NULL) {
|
2011-01-10 05:32:04 +00:00
|
|
|
return (ISC_R_NOMEMORY);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2011-01-10 05:32:04 +00:00
|
|
|
|
|
|
|
result = (dst_t_func[alg]->restore)(key, keystr);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (result == ISC_R_SUCCESS) {
|
2011-01-10 05:32:04 +00:00
|
|
|
*keyp = key;
|
2020-02-13 21:48:23 +01:00
|
|
|
} else {
|
2011-01-10 05:32:04 +00:00
|
|
|
dst_key_free(&key);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2011-01-10 05:32:04 +00:00
|
|
|
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
1999-07-12 20:08:42 +00:00
|
|
|
/***
|
|
|
|
*** Static methods
|
|
|
|
***/
|
|
|
|
|
2005-04-27 04:57:32 +00:00
|
|
|
/*%
|
2000-08-01 01:33:37 +00:00
|
|
|
* Allocates a key structure and fills in some of the fields.
|
1999-07-12 20:08:42 +00:00
|
|
|
*/
|
|
|
|
static dst_key_t *
|
2020-02-12 13:59:18 +01:00
|
|
|
get_key_struct(const dns_name_t *name, unsigned int alg, unsigned int flags,
|
|
|
|
unsigned int protocol, unsigned int bits,
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_rdataclass_t rdclass, dns_ttl_t ttl, isc_mem_t *mctx) {
|
2000-08-01 01:33:37 +00:00
|
|
|
dst_key_t *key;
|
2020-02-13 14:44:37 -08:00
|
|
|
int i;
|
1999-07-12 20:08:42 +00:00
|
|
|
|
2019-07-16 15:52:14 +02:00
|
|
|
key = isc_mem_get(mctx, sizeof(dst_key_t));
|
1999-07-12 20:08:42 +00:00
|
|
|
|
|
|
|
memset(key, 0, sizeof(dst_key_t));
|
2010-12-09 00:54:34 +00:00
|
|
|
|
2000-05-24 23:13:32 +00:00
|
|
|
key->key_name = isc_mem_get(mctx, sizeof(dns_name_t));
|
2012-12-13 11:18:01 +11:00
|
|
|
|
2000-05-24 23:13:32 +00:00
|
|
|
dns_name_init(key->key_name, NULL);
|
2019-11-01 08:31:13 -05:00
|
|
|
dns_name_dup(name, mctx, key->key_name);
|
2012-12-13 11:18:01 +11:00
|
|
|
|
2018-08-01 11:46:11 +02:00
|
|
|
isc_refcount_init(&key->refs, 1);
|
2013-02-20 21:39:05 -08:00
|
|
|
isc_mem_attach(mctx, &key->mctx);
|
1999-07-12 20:08:42 +00:00
|
|
|
key->key_alg = alg;
|
|
|
|
key->key_flags = flags;
|
|
|
|
key->key_proto = protocol;
|
2006-12-04 01:54:53 +00:00
|
|
|
key->keydata.generic = NULL;
|
1999-07-12 20:08:42 +00:00
|
|
|
key->key_size = bits;
|
2000-09-12 09:54:36 +00:00
|
|
|
key->key_class = rdclass;
|
2011-03-17 01:40:40 +00:00
|
|
|
key->key_ttl = ttl;
|
1999-07-12 20:08:42 +00:00
|
|
|
key->func = dst_t_func[alg];
|
2009-09-02 06:29:01 +00:00
|
|
|
key->fmt_major = 0;
|
|
|
|
key->fmt_minor = 0;
|
|
|
|
for (i = 0; i < (DST_MAX_TIMES + 1); i++) {
|
|
|
|
key->times[i] = 0;
|
2018-04-17 08:29:14 -07:00
|
|
|
key->timeset[i] = false;
|
2009-09-02 06:29:01 +00:00
|
|
|
}
|
2018-04-17 08:29:14 -07:00
|
|
|
key->inactive = false;
|
2012-12-13 11:18:01 +11:00
|
|
|
key->magic = KEY_MAGIC;
|
1999-07-12 20:08:42 +00:00
|
|
|
return (key);
|
|
|
|
}
|
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
bool
|
2020-02-13 14:44:37 -08:00
|
|
|
dst_key_inactive(const dst_key_t *key) {
|
2013-08-15 10:48:05 +10:00
|
|
|
REQUIRE(VALID_KEY(key));
|
|
|
|
|
|
|
|
return (key->inactive);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-02-13 14:44:37 -08:00
|
|
|
dst_key_setinactive(dst_key_t *key, bool inactive) {
|
2013-08-15 10:48:05 +10:00
|
|
|
REQUIRE(VALID_KEY(key));
|
|
|
|
|
|
|
|
key->inactive = inactive;
|
|
|
|
}
|
|
|
|
|
2005-04-27 04:57:32 +00:00
|
|
|
/*%
|
2019-09-12 11:45:10 +02:00
|
|
|
* Reads a public key from disk.
|
1999-07-12 20:08:42 +00:00
|
|
|
*/
|
2004-10-14 05:55:52 +00:00
|
|
|
isc_result_t
|
2020-02-12 13:59:18 +01:00
|
|
|
dst_key_read_public(const char *filename, int type, isc_mem_t *mctx,
|
2020-02-13 14:44:37 -08:00
|
|
|
dst_key_t **keyp) {
|
|
|
|
u_char rdatabuf[DST_KEY_MAXSIZE];
|
|
|
|
isc_buffer_t b;
|
|
|
|
dns_fixedname_t name;
|
|
|
|
isc_lex_t *lex = NULL;
|
|
|
|
isc_token_t token;
|
|
|
|
isc_result_t ret;
|
|
|
|
dns_rdata_t rdata = DNS_RDATA_INIT;
|
|
|
|
unsigned int opt = ISC_LEXOPT_DNSMULTILINE;
|
|
|
|
dns_rdataclass_t rdclass = dns_rdataclass_in;
|
2002-11-12 22:22:32 +00:00
|
|
|
isc_lexspecials_t specials;
|
2020-02-13 14:44:37 -08:00
|
|
|
uint32_t ttl = 0;
|
|
|
|
isc_result_t result;
|
|
|
|
dns_rdatatype_t keytype;
|
1999-07-12 20:08:42 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Open the file and read its formatted contents
|
|
|
|
* File format:
|
2020-02-12 13:59:18 +01:00
|
|
|
* domain.name [ttl] [class] [KEY|DNSKEY] <flags> <protocol>
|
|
|
|
* <algorithm> <key>
|
1999-07-12 20:08:42 +00:00
|
|
|
*/
|
|
|
|
|
1999-08-20 17:03:30 +00:00
|
|
|
/* 1500 should be large enough for any key */
|
1999-10-14 18:32:49 +00:00
|
|
|
ret = isc_lex_create(mctx, 1500, &lex);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (ret != ISC_R_SUCCESS) {
|
2000-06-06 21:58:16 +00:00
|
|
|
goto cleanup;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-07-12 20:08:42 +00:00
|
|
|
|
2002-11-12 22:22:32 +00:00
|
|
|
memset(specials, 0, sizeof(specials));
|
|
|
|
specials['('] = 1;
|
|
|
|
specials[')'] = 1;
|
|
|
|
specials['"'] = 1;
|
|
|
|
isc_lex_setspecials(lex, specials);
|
|
|
|
isc_lex_setcomments(lex, ISC_LEXCOMMENT_DNSMASTERFILE);
|
|
|
|
|
2004-10-14 05:55:52 +00:00
|
|
|
ret = isc_lex_openfile(lex, filename);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (ret != ISC_R_SUCCESS) {
|
1999-07-12 20:08:42 +00:00
|
|
|
goto cleanup;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-07-12 20:08:42 +00:00
|
|
|
|
|
|
|
/* Read the domain name */
|
|
|
|
NEXTTOKEN(lex, opt, &token);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (token.type != isc_tokentype_string) {
|
2000-06-06 21:58:16 +00:00
|
|
|
BADTOKEN();
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2008-11-14 22:53:46 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* We don't support "@" in .key files.
|
|
|
|
*/
|
2020-02-13 21:48:23 +01:00
|
|
|
if (!strcmp(DST_AS_STR(token), "@")) {
|
2008-11-14 22:53:46 +00:00
|
|
|
BADTOKEN();
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2008-11-14 22:53:46 +00:00
|
|
|
|
2000-06-06 21:58:16 +00:00
|
|
|
dns_fixedname_init(&name);
|
2002-01-21 01:07:32 +00:00
|
|
|
isc_buffer_init(&b, DST_AS_STR(token), strlen(DST_AS_STR(token)));
|
|
|
|
isc_buffer_add(&b, strlen(DST_AS_STR(token)));
|
2020-02-12 13:59:18 +01:00
|
|
|
ret = dns_name_fromtext(dns_fixedname_name(&name), &b, dns_rootname, 0,
|
|
|
|
NULL);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (ret != ISC_R_SUCCESS) {
|
2000-06-06 21:58:16 +00:00
|
|
|
goto cleanup;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2000-08-01 01:33:37 +00:00
|
|
|
|
2000-09-12 09:54:36 +00:00
|
|
|
/* Read the next word: either TTL, class, or 'KEY' */
|
1999-07-12 20:08:42 +00:00
|
|
|
NEXTTOKEN(lex, opt, &token);
|
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (token.type != isc_tokentype_string) {
|
2009-07-29 23:45:24 +00:00
|
|
|
BADTOKEN();
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2009-07-29 23:45:24 +00:00
|
|
|
|
1999-07-12 20:08:42 +00:00
|
|
|
/* If it's a TTL, read the next one */
|
2002-11-12 22:22:32 +00:00
|
|
|
result = dns_ttl_fromtext(&token.value.as_textregion, &ttl);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (result == ISC_R_SUCCESS) {
|
1999-07-12 20:08:42 +00:00
|
|
|
NEXTTOKEN(lex, opt, &token);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2000-08-01 01:33:37 +00:00
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (token.type != isc_tokentype_string) {
|
2000-03-14 22:05:08 +00:00
|
|
|
BADTOKEN();
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-07-12 20:08:42 +00:00
|
|
|
|
2002-01-21 01:07:32 +00:00
|
|
|
ret = dns_rdataclass_fromtext(&rdclass, &token.value.as_textregion);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (ret == ISC_R_SUCCESS) {
|
1999-07-12 20:08:42 +00:00
|
|
|
NEXTTOKEN(lex, opt, &token);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2000-08-01 01:33:37 +00:00
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (token.type != isc_tokentype_string) {
|
2000-03-14 22:05:08 +00:00
|
|
|
BADTOKEN();
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-07-12 20:08:42 +00:00
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (strcasecmp(DST_AS_STR(token), "DNSKEY") == 0) {
|
2004-06-11 00:27:06 +00:00
|
|
|
keytype = dns_rdatatype_dnskey;
|
2020-02-13 21:48:23 +01:00
|
|
|
} else if (strcasecmp(DST_AS_STR(token), "KEY") == 0) {
|
2005-04-27 04:57:32 +00:00
|
|
|
keytype = dns_rdatatype_key; /*%< SIG(0), TKEY */
|
2020-02-13 21:48:23 +01:00
|
|
|
} else {
|
2000-03-14 22:05:08 +00:00
|
|
|
BADTOKEN();
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2000-08-01 01:33:37 +00:00
|
|
|
|
2004-06-11 00:27:06 +00:00
|
|
|
if (((type & DST_TYPE_KEY) != 0 && keytype != dns_rdatatype_key) ||
|
2020-02-13 14:44:37 -08:00
|
|
|
((type & DST_TYPE_KEY) == 0 && keytype != dns_rdatatype_dnskey))
|
|
|
|
{
|
2004-06-11 00:27:06 +00:00
|
|
|
ret = DST_R_BADKEYTYPE;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
103. [func] libisc buffer API changes for <isc/buffer.h>:
Added:
isc_buffer_base(b) (pointer)
isc_buffer_current(b) (pointer)
isc_buffer_active(b) (pointer)
isc_buffer_used(b) (pointer)
isc_buffer_length(b) (int)
isc_buffer_usedlength(b) (int)
isc_buffer_consumedlength(b) (int)
isc_buffer_remaininglength(b) (int)
isc_buffer_activelength(b) (int)
isc_buffer_availablelength(b) (int)
Removed:
ISC_BUFFER_USEDCOUNT(b)
ISC_BUFFER_AVAILABLECOUNT(b)
isc_buffer_type(b)
Changed names:
isc_buffer_used(b, r) ->
isc_buffer_usedregion(b, r)
isc_buffer_available(b, r) ->
isc_buffer_available_region(b, r)
isc_buffer_consumed(b, r) ->
isc_buffer_consumedregion(b, r)
isc_buffer_active(b, r) ->
isc_buffer_activeregion(b, r)
isc_buffer_remaining(b, r) ->
isc_buffer_remainingregion(b, r)
Buffer types were removed, so the ISC_BUFFERTYPE_*
macros are no more, and the type argument to
isc_buffer_init and isc_buffer_allocate were removed.
isc_buffer_putstr is now void (instead of isc_result_t)
and requires that the caller ensure that there
is enough available buffer space for the string.
2000-04-27 00:03:12 +00:00
|
|
|
isc_buffer_init(&b, rdatabuf, sizeof(rdatabuf));
|
2020-02-12 13:59:18 +01:00
|
|
|
ret = dns_rdata_fromtext(&rdata, rdclass, keytype, lex, NULL, false,
|
|
|
|
mctx, &b, NULL);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (ret != ISC_R_SUCCESS) {
|
1999-07-12 20:08:42 +00:00
|
|
|
goto cleanup;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-07-12 20:08:42 +00:00
|
|
|
|
2000-09-12 09:54:36 +00:00
|
|
|
ret = dst_key_fromdns(dns_fixedname_name(&name), rdclass, &b, mctx,
|
|
|
|
keyp);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (ret != ISC_R_SUCCESS) {
|
1999-07-12 20:08:42 +00:00
|
|
|
goto cleanup;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-07-12 20:08:42 +00:00
|
|
|
|
2011-03-17 01:40:40 +00:00
|
|
|
dst_key_setttl(*keyp, ttl);
|
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
cleanup:
|
2020-02-13 21:48:23 +01:00
|
|
|
if (lex != NULL) {
|
1999-07-12 20:08:42 +00:00
|
|
|
isc_lex_destroy(&lex);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-10-14 18:32:49 +00:00
|
|
|
return (ret);
|
1999-07-12 20:08:42 +00:00
|
|
|
}
|
|
|
|
|
2019-09-12 11:45:10 +02:00
|
|
|
static int
|
2020-02-13 14:44:37 -08:00
|
|
|
find_metadata(const char *s, const char *tags[], int ntags) {
|
2019-09-12 11:45:10 +02:00
|
|
|
for (int i = 0; i < ntags; i++) {
|
2020-02-13 21:48:23 +01:00
|
|
|
if (tags[i] != NULL && strcasecmp(s, tags[i]) == 0) {
|
2019-09-12 11:45:10 +02:00
|
|
|
return (i);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2019-09-12 11:45:10 +02:00
|
|
|
}
|
|
|
|
return (-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2020-02-13 14:44:37 -08:00
|
|
|
find_numericdata(const char *s) {
|
2019-09-12 11:45:10 +02:00
|
|
|
return (find_metadata(s, numerictags, NUMERIC_NTAGS));
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2020-02-13 14:44:37 -08:00
|
|
|
find_booleandata(const char *s) {
|
2019-09-12 11:45:10 +02:00
|
|
|
return (find_metadata(s, booleantags, BOOLEAN_NTAGS));
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2020-02-13 14:44:37 -08:00
|
|
|
find_timingdata(const char *s) {
|
2019-09-12 11:45:10 +02:00
|
|
|
return (find_metadata(s, timingtags, TIMING_NTAGS));
|
|
|
|
}
|
|
|
|
|
2019-09-12 11:57:55 +02:00
|
|
|
static int
|
2020-02-13 14:44:37 -08:00
|
|
|
find_keystatedata(const char *s) {
|
2019-09-12 11:57:55 +02:00
|
|
|
return (find_metadata(s, keystatestags, KEYSTATES_NTAGS));
|
|
|
|
}
|
|
|
|
|
|
|
|
static isc_result_t
|
2020-02-13 14:44:37 -08:00
|
|
|
keystate_fromtext(const char *s, dst_key_state_t *state) {
|
2019-09-12 11:57:55 +02:00
|
|
|
for (int i = 0; i < KEYSTATES_NVALUES; i++) {
|
|
|
|
if (keystates[i] != NULL && strcasecmp(s, keystates[i]) == 0) {
|
2020-02-12 13:59:18 +01:00
|
|
|
*state = (dst_key_state_t)i;
|
2019-09-12 11:57:55 +02:00
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return (ISC_R_NOTFOUND);
|
|
|
|
}
|
2019-09-12 11:45:10 +02:00
|
|
|
|
|
|
|
/*%
|
|
|
|
* Reads a key state from disk.
|
|
|
|
*/
|
|
|
|
isc_result_t
|
2020-02-13 14:44:37 -08:00
|
|
|
dst_key_read_state(const char *filename, isc_mem_t *mctx, dst_key_t **keyp) {
|
|
|
|
isc_lex_t *lex = NULL;
|
|
|
|
isc_token_t token;
|
2019-09-12 11:45:10 +02:00
|
|
|
isc_result_t ret;
|
2019-09-12 11:57:55 +02:00
|
|
|
unsigned int opt = ISC_LEXOPT_EOL;
|
2019-09-12 11:45:10 +02:00
|
|
|
|
|
|
|
ret = isc_lex_create(mctx, 1500, &lex);
|
|
|
|
if (ret != ISC_R_SUCCESS) {
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
isc_lex_setcomments(lex, ISC_LEXCOMMENT_DNSMASTERFILE);
|
|
|
|
|
|
|
|
ret = isc_lex_openfile(lex, filename);
|
|
|
|
if (ret != ISC_R_SUCCESS) {
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2019-09-12 11:57:55 +02:00
|
|
|
/*
|
|
|
|
* Read the comment line.
|
|
|
|
*/
|
|
|
|
READLINE(lex, opt, &token);
|
|
|
|
|
2019-09-12 11:45:10 +02:00
|
|
|
/*
|
|
|
|
* Read the algorithm line.
|
|
|
|
*/
|
|
|
|
NEXTTOKEN(lex, opt, &token);
|
|
|
|
if (token.type != isc_tokentype_string ||
|
2020-02-13 14:44:37 -08:00
|
|
|
strcmp(DST_AS_STR(token), STATE_ALGORITHM_STR) != 0)
|
|
|
|
{
|
2019-09-12 11:45:10 +02:00
|
|
|
BADTOKEN();
|
|
|
|
}
|
|
|
|
|
|
|
|
NEXTTOKEN(lex, opt | ISC_LEXOPT_NUMBER, &token);
|
|
|
|
if (token.type != isc_tokentype_number ||
|
2020-02-13 14:44:37 -08:00
|
|
|
token.value.as_ulong != (unsigned long)dst_key_alg(*keyp))
|
|
|
|
{
|
2019-09-12 11:45:10 +02:00
|
|
|
BADTOKEN();
|
|
|
|
}
|
|
|
|
|
2019-09-12 11:57:55 +02:00
|
|
|
READLINE(lex, opt, &token);
|
|
|
|
|
2019-09-12 11:45:10 +02:00
|
|
|
/*
|
|
|
|
* Read the length line.
|
|
|
|
*/
|
|
|
|
NEXTTOKEN(lex, opt, &token);
|
|
|
|
if (token.type != isc_tokentype_string ||
|
2020-02-13 14:44:37 -08:00
|
|
|
strcmp(DST_AS_STR(token), STATE_LENGTH_STR) != 0)
|
|
|
|
{
|
2019-09-12 11:45:10 +02:00
|
|
|
BADTOKEN();
|
|
|
|
}
|
|
|
|
|
|
|
|
NEXTTOKEN(lex, opt | ISC_LEXOPT_NUMBER, &token);
|
|
|
|
if (token.type != isc_tokentype_number ||
|
2020-02-13 14:44:37 -08:00
|
|
|
token.value.as_ulong != (unsigned long)dst_key_size(*keyp))
|
|
|
|
{
|
2019-09-12 11:45:10 +02:00
|
|
|
BADTOKEN();
|
|
|
|
}
|
|
|
|
|
2019-09-12 11:57:55 +02:00
|
|
|
READLINE(lex, opt, &token);
|
|
|
|
|
2019-09-12 11:45:10 +02:00
|
|
|
/*
|
|
|
|
* Read the metadata.
|
|
|
|
*/
|
|
|
|
for (int n = 0; n < MAX_NTAGS; n++) {
|
|
|
|
int tag;
|
|
|
|
|
|
|
|
NEXTTOKEN_OR_EOF(lex, opt, &token);
|
2019-09-12 11:57:55 +02:00
|
|
|
if (ret == ISC_R_EOF) {
|
|
|
|
break;
|
|
|
|
}
|
2019-09-12 11:45:10 +02:00
|
|
|
if (token.type != isc_tokentype_string) {
|
|
|
|
BADTOKEN();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Numeric metadata */
|
|
|
|
tag = find_numericdata(DST_AS_STR(token));
|
|
|
|
if (tag >= 0) {
|
2019-09-12 11:57:55 +02:00
|
|
|
INSIST(tag < NUMERIC_NTAGS);
|
|
|
|
|
2019-09-12 11:45:10 +02:00
|
|
|
NEXTTOKEN(lex, opt | ISC_LEXOPT_NUMBER, &token);
|
|
|
|
if (token.type != isc_tokentype_number) {
|
|
|
|
BADTOKEN();
|
|
|
|
}
|
|
|
|
|
2019-09-12 11:57:55 +02:00
|
|
|
dst_key_setnum(*keyp, tag, token.value.as_ulong);
|
2019-09-12 11:45:10 +02:00
|
|
|
goto next;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Boolean metadata */
|
|
|
|
tag = find_booleandata(DST_AS_STR(token));
|
|
|
|
if (tag >= 0) {
|
|
|
|
INSIST(tag < BOOLEAN_NTAGS);
|
|
|
|
|
|
|
|
NEXTTOKEN(lex, opt, &token);
|
|
|
|
if (token.type != isc_tokentype_string) {
|
|
|
|
BADTOKEN();
|
|
|
|
}
|
2019-09-12 11:57:55 +02:00
|
|
|
|
2019-09-12 11:45:10 +02:00
|
|
|
if (strcmp(DST_AS_STR(token), "yes") == 0) {
|
2019-09-12 11:57:55 +02:00
|
|
|
dst_key_setbool(*keyp, tag, true);
|
2019-09-12 11:45:10 +02:00
|
|
|
} else if (strcmp(DST_AS_STR(token), "no") == 0) {
|
2019-09-12 11:57:55 +02:00
|
|
|
dst_key_setbool(*keyp, tag, false);
|
2019-09-12 11:45:10 +02:00
|
|
|
} else {
|
|
|
|
BADTOKEN();
|
|
|
|
}
|
|
|
|
goto next;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Timing metadata */
|
|
|
|
tag = find_timingdata(DST_AS_STR(token));
|
|
|
|
if (tag >= 0) {
|
|
|
|
uint32_t when;
|
|
|
|
|
|
|
|
INSIST(tag < TIMING_NTAGS);
|
|
|
|
|
|
|
|
NEXTTOKEN(lex, opt, &token);
|
|
|
|
if (token.type != isc_tokentype_string) {
|
|
|
|
BADTOKEN();
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = dns_time32_fromtext(DST_AS_STR(token), &when);
|
|
|
|
if (ret != ISC_R_SUCCESS) {
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2019-09-12 11:57:55 +02:00
|
|
|
dst_key_settime(*keyp, tag, when);
|
|
|
|
goto next;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Keystate metadata */
|
|
|
|
tag = find_keystatedata(DST_AS_STR(token));
|
|
|
|
if (tag >= 0) {
|
|
|
|
dst_key_state_t state;
|
|
|
|
|
|
|
|
INSIST(tag < KEYSTATES_NTAGS);
|
|
|
|
|
|
|
|
NEXTTOKEN(lex, opt, &token);
|
|
|
|
if (token.type != isc_tokentype_string) {
|
|
|
|
BADTOKEN();
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = keystate_fromtext(DST_AS_STR(token), &state);
|
|
|
|
if (ret != ISC_R_SUCCESS) {
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
dst_key_setstate(*keyp, tag, state);
|
2019-09-12 11:45:10 +02:00
|
|
|
goto next;
|
|
|
|
}
|
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
next:
|
2019-09-12 11:45:10 +02:00
|
|
|
READLINE(lex, opt, &token);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Done, successfully parsed the whole file. */
|
|
|
|
ret = ISC_R_SUCCESS;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (lex != NULL) {
|
|
|
|
isc_lex_destroy(&lex);
|
|
|
|
}
|
|
|
|
return (ret);
|
|
|
|
}
|
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
static bool
|
2020-02-13 14:44:37 -08:00
|
|
|
issymmetric(const dst_key_t *key) {
|
2020-03-30 13:47:58 -07:00
|
|
|
REQUIRE(dst_initialized);
|
2001-11-06 20:47:59 +00:00
|
|
|
REQUIRE(VALID_KEY(key));
|
|
|
|
|
2004-02-01 23:56:19 +00:00
|
|
|
/* XXXVIX this switch statement is too sparse to gen a jump table. */
|
2001-11-06 20:47:59 +00:00
|
|
|
switch (key->key_alg) {
|
2004-02-01 23:56:19 +00:00
|
|
|
case DST_ALG_RSASHA1:
|
2008-09-24 02:46:23 +00:00
|
|
|
case DST_ALG_NSEC3RSASHA1:
|
2009-10-22 02:21:31 +00:00
|
|
|
case DST_ALG_RSASHA256:
|
|
|
|
case DST_ALG_RSASHA512:
|
2004-02-01 23:56:19 +00:00
|
|
|
case DST_ALG_DH:
|
2012-05-02 23:20:17 +10:00
|
|
|
case DST_ALG_ECDSA256:
|
|
|
|
case DST_ALG_ECDSA384:
|
2017-07-31 15:26:00 +02:00
|
|
|
case DST_ALG_ED25519:
|
|
|
|
case DST_ALG_ED448:
|
2018-04-17 08:29:14 -07:00
|
|
|
return (false);
|
2004-02-01 23:56:19 +00:00
|
|
|
case DST_ALG_HMACMD5:
|
2016-06-01 09:18:49 +02:00
|
|
|
case DST_ALG_HMACSHA1:
|
|
|
|
case DST_ALG_HMACSHA224:
|
|
|
|
case DST_ALG_HMACSHA256:
|
|
|
|
case DST_ALG_HMACSHA384:
|
|
|
|
case DST_ALG_HMACSHA512:
|
2004-02-01 23:56:19 +00:00
|
|
|
case DST_ALG_GSSAPI:
|
2018-04-17 08:29:14 -07:00
|
|
|
return (true);
|
2004-02-01 23:56:19 +00:00
|
|
|
default:
|
2018-04-17 08:29:14 -07:00
|
|
|
return (false);
|
2001-11-06 20:47:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-11 16:29:33 +02:00
|
|
|
/*%
|
|
|
|
* Write key boolean metadata to a file pointer, preceded by 'tag'
|
|
|
|
*/
|
|
|
|
static void
|
2020-02-13 14:44:37 -08:00
|
|
|
printbool(const dst_key_t *key, int type, const char *tag, FILE *stream) {
|
2019-09-11 16:29:33 +02:00
|
|
|
isc_result_t result;
|
2020-02-13 14:44:37 -08:00
|
|
|
bool value = 0;
|
2019-09-11 16:29:33 +02:00
|
|
|
|
|
|
|
result = dst_key_getbool(key, type, &value);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
fprintf(stream, "%s: %s\n", tag, value ? "yes" : "no");
|
|
|
|
}
|
|
|
|
|
|
|
|
/*%
|
|
|
|
* Write key numeric metadata to a file pointer, preceded by 'tag'
|
|
|
|
*/
|
|
|
|
static void
|
2020-02-13 14:44:37 -08:00
|
|
|
printnum(const dst_key_t *key, int type, const char *tag, FILE *stream) {
|
2019-09-11 16:29:33 +02:00
|
|
|
isc_result_t result;
|
2020-02-13 14:44:37 -08:00
|
|
|
uint32_t value = 0;
|
2019-09-11 16:29:33 +02:00
|
|
|
|
|
|
|
result = dst_key_getnum(key, type, &value);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
fprintf(stream, "%s: %u\n", tag, value);
|
|
|
|
}
|
|
|
|
|
2009-07-19 04:18:05 +00:00
|
|
|
/*%
|
|
|
|
* Write key timing metadata to a file pointer, preceded by 'tag'
|
|
|
|
*/
|
|
|
|
static void
|
2020-02-13 14:44:37 -08:00
|
|
|
printtime(const dst_key_t *key, int type, const char *tag, FILE *stream) {
|
2009-07-19 04:18:05 +00:00
|
|
|
isc_result_t result;
|
2010-05-12 23:49:40 +00:00
|
|
|
char output[26]; /* Minimum buffer as per ctime_r() specification. */
|
2009-08-14 06:28:40 +00:00
|
|
|
isc_stdtime_t when;
|
2020-02-13 14:44:37 -08:00
|
|
|
char utc[sizeof("YYYYMMDDHHSSMM")];
|
|
|
|
isc_buffer_t b;
|
|
|
|
isc_region_t r;
|
2009-07-19 04:18:05 +00:00
|
|
|
|
|
|
|
result = dst_key_gettime(key, type, &when);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (result == ISC_R_NOTFOUND) {
|
2009-07-19 04:18:05 +00:00
|
|
|
return;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2009-07-19 04:18:05 +00:00
|
|
|
|
2020-06-17 14:00:09 +02:00
|
|
|
isc_stdtime_tostring(when, output, sizeof(output));
|
2010-05-12 23:49:40 +00:00
|
|
|
isc_buffer_init(&b, utc, sizeof(utc));
|
|
|
|
result = dns_time32_totext(when, &b);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2010-05-12 23:49:40 +00:00
|
|
|
goto error;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2010-05-12 23:49:40 +00:00
|
|
|
|
|
|
|
isc_buffer_usedregion(&b, &r);
|
2020-07-31 08:52:05 +02:00
|
|
|
fprintf(stream, "%s: %.*s (%s)\n", tag, (int)r.length, r.base, output);
|
2010-05-12 23:49:40 +00:00
|
|
|
return;
|
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
error:
|
2010-05-12 23:49:40 +00:00
|
|
|
fprintf(stream, "%s: (set, unable to display)\n", tag);
|
2009-07-19 04:18:05 +00:00
|
|
|
}
|
|
|
|
|
2019-09-12 11:57:55 +02:00
|
|
|
/*%
|
|
|
|
* Write key state metadata to a file pointer, preceded by 'tag'
|
|
|
|
*/
|
|
|
|
static void
|
2020-02-13 14:44:37 -08:00
|
|
|
printstate(const dst_key_t *key, int type, const char *tag, FILE *stream) {
|
|
|
|
isc_result_t result;
|
2019-09-12 11:57:55 +02:00
|
|
|
dst_key_state_t value = 0;
|
|
|
|
|
|
|
|
result = dst_key_getstate(key, type, &value);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
fprintf(stream, "%s: %s\n", tag, keystates[value]);
|
|
|
|
}
|
|
|
|
|
2019-09-11 16:29:33 +02:00
|
|
|
/*%
|
|
|
|
* Writes a key state to disk.
|
|
|
|
*/
|
|
|
|
static isc_result_t
|
2020-02-13 14:44:37 -08:00
|
|
|
write_key_state(const dst_key_t *key, int type, const char *directory) {
|
|
|
|
FILE *fp;
|
|
|
|
isc_buffer_t fileb;
|
|
|
|
char filename[NAME_MAX];
|
|
|
|
isc_result_t ret;
|
2019-09-11 16:29:33 +02:00
|
|
|
isc_fsaccess_t access;
|
|
|
|
|
|
|
|
REQUIRE(VALID_KEY(key));
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Make the filename.
|
|
|
|
*/
|
|
|
|
isc_buffer_init(&fileb, filename, sizeof(filename));
|
|
|
|
ret = dst_key_buildfilename(key, DST_TYPE_STATE, directory, &fileb);
|
|
|
|
if (ret != ISC_R_SUCCESS) {
|
|
|
|
return (ret);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Create public key file.
|
|
|
|
*/
|
|
|
|
if ((fp = fopen(filename, "w")) == NULL) {
|
|
|
|
return (DST_R_WRITEERROR);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (issymmetric(key)) {
|
|
|
|
access = 0;
|
|
|
|
isc_fsaccess_add(ISC_FSACCESS_OWNER,
|
|
|
|
ISC_FSACCESS_READ | ISC_FSACCESS_WRITE,
|
|
|
|
&access);
|
|
|
|
(void)isc_fsaccess_set(filename, access);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Write key state */
|
|
|
|
if ((type & DST_TYPE_KEY) == 0) {
|
2020-02-12 13:59:18 +01:00
|
|
|
fprintf(fp, "; This is the state of key %d, for ", key->key_id);
|
2019-09-11 16:29:33 +02:00
|
|
|
ret = dns_name_print(key->key_name, fp);
|
|
|
|
if (ret != ISC_R_SUCCESS) {
|
|
|
|
fclose(fp);
|
|
|
|
return (ret);
|
|
|
|
}
|
|
|
|
fputc('\n', fp);
|
|
|
|
|
2019-09-12 11:45:10 +02:00
|
|
|
fprintf(fp, "Algorithm: %u\n", key->key_alg);
|
|
|
|
fprintf(fp, "Length: %u\n", key->key_size);
|
|
|
|
|
2019-09-12 11:57:55 +02:00
|
|
|
printnum(key, DST_NUM_LIFETIME, "Lifetime", fp);
|
2019-10-16 17:43:30 +02:00
|
|
|
printnum(key, DST_NUM_PREDECESSOR, "Predecessor", fp);
|
|
|
|
printnum(key, DST_NUM_SUCCESSOR, "Successor", fp);
|
2019-09-12 11:57:55 +02:00
|
|
|
|
|
|
|
printbool(key, DST_BOOL_KSK, "KSK", fp);
|
|
|
|
printbool(key, DST_BOOL_ZSK, "ZSK", fp);
|
|
|
|
|
2019-09-11 16:29:33 +02:00
|
|
|
printtime(key, DST_TIME_CREATED, "Generated", fp);
|
|
|
|
printtime(key, DST_TIME_PUBLISH, "Published", fp);
|
|
|
|
printtime(key, DST_TIME_ACTIVATE, "Active", fp);
|
|
|
|
printtime(key, DST_TIME_INACTIVE, "Retired", fp);
|
|
|
|
printtime(key, DST_TIME_REVOKE, "Revoked", fp);
|
|
|
|
printtime(key, DST_TIME_DELETE, "Removed", fp);
|
Implement 'rndc dnssec -checkds'
Add a new 'rndc' command 'dnssec -checkds' that allows the user to
signal named that a new DS record has been seen published in the
parent, or that an existing DS record has been withdrawn from the
parent.
Upon the 'checkds' request, 'named' will write out the new state for
the key, updating the 'DSPublish' or 'DSRemoved' timing metadata.
This replaces the "parent-registration-delay" configuration option,
this was unreliable because it was purely time based (if the user
did not actually submit the new DS to the parent for example, this
could result in an invalid DNSSEC state).
Because we cannot rely on the parent registration delay for state
transition, we need to replace it with a different guard. Instead,
if a key wants its DS state to be moved to RUMOURED, the "DSPublish"
time must be set and must not be in the future. If a key wants its
DS state to be moved to UNRETENTIVE, the "DSRemoved" time must be set
and must not be in the future.
By default, with '-checkds' you set the time that the DS has been
published or withdrawn to now, but you can set a different time with
'-when'. If there is only one KSK for the zone, that key has its
DS state moved to RUMOURED. If there are multiple keys for the zone,
specify the right key with '-key'.
2020-07-31 08:37:51 +02:00
|
|
|
printtime(key, DST_TIME_DSPUBLISH, "DSPublish", fp);
|
|
|
|
printtime(key, DST_TIME_DSDELETE, "DSRemoved", fp);
|
2020-04-28 15:05:43 +02:00
|
|
|
printtime(key, DST_TIME_SYNCPUBLISH, "PublishCDS", fp);
|
|
|
|
printtime(key, DST_TIME_SYNCDELETE, "DeleteCDS", fp);
|
2019-09-11 16:29:33 +02:00
|
|
|
|
2019-09-12 11:57:55 +02:00
|
|
|
printtime(key, DST_TIME_DNSKEY, "DNSKEYChange", fp);
|
|
|
|
printtime(key, DST_TIME_ZRRSIG, "ZRRSIGChange", fp);
|
|
|
|
printtime(key, DST_TIME_KRRSIG, "KRRSIGChange", fp);
|
|
|
|
printtime(key, DST_TIME_DS, "DSChange", fp);
|
2019-09-11 16:29:33 +02:00
|
|
|
|
2019-09-12 11:57:55 +02:00
|
|
|
printstate(key, DST_KEY_DNSKEY, "DNSKEYState", fp);
|
|
|
|
printstate(key, DST_KEY_ZRRSIG, "ZRRSIGState", fp);
|
|
|
|
printstate(key, DST_KEY_KRRSIG, "KRRSIGState", fp);
|
|
|
|
printstate(key, DST_KEY_DS, "DSState", fp);
|
|
|
|
printstate(key, DST_KEY_GOAL, "GoalState", fp);
|
2019-09-11 16:29:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
fflush(fp);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (ferror(fp)) {
|
2019-09-11 16:29:33 +02:00
|
|
|
ret = DST_R_WRITEERROR;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2019-09-11 16:29:33 +02:00
|
|
|
fclose(fp);
|
|
|
|
|
|
|
|
return (ret);
|
|
|
|
}
|
|
|
|
|
2005-04-27 04:57:32 +00:00
|
|
|
/*%
|
2000-06-02 23:36:14 +00:00
|
|
|
* Writes a public key to disk in DNS format.
|
1999-07-12 20:08:42 +00:00
|
|
|
*/
|
2000-03-06 20:06:01 +00:00
|
|
|
static isc_result_t
|
2020-02-13 14:44:37 -08:00
|
|
|
write_public_key(const dst_key_t *key, int type, const char *directory) {
|
|
|
|
FILE *fp;
|
|
|
|
isc_buffer_t keyb, textb, fileb, classb;
|
|
|
|
isc_region_t r;
|
|
|
|
char filename[NAME_MAX];
|
|
|
|
unsigned char key_array[DST_KEY_MAXSIZE];
|
|
|
|
char text_array[DST_KEY_MAXTEXTSIZE];
|
|
|
|
char class_array[10];
|
|
|
|
isc_result_t ret;
|
|
|
|
dns_rdata_t rdata = DNS_RDATA_INIT;
|
2001-01-09 00:53:06 +00:00
|
|
|
isc_fsaccess_t access;
|
1999-07-12 20:08:42 +00:00
|
|
|
|
|
|
|
REQUIRE(VALID_KEY(key));
|
|
|
|
|
103. [func] libisc buffer API changes for <isc/buffer.h>:
Added:
isc_buffer_base(b) (pointer)
isc_buffer_current(b) (pointer)
isc_buffer_active(b) (pointer)
isc_buffer_used(b) (pointer)
isc_buffer_length(b) (int)
isc_buffer_usedlength(b) (int)
isc_buffer_consumedlength(b) (int)
isc_buffer_remaininglength(b) (int)
isc_buffer_activelength(b) (int)
isc_buffer_availablelength(b) (int)
Removed:
ISC_BUFFER_USEDCOUNT(b)
ISC_BUFFER_AVAILABLECOUNT(b)
isc_buffer_type(b)
Changed names:
isc_buffer_used(b, r) ->
isc_buffer_usedregion(b, r)
isc_buffer_available(b, r) ->
isc_buffer_available_region(b, r)
isc_buffer_consumed(b, r) ->
isc_buffer_consumedregion(b, r)
isc_buffer_active(b, r) ->
isc_buffer_activeregion(b, r)
isc_buffer_remaining(b, r) ->
isc_buffer_remainingregion(b, r)
Buffer types were removed, so the ISC_BUFFERTYPE_*
macros are no more, and the type argument to
isc_buffer_init and isc_buffer_allocate were removed.
isc_buffer_putstr is now void (instead of isc_result_t)
and requires that the caller ensure that there
is enough available buffer space for the string.
2000-04-27 00:03:12 +00:00
|
|
|
isc_buffer_init(&keyb, key_array, sizeof(key_array));
|
|
|
|
isc_buffer_init(&textb, text_array, sizeof(text_array));
|
2000-09-12 09:54:36 +00:00
|
|
|
isc_buffer_init(&classb, class_array, sizeof(class_array));
|
1999-07-12 20:08:42 +00:00
|
|
|
|
|
|
|
ret = dst_key_todns(key, &keyb);
|
2019-09-11 16:29:33 +02:00
|
|
|
if (ret != ISC_R_SUCCESS) {
|
1999-07-12 20:08:42 +00:00
|
|
|
return (ret);
|
2019-09-11 16:29:33 +02:00
|
|
|
}
|
1999-07-12 20:08:42 +00:00
|
|
|
|
103. [func] libisc buffer API changes for <isc/buffer.h>:
Added:
isc_buffer_base(b) (pointer)
isc_buffer_current(b) (pointer)
isc_buffer_active(b) (pointer)
isc_buffer_used(b) (pointer)
isc_buffer_length(b) (int)
isc_buffer_usedlength(b) (int)
isc_buffer_consumedlength(b) (int)
isc_buffer_remaininglength(b) (int)
isc_buffer_activelength(b) (int)
isc_buffer_availablelength(b) (int)
Removed:
ISC_BUFFER_USEDCOUNT(b)
ISC_BUFFER_AVAILABLECOUNT(b)
isc_buffer_type(b)
Changed names:
isc_buffer_used(b, r) ->
isc_buffer_usedregion(b, r)
isc_buffer_available(b, r) ->
isc_buffer_available_region(b, r)
isc_buffer_consumed(b, r) ->
isc_buffer_consumedregion(b, r)
isc_buffer_active(b, r) ->
isc_buffer_activeregion(b, r)
isc_buffer_remaining(b, r) ->
isc_buffer_remainingregion(b, r)
Buffer types were removed, so the ISC_BUFFERTYPE_*
macros are no more, and the type argument to
isc_buffer_init and isc_buffer_allocate were removed.
isc_buffer_putstr is now void (instead of isc_result_t)
and requires that the caller ensure that there
is enough available buffer space for the string.
2000-04-27 00:03:12 +00:00
|
|
|
isc_buffer_usedregion(&keyb, &r);
|
2003-09-30 06:00:40 +00:00
|
|
|
dns_rdata_fromregion(&rdata, key->key_class, dns_rdatatype_dnskey, &r);
|
1999-07-12 20:08:42 +00:00
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
ret = dns_rdata_totext(&rdata, (dns_name_t *)NULL, &textb);
|
2019-09-11 16:29:33 +02:00
|
|
|
if (ret != ISC_R_SUCCESS) {
|
1999-09-01 18:56:19 +00:00
|
|
|
return (DST_R_INVALIDPUBLICKEY);
|
2019-09-11 16:29:33 +02:00
|
|
|
}
|
1999-07-12 20:08:42 +00:00
|
|
|
|
2000-09-12 09:54:36 +00:00
|
|
|
ret = dns_rdataclass_totext(key->key_class, &classb);
|
2019-09-11 16:29:33 +02:00
|
|
|
if (ret != ISC_R_SUCCESS) {
|
2000-09-12 09:54:36 +00:00
|
|
|
return (DST_R_INVALIDPUBLICKEY);
|
2019-09-11 16:29:33 +02:00
|
|
|
}
|
2000-08-01 01:33:37 +00:00
|
|
|
|
1999-10-08 22:24:06 +00:00
|
|
|
/*
|
|
|
|
* Make the filename.
|
|
|
|
*/
|
2000-05-15 21:02:39 +00:00
|
|
|
isc_buffer_init(&fileb, filename, sizeof(filename));
|
2000-06-06 21:58:16 +00:00
|
|
|
ret = dst_key_buildfilename(key, DST_TYPE_PUBLIC, directory, &fileb);
|
2019-09-11 16:29:33 +02:00
|
|
|
if (ret != ISC_R_SUCCESS) {
|
2000-05-15 21:02:39 +00:00
|
|
|
return (ret);
|
2019-09-11 16:29:33 +02:00
|
|
|
}
|
1999-07-12 20:08:42 +00:00
|
|
|
|
1999-10-08 22:24:06 +00:00
|
|
|
/*
|
|
|
|
* Create public key file.
|
|
|
|
*/
|
2019-09-11 16:29:33 +02:00
|
|
|
if ((fp = fopen(filename, "w")) == NULL) {
|
1999-09-01 18:56:19 +00:00
|
|
|
return (DST_R_WRITEERROR);
|
2019-09-11 16:29:33 +02:00
|
|
|
}
|
1999-07-12 20:08:42 +00:00
|
|
|
|
2001-11-06 20:47:59 +00:00
|
|
|
if (issymmetric(key)) {
|
2001-05-31 10:45:32 +00:00
|
|
|
access = 0;
|
|
|
|
isc_fsaccess_add(ISC_FSACCESS_OWNER,
|
|
|
|
ISC_FSACCESS_READ | ISC_FSACCESS_WRITE,
|
|
|
|
&access);
|
|
|
|
(void)isc_fsaccess_set(filename, access);
|
|
|
|
}
|
|
|
|
|
2009-07-19 04:18:05 +00:00
|
|
|
/* Write key information in comments */
|
|
|
|
if ((type & DST_TYPE_KEY) == 0) {
|
2009-07-19 23:47:55 +00:00
|
|
|
fprintf(fp, "; This is a %s%s-signing key, keyid %d, for ",
|
2020-02-12 13:59:18 +01:00
|
|
|
(key->key_flags & DNS_KEYFLAG_REVOKE) != 0 ? "revoked "
|
|
|
|
: "",
|
|
|
|
(key->key_flags & DNS_KEYFLAG_KSK) != 0 ? "key"
|
|
|
|
: "zone",
|
2009-07-19 04:18:05 +00:00
|
|
|
key->key_id);
|
|
|
|
ret = dns_name_print(key->key_name, fp);
|
|
|
|
if (ret != ISC_R_SUCCESS) {
|
|
|
|
fclose(fp);
|
|
|
|
return (ret);
|
|
|
|
}
|
|
|
|
fputc('\n', fp);
|
|
|
|
|
|
|
|
printtime(key, DST_TIME_CREATED, "; Created", fp);
|
|
|
|
printtime(key, DST_TIME_PUBLISH, "; Publish", fp);
|
|
|
|
printtime(key, DST_TIME_ACTIVATE, "; Activate", fp);
|
|
|
|
printtime(key, DST_TIME_REVOKE, "; Revoke", fp);
|
2009-09-14 18:45:45 +00:00
|
|
|
printtime(key, DST_TIME_INACTIVE, "; Inactive", fp);
|
2009-07-19 04:18:05 +00:00
|
|
|
printtime(key, DST_TIME_DELETE, "; Delete", fp);
|
2020-02-12 13:59:18 +01:00
|
|
|
printtime(key, DST_TIME_SYNCPUBLISH, "; SyncPublish", fp);
|
|
|
|
printtime(key, DST_TIME_SYNCDELETE, "; SyncDelete", fp);
|
2005-11-30 03:33:49 +00:00
|
|
|
}
|
2000-05-24 23:13:32 +00:00
|
|
|
|
2009-07-19 04:18:05 +00:00
|
|
|
/* Now print the actual key */
|
|
|
|
ret = dns_name_print(key->key_name, fp);
|
2000-09-12 09:54:36 +00:00
|
|
|
fprintf(fp, " ");
|
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (key->key_ttl != 0) {
|
2018-02-14 19:26:37 +11:00
|
|
|
fprintf(fp, "%u ", key->key_ttl);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2011-03-17 01:40:40 +00:00
|
|
|
|
2000-09-12 09:54:36 +00:00
|
|
|
isc_buffer_usedregion(&classb, &r);
|
2020-02-13 21:48:23 +01:00
|
|
|
if ((unsigned)fwrite(r.base, 1, r.length, fp) != r.length) {
|
2020-02-12 13:59:18 +01:00
|
|
|
ret = DST_R_WRITEERROR;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2000-09-12 09:54:36 +00:00
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if ((type & DST_TYPE_KEY) != 0) {
|
2004-03-10 02:19:58 +00:00
|
|
|
fprintf(fp, " KEY ");
|
2020-02-13 21:48:23 +01:00
|
|
|
} else {
|
2004-03-10 02:19:58 +00:00
|
|
|
fprintf(fp, " DNSKEY ");
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2000-09-12 09:54:36 +00:00
|
|
|
|
|
|
|
isc_buffer_usedregion(&textb, &r);
|
2020-02-13 21:48:23 +01:00
|
|
|
if ((unsigned)fwrite(r.base, 1, r.length, fp) != r.length) {
|
2020-02-12 13:59:18 +01:00
|
|
|
ret = DST_R_WRITEERROR;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2000-09-12 09:54:36 +00:00
|
|
|
|
1999-07-12 20:08:42 +00:00
|
|
|
fputc('\n', fp);
|
2009-03-02 02:03:59 +00:00
|
|
|
fflush(fp);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (ferror(fp)) {
|
2009-03-02 02:03:59 +00:00
|
|
|
ret = DST_R_WRITEERROR;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-07-12 20:08:42 +00:00
|
|
|
fclose(fp);
|
2001-01-09 00:53:06 +00:00
|
|
|
|
2009-03-02 02:03:59 +00:00
|
|
|
return (ret);
|
1999-07-12 20:08:42 +00:00
|
|
|
}
|
|
|
|
|
2000-06-08 20:38:48 +00:00
|
|
|
static isc_result_t
|
2020-02-12 13:59:18 +01:00
|
|
|
buildfilename(dns_name_t *name, dns_keytag_t id, unsigned int alg,
|
2020-02-13 14:44:37 -08:00
|
|
|
unsigned int type, const char *directory, isc_buffer_t *out) {
|
|
|
|
const char *suffix = "";
|
2000-06-06 21:58:16 +00:00
|
|
|
isc_result_t result;
|
|
|
|
|
|
|
|
REQUIRE(out != NULL);
|
2019-09-11 16:29:33 +02:00
|
|
|
if ((type & DST_TYPE_PRIVATE) != 0) {
|
2000-06-06 21:58:16 +00:00
|
|
|
suffix = ".private";
|
2019-09-11 16:29:33 +02:00
|
|
|
} else if ((type & DST_TYPE_PUBLIC) != 0) {
|
2000-06-06 21:58:16 +00:00
|
|
|
suffix = ".key";
|
2019-09-11 16:29:33 +02:00
|
|
|
} else if ((type & DST_TYPE_STATE) != 0) {
|
|
|
|
suffix = ".state";
|
|
|
|
}
|
|
|
|
|
2000-06-06 21:58:16 +00:00
|
|
|
if (directory != NULL) {
|
2020-02-13 21:48:23 +01:00
|
|
|
if (isc_buffer_availablelength(out) < strlen(directory)) {
|
2000-06-06 21:58:16 +00:00
|
|
|
return (ISC_R_NOSPACE);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2000-06-06 21:58:16 +00:00
|
|
|
isc_buffer_putstr(out, directory);
|
2003-07-25 00:01:16 +00:00
|
|
|
if (strlen(directory) > 0U &&
|
2020-02-13 21:48:23 +01:00
|
|
|
directory[strlen(directory) - 1] != '/') {
|
2000-06-06 21:58:16 +00:00
|
|
|
isc_buffer_putstr(out, "/");
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2000-06-06 21:58:16 +00:00
|
|
|
}
|
2020-02-13 21:48:23 +01:00
|
|
|
if (isc_buffer_availablelength(out) < 1) {
|
2000-06-06 21:58:16 +00:00
|
|
|
return (ISC_R_NOSPACE);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2000-06-06 21:58:16 +00:00
|
|
|
isc_buffer_putstr(out, "K");
|
2018-04-17 08:29:14 -07:00
|
|
|
result = dns_name_tofilenametext(name, false, out);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2000-06-06 21:58:16 +00:00
|
|
|
return (result);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2006-12-04 01:54:53 +00:00
|
|
|
|
2017-10-09 11:43:07 +02:00
|
|
|
return (isc_buffer_printf(out, "+%03d+%05d%s", alg, id, suffix));
|
2000-06-06 21:58:16 +00:00
|
|
|
}
|
|
|
|
|
2001-04-04 02:02:58 +00:00
|
|
|
static isc_result_t
|
2020-02-13 14:44:37 -08:00
|
|
|
computeid(dst_key_t *key) {
|
|
|
|
isc_buffer_t dnsbuf;
|
2001-04-04 02:02:58 +00:00
|
|
|
unsigned char dns_array[DST_KEY_MAXSIZE];
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_region_t r;
|
|
|
|
isc_result_t ret;
|
2001-04-04 02:02:58 +00:00
|
|
|
|
|
|
|
isc_buffer_init(&dnsbuf, dns_array, sizeof(dns_array));
|
|
|
|
ret = dst_key_todns(key, &dnsbuf);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (ret != ISC_R_SUCCESS) {
|
2001-04-04 02:02:58 +00:00
|
|
|
return (ret);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2001-04-04 02:02:58 +00:00
|
|
|
|
|
|
|
isc_buffer_usedregion(&dnsbuf, &r);
|
2018-10-25 10:27:49 +02:00
|
|
|
key->key_id = dst_region_computeid(&r);
|
|
|
|
key->key_rid = dst_region_computerid(&r);
|
2001-04-04 02:02:58 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2001-05-04 17:57:33 +00:00
|
|
|
static isc_result_t
|
2016-12-30 15:45:08 +11:00
|
|
|
frombuffer(const dns_name_t *name, unsigned int alg, unsigned int flags,
|
2001-05-21 22:10:23 +00:00
|
|
|
unsigned int protocol, dns_rdataclass_t rdclass,
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp) {
|
|
|
|
dst_key_t *key;
|
2001-04-04 02:02:58 +00:00
|
|
|
isc_result_t ret;
|
|
|
|
|
|
|
|
REQUIRE(dns_name_isabsolute(name));
|
|
|
|
REQUIRE(source != NULL);
|
|
|
|
REQUIRE(mctx != NULL);
|
|
|
|
REQUIRE(keyp != NULL && *keyp == NULL);
|
|
|
|
|
2011-03-17 01:40:40 +00:00
|
|
|
key = get_key_struct(name, alg, flags, protocol, 0, rdclass, 0, mctx);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (key == NULL) {
|
2001-04-04 02:02:58 +00:00
|
|
|
return (ISC_R_NOMEMORY);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2001-04-04 02:02:58 +00:00
|
|
|
|
2001-11-06 22:27:52 +00:00
|
|
|
if (isc_buffer_remaininglength(source) > 0) {
|
2001-11-28 02:35:02 +00:00
|
|
|
ret = algorithm_status(alg);
|
|
|
|
if (ret != ISC_R_SUCCESS) {
|
|
|
|
dst_key_free(&key);
|
|
|
|
return (ret);
|
|
|
|
}
|
2001-11-06 22:27:52 +00:00
|
|
|
if (key->func->fromdns == NULL) {
|
|
|
|
dst_key_free(&key);
|
|
|
|
return (DST_R_UNSUPPORTEDALG);
|
|
|
|
}
|
2001-04-04 02:02:58 +00:00
|
|
|
|
2001-11-06 22:27:52 +00:00
|
|
|
ret = key->func->fromdns(key, source);
|
|
|
|
if (ret != ISC_R_SUCCESS) {
|
|
|
|
dst_key_free(&key);
|
|
|
|
return (ret);
|
|
|
|
}
|
2001-04-04 02:02:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
*keyp = key;
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2001-07-10 19:05:53 +00:00
|
|
|
static isc_result_t
|
2020-02-13 14:44:37 -08:00
|
|
|
algorithm_status(unsigned int alg) {
|
2020-03-30 13:47:58 -07:00
|
|
|
REQUIRE(dst_initialized);
|
2001-07-10 19:05:53 +00:00
|
|
|
|
2018-05-22 18:41:23 -07:00
|
|
|
if (dst_algorithm_supported(alg)) {
|
2001-11-06 18:08:07 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
2018-05-22 15:24:37 +02:00
|
|
|
}
|
2001-11-06 18:08:07 +00:00
|
|
|
return (DST_R_UNSUPPORTEDALG);
|
2001-07-10 19:05:53 +00:00
|
|
|
}
|
|
|
|
|
2004-03-18 02:58:08 +00:00
|
|
|
static isc_result_t
|
2020-02-12 13:59:18 +01:00
|
|
|
addsuffix(char *filename, int len, const char *odirname, const char *ofilename,
|
2020-02-13 14:44:37 -08:00
|
|
|
const char *suffix) {
|
2001-05-10 04:50:28 +00:00
|
|
|
int olen = strlen(ofilename);
|
2001-05-09 23:04:50 +00:00
|
|
|
int n;
|
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (olen > 1 && ofilename[olen - 1] == '.') {
|
2001-05-09 23:04:50 +00:00
|
|
|
olen -= 1;
|
2020-02-13 21:48:23 +01:00
|
|
|
} else if (olen > 8 && strcmp(ofilename + olen - 8, ".private") == 0) {
|
2001-05-09 23:04:50 +00:00
|
|
|
olen -= 8;
|
2020-02-13 21:48:23 +01:00
|
|
|
} else if (olen > 4 && strcmp(ofilename + olen - 4, ".key") == 0) {
|
2001-05-09 23:04:50 +00:00
|
|
|
olen -= 4;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2001-05-09 23:04:50 +00:00
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (odirname == NULL) {
|
2009-07-19 04:18:05 +00:00
|
|
|
n = snprintf(filename, len, "%.*s%s", olen, ofilename, suffix);
|
2020-02-13 21:48:23 +01:00
|
|
|
} else {
|
2020-02-12 13:59:18 +01:00
|
|
|
n = snprintf(filename, len, "%s/%.*s%s", odirname, olen,
|
|
|
|
ofilename, suffix);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
|
|
|
if (n < 0) {
|
2009-09-24 22:19:08 +00:00
|
|
|
return (ISC_R_FAILURE);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
|
|
|
if (n >= len) {
|
2001-05-09 23:04:50 +00:00
|
|
|
return (ISC_R_NOSPACE);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2001-05-09 23:04:50 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2010-12-18 01:56:23 +00:00
|
|
|
isc_buffer_t *
|
2020-02-13 14:44:37 -08:00
|
|
|
dst_key_tkeytoken(const dst_key_t *key) {
|
2011-03-21 19:54:03 +00:00
|
|
|
REQUIRE(VALID_KEY(key));
|
2010-12-18 01:56:23 +00:00
|
|
|
return (key->key_tkeytoken);
|
|
|
|
}
|
2019-10-17 10:21:12 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* A key is considered unused if it does not have any timing metadata set
|
|
|
|
* other than "Created".
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
bool
|
2020-02-13 14:44:37 -08:00
|
|
|
dst_key_is_unused(dst_key_t *key) {
|
|
|
|
isc_stdtime_t val;
|
2019-10-17 10:21:12 +02:00
|
|
|
dst_key_state_t st;
|
2020-02-13 14:44:37 -08:00
|
|
|
int state_type;
|
|
|
|
bool state_type_set;
|
2019-10-17 10:21:12 +02:00
|
|
|
|
|
|
|
REQUIRE(VALID_KEY(key));
|
|
|
|
|
|
|
|
/*
|
|
|
|
* None of the key timing metadata, except Created, may be set. Key
|
|
|
|
* state times may be set only if their respective state is HIDDEN.
|
|
|
|
*/
|
2020-02-12 13:59:18 +01:00
|
|
|
for (int i = 0; i < DST_MAX_TIMES + 1; i++) {
|
2019-10-17 10:21:12 +02:00
|
|
|
state_type_set = false;
|
|
|
|
|
|
|
|
switch (i) {
|
|
|
|
case DST_TIME_CREATED:
|
|
|
|
break;
|
|
|
|
case DST_TIME_DNSKEY:
|
|
|
|
state_type = DST_KEY_DNSKEY;
|
|
|
|
state_type_set = true;
|
|
|
|
break;
|
|
|
|
case DST_TIME_ZRRSIG:
|
|
|
|
state_type = DST_KEY_ZRRSIG;
|
|
|
|
state_type_set = true;
|
|
|
|
break;
|
|
|
|
case DST_TIME_KRRSIG:
|
|
|
|
state_type = DST_KEY_KRRSIG;
|
|
|
|
state_type_set = true;
|
|
|
|
break;
|
|
|
|
case DST_TIME_DS:
|
|
|
|
state_type = DST_KEY_DS;
|
|
|
|
state_type_set = true;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Created is fine. */
|
|
|
|
if (i == DST_TIME_CREATED) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
/* No such timing metadata found, that is fine too. */
|
|
|
|
if (dst_key_gettime(key, i, &val) == ISC_R_NOTFOUND) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* Found timing metadata and it is not related to key states.
|
|
|
|
* This key is used.
|
|
|
|
*/
|
|
|
|
if (!state_type_set) {
|
2020-02-06 09:29:01 +01:00
|
|
|
return (false);
|
2019-10-17 10:21:12 +02:00
|
|
|
}
|
|
|
|
/*
|
|
|
|
* If the state is not HIDDEN, the key is in use.
|
|
|
|
* If the state is not set, this is odd and we default to NA.
|
|
|
|
*/
|
|
|
|
if (dst_key_getstate(key, state_type, &st) != ISC_R_SUCCESS) {
|
|
|
|
st = DST_KEY_STATE_NA;
|
|
|
|
}
|
|
|
|
if (st != DST_KEY_STATE_HIDDEN) {
|
2020-02-06 09:29:01 +01:00
|
|
|
return (false);
|
2019-10-17 10:21:12 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
/* This key is unused. */
|
2020-02-06 09:29:01 +01:00
|
|
|
return (true);
|
2019-10-17 10:21:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2020-02-13 14:44:37 -08:00
|
|
|
get_ksk_zsk(dst_key_t *key, bool *ksk, bool *zsk) {
|
2019-10-17 10:21:12 +02:00
|
|
|
bool k = false, z = false;
|
|
|
|
|
|
|
|
if (dst_key_getbool(key, DST_BOOL_KSK, &k) == ISC_R_SUCCESS) {
|
|
|
|
*ksk = k;
|
|
|
|
} else {
|
|
|
|
*ksk = ((dst_key_flags(key) & DNS_KEYFLAG_KSK) != 0);
|
|
|
|
}
|
|
|
|
if (dst_key_getbool(key, DST_BOOL_ZSK, &z) == ISC_R_SUCCESS) {
|
|
|
|
*zsk = z;
|
|
|
|
} else {
|
|
|
|
*zsk = ((dst_key_flags(key) & DNS_KEYFLAG_KSK) == 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Hints on key whether it can be published and/or used for signing. */
|
|
|
|
|
|
|
|
bool
|
2020-02-13 14:44:37 -08:00
|
|
|
dst_key_is_published(dst_key_t *key, isc_stdtime_t now,
|
|
|
|
isc_stdtime_t *publish) {
|
2019-10-17 10:21:12 +02:00
|
|
|
dst_key_state_t state;
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_result_t result;
|
|
|
|
isc_stdtime_t when;
|
|
|
|
bool state_ok = true, time_ok = false;
|
2019-10-17 10:21:12 +02:00
|
|
|
|
|
|
|
REQUIRE(VALID_KEY(key));
|
|
|
|
|
|
|
|
result = dst_key_gettime(key, DST_TIME_PUBLISH, &when);
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
*publish = when;
|
|
|
|
time_ok = (when <= now);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check key states:
|
|
|
|
* If the DNSKEY state is RUMOURED or OMNIPRESENT, it means it
|
|
|
|
* should be published.
|
|
|
|
*/
|
|
|
|
result = dst_key_getstate(key, DST_KEY_DNSKEY, &state);
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
state_ok = ((state == DST_KEY_STATE_RUMOURED) ||
|
|
|
|
(state == DST_KEY_STATE_OMNIPRESENT));
|
|
|
|
/*
|
|
|
|
* Key states trump timing metadata.
|
|
|
|
* Ignore inactive time.
|
|
|
|
*/
|
|
|
|
time_ok = true;
|
|
|
|
}
|
|
|
|
|
2020-02-06 09:29:01 +01:00
|
|
|
return (state_ok && time_ok);
|
2019-10-17 10:21:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2020-02-13 14:44:37 -08:00
|
|
|
dst_key_is_active(dst_key_t *key, isc_stdtime_t now) {
|
2019-10-17 10:21:12 +02:00
|
|
|
dst_key_state_t state;
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_result_t result;
|
|
|
|
isc_stdtime_t when = 0;
|
|
|
|
bool ksk = false, zsk = false, inactive = false;
|
|
|
|
bool ds_ok = true, zrrsig_ok = true, time_ok = false;
|
2019-10-17 10:21:12 +02:00
|
|
|
|
|
|
|
REQUIRE(VALID_KEY(key));
|
|
|
|
|
|
|
|
result = dst_key_gettime(key, DST_TIME_INACTIVE, &when);
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
inactive = (when <= now);
|
|
|
|
}
|
|
|
|
|
|
|
|
result = dst_key_gettime(key, DST_TIME_ACTIVATE, &when);
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
time_ok = (when <= now);
|
|
|
|
}
|
|
|
|
|
|
|
|
get_ksk_zsk(key, &ksk, &zsk);
|
|
|
|
|
|
|
|
/* Check key states:
|
|
|
|
* KSK: If the DS is RUMOURED or OMNIPRESENT the key is considered
|
|
|
|
* active.
|
|
|
|
*/
|
|
|
|
if (ksk) {
|
|
|
|
result = dst_key_getstate(key, DST_KEY_DS, &state);
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
ds_ok = ((state == DST_KEY_STATE_RUMOURED) ||
|
|
|
|
(state == DST_KEY_STATE_OMNIPRESENT));
|
|
|
|
/*
|
|
|
|
* Key states trump timing metadata.
|
|
|
|
* Ignore inactive time.
|
|
|
|
*/
|
|
|
|
time_ok = true;
|
|
|
|
inactive = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* ZSK: If the ZRRSIG state is RUMOURED or OMNIPRESENT, it means the
|
|
|
|
* key is active.
|
|
|
|
*/
|
|
|
|
if (zsk) {
|
|
|
|
result = dst_key_getstate(key, DST_KEY_ZRRSIG, &state);
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
zrrsig_ok = ((state == DST_KEY_STATE_RUMOURED) ||
|
2020-02-12 13:59:18 +01:00
|
|
|
(state == DST_KEY_STATE_OMNIPRESENT));
|
2019-10-17 10:21:12 +02:00
|
|
|
/*
|
|
|
|
* Key states trump timing metadata.
|
|
|
|
* Ignore inactive time.
|
|
|
|
*/
|
|
|
|
time_ok = true;
|
|
|
|
inactive = false;
|
|
|
|
}
|
|
|
|
}
|
2020-02-06 09:29:01 +01:00
|
|
|
return (ds_ok && zrrsig_ok && time_ok && !inactive);
|
2019-10-17 10:21:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2020-02-12 13:59:18 +01:00
|
|
|
dst_key_is_signing(dst_key_t *key, int role, isc_stdtime_t now,
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_stdtime_t *active) {
|
2019-10-17 10:21:12 +02:00
|
|
|
dst_key_state_t state;
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_result_t result;
|
|
|
|
isc_stdtime_t when = 0;
|
|
|
|
bool ksk = false, zsk = false, inactive = false;
|
|
|
|
bool krrsig_ok = true, zrrsig_ok = true, time_ok = false;
|
2019-10-17 10:21:12 +02:00
|
|
|
|
|
|
|
REQUIRE(VALID_KEY(key));
|
|
|
|
|
|
|
|
result = dst_key_gettime(key, DST_TIME_INACTIVE, &when);
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
inactive = (when <= now);
|
|
|
|
}
|
|
|
|
|
|
|
|
result = dst_key_gettime(key, DST_TIME_ACTIVATE, &when);
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
*active = when;
|
|
|
|
time_ok = (when <= now);
|
|
|
|
}
|
|
|
|
|
|
|
|
get_ksk_zsk(key, &ksk, &zsk);
|
|
|
|
|
|
|
|
/* Check key states:
|
|
|
|
* If the RRSIG state is RUMOURED or OMNIPRESENT, it means the key
|
|
|
|
* is active.
|
|
|
|
*/
|
2019-10-30 14:38:28 +01:00
|
|
|
if (ksk && role == DST_BOOL_KSK) {
|
2019-10-17 10:21:12 +02:00
|
|
|
result = dst_key_getstate(key, DST_KEY_KRRSIG, &state);
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
krrsig_ok = ((state == DST_KEY_STATE_RUMOURED) ||
|
2020-02-12 13:59:18 +01:00
|
|
|
(state == DST_KEY_STATE_OMNIPRESENT));
|
2019-10-17 10:21:12 +02:00
|
|
|
/*
|
|
|
|
* Key states trump timing metadata.
|
|
|
|
* Ignore inactive time.
|
|
|
|
*/
|
|
|
|
time_ok = true;
|
|
|
|
inactive = false;
|
|
|
|
}
|
2019-10-30 14:38:28 +01:00
|
|
|
} else if (zsk && role == DST_BOOL_ZSK) {
|
2019-10-17 10:21:12 +02:00
|
|
|
result = dst_key_getstate(key, DST_KEY_ZRRSIG, &state);
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
zrrsig_ok = ((state == DST_KEY_STATE_RUMOURED) ||
|
2020-02-12 13:59:18 +01:00
|
|
|
(state == DST_KEY_STATE_OMNIPRESENT));
|
2019-10-17 10:21:12 +02:00
|
|
|
/*
|
|
|
|
* Key states trump timing metadata.
|
|
|
|
* Ignore inactive time.
|
|
|
|
*/
|
|
|
|
time_ok = true;
|
|
|
|
inactive = false;
|
|
|
|
}
|
|
|
|
}
|
2020-02-06 09:29:01 +01:00
|
|
|
return (krrsig_ok && zrrsig_ok && time_ok && !inactive);
|
2019-10-17 10:21:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2020-02-13 14:44:37 -08:00
|
|
|
dst_key_is_revoked(dst_key_t *key, isc_stdtime_t now, isc_stdtime_t *revoke) {
|
|
|
|
isc_result_t result;
|
2019-10-17 10:21:12 +02:00
|
|
|
isc_stdtime_t when = 0;
|
2020-02-13 14:44:37 -08:00
|
|
|
bool time_ok = false;
|
2019-10-17 10:21:12 +02:00
|
|
|
|
|
|
|
REQUIRE(VALID_KEY(key));
|
|
|
|
|
|
|
|
result = dst_key_gettime(key, DST_TIME_REVOKE, &when);
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
*revoke = when;
|
|
|
|
time_ok = (when <= now);
|
|
|
|
}
|
|
|
|
|
2020-02-06 09:29:01 +01:00
|
|
|
return (time_ok);
|
2019-10-17 10:21:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2020-02-13 14:44:37 -08:00
|
|
|
dst_key_is_removed(dst_key_t *key, isc_stdtime_t now, isc_stdtime_t *remove) {
|
2019-10-17 10:21:12 +02:00
|
|
|
dst_key_state_t state;
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_result_t result;
|
|
|
|
isc_stdtime_t when = 0;
|
|
|
|
bool state_ok = true, time_ok = false;
|
2019-10-17 10:21:12 +02:00
|
|
|
|
|
|
|
REQUIRE(VALID_KEY(key));
|
|
|
|
|
|
|
|
if (dst_key_is_unused(key)) {
|
|
|
|
/* This key was never used. */
|
2020-02-06 09:29:01 +01:00
|
|
|
return (false);
|
2019-10-17 10:21:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
result = dst_key_gettime(key, DST_TIME_DELETE, &when);
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
*remove = when;
|
|
|
|
time_ok = (when <= now);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check key states:
|
|
|
|
* If the DNSKEY state is UNRETENTIVE or HIDDEN, it means the key
|
|
|
|
* should not be published.
|
|
|
|
*/
|
|
|
|
result = dst_key_getstate(key, DST_KEY_DNSKEY, &state);
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
state_ok = ((state == DST_KEY_STATE_UNRETENTIVE) ||
|
|
|
|
(state == DST_KEY_STATE_HIDDEN));
|
|
|
|
/*
|
|
|
|
* Key states trump timing metadata.
|
|
|
|
* Ignore delete time.
|
|
|
|
*/
|
|
|
|
time_ok = true;
|
|
|
|
}
|
|
|
|
|
2020-02-06 09:29:01 +01:00
|
|
|
return (state_ok && time_ok);
|
2019-10-17 10:21:12 +02:00
|
|
|
}
|
2019-11-04 11:12:26 +01:00
|
|
|
|
2020-02-06 08:57:13 +01:00
|
|
|
dst_key_state_t
|
2020-02-13 14:44:37 -08:00
|
|
|
dst_key_goal(dst_key_t *key) {
|
2020-02-06 08:57:13 +01:00
|
|
|
dst_key_state_t state;
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_result_t result;
|
2020-02-06 08:57:13 +01:00
|
|
|
|
|
|
|
result = dst_key_getstate(key, DST_KEY_GOAL, &state);
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
2020-02-06 09:29:01 +01:00
|
|
|
return (state);
|
2020-02-06 08:57:13 +01:00
|
|
|
}
|
2020-02-06 09:29:01 +01:00
|
|
|
return (DST_KEY_STATE_HIDDEN);
|
2020-02-06 08:57:13 +01:00
|
|
|
}
|
|
|
|
|
2019-11-04 11:12:26 +01:00
|
|
|
void
|
2020-02-13 14:44:37 -08:00
|
|
|
dst_key_copy_metadata(dst_key_t *to, dst_key_t *from) {
|
2019-11-04 11:12:26 +01:00
|
|
|
dst_key_state_t state;
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_stdtime_t when;
|
|
|
|
uint32_t num;
|
|
|
|
bool yesno;
|
|
|
|
isc_result_t result;
|
2019-11-04 11:12:26 +01:00
|
|
|
|
|
|
|
REQUIRE(VALID_KEY(to));
|
|
|
|
REQUIRE(VALID_KEY(from));
|
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
for (int i = 0; i < DST_MAX_TIMES + 1; i++) {
|
2019-11-04 11:12:26 +01:00
|
|
|
result = dst_key_gettime(from, i, &when);
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
dst_key_settime(to, i, when);
|
|
|
|
} else {
|
|
|
|
dst_key_unsettime(to, i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
for (int i = 0; i < DST_MAX_NUMERIC + 1; i++) {
|
2019-11-04 11:12:26 +01:00
|
|
|
result = dst_key_getnum(from, i, &num);
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
dst_key_setnum(to, i, num);
|
|
|
|
} else {
|
|
|
|
dst_key_unsetnum(to, i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
for (int i = 0; i < DST_MAX_BOOLEAN + 1; i++) {
|
2019-11-04 11:12:26 +01:00
|
|
|
result = dst_key_getbool(from, i, &yesno);
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
dst_key_setbool(to, i, yesno);
|
|
|
|
} else {
|
|
|
|
dst_key_unsetnum(to, i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
for (int i = 0; i < DST_MAX_KEYSTATES + 1; i++) {
|
2019-11-04 11:12:26 +01:00
|
|
|
result = dst_key_getstate(from, i, &state);
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
dst_key_setstate(to, i, state);
|
|
|
|
} else {
|
|
|
|
dst_key_unsetstate(to, i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|