Super User's BSD Cross Reference: /OpenBSD/usr.sbin/unbound/util/edns.c

1 /*
2 * util/edns.c - handle base EDNS options.
3 *
4 * Copyright (c) 2018, NLnet Labs. All rights reserved.
5 *
6 * This software is open source.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * Redistributions of source code must retain the above copyright notice,
13 * this list of conditions and the following disclaimer.
14 *
15 * Redistributions in binary form must reproduce the above copyright notice,
16 * this list of conditions and the following disclaimer in the documentation
17 * and/or other materials provided with the distribution.
18 *
19 * Neither the name of the NLNET LABS nor the names of its contributors may
20 * be used to endorse or promote products derived from this software without
21 * specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
29 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 */
35
36 /**
37 * \file
38 *
39 * This file contains functions for base EDNS options.
40 */
41
42#include "config.h"
43#include "util/edns.h"
44#include "util/config_file.h"
45#include "util/netevent.h"
46#include "util/net_help.h"
47#include "util/regional.h"
48#include "util/rfc_1982.h"
49#include "util/siphash.h"
50#include "util/data/msgparse.h"
51#include "util/data/msgreply.h"
52#include "sldns/sbuffer.h"
53
54 struct edns_strings* edns_strings_create(void)
55{
56 struct edns_strings* edns_strings = calloc(1,
57 sizeof(struct edns_strings));
58 if(!edns_strings)
59 return NULL;
60 if(!(edns_strings->region = regional_create())) {
61 edns_strings_delete(edns_strings);
62 return NULL;
63 }
64 return edns_strings;
65}
66
67 void edns_strings_delete(struct edns_strings* edns_strings)
68{
69 if(!edns_strings)
70 return;
71 regional_destroy(edns_strings->region);
72 free(edns_strings);
73}
74
75 static int
76 edns_strings_client_insert(struct edns_strings* edns_strings,
77 struct sockaddr_storage* addr, socklen_t addrlen, int net,
78 const char* string)
79{
80 struct edns_string_addr* esa = regional_alloc_zero(edns_strings->region,
81 sizeof(struct edns_string_addr));
82 if(!esa)
83 return 0;
84 esa->string_len = strlen(string);
85 esa->string = regional_alloc_init(edns_strings->region, string,
86 esa->string_len);
87 if(!esa->string)
88 return 0;
89 if(!addr_tree_insert(&edns_strings->client_strings, &esa->node, addr,
90 addrlen, net)) {
91 verbose(VERB_QUERY, "duplicate EDNS client string ignored.");
92 }
93 return 1;
94}
95
96 int edns_strings_apply_cfg(struct edns_strings* edns_strings,
97 struct config_file* config)
98{
99 struct config_str2list* c;
100 regional_free_all(edns_strings->region);
101 addr_tree_init(&edns_strings->client_strings);
102
103 for(c=config->edns_client_strings; c; c=c->next) {
104 struct sockaddr_storage addr;
105 socklen_t addrlen;
106 int net;
107 log_assert(c->str && c->str2);
108
109 if(!netblockstrtoaddr(c->str, UNBOUND_DNS_PORT, &addr, &addrlen,
110 &net)) {
111 log_err("cannot parse EDNS client string IP netblock: "
112 "%s", c->str);
113 return 0;
114 }
115 if(!edns_strings_client_insert(edns_strings, &addr, addrlen,
116 net, c->str2)) {
117 log_err("out of memory while adding EDNS strings");
118 return 0;
119 }
120 }
121 edns_strings->client_string_opcode = config->edns_client_string_opcode;
122
123 addr_tree_init_parents(&edns_strings->client_strings);
124 return 1;
125}
126
127 struct edns_string_addr*
128 edns_string_addr_lookup(rbtree_type* tree, struct sockaddr_storage* addr,
129 socklen_t addrlen)
130{
131 return (struct edns_string_addr*)addr_tree_lookup(tree, addr, addrlen);
132}
133
134 size_t
135 edns_strings_get_mem(struct edns_strings* edns_strings)
136{
137 if(!edns_strings) return 0;
138 return regional_get_mem(edns_strings->region) + sizeof(*edns_strings);
139}
140
141 void
142 edns_strings_swap_tree(struct edns_strings* edns_strings,
143 struct edns_strings* data)
144{
145 rbtree_type tree = edns_strings->client_strings;
146 uint16_t opcode = edns_strings->client_string_opcode;
147 struct regional* region = edns_strings->region;
148
149 edns_strings->client_strings = data->client_strings;
150 edns_strings->client_string_opcode = data->client_string_opcode;
151 edns_strings->region = data->region;
152 data->client_strings = tree;
153 data->client_string_opcode = opcode;
154 data->region = region;
155}
156
157 uint8_t*
158 edns_cookie_server_hash(const uint8_t* in, const uint8_t* secret, int v4,
159 uint8_t* hash)
160{
161 v4?siphash(in, 20, secret, hash, 8):siphash(in, 32, secret, hash, 8);
162 return hash;
163}
164
165 void
166 edns_cookie_server_write(uint8_t* buf, const uint8_t* secret, int v4,
167 uint32_t timestamp)
168{
169 uint8_t hash[8];
170 buf[ 8] = 1; /* Version */
171 buf[ 9] = 0; /* Reserved */
172 buf[10] = 0; /* Reserved */
173 buf[11] = 0; /* Reserved */
174 sldns_write_uint32(buf + 12, timestamp);
175 (void)edns_cookie_server_hash(buf, secret, v4, hash);
176 memcpy(buf + 16, hash, 8);
177}
178
179 enum edns_cookie_val_status
180 edns_cookie_server_validate(const uint8_t* cookie, size_t cookie_len,
181 const uint8_t* secret, size_t secret_len, int v4,
182 const uint8_t* hash_input, uint32_t now)
183{
184 uint8_t hash[8];
185 uint32_t timestamp;
186 uint32_t subt_1982 = 0; /* Initialize for the compiler; unused value */
187 int comp_1982;
188 if(cookie_len != 24)
189 /* RFC9018 cookies are 24 bytes long */
190 return COOKIE_STATUS_CLIENT_ONLY;
191 if(secret_len != 16 || /* RFC9018 cookies have 16 byte secrets */
192 cookie[8] != 1) /* RFC9018 cookies are cookie version 1 */
193 return COOKIE_STATUS_INVALID;
194 timestamp = sldns_read_uint32(cookie + 12);
195 if((comp_1982 = compare_1982(now, timestamp)) > 0
196 && (subt_1982 = subtract_1982(timestamp, now)) > 3600)
197 /* Cookie is older than 1 hour (see RFC9018 Section 4.3.) */
198 return COOKIE_STATUS_EXPIRED;
199 if(comp_1982 <= 0 && subtract_1982(now, timestamp) > 300)
200 /* Cookie time is more than 5 minutes in the future.
201 * (see RFC9018 Section 4.3.) */
202 return COOKIE_STATUS_FUTURE;
203 if(memcmp(edns_cookie_server_hash(hash_input, secret, v4, hash),
204 cookie + 16, 8) != 0)
205 /* Hashes do not match */
206 return COOKIE_STATUS_INVALID;
207 if(comp_1982 > 0 && subt_1982 > 1800)
208 /* Valid cookie but older than 30 minutes, so create a new one
209 * anyway */
210 return COOKIE_STATUS_VALID_RENEW;
211 return COOKIE_STATUS_VALID;
212}
213
214 struct cookie_secrets*
215 cookie_secrets_create(void)
216{
217 struct cookie_secrets* cookie_secrets = calloc(1,
218 sizeof(*cookie_secrets));
219 if(!cookie_secrets)
220 return NULL;
221 lock_basic_init(&cookie_secrets->lock);
222 lock_protect(&cookie_secrets->lock, &cookie_secrets->cookie_count,
223 sizeof(cookie_secrets->cookie_count));
224 lock_protect(&cookie_secrets->lock, cookie_secrets->cookie_secrets,
225 sizeof(cookie_secret_type)*UNBOUND_COOKIE_HISTORY_SIZE);
226 return cookie_secrets;
227}
228
229 void
230 cookie_secrets_delete(struct cookie_secrets* cookie_secrets)
231{
232 if(!cookie_secrets)
233 return;
234 lock_basic_destroy(&cookie_secrets->lock);
235 explicit_bzero(cookie_secrets->cookie_secrets,
236 sizeof(cookie_secret_type)*UNBOUND_COOKIE_HISTORY_SIZE);
237 free(cookie_secrets);
238}
239
240 /** Read the cookie secret file */
241 static int
242 cookie_secret_file_read(struct cookie_secrets* cookie_secrets,
243 char* cookie_secret_file)
244{
245 char secret[UNBOUND_COOKIE_SECRET_SIZE * 2 + 2/*'\n' and '0円'*/];
246 FILE* f;
247 int corrupt = 0;
248 size_t count;
249
250 log_assert(cookie_secret_file != NULL);
251 cookie_secrets->cookie_count = 0;
252 f = fopen(cookie_secret_file, "r");
253 /* a non-existing cookie file is not an error */
254 if( f == NULL ) {
255 if(errno != EPERM) {
256 log_err("Could not read cookie-secret-file '%s': %s",
257 cookie_secret_file, strerror(errno));
258 return 0;
259 }
260 return 1;
261 }
262 /* cookie secret file exists and is readable */
263 for( count = 0; count < UNBOUND_COOKIE_HISTORY_SIZE; count++ ) {
264 size_t secret_len = 0;
265 ssize_t decoded_len = 0;
266 if( fgets(secret, sizeof(secret), f) == NULL ) { break; }
267 secret_len = strlen(secret);
268 if( secret_len == 0 ) { break; }
269 log_assert( secret_len <= sizeof(secret) );
270 secret_len = secret[secret_len - 1] == '\n' ? secret_len - 1 : secret_len;
271 if( secret_len != UNBOUND_COOKIE_SECRET_SIZE * 2 ) { corrupt++; break; }
272 /* needed for `hex_pton`; stripping potential `\n` */
273 secret[secret_len] = '0円';
274 decoded_len = hex_pton(secret, cookie_secrets->cookie_secrets[count].cookie_secret,
275 UNBOUND_COOKIE_SECRET_SIZE);
276 if( decoded_len != UNBOUND_COOKIE_SECRET_SIZE ) { corrupt++; break; }
277 cookie_secrets->cookie_count++;
278 }
279 fclose(f);
280 return corrupt == 0;
281}
282
283 int
284 cookie_secrets_apply_cfg(struct cookie_secrets* cookie_secrets,
285 char* cookie_secret_file)
286{
287 if(!cookie_secrets) {
288 if(!cookie_secret_file || !cookie_secret_file[0])
289 return 1; /* There is nothing to read anyway */
290 log_err("Could not read cookie secrets, no structure alloced");
291 return 0;
292 }
293 if(!cookie_secret_file_read(cookie_secrets, cookie_secret_file))
294 return 0;
295 return 1;
296}
297
298 enum edns_cookie_val_status
299 cookie_secrets_server_validate(const uint8_t* cookie, size_t cookie_len,
300 struct cookie_secrets* cookie_secrets, int v4,
301 const uint8_t* hash_input, uint32_t now)
302{
303 size_t i;
304 enum edns_cookie_val_status cookie_val_status,
305 last = COOKIE_STATUS_INVALID;
306 if(!cookie_secrets)
307 return COOKIE_STATUS_INVALID; /* There are no cookie secrets.*/
308 lock_basic_lock(&cookie_secrets->lock);
309 if(cookie_secrets->cookie_count == 0) {
310 lock_basic_unlock(&cookie_secrets->lock);
311 return COOKIE_STATUS_INVALID; /* There are no cookie secrets.*/
312 }
313 for(i=0; i<cookie_secrets->cookie_count; i++) {
314 cookie_val_status = edns_cookie_server_validate(cookie,
315 cookie_len,
316 cookie_secrets->cookie_secrets[i].cookie_secret,
317 UNBOUND_COOKIE_SECRET_SIZE, v4, hash_input, now);
318 if(cookie_val_status == COOKIE_STATUS_VALID ||
319 cookie_val_status == COOKIE_STATUS_VALID_RENEW) {
320 lock_basic_unlock(&cookie_secrets->lock);
321 /* For staging cookies, write a fresh cookie. */
322 if(i != 0)
323 return COOKIE_STATUS_VALID_RENEW;
324 return cookie_val_status;
325 }
326 if(last == COOKIE_STATUS_INVALID)
327 last = cookie_val_status; /* Store more interesting
328 failure to return. */
329 }
330 lock_basic_unlock(&cookie_secrets->lock);
331 return last;
332}
333
334 void add_cookie_secret(struct cookie_secrets* cookie_secrets,
335 uint8_t* secret, size_t secret_len)
336{
337 log_assert(secret_len == UNBOUND_COOKIE_SECRET_SIZE);
338 (void)secret_len;
339 if(!cookie_secrets)
340 return;
341
342 /* New cookie secret becomes the staging secret (position 1)
343 * unless there is no active cookie yet, then it becomes the active
344 * secret. If the UNBOUND_COOKIE_HISTORY_SIZE > 2 then all staging cookies
345 * are moved one position down.
346 */
347 if(cookie_secrets->cookie_count == 0) {
348 memcpy( cookie_secrets->cookie_secrets->cookie_secret
349 , secret, UNBOUND_COOKIE_SECRET_SIZE);
350 cookie_secrets->cookie_count = 1;
351 explicit_bzero(secret, UNBOUND_COOKIE_SECRET_SIZE);
352 return;
353 }
354#if UNBOUND_COOKIE_HISTORY_SIZE > 2
355 memmove( &cookie_secrets->cookie_secrets[2], &cookie_secrets->cookie_secrets[1]
356 , sizeof(struct cookie_secret) * (UNBOUND_COOKIE_HISTORY_SIZE - 2));
357#endif
358 memcpy( cookie_secrets->cookie_secrets[1].cookie_secret
359 , secret, UNBOUND_COOKIE_SECRET_SIZE);
360 cookie_secrets->cookie_count = cookie_secrets->cookie_count < UNBOUND_COOKIE_HISTORY_SIZE
361 ? cookie_secrets->cookie_count + 1 : UNBOUND_COOKIE_HISTORY_SIZE;
362 explicit_bzero(secret, UNBOUND_COOKIE_SECRET_SIZE);
363}
364
365 void activate_cookie_secret(struct cookie_secrets* cookie_secrets)
366{
367 uint8_t active_secret[UNBOUND_COOKIE_SECRET_SIZE];
368 if(!cookie_secrets)
369 return;
370 /* The staging secret becomes the active secret.
371 * The active secret becomes a staging secret.
372 * If the UNBOUND_COOKIE_HISTORY_SIZE > 2 then all staging secrets are moved
373 * one position up and the previously active secret becomes the last
374 * staging secret.
375 */
376 if(cookie_secrets->cookie_count < 2)
377 return;
378 memcpy( active_secret, cookie_secrets->cookie_secrets[0].cookie_secret
379 , UNBOUND_COOKIE_SECRET_SIZE);
380 memmove( &cookie_secrets->cookie_secrets[0], &cookie_secrets->cookie_secrets[1]
381 , sizeof(struct cookie_secret) * (UNBOUND_COOKIE_HISTORY_SIZE - 1));
382 memcpy( cookie_secrets->cookie_secrets[cookie_secrets->cookie_count - 1].cookie_secret
383 , active_secret, UNBOUND_COOKIE_SECRET_SIZE);
384 explicit_bzero(active_secret, UNBOUND_COOKIE_SECRET_SIZE);
385}
386
387 void drop_cookie_secret(struct cookie_secrets* cookie_secrets)
388{
389 if(!cookie_secrets)
390 return;
391 /* Drops a staging cookie secret. If there are more than one, it will
392 * drop the last staging secret. */
393 if(cookie_secrets->cookie_count < 2)
394 return;
395 explicit_bzero( cookie_secrets->cookie_secrets[cookie_secrets->cookie_count - 1].cookie_secret
396 , UNBOUND_COOKIE_SECRET_SIZE);
397 cookie_secrets->cookie_count -= 1;
398}
399 

AltStyle によって変換されたページ (->オリジナル) /