diff --git a/lib/dns/Makefile.am b/lib/dns/Makefile.am index 27a5f14ddb..e18a393609 100644 --- a/lib/dns/Makefile.am +++ b/lib/dns/Makefile.am @@ -83,6 +83,7 @@ libdns_la_HEADERS = \ include/dns/keydata.h \ include/dns/keyflags.h \ include/dns/keymgr.h \ + include/dns/keystore.h \ include/dns/keytable.h \ include/dns/keyvalues.h \ include/dns/librpz.h \ @@ -190,6 +191,7 @@ libdns_la_SOURCES = \ key.c \ keydata.c \ keymgr.c \ + keystore.c \ keytable.c \ log.c \ master.c \ diff --git a/lib/dns/include/dns/keystore.h b/lib/dns/include/dns/keystore.h new file mode 100644 index 0000000000..f898817f57 --- /dev/null +++ b/lib/dns/include/dns/keystore.h @@ -0,0 +1,194 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#pragma once + +/***** +***** Module Info +*****/ + +/*! \file dns/keystore.h + * \brief + * DNSSEC Key Store + * + * A key store defines where to store DNSSEC keys. + */ + +#include +#include +#include +#include + +#include + +ISC_LANG_BEGINDECLS + +/* Key store */ +struct dns_keystore { + unsigned int magic; + isc_mem_t *mctx; + const char *name; + const char *engine; + + /* Internals. */ + isc_mutex_t lock; + + /* Locked by themselves. */ + isc_refcount_t references; + + /* Under owner's locking control. */ + ISC_LINK(struct dns_keystore) link; + + /* Configuration values */ + char *directory; + char *pkcs11uri; +}; + +#define DNS_KEYSTORE_MAGIC ISC_MAGIC('K', 'E', 'Y', 'S') +#define DNS_KEYSTORE_VALID(ks) ISC_MAGIC_VALID(ks, DNS_KEYSTORE_MAGIC) + +isc_result_t +dns_keystore_create(isc_mem_t *mctx, const char *name, dns_keystore_t **kspp); +/*%< + * Create a key store. + * + * Requires: + * + *\li 'mctx' is a valid memory context. + * + *\li 'name' is a valid C string. + * + *\li kspp != NULL && *kspp == NULL + * + * Returns: + * + *\li #ISC_R_SUCCESS + *\li #ISC_R_NOMEMORY + * + *\li Other errors are possible. + */ + +void +dns_keystore_attach(dns_keystore_t *source, dns_keystore_t **targetp); +/*%< + * Attach '*targetp' to 'source'. + * + * Requires: + * + *\li 'source' is a valid keystore. + * + *\li 'targetp' points to a NULL dns_keystore_t *. + * + * Ensures: + * + *\li *targetp is attached to source. + * + *\li While *targetp is attached, the keystore will not shut down. + */ + +void +dns_keystore_detach(dns_keystore_t **kspp); +/*%< + * Detach keystore. + * + * Requires: + * + *\li 'kspp' points to a valid dns_keystore_t * + * + * Ensures: + * + *\li *kspp is NULL. + */ + +const char * +dns_keystore_name(dns_keystore_t *keystore); +/*%< + * Get keystore name. + * + * Requires: + * + *\li 'keystore' is a valid keystore. + * + * Returns: + * + *\li name of 'keystore'. + */ + +const char * +dns_keystore_directory(dns_keystore_t *keystore); +/*%< + * Get keystore directory. + * + * Requires: + * + *\li 'keystore' is a valid keystore. + * + * Returns: + * + *\li directory of 'keystore'. + */ + +void +dns_keystore_setdirectory(dns_keystore_t *keystore, const char *dir); +/*%< + * Set keystore directory. + * + * Requires: + * + *\li 'keystore' is a valid keystore. + * + */ + +const char * +dns_keystore_pkcs11uri(dns_keystore_t *keystore); +/*%< + * Get keystore PKCS#11 URI. + * + * Requires: + * + *\li 'keystore' is a valid keystore. + * + * Returns: + * + *\li PKCS#11 URI of 'keystore'. + */ + +void +dns_keystore_setpkcs11uri(dns_keystore_t *keystore, const char *uri); +/*%< + * Set keystore PKCS#11 URI. + * + * Requires: + * + *\li 'keystore' is a valid keystore. + * + */ + +isc_result_t +dns_keystorelist_find(dns_keystorelist_t *list, const char *name, + dns_keystore_t **kspp); +/*%< + * Search for a keystore with name 'name' in 'list'. + * If found, '*kspp' is (strongly) attached to it. + * + * Requires: + * + *\li 'kspp' points to a NULL dns_keystore_t *. + * + * Returns: + * + *\li #ISC_R_SUCCESS A matching keystore was found. + *\li #ISC_R_NOTFOUND No matching keystore was found. + */ + +ISC_LANG_ENDDECLS diff --git a/lib/dns/keystore.c b/lib/dns/keystore.c new file mode 100644 index 0000000000..e7fac0ab62 --- /dev/null +++ b/lib/dns/keystore.c @@ -0,0 +1,164 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +#ifdef HAVE_GNUTLS +#include +#include +#endif + +#include + +#include +#include +#include +#include + +#include + +isc_result_t +dns_keystore_create(isc_mem_t *mctx, const char *name, dns_keystore_t **kspp) { + dns_keystore_t *keystore; + + REQUIRE(name != NULL); + REQUIRE(kspp != NULL && *kspp == NULL); + + keystore = isc_mem_get(mctx, sizeof(*keystore)); + keystore->mctx = NULL; + isc_mem_attach(mctx, &keystore->mctx); + + keystore->name = isc_mem_strdup(mctx, name); + isc_mutex_init(&keystore->lock); + + isc_refcount_init(&keystore->references, 1); + + ISC_LINK_INIT(keystore, link); + + keystore->directory = NULL; + keystore->pkcs11uri = NULL; + + keystore->magic = DNS_KEYSTORE_MAGIC; + *kspp = keystore; + + return (ISC_R_SUCCESS); +} + +void +dns_keystore_attach(dns_keystore_t *source, dns_keystore_t **targetp) { + REQUIRE(DNS_KEYSTORE_VALID(source)); + REQUIRE(targetp != NULL && *targetp == NULL); + + isc_refcount_increment(&source->references); + *targetp = source; +} + +static inline void +destroy(dns_keystore_t *keystore) { + REQUIRE(!ISC_LINK_LINKED(keystore, link)); + + isc_mutex_destroy(&keystore->lock); + name = UNCONST(keystore->name); + isc_mem_free(keystore->mctx, name); + if (keystore->directory != NULL) { + isc_mem_free(keystore->mctx, keystore->directory); + } + if (keystore->pkcs11uri != NULL) { + isc_mem_free(keystore->mctx, keystore->pkcs11uri); + } + isc_mem_putanddetach(&keystore->mctx, keystore, sizeof(*keystore)); +} + +void +dns_keystore_detach(dns_keystore_t **kspp) { + REQUIRE(kspp != NULL && DNS_KEYSTORE_VALID(*kspp)); + + dns_keystore_t *ks = *kspp; + *kspp = NULL; + + if (isc_refcount_decrement(&ks->references) == 1) { + destroy(ks); + } +} + +const char * +dns_keystore_name(dns_keystore_t *keystore) { + REQUIRE(DNS_KEYSTORE_VALID(keystore)); + + return (keystore->name); +} + +const char * +dns_keystore_directory(dns_keystore_t *keystore) { + REQUIRE(DNS_KEYSTORE_VALID(keystore)); + + return (keystore->directory); +} + +void +dns_keystore_setdirectory(dns_keystore_t *keystore, const char *dir) { + REQUIRE(DNS_KEYSTORE_VALID(keystore)); + + if (keystore->directory != NULL) { + isc_mem_free(keystore->mctx, keystore->directory); + } + keystore->directory = (dir == NULL) + ? NULL + : isc_mem_strdup(keystore->mctx, dir); +} + +const char * +dns_keystore_pkcs11uri(dns_keystore_t *keystore) { + REQUIRE(DNS_KEYSTORE_VALID(keystore)); + + return (keystore->pkcs11uri); +} + +void +dns_keystore_setpkcs11uri(dns_keystore_t *keystore, const char *uri) { + REQUIRE(DNS_KEYSTORE_VALID(keystore)); + + if (keystore->pkcs11uri != NULL) { + isc_mem_free(keystore->mctx, keystore->pkcs11uri); + } + keystore->pkcs11uri = (uri == NULL) + ? NULL + : isc_mem_strdup(keystore->mctx, uri); +} + +isc_result_t +dns_keystorelist_find(dns_keystorelist_t *list, const char *name, + dns_keystore_t **kspp) { + dns_keystore_t *keystore = NULL; + + REQUIRE(kspp != NULL && *kspp == NULL); + + if (list == NULL) { + return (ISC_R_NOTFOUND); + } + + for (keystore = ISC_LIST_HEAD(*list); keystore != NULL; + keystore = ISC_LIST_NEXT(keystore, link)) + { + if (strcmp(keystore->name, name) == 0) { + break; + } + } + + if (keystore == NULL) { + return (ISC_R_NOTFOUND); + } + + dns_keystore_attach(keystore, kspp); + return (ISC_R_SUCCESS); +}