1/*	$NetBSD: keytable.h,v 1.8 2024/02/21 22:52:10 christos Exp $	*/
2
3/*
4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
5 *
6 * SPDX-License-Identifier: MPL-2.0
7 *
8 * This Source Code Form is subject to the terms of the Mozilla Public
9 * License, v. 2.0. If a copy of the MPL was not distributed with this
10 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
11 *
12 * See the COPYRIGHT file distributed with this work for additional
13 * information regarding copyright ownership.
14 */
15
16#pragma once
17
18/*****
19***** Module Info
20*****/
21
22/*! \file
23 * \brief
24 * The keytable module provides services for storing and retrieving DNSSEC
25 * trusted keys, as well as the ability to find the deepest matching key
26 * for a given domain name.
27 *
28 * MP:
29 *\li	The module ensures appropriate synchronization of data structures it
30 *	creates and manipulates.
31 *
32 * Resources:
33 *\li	TBS
34 *
35 * Security:
36 *\li	No anticipated impact.
37 */
38
39#include <stdbool.h>
40
41#include <isc/lang.h>
42#include <isc/magic.h>
43#include <isc/refcount.h>
44#include <isc/rwlock.h>
45#include <isc/stdtime.h>
46
47#include <dns/rdatastruct.h>
48#include <dns/types.h>
49
50#include <dst/dst.h>
51
52ISC_LANG_BEGINDECLS
53
54typedef void (*dns_keytable_callback_t)(const dns_name_t *name, void *fn_arg);
55
56isc_result_t
57dns_keytable_create(isc_mem_t *mctx, dns_keytable_t **keytablep);
58/*%<
59 * Create a keytable.
60 *
61 * Requires:
62 *
63 *\li	'mctx' is a valid memory context.
64 *
65 *\li	keytablep != NULL && *keytablep == NULL
66 *
67 * Ensures:
68 *
69 *\li	On success, *keytablep is a valid, empty key table.
70 *
71 * Returns:
72 *
73 *\li	ISC_R_SUCCESS
74 *
75 *\li	Any other result indicates failure.
76 */
77
78void
79dns_keytable_attach(dns_keytable_t *source, dns_keytable_t **targetp);
80/*%<
81 * Attach *targetp to source.
82 *
83 * Requires:
84 *
85 *\li	'source' is a valid keytable.
86 *
87 *\li	'targetp' points to a NULL dns_keytable_t *.
88 *
89 * Ensures:
90 *
91 *\li	*targetp is attached to source.
92 */
93
94void
95dns_keytable_detach(dns_keytable_t **keytablep);
96/*%<
97 * Detach *keytablep from its keytable.
98 *
99 * Requires:
100 *
101 *\li	'keytablep' points to a valid keytable.
102 *
103 * Ensures:
104 *
105 *\li	*keytablep is NULL.
106 *
107 *\li	If '*keytablep' is the last reference to the keytable,
108 *		all resources used by the keytable will be freed
109 */
110
111isc_result_t
112dns_keytable_add(dns_keytable_t *keytable, bool managed, bool initial,
113		 dns_name_t *name, dns_rdata_ds_t *ds,
114		 dns_keytable_callback_t callback, void *callback_arg);
115/*%<
116 * Add a key to 'keytable'. The keynode associated with 'name'
117 * is updated with the DS specified in 'ds'.
118 *
119 * The value of keynode->managed is set to 'managed', and the
120 * value of keynode->initial is set to 'initial'. (Note: 'initial'
121 * should only be used when adding managed-keys from configuration.
122 * This indicates the key is in "initializing" state, and has not yet
123 * been confirmed with a key refresh query.  Once a key refresh query
124 * has validated, we update the keynode with initial == false.)
125 *
126 * Notes:
127 *
128 *\li   If the key already exists in the table, adding it again
129 *      has no effect and ISC_R_SUCCESS is returned.
130 *
131 * Requires:
132 *
133 *\li	'keytable' points to a valid keytable.
134 *\li	'ds' is not NULL.
135 *\li	if 'initial' is true then 'managed' must also be true.
136 *
137 * Returns:
138 *
139 *\li	ISC_R_SUCCESS
140 *\li	ISC_R_EXISTS
141 *
142 *\li	Any other result indicates failure.
143 */
144
145isc_result_t
146dns_keytable_marksecure(dns_keytable_t *keytable, const dns_name_t *name);
147/*%<
148 * Add a null key to 'keytable' for name 'name'.  This marks the
149 * name as a secure domain, but doesn't supply any key data to allow the
150 * domain to be validated.  (Used when automated trust anchor management
151 * has gotten broken by a zone misconfiguration; for example, when the
152 * active key has been revoked but the stand-by key was still in its 30-day
153 * waiting period for validity.)
154 *
155 * Notes:
156 *
157 *\li   If a key already exists in the table, ISC_R_EXISTS is
158 *      returned and nothing is done.
159 *
160 * Requires:
161 *
162 *\li	'keytable' points to a valid keytable.
163 *
164 *\li	keyp != NULL && *keyp is a valid dst_key_t *.
165 *
166 * Returns:
167 *
168 *\li	ISC_R_SUCCESS
169 *\li	ISC_R_EXISTS
170 *
171 *\li	Any other result indicates failure.
172 */
173
174isc_result_t
175dns_keytable_delete(dns_keytable_t *keytable, const dns_name_t *keyname,
176		    dns_keytable_callback_t callback, void *callback_arg);
177/*%<
178 * Delete all trust anchors from 'keytable' matching name 'keyname'
179 *
180 * Requires:
181 *
182 *\li	'keytable' points to a valid keytable.
183 *
184 *\li	'name' is not NULL
185 *
186 * Returns:
187 *
188 *\li	ISC_R_SUCCESS
189 *
190 *\li	Any other result indicates failure.
191 */
192
193isc_result_t
194dns_keytable_deletekey(dns_keytable_t *keytable, const dns_name_t *keyname,
195		       dns_rdata_dnskey_t *dnskey);
196/*%<
197 * Remove the trust anchor matching the name 'keyname' and the DNSKEY
198 * rdata struct 'dnskey' from 'keytable'.
199 *
200 * Requires:
201 *
202 *\li	'keytable' points to a valid keytable.
203 *\li	'dnskey' is not NULL
204 *
205 * Returns:
206 *
207 *\li	ISC_R_SUCCESS
208 *
209 *\li	Any other result indicates failure.
210 */
211
212isc_result_t
213dns_keytable_find(dns_keytable_t *keytable, const dns_name_t *keyname,
214		  dns_keynode_t **keynodep);
215/*%<
216 * Search for the first instance of a trust anchor named 'name' in
217 * 'keytable', without regard to keyid and algorithm.
218 *
219 * Requires:
220 *
221 *\li	'keytable' is a valid keytable.
222 *
223 *\li	'name' is a valid absolute name.
224 *
225 *\li	keynodep != NULL && *keynodep == NULL
226 *
227 * Returns:
228 *
229 *\li	ISC_R_SUCCESS
230 *\li	ISC_R_NOTFOUND
231 *
232 *\li	Any other result indicates an error.
233 */
234
235isc_result_t
236dns_keytable_finddeepestmatch(dns_keytable_t *keytable, const dns_name_t *name,
237			      dns_name_t *foundname);
238/*%<
239 * Search for the deepest match of 'name' in 'keytable'.
240 *
241 * Requires:
242 *
243 *\li	'keytable' is a valid keytable.
244 *
245 *\li	'name' is a valid absolute name.
246 *
247 *\li	'foundname' is a name with a dedicated buffer.
248 *
249 * Returns:
250 *
251 *\li	ISC_R_SUCCESS
252 *\li	ISC_R_NOTFOUND
253 *
254 *\li	Any other result indicates an error.
255 */
256
257void
258dns_keytable_detachkeynode(dns_keytable_t *keytable, dns_keynode_t **keynodep);
259/*%<
260 * Detach a keynode found via dns_keytable_find().
261 *
262 * Requires:
263 *
264 *\li	*keynodep is a valid keynode returned by a call to dns_keytable_find().
265 *
266 * Ensures:
267 *
268 *\li	*keynodep == NULL
269 */
270
271isc_result_t
272dns_keytable_issecuredomain(dns_keytable_t *keytable, const dns_name_t *name,
273			    dns_name_t *foundname, bool *wantdnssecp);
274/*%<
275 * Is 'name' at or beneath a trusted key?
276 *
277 * Requires:
278 *
279 *\li	'keytable' is a valid keytable.
280 *
281 *\li	'name' is a valid absolute name.
282 *
283 *\li	'foundanme' is NULL or is a pointer to an initialized dns_name_t
284 *
285 *\li	'*wantsdnssecp' is a valid bool.
286 *
287 * Ensures:
288 *
289 *\li	On success, *wantsdnssecp will be true if and only if 'name'
290 *	is at or beneath a trusted key.  If 'foundname' is not NULL, then
291 *	it will be updated to contain the name of the closest enclosing
292 *	trust anchor.
293 *
294 * Returns:
295 *
296 *\li	ISC_R_SUCCESS
297 *
298 *\li	Any other result is an error.
299 */
300
301isc_result_t
302dns_keytable_dump(dns_keytable_t *keytable, FILE *fp);
303/*%<
304 * Dump the keytable on fp.
305 */
306
307isc_result_t
308dns_keytable_totext(dns_keytable_t *keytable, isc_buffer_t **buf);
309/*%<
310 * Dump the keytable to buffer at 'buf'
311 */
312
313bool
314dns_keynode_dsset(dns_keynode_t *keynode, dns_rdataset_t *rdataset);
315/*%<
316 * Clone the DS RRset associated with 'keynode' into 'rdataset' if
317 * it exists.  'dns_rdataset_disassociate(rdataset)' needs to be
318 * called when done.
319 *
320 * Returns:
321 *\li	true if there is a DS RRset.
322 *\li	false if there isn't DS RRset.
323 *
324 * Requires:
325 *\li	'keynode' is valid.
326 *\li	'rdataset' is valid or NULL.
327 */
328
329bool
330dns_keynode_managed(dns_keynode_t *keynode);
331/*%<
332 * Is this flagged as a managed key?
333 */
334
335bool
336dns_keynode_initial(dns_keynode_t *keynode);
337/*%<
338 * Is this flagged as an initializing key?
339 */
340
341void
342dns_keynode_trust(dns_keynode_t *keynode);
343/*%<
344 * Sets keynode->initial to false in order to mark the key as
345 * trusted: no longer an initializing key.
346 */
347
348isc_result_t
349dns_keytable_forall(dns_keytable_t *keytable,
350		    void (*func)(dns_keytable_t *, dns_keynode_t *,
351				 dns_name_t *, void *),
352		    void *arg);
353ISC_LANG_ENDDECLS
354