xref: /openbsd-src/usr.sbin/unbound/util/edns.h (revision a43524d9cc222a049058246319ec6a29f2d9ca78)
17bc20e6dSsthen /*
27bc20e6dSsthen  * util/edns.h - handle base EDNS options.
37bc20e6dSsthen  *
47bc20e6dSsthen  * Copyright (c) 2018, NLnet Labs. All rights reserved.
57bc20e6dSsthen  *
67bc20e6dSsthen  * This software is open source.
77bc20e6dSsthen  *
87bc20e6dSsthen  * Redistribution and use in source and binary forms, with or without
97bc20e6dSsthen  * modification, are permitted provided that the following conditions
107bc20e6dSsthen  * are met:
117bc20e6dSsthen  *
127bc20e6dSsthen  * Redistributions of source code must retain the above copyright notice,
137bc20e6dSsthen  * this list of conditions and the following disclaimer.
147bc20e6dSsthen  *
157bc20e6dSsthen  * Redistributions in binary form must reproduce the above copyright notice,
167bc20e6dSsthen  * this list of conditions and the following disclaimer in the documentation
177bc20e6dSsthen  * and/or other materials provided with the distribution.
187bc20e6dSsthen  *
197bc20e6dSsthen  * Neither the name of the NLNET LABS nor the names of its contributors may
207bc20e6dSsthen  * be used to endorse or promote products derived from this software without
217bc20e6dSsthen  * specific prior written permission.
227bc20e6dSsthen  *
237bc20e6dSsthen  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
247bc20e6dSsthen  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
257bc20e6dSsthen  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
267bc20e6dSsthen  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
277bc20e6dSsthen  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
287bc20e6dSsthen  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
297bc20e6dSsthen  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
307bc20e6dSsthen  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
317bc20e6dSsthen  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
327bc20e6dSsthen  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
337bc20e6dSsthen  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
347bc20e6dSsthen  */
357bc20e6dSsthen 
367bc20e6dSsthen /**
377bc20e6dSsthen  * \file
387bc20e6dSsthen  *
397bc20e6dSsthen  * This file contains functions for base EDNS options.
407bc20e6dSsthen  */
417bc20e6dSsthen 
427bc20e6dSsthen #ifndef UTIL_EDNS_H
437bc20e6dSsthen #define UTIL_EDNS_H
447bc20e6dSsthen 
45e2a0f313Ssthen #include "util/storage/dnstree.h"
46*a43524d9Ssthen #include "util/locks.h"
47e2a0f313Ssthen 
487bc20e6dSsthen struct edns_data;
497bc20e6dSsthen struct config_file;
507bc20e6dSsthen struct comm_point;
517bc20e6dSsthen struct regional;
527bc20e6dSsthen 
537bc20e6dSsthen /**
5472f58708Ssthen  * Structure containing all EDNS strings.
55e2a0f313Ssthen  */
5672f58708Ssthen struct edns_strings {
5772f58708Ssthen 	/** Tree of EDNS client strings to use in upstream queries, per address
5872f58708Ssthen 	 * prefix. Contains nodes of type edns_string_addr. */
5972f58708Ssthen 	rbtree_type client_strings;
6072f58708Ssthen 	/** EDNS opcode to use for client strings */
6172f58708Ssthen 	uint16_t client_string_opcode;
62e2a0f313Ssthen 	/** region to allocate tree nodes in */
63e2a0f313Ssthen 	struct regional* region;
64e2a0f313Ssthen };
65e2a0f313Ssthen 
66e2a0f313Ssthen /**
6772f58708Ssthen  * EDNS string. Node of rbtree, containing string and prefix.
68e2a0f313Ssthen  */
6972f58708Ssthen struct edns_string_addr {
70e2a0f313Ssthen 	/** node in address tree, used for tree lookups. Need to be the first
71e2a0f313Ssthen 	 * member of this struct. */
72e2a0f313Ssthen 	struct addr_tree_node node;
7372f58708Ssthen 	/** string, ascii format */
7472f58708Ssthen 	uint8_t* string;
7572f58708Ssthen 	/** length of string */
7672f58708Ssthen 	size_t string_len;
77e2a0f313Ssthen };
78e2a0f313Ssthen 
79*a43524d9Ssthen #define UNBOUND_COOKIE_HISTORY_SIZE 2
80*a43524d9Ssthen #define UNBOUND_COOKIE_SECRET_SIZE 16
81*a43524d9Ssthen 
82*a43524d9Ssthen typedef struct cookie_secret cookie_secret_type;
83*a43524d9Ssthen struct cookie_secret {
84*a43524d9Ssthen 	/** cookie secret */
85*a43524d9Ssthen 	uint8_t cookie_secret[UNBOUND_COOKIE_SECRET_SIZE];
86*a43524d9Ssthen };
87*a43524d9Ssthen 
88*a43524d9Ssthen /**
89*a43524d9Ssthen  * The cookie secrets from the cookie-secret-file.
90*a43524d9Ssthen  */
91*a43524d9Ssthen struct cookie_secrets {
92*a43524d9Ssthen 	/** lock on the structure, in case there are modifications
93*a43524d9Ssthen 	 * from remote control, this avoids race conditions. */
94*a43524d9Ssthen 	lock_basic_type lock;
95*a43524d9Ssthen 
96*a43524d9Ssthen 	/** how many cookies are there in the cookies array */
97*a43524d9Ssthen 	size_t cookie_count;
98*a43524d9Ssthen 
99*a43524d9Ssthen 	/* keep track of the last `UNBOUND_COOKIE_HISTORY_SIZE`
100*a43524d9Ssthen 	 * cookies as per rfc requirement .*/
101*a43524d9Ssthen 	cookie_secret_type cookie_secrets[UNBOUND_COOKIE_HISTORY_SIZE];
102*a43524d9Ssthen };
103*a43524d9Ssthen 
104437d2860Ssthen enum edns_cookie_val_status {
105437d2860Ssthen 	COOKIE_STATUS_CLIENT_ONLY = -3,
106437d2860Ssthen 	COOKIE_STATUS_FUTURE = -2,
107437d2860Ssthen 	COOKIE_STATUS_EXPIRED = -1,
108437d2860Ssthen 	COOKIE_STATUS_INVALID = 0,
109437d2860Ssthen 	COOKIE_STATUS_VALID = 1,
110437d2860Ssthen 	COOKIE_STATUS_VALID_RENEW = 2,
111437d2860Ssthen };
112437d2860Ssthen 
113e2a0f313Ssthen /**
11472f58708Ssthen  * Create structure to hold EDNS strings
11572f58708Ssthen  * @return: newly created edns_strings, NULL on alloc failure.
116e2a0f313Ssthen  */
11772f58708Ssthen struct edns_strings* edns_strings_create(void);
118e2a0f313Ssthen 
11972f58708Ssthen /** Delete EDNS strings structure
12072f58708Ssthen  * @param edns_strings: struct to delete
121e2a0f313Ssthen  */
12272f58708Ssthen void edns_strings_delete(struct edns_strings* edns_strings);
123e2a0f313Ssthen 
124e2a0f313Ssthen /**
12572f58708Ssthen  * Add configured EDNS strings
12672f58708Ssthen  * @param edns_strings: edns strings to apply config to
12772f58708Ssthen  * @param config: struct containing EDNS strings configuration
128e2a0f313Ssthen  * @return 0 on error
129e2a0f313Ssthen  */
13072f58708Ssthen int edns_strings_apply_cfg(struct edns_strings* edns_strings,
131e2a0f313Ssthen 	struct config_file* config);
132e2a0f313Ssthen 
133e2a0f313Ssthen /**
13472f58708Ssthen  * Find string for address.
13572f58708Ssthen  * @param tree: tree containing EDNS strings per address prefix.
136e2a0f313Ssthen  * @param addr: address to use for tree lookup
137e2a0f313Ssthen  * @param addrlen: length of address
138e2a0f313Ssthen  * @return: matching tree node, NULL otherwise
139e2a0f313Ssthen  */
14072f58708Ssthen struct edns_string_addr*
14172f58708Ssthen edns_string_addr_lookup(rbtree_type* tree, struct sockaddr_storage* addr,
142e2a0f313Ssthen 	socklen_t addrlen);
143e2a0f313Ssthen 
144437d2860Ssthen /**
145437d2860Ssthen  * Compute the interoperable DNS cookie (RFC9018) hash.
146437d2860Ssthen  * @param in: buffer input for the hash generation. It needs to be:
147437d2860Ssthen  *	Client Cookie | Version | Reserved | Timestamp | Client-IP
148437d2860Ssthen  * @param secret: the server secret; implicit length of 16 octets.
149437d2860Ssthen  * @param v4: if the client IP is v4 or v6.
150437d2860Ssthen  * @param hash: buffer to write the hash to.
151437d2860Ssthen  * return a pointer to the hash.
152437d2860Ssthen  */
153437d2860Ssthen uint8_t* edns_cookie_server_hash(const uint8_t* in, const uint8_t* secret,
154437d2860Ssthen 	int v4, uint8_t* hash);
155437d2860Ssthen 
156437d2860Ssthen /**
157437d2860Ssthen  * Write an interoperable DNS server cookie (RFC9018).
158437d2860Ssthen  * @param buf: buffer to write to. It should have a size of at least 32 octets
159437d2860Ssthen  *	as it doubles as the output buffer and the hash input buffer.
160437d2860Ssthen  *	The first 8 octets are expected to be the Client Cookie and will be
161437d2860Ssthen  *		left untouched.
162437d2860Ssthen  *	The next 8 octets will be written with Version | Reserved | Timestamp.
163437d2860Ssthen  *	The next 4 or 16 octets are expected to be the IPv4 or the IPv6 address
164437d2860Ssthen  *		based on the v4 flag.
165437d2860Ssthen  *	Thus the first 20 or 32 octets, based on the v4 flag, will be used as
166437d2860Ssthen  *		the hash input.
167437d2860Ssthen  *	The server hash (8 octets) will be written after the first 16 octets;
168437d2860Ssthen  *		overwriting the address information.
169437d2860Ssthen  *	The caller expects a complete, 24 octet long cookie in the buffer.
170437d2860Ssthen  * @param secret: the server secret; implicit length of 16 octets.
171437d2860Ssthen  * @param v4: if the client IP is v4 or v6.
172437d2860Ssthen  * @param timestamp: the timestamp to use.
173437d2860Ssthen  */
174437d2860Ssthen void edns_cookie_server_write(uint8_t* buf, const uint8_t* secret, int v4,
175437d2860Ssthen 	uint32_t timestamp);
176437d2860Ssthen 
177437d2860Ssthen /**
178437d2860Ssthen  * Validate an interoperable DNS cookie (RFC9018).
179437d2860Ssthen  * @param cookie: pointer to the cookie data.
180437d2860Ssthen  * @param cookie_len: the length of the cookie data.
181437d2860Ssthen  * @param secret: pointer to the server secret.
182437d2860Ssthen  * @param secret_len: the length of the secret.
183437d2860Ssthen  * @param v4: if the client IP is v4 or v6.
184437d2860Ssthen  * @param hash_input: pointer to the hash input for validation. It needs to be:
185437d2860Ssthen  *	Client Cookie | Version | Reserved | Timestamp | Client-IP
186437d2860Ssthen  * @param now: the current time.
187437d2860Ssthen  * return edns_cookie_val_status with the cookie validation status i.e.,
188437d2860Ssthen  *	<=0 for invalid, else valid.
189437d2860Ssthen  */
190437d2860Ssthen enum edns_cookie_val_status edns_cookie_server_validate(const uint8_t* cookie,
191437d2860Ssthen 	size_t cookie_len, const uint8_t* secret, size_t secret_len, int v4,
192437d2860Ssthen 	const uint8_t* hash_input, uint32_t now);
193437d2860Ssthen 
194*a43524d9Ssthen /**
195*a43524d9Ssthen  * Create the cookie secrets structure.
196*a43524d9Ssthen  * @return the structure or NULL on failure.
197*a43524d9Ssthen  */
198*a43524d9Ssthen struct cookie_secrets* cookie_secrets_create(void);
199*a43524d9Ssthen 
200*a43524d9Ssthen /**
201*a43524d9Ssthen  * Delete the cookie secrets.
202*a43524d9Ssthen  * @param cookie_secrets: the cookie secrets.
203*a43524d9Ssthen  */
204*a43524d9Ssthen void cookie_secrets_delete(struct cookie_secrets* cookie_secrets);
205*a43524d9Ssthen 
206*a43524d9Ssthen /**
207*a43524d9Ssthen  * Apply configuration to cookie secrets, read them from file.
208*a43524d9Ssthen  * @param cookie_secrets: the cookie secrets structure.
209*a43524d9Ssthen  * @param cookie_secret_file: the file name, it is read.
210*a43524d9Ssthen  * @return false on failure.
211*a43524d9Ssthen  */
212*a43524d9Ssthen int cookie_secrets_apply_cfg(struct cookie_secrets* cookie_secrets,
213*a43524d9Ssthen 	char* cookie_secret_file);
214*a43524d9Ssthen 
215*a43524d9Ssthen /**
216*a43524d9Ssthen  * Validate the cookie secrets, try all of them.
217*a43524d9Ssthen  * @param cookie: pointer to the cookie data.
218*a43524d9Ssthen  * @param cookie_len: the length of the cookie data.
219*a43524d9Ssthen  * @param cookie_secrets: struct of cookie secrets.
220*a43524d9Ssthen  * @param v4: if the client IP is v4 or v6.
221*a43524d9Ssthen  * @param hash_input: pointer to the hash input for validation. It needs to be:
222*a43524d9Ssthen  *	Client Cookie | Version | Reserved | Timestamp | Client-IP
223*a43524d9Ssthen  * @param now: the current time.
224*a43524d9Ssthen  * return edns_cookie_val_status with the cookie validation status i.e.,
225*a43524d9Ssthen  *	<=0 for invalid, else valid.
226*a43524d9Ssthen  */
227*a43524d9Ssthen enum edns_cookie_val_status cookie_secrets_server_validate(
228*a43524d9Ssthen 	const uint8_t* cookie, size_t cookie_len,
229*a43524d9Ssthen 	struct cookie_secrets* cookie_secrets, int v4,
230*a43524d9Ssthen 	const uint8_t* hash_input, uint32_t now);
231*a43524d9Ssthen 
232*a43524d9Ssthen /**
233*a43524d9Ssthen  * Add a cookie secret. If there are no secrets yet, the secret will become
234*a43524d9Ssthen  * the active secret. Otherwise it will become the staging secret.
235*a43524d9Ssthen  * Active secrets are used to both verify and create new DNS Cookies.
236*a43524d9Ssthen  * Staging secrets are only used to verify DNS Cookies. Caller has to lock.
237*a43524d9Ssthen  */
238*a43524d9Ssthen void add_cookie_secret(struct cookie_secrets* cookie_secrets, uint8_t* secret,
239*a43524d9Ssthen 	size_t secret_len);
240*a43524d9Ssthen 
241*a43524d9Ssthen /**
242*a43524d9Ssthen  * Makes the staging cookie secret active and the active secret staging.
243*a43524d9Ssthen  * Caller has to lock.
244*a43524d9Ssthen  */
245*a43524d9Ssthen void activate_cookie_secret(struct cookie_secrets* cookie_secrets);
246*a43524d9Ssthen 
247*a43524d9Ssthen /**
248*a43524d9Ssthen  * Drop a cookie secret. Drops the staging secret. An active secret will not
249*a43524d9Ssthen  * be dropped. Caller has to lock.
250*a43524d9Ssthen  */
251*a43524d9Ssthen void drop_cookie_secret(struct cookie_secrets* cookie_secrets);
252*a43524d9Ssthen 
2537bc20e6dSsthen #endif
254