xref: /openbsd-src/usr.sbin/nsd/tsig.c (revision f2da64fbbbf1b03f09f390ab01267c93dfd77c4c)
1 /*
2  * tsig.c -- TSIG implementation (RFC 2845).
3  *
4  * Copyright (c) 2001-2006, NLnet Labs. All rights reserved.
5  *
6  * See LICENSE for the license.
7  *
8  */
9 
10 
11 #include "config.h"
12 #include <stdlib.h>
13 #include <ctype.h>
14 
15 #include "tsig.h"
16 #include "tsig-openssl.h"
17 #include "dns.h"
18 #include "packet.h"
19 #include "query.h"
20 #include "rbtree.h"
21 
22 static region_type *tsig_region;
23 
24 struct tsig_key_table
25 {
26 	rbnode_t node; /* by dname */
27 	tsig_key_type *key;
28 };
29 typedef struct tsig_key_table tsig_key_table_type;
30 static rbtree_t *tsig_key_table;
31 
32 struct tsig_algorithm_table
33 {
34 	struct tsig_algorithm_table *next;
35 	tsig_algorithm_type *algorithm;
36 };
37 typedef struct tsig_algorithm_table tsig_algorithm_table_type;
38 static tsig_algorithm_table_type *tsig_algorithm_table;
39 static size_t max_algo_digest_size = 0;
40 
41 static void
42 tsig_digest_variables(tsig_record_type *tsig, int tsig_timers_only)
43 {
44 	uint16_t klass = htons(CLASS_ANY);
45 	uint32_t ttl = htonl(0);
46 	uint16_t signed_time_high = htons(tsig->signed_time_high);
47 	uint32_t signed_time_low = htonl(tsig->signed_time_low);
48 	uint16_t signed_time_fudge = htons(tsig->signed_time_fudge);
49 	uint16_t error_code = htons(tsig->error_code);
50 	uint16_t other_size = htons(tsig->other_size);
51 
52 	if (!tsig_timers_only) {
53 		tsig->algorithm->hmac_update(tsig->context,
54 					     dname_name(tsig->key_name),
55 					     tsig->key_name->name_size);
56 		tsig->algorithm->hmac_update(tsig->context,
57 					     &klass,
58 					     sizeof(klass));
59 		tsig->algorithm->hmac_update(tsig->context,
60 					     &ttl,
61 					     sizeof(ttl));
62 		tsig->algorithm->hmac_update(tsig->context,
63 					     dname_name(tsig->algorithm_name),
64 					     tsig->algorithm_name->name_size);
65 	}
66 	tsig->algorithm->hmac_update(tsig->context,
67 				     &signed_time_high,
68 				     sizeof(signed_time_high));
69 	tsig->algorithm->hmac_update(tsig->context,
70 				     &signed_time_low,
71 				     sizeof(signed_time_low));
72 	tsig->algorithm->hmac_update(tsig->context,
73 				     &signed_time_fudge,
74 				     sizeof(signed_time_fudge));
75 	if (!tsig_timers_only) {
76 		tsig->algorithm->hmac_update(tsig->context,
77 					     &error_code,
78 					     sizeof(error_code));
79 		tsig->algorithm->hmac_update(tsig->context,
80 					     &other_size,
81 					     sizeof(other_size));
82 		tsig->algorithm->hmac_update(tsig->context,
83 					     tsig->other_data,
84 					     tsig->other_size);
85 	}
86 }
87 
88 static int
89 tree_dname_compare(const void* a, const void* b)
90 {
91 	return dname_compare((const dname_type*)a, (const dname_type*)b);
92 }
93 
94 int
95 tsig_init(region_type *region)
96 {
97 	tsig_region = region;
98 	tsig_key_table = rbtree_create(region, &tree_dname_compare);
99 	tsig_algorithm_table = NULL;
100 
101 #if defined(HAVE_SSL)
102 	return tsig_openssl_init(region);
103 #endif /* defined(HAVE_SSL) */
104 	return 1;
105 }
106 
107 void
108 tsig_add_key(tsig_key_type *key)
109 {
110 	tsig_key_table_type *entry = (tsig_key_table_type *) region_alloc_zero(
111 		tsig_region, sizeof(tsig_key_table_type));
112 	entry->key = key;
113 	entry->node.key = entry->key->name;
114 	(void)rbtree_insert(tsig_key_table, &entry->node);
115 }
116 
117 void
118 tsig_del_key(tsig_key_type *key)
119 {
120 	tsig_key_table_type *entry;
121 	if(!key) return;
122 	entry = (tsig_key_table_type*)rbtree_delete(tsig_key_table, key->name);
123 	if(!entry) return;
124 	region_recycle(tsig_region, entry, sizeof(tsig_key_table_type));
125 }
126 
127 tsig_key_type*
128 tsig_find_key(const dname_type* name)
129 {
130 	tsig_key_table_type* entry;
131 	entry = (tsig_key_table_type*)rbtree_search(tsig_key_table, name);
132 	if(entry)
133 		return entry->key;
134 	return NULL;
135 }
136 
137 void
138 tsig_add_algorithm(tsig_algorithm_type *algorithm)
139 {
140 	tsig_algorithm_table_type *entry
141 		= (tsig_algorithm_table_type *) region_alloc(
142 			tsig_region, sizeof(tsig_algorithm_table_type));
143 	entry->algorithm = algorithm;
144 	entry->next = tsig_algorithm_table;
145 	tsig_algorithm_table = entry;
146 	if(algorithm->maximum_digest_size > max_algo_digest_size)
147 		max_algo_digest_size = algorithm->maximum_digest_size;
148 }
149 
150 /**
151  * compare a tsig algorithm string lowercased
152  */
153 int
154 tsig_strlowercmp(const char* str1, const char* str2)
155 {
156 	while (str1 && str2 && *str1 != '\0' && *str2 != '\0') {
157 		if(tolower((unsigned char)*str1) != tolower((unsigned char)*str2)) {
158 			if(tolower((unsigned char)*str1) < tolower((unsigned char)*str2))
159 				return -1;
160 			return 1;
161 		}
162 		str1++;
163 		str2++;
164 	}
165 	if (str1 && str2) {
166 		if (*str1 == *str2)
167 			return 0;
168 		else if (*str1 == '\0')
169 			return -1;
170 	}
171 	else if (!str1 && !str2)
172 		return 0;
173 	else if (!str1 && str2)
174 		return -1;
175 	return 1;
176 }
177 
178 
179 /*
180  * Find an HMAC algorithm based on its short name.
181  */
182 tsig_algorithm_type *
183 tsig_get_algorithm_by_name(const char *name)
184 {
185 	tsig_algorithm_table_type *algorithm_entry;
186 
187 	for (algorithm_entry = tsig_algorithm_table;
188 	     algorithm_entry;
189 	     algorithm_entry = algorithm_entry->next)
190 	{
191 		if (tsig_strlowercmp(name, algorithm_entry->algorithm->short_name) == 0)
192 		{
193 			return algorithm_entry->algorithm;
194 		}
195 	}
196 
197 	return NULL;
198 }
199 
200 
201 const char *
202 tsig_error(int error_code)
203 {
204 	static char message[1000];
205 
206 	switch (error_code) {
207 	case TSIG_ERROR_NOERROR:
208 		return "No Error";
209 		break;
210 	case TSIG_ERROR_BADSIG:
211 		return "Bad Signature";
212 		break;
213 	case TSIG_ERROR_BADKEY:
214 		return "Bad Key";
215 		break;
216 	case TSIG_ERROR_BADTIME:
217 		return "Bad Time";
218 		break;
219 	default:
220 		if(error_code < 16) /* DNS rcodes */
221 			return rcode2str(error_code);
222 
223 		snprintf(message, sizeof(message),
224 			 "Unknown Error %d", error_code);
225 		break;
226 	}
227 	return message;
228 }
229 
230 static void
231 tsig_cleanup(void *data)
232 {
233 	tsig_record_type *tsig = (tsig_record_type *) data;
234 	region_destroy(tsig->rr_region);
235 	region_destroy(tsig->context_region);
236 }
237 
238 void
239 tsig_create_record(tsig_record_type *tsig, region_type *region)
240 {
241 	tsig_create_record_custom(tsig, region, DEFAULT_CHUNK_SIZE,
242 		DEFAULT_LARGE_OBJECT_SIZE, DEFAULT_INITIAL_CLEANUP_SIZE);
243 }
244 
245 void
246 tsig_create_record_custom(tsig_record_type *tsig, region_type *region,
247 	size_t chunk_size, size_t large_object_size, size_t initial_cleanup_size)
248 {
249 	tsig->rr_region = region_create_custom(xalloc, free, chunk_size,
250 		large_object_size, initial_cleanup_size, 0);
251 	tsig->context_region = region_create_custom(xalloc, free, chunk_size,
252 		large_object_size, initial_cleanup_size, 0);
253 	if(region)
254 		region_add_cleanup(region, tsig_cleanup, tsig);
255 	tsig_init_record(tsig, NULL, NULL);
256 }
257 
258 void
259 tsig_delete_record(tsig_record_type* tsig, region_type* region)
260 {
261 	if(region)
262 		region_remove_cleanup(region, tsig_cleanup, tsig);
263 	region_destroy(tsig->rr_region);
264 	region_destroy(tsig->context_region);
265 }
266 
267 void
268 tsig_init_record(tsig_record_type *tsig,
269 		 tsig_algorithm_type *algorithm,
270 		 tsig_key_type *key)
271 {
272 	tsig->status = TSIG_NOT_PRESENT;
273 	tsig->error_code = TSIG_ERROR_NOERROR;
274 	tsig->position = 0;
275 	tsig->response_count = 0;
276 	tsig->context = NULL;
277 	tsig->algorithm = algorithm;
278 	tsig->key = key;
279 	tsig->prior_mac_size = 0;
280 	tsig->prior_mac_data = NULL;
281 	region_free_all(tsig->context_region);
282 }
283 
284 int
285 tsig_from_query(tsig_record_type *tsig)
286 {
287 	tsig_key_type *key = NULL;
288 	tsig_algorithm_table_type *algorithm_entry;
289 	tsig_algorithm_type *algorithm = NULL;
290 	uint64_t current_time;
291 	uint64_t signed_time;
292 
293 	assert(tsig->status == TSIG_OK);
294 	assert(!tsig->algorithm);
295 	assert(!tsig->key);
296 
297 	key = (tsig_key_type*)tsig_find_key(tsig->key_name);
298 
299 	for (algorithm_entry = tsig_algorithm_table;
300 	     algorithm_entry;
301 	     algorithm_entry = algorithm_entry->next)
302 	{
303 		if (dname_compare(
304 			    tsig->algorithm_name,
305 			    algorithm_entry->algorithm->wireformat_name) == 0)
306 		{
307 			algorithm = algorithm_entry->algorithm;
308 			break;
309 		}
310 	}
311 
312 	if (!algorithm || !key) {
313 		/* Algorithm or key is unknown, cannot authenticate.  */
314 		tsig->error_code = TSIG_ERROR_BADKEY;
315 		return 0;
316 	}
317 
318 	if ((tsig->algorithm && algorithm != tsig->algorithm)
319 	    || (tsig->key && key != tsig->key))
320 	{
321 		/*
322 		 * Algorithm or key changed during a single connection,
323 		 * return error.
324 		 */
325 		tsig->error_code = TSIG_ERROR_BADKEY;
326 		return 0;
327 	}
328 
329 	signed_time = ((((uint64_t) tsig->signed_time_high) << 32) |
330 		       ((uint64_t) tsig->signed_time_low));
331 
332 	current_time = (uint64_t) time(NULL);
333 	if ((current_time < signed_time - tsig->signed_time_fudge)
334 	    || (current_time > signed_time + tsig->signed_time_fudge))
335 	{
336 		uint16_t current_time_high;
337 		uint32_t current_time_low;
338 
339 #if 0 /* debug */
340 		char current_time_text[26];
341 		char signed_time_text[26];
342 		time_t clock;
343 
344 		clock = (time_t) current_time;
345 		ctime_r(&clock, current_time_text);
346 		current_time_text[24] = '\0';
347 
348 		clock = (time_t) signed_time;
349 		ctime_r(&clock, signed_time_text);
350 		signed_time_text[24] = '\0';
351 
352 		log_msg(LOG_ERR,
353 			"current server time %s is outside the range of TSIG"
354 			" signed time %s with fudge %u",
355 			current_time_text,
356 			signed_time_text,
357 			(unsigned) tsig->signed_time_fudge);
358 #endif
359 
360 		tsig->error_code = TSIG_ERROR_BADTIME;
361 		current_time_high = (uint16_t) (current_time >> 32);
362 		current_time_low = (uint32_t) current_time;
363 		tsig->other_size = 6;
364 		tsig->other_data = (uint8_t *) region_alloc(
365 			tsig->rr_region, sizeof(uint16_t) + sizeof(uint32_t));
366 		write_uint16(tsig->other_data, current_time_high);
367 		write_uint32(tsig->other_data + 2, current_time_low);
368 		return 0;
369 	}
370 
371 	tsig->algorithm = algorithm;
372 	tsig->key = key;
373 	tsig->response_count = 0;
374 	tsig->prior_mac_size = 0;
375 
376 	return 1;
377 }
378 
379 void
380 tsig_init_query(tsig_record_type *tsig, uint16_t original_query_id)
381 {
382 	assert(tsig);
383 	assert(tsig->algorithm);
384 	assert(tsig->key);
385 
386 	tsig->response_count = 0;
387 	tsig->prior_mac_size = 0;
388 	tsig->algorithm_name = tsig->algorithm->wireformat_name;
389 	tsig->key_name = tsig->key->name;
390 	tsig->mac_size = 0;
391 	tsig->mac_data = NULL;
392 	tsig->original_query_id = original_query_id;
393 	tsig->error_code = TSIG_ERROR_NOERROR;
394 	tsig->other_size = 0;
395 	tsig->other_data = NULL;
396 }
397 
398 void
399 tsig_prepare(tsig_record_type *tsig)
400 {
401 	if (!tsig->context) {
402 		assert(tsig->algorithm);
403 		tsig->context = tsig->algorithm->hmac_create_context(
404 			tsig->context_region);
405 		tsig->prior_mac_data = (uint8_t *) region_alloc(
406 			tsig->context_region,
407 			tsig->algorithm->maximum_digest_size);
408 	}
409 	tsig->algorithm->hmac_init_context(tsig->context,
410 					   tsig->algorithm,
411 					   tsig->key);
412 
413 	if (tsig->prior_mac_size > 0) {
414 		uint16_t mac_size = htons(tsig->prior_mac_size);
415 		tsig->algorithm->hmac_update(tsig->context,
416 					     &mac_size,
417 					     sizeof(mac_size));
418 		tsig->algorithm->hmac_update(tsig->context,
419 					     tsig->prior_mac_data,
420 					     tsig->prior_mac_size);
421 	}
422 
423 	tsig->updates_since_last_prepare = 0;
424 }
425 
426 void
427 tsig_update(tsig_record_type *tsig, buffer_type *packet, size_t length)
428 {
429 	uint16_t original_query_id = htons(tsig->original_query_id);
430 
431 	assert(length <= buffer_limit(packet));
432 
433 	tsig->algorithm->hmac_update(tsig->context,
434 				     &original_query_id,
435 				     sizeof(original_query_id));
436 	tsig->algorithm->hmac_update(
437 		tsig->context,
438 		buffer_at(packet, sizeof(original_query_id)),
439 		length - sizeof(original_query_id));
440 	if (QR(packet)) {
441 		++tsig->response_count;
442 	}
443 
444 	++tsig->updates_since_last_prepare;
445 }
446 
447 void
448 tsig_sign(tsig_record_type *tsig)
449 {
450 	uint64_t current_time = (uint64_t) time(NULL);
451 	tsig->signed_time_high = (uint16_t) (current_time >> 32);
452 	tsig->signed_time_low = (uint32_t) current_time;
453 	tsig->signed_time_fudge = 300; /* XXX; hardcoded value */
454 
455 	tsig_digest_variables(tsig, tsig->response_count > 1);
456 
457 	tsig->algorithm->hmac_final(tsig->context,
458 				    tsig->prior_mac_data,
459 				    &tsig->prior_mac_size);
460 
461 	tsig->mac_size = tsig->prior_mac_size;
462 	tsig->mac_data = tsig->prior_mac_data;
463 }
464 
465 int
466 tsig_verify(tsig_record_type *tsig)
467 {
468 	tsig_digest_variables(tsig, tsig->response_count > 1);
469 
470 	tsig->algorithm->hmac_final(tsig->context,
471 				    tsig->prior_mac_data,
472 				    &tsig->prior_mac_size);
473 
474 	if (tsig->mac_size != tsig->prior_mac_size
475 	    || memcmp(tsig->mac_data,
476 		      tsig->prior_mac_data,
477 		      tsig->mac_size) != 0)
478 	{
479 		/* Digest is incorrect, cannot authenticate.  */
480 		tsig->error_code = TSIG_ERROR_BADSIG;
481 		return 0;
482 	} else {
483 		return 1;
484 	}
485 }
486 
487 int
488 tsig_find_rr(tsig_record_type *tsig, buffer_type *packet)
489 {
490 	size_t saved_position = buffer_position(packet);
491 	size_t rrcount = (QDCOUNT(packet)
492 			  + ANCOUNT(packet)
493 			  + NSCOUNT(packet)
494 			  + ARCOUNT(packet));
495 	size_t i;
496 	int result;
497 
498 	if (ARCOUNT(packet) == 0) {
499 		tsig->status = TSIG_NOT_PRESENT;
500 		return 1;
501 	}
502 
503 	buffer_set_position(packet, QHEADERSZ);
504 
505 	/* TSIG must be the last record, so skip all others. */
506 	for (i = 0; i < rrcount - 1; ++i) {
507 		if (!packet_skip_rr(packet, i < QDCOUNT(packet))) {
508 			buffer_set_position(packet, saved_position);
509 			return 0;
510 		}
511 	}
512 
513 	result = tsig_parse_rr(tsig, packet);
514 	buffer_set_position(packet, saved_position);
515 	return result;
516 }
517 
518 int
519 tsig_parse_rr(tsig_record_type *tsig, buffer_type *packet)
520 {
521 	uint16_t type;
522 	uint16_t klass;
523 	uint32_t ttl;
524 	uint16_t rdlen;
525 
526 	tsig->status = TSIG_NOT_PRESENT;
527 	tsig->position = buffer_position(packet);
528 	tsig->key_name = NULL;
529 	tsig->algorithm_name = NULL;
530 	tsig->mac_data = NULL;
531 	tsig->other_data = NULL;
532 	region_free_all(tsig->rr_region);
533 
534 	tsig->key_name = dname_make_from_packet(tsig->rr_region, packet, 1, 1);
535 	if (!tsig->key_name) {
536 		buffer_set_position(packet, tsig->position);
537 		return 0;
538 	}
539 
540 	if (!buffer_available(packet, 10)) {
541 		buffer_set_position(packet, tsig->position);
542 		return 0;
543 	}
544 
545 	type = buffer_read_u16(packet);
546 	klass = buffer_read_u16(packet);
547 
548 	/* TSIG not present */
549 	if (type != TYPE_TSIG || klass != CLASS_ANY) {
550 		buffer_set_position(packet, tsig->position);
551 		return 1;
552 	}
553 
554 	ttl = buffer_read_u32(packet);
555 	rdlen = buffer_read_u16(packet);
556 
557 	tsig->status = TSIG_ERROR;
558 	tsig->error_code = RCODE_FORMAT;
559 	if (ttl != 0 || !buffer_available(packet, rdlen)) {
560 		buffer_set_position(packet, tsig->position);
561 		return 0;
562 	}
563 
564 	tsig->algorithm_name = dname_make_from_packet(
565 		tsig->rr_region, packet, 1, 1);
566 	if (!tsig->algorithm_name || !buffer_available(packet, 10)) {
567 		buffer_set_position(packet, tsig->position);
568 		return 0;
569 	}
570 
571 	tsig->signed_time_high = buffer_read_u16(packet);
572 	tsig->signed_time_low = buffer_read_u32(packet);
573 	tsig->signed_time_fudge = buffer_read_u16(packet);
574 	tsig->mac_size = buffer_read_u16(packet);
575 	if (!buffer_available(packet, tsig->mac_size)) {
576 		buffer_set_position(packet, tsig->position);
577 		tsig->mac_size = 0;
578 		return 0;
579 	}
580 	tsig->mac_data = (uint8_t *) region_alloc_init(
581 		tsig->rr_region, buffer_current(packet), tsig->mac_size);
582 	buffer_skip(packet, tsig->mac_size);
583 	if (!buffer_available(packet, 6)) {
584 		buffer_set_position(packet, tsig->position);
585 		return 0;
586 	}
587 	tsig->original_query_id = buffer_read_u16(packet);
588 	tsig->error_code = buffer_read_u16(packet);
589 	tsig->other_size = buffer_read_u16(packet);
590 	if (!buffer_available(packet, tsig->other_size) || tsig->other_size > 16) {
591 		tsig->other_size = 0;
592 		buffer_set_position(packet, tsig->position);
593 		return 0;
594 	}
595 	tsig->other_data = (uint8_t *) region_alloc_init(
596 		tsig->rr_region, buffer_current(packet), tsig->other_size);
597 	buffer_skip(packet, tsig->other_size);
598 	tsig->status = TSIG_OK;
599 	return 1;
600 }
601 
602 void
603 tsig_append_rr(tsig_record_type *tsig, buffer_type *packet)
604 {
605 	size_t rdlength_pos;
606 
607 	/* XXX: TODO key name compression? */
608 	if(tsig->key_name)
609 		buffer_write(packet, dname_name(tsig->key_name),
610 		     tsig->key_name->name_size);
611 	else	buffer_write_u8(packet, 0);
612 	buffer_write_u16(packet, TYPE_TSIG);
613 	buffer_write_u16(packet, CLASS_ANY);
614 	buffer_write_u32(packet, 0); /* TTL */
615 	rdlength_pos = buffer_position(packet);
616 	buffer_skip(packet, sizeof(uint16_t));
617 	if(tsig->algorithm_name)
618 		buffer_write(packet, dname_name(tsig->algorithm_name),
619 		     tsig->algorithm_name->name_size);
620 	else 	buffer_write_u8(packet, 0);
621 	buffer_write_u16(packet, tsig->signed_time_high);
622 	buffer_write_u32(packet, tsig->signed_time_low);
623 	buffer_write_u16(packet, tsig->signed_time_fudge);
624 	buffer_write_u16(packet, tsig->mac_size);
625 	buffer_write(packet, tsig->mac_data, tsig->mac_size);
626 	buffer_write_u16(packet, tsig->original_query_id);
627 	buffer_write_u16(packet, tsig->error_code);
628 	buffer_write_u16(packet, tsig->other_size);
629 	buffer_write(packet, tsig->other_data, tsig->other_size);
630 
631 	buffer_write_u16_at(packet, rdlength_pos,
632 			    buffer_position(packet) - rdlength_pos
633 			    - sizeof(uint16_t));
634 }
635 
636 size_t
637 tsig_reserved_space(tsig_record_type *tsig)
638 {
639 	if (tsig->status == TSIG_NOT_PRESENT)
640 		return 0;
641 
642 	return (
643 		(tsig->key_name?tsig->key_name->name_size:1)   /* Owner */
644 		+ sizeof(uint16_t)	    /* Type */
645 		+ sizeof(uint16_t)	    /* Class */
646 		+ sizeof(uint32_t)	    /* TTL */
647 		+ sizeof(uint16_t)	    /* RDATA length */
648 		+ (tsig->algorithm_name?tsig->algorithm_name->name_size:1)
649 		+ sizeof(uint16_t)	    /* Signed time (high) */
650 		+ sizeof(uint32_t)	    /* Signed time (low) */
651 		+ sizeof(uint16_t)	    /* Signed time fudge */
652 		+ sizeof(uint16_t)	    /* MAC size */
653 		+ max_algo_digest_size 	    /* MAC data */
654 		+ sizeof(uint16_t)	    /* Original query ID */
655 		+ sizeof(uint16_t)	    /* Error code */
656 		+ sizeof(uint16_t)	    /* Other size */
657 		+ tsig->other_size);	    /* Other data */
658 }
659 
660 void
661 tsig_error_reply(tsig_record_type *tsig)
662 {
663 	if(tsig->mac_data)
664 		memset(tsig->mac_data, 0, tsig->mac_size);
665 	tsig->mac_size = 0;
666 }
667 
668 void
669 tsig_finalize()
670 {
671 #if defined(HAVE_SSL)
672 	tsig_openssl_finalize();
673 #endif /* defined(HAVE_SSL) */
674 }
675