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