xref: /netbsd-src/external/bsd/nsd/dist/tsig.c (revision bdc22b2e01993381dcefeff2bc9b56ca75a4235c)
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_type node; /* by dname */
27 	tsig_key_type *key;
28 };
29 typedef struct tsig_key_table tsig_key_table_type;
30 static rbtree_type *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 		if(strncmp("hmac-", algorithm_entry->algorithm->short_name, 5) == 0 && tsig_strlowercmp(name, algorithm_entry->algorithm->short_name+5) == 0) {
196 			return algorithm_entry->algorithm;
197 		}
198 	}
199 
200 	return NULL;
201 }
202 
203 
204 const char *
205 tsig_error(int error_code)
206 {
207 	static char message[1000];
208 
209 	switch (error_code) {
210 	case TSIG_ERROR_NOERROR:
211 		return "No Error";
212 		break;
213 	case TSIG_ERROR_BADSIG:
214 		return "Bad Signature";
215 		break;
216 	case TSIG_ERROR_BADKEY:
217 		return "Bad Key";
218 		break;
219 	case TSIG_ERROR_BADTIME:
220 		return "Bad Time";
221 		break;
222 	default:
223 		if(error_code < 16) /* DNS rcodes */
224 			return rcode2str(error_code);
225 
226 		snprintf(message, sizeof(message),
227 			 "Unknown Error %d", error_code);
228 		break;
229 	}
230 	return message;
231 }
232 
233 static void
234 tsig_cleanup(void *data)
235 {
236 	tsig_record_type *tsig = (tsig_record_type *) data;
237 	region_destroy(tsig->rr_region);
238 	region_destroy(tsig->context_region);
239 }
240 
241 void
242 tsig_create_record(tsig_record_type *tsig, region_type *region)
243 {
244 	tsig_create_record_custom(tsig, region, DEFAULT_CHUNK_SIZE,
245 		DEFAULT_LARGE_OBJECT_SIZE, DEFAULT_INITIAL_CLEANUP_SIZE);
246 }
247 
248 void
249 tsig_create_record_custom(tsig_record_type *tsig, region_type *region,
250 	size_t chunk_size, size_t large_object_size, size_t initial_cleanup_size)
251 {
252 	tsig->rr_region = region_create_custom(xalloc, free, chunk_size,
253 		large_object_size, initial_cleanup_size, 0);
254 	tsig->context_region = region_create_custom(xalloc, free, chunk_size,
255 		large_object_size, initial_cleanup_size, 0);
256 	if(region)
257 		region_add_cleanup(region, tsig_cleanup, tsig);
258 	tsig_init_record(tsig, NULL, NULL);
259 }
260 
261 void
262 tsig_delete_record(tsig_record_type* tsig, region_type* region)
263 {
264 	if(region)
265 		region_remove_cleanup(region, tsig_cleanup, tsig);
266 	region_destroy(tsig->rr_region);
267 	region_destroy(tsig->context_region);
268 }
269 
270 void
271 tsig_init_record(tsig_record_type *tsig,
272 		 tsig_algorithm_type *algorithm,
273 		 tsig_key_type *key)
274 {
275 	tsig->status = TSIG_NOT_PRESENT;
276 	tsig->error_code = TSIG_ERROR_NOERROR;
277 	tsig->position = 0;
278 	tsig->response_count = 0;
279 	tsig->context = NULL;
280 	tsig->algorithm = algorithm;
281 	tsig->key = key;
282 	tsig->prior_mac_size = 0;
283 	tsig->prior_mac_data = NULL;
284 	region_free_all(tsig->context_region);
285 }
286 
287 int
288 tsig_from_query(tsig_record_type *tsig)
289 {
290 	tsig_key_type *key = NULL;
291 	tsig_algorithm_table_type *algorithm_entry;
292 	tsig_algorithm_type *algorithm = NULL;
293 	uint64_t current_time;
294 	uint64_t signed_time;
295 
296 	assert(tsig->status == TSIG_OK);
297 	assert(!tsig->algorithm);
298 	assert(!tsig->key);
299 
300 	key = (tsig_key_type*)tsig_find_key(tsig->key_name);
301 
302 	for (algorithm_entry = tsig_algorithm_table;
303 	     algorithm_entry;
304 	     algorithm_entry = algorithm_entry->next)
305 	{
306 		if (dname_compare(
307 			    tsig->algorithm_name,
308 			    algorithm_entry->algorithm->wireformat_name) == 0)
309 		{
310 			algorithm = algorithm_entry->algorithm;
311 			break;
312 		}
313 	}
314 
315 	if (!algorithm || !key) {
316 		/* Algorithm or key is unknown, cannot authenticate.  */
317 		tsig->error_code = TSIG_ERROR_BADKEY;
318 		return 0;
319 	}
320 
321 	if ((tsig->algorithm && algorithm != tsig->algorithm)
322 	    || (tsig->key && key != tsig->key))
323 	{
324 		/*
325 		 * Algorithm or key changed during a single connection,
326 		 * return error.
327 		 */
328 		tsig->error_code = TSIG_ERROR_BADKEY;
329 		return 0;
330 	}
331 
332 	signed_time = ((((uint64_t) tsig->signed_time_high) << 32) |
333 		       ((uint64_t) tsig->signed_time_low));
334 
335 	current_time = (uint64_t) time(NULL);
336 	if ((current_time < signed_time - tsig->signed_time_fudge)
337 	    || (current_time > signed_time + tsig->signed_time_fudge))
338 	{
339 		uint16_t current_time_high;
340 		uint32_t current_time_low;
341 
342 #if 0 /* debug */
343 		char current_time_text[26];
344 		char signed_time_text[26];
345 		time_t clock;
346 
347 		clock = (time_t) current_time;
348 		ctime_r(&clock, current_time_text);
349 		current_time_text[24] = '\0';
350 
351 		clock = (time_t) signed_time;
352 		ctime_r(&clock, signed_time_text);
353 		signed_time_text[24] = '\0';
354 
355 		log_msg(LOG_ERR,
356 			"current server time %s is outside the range of TSIG"
357 			" signed time %s with fudge %u",
358 			current_time_text,
359 			signed_time_text,
360 			(unsigned) tsig->signed_time_fudge);
361 #endif
362 
363 		tsig->error_code = TSIG_ERROR_BADTIME;
364 		current_time_high = (uint16_t) (current_time >> 32);
365 		current_time_low = (uint32_t) current_time;
366 		tsig->other_size = 6;
367 		tsig->other_data = (uint8_t *) region_alloc(
368 			tsig->rr_region, sizeof(uint16_t) + sizeof(uint32_t));
369 		write_uint16(tsig->other_data, current_time_high);
370 		write_uint32(tsig->other_data + 2, current_time_low);
371 		return 0;
372 	}
373 
374 	tsig->algorithm = algorithm;
375 	tsig->key = key;
376 	tsig->response_count = 0;
377 	tsig->prior_mac_size = 0;
378 
379 	return 1;
380 }
381 
382 void
383 tsig_init_query(tsig_record_type *tsig, uint16_t original_query_id)
384 {
385 	assert(tsig);
386 	assert(tsig->algorithm);
387 	assert(tsig->key);
388 
389 	tsig->response_count = 0;
390 	tsig->prior_mac_size = 0;
391 	tsig->algorithm_name = tsig->algorithm->wireformat_name;
392 	tsig->key_name = tsig->key->name;
393 	tsig->mac_size = 0;
394 	tsig->mac_data = NULL;
395 	tsig->original_query_id = original_query_id;
396 	tsig->error_code = TSIG_ERROR_NOERROR;
397 	tsig->other_size = 0;
398 	tsig->other_data = NULL;
399 }
400 
401 void
402 tsig_prepare(tsig_record_type *tsig)
403 {
404 	if (!tsig->context) {
405 		assert(tsig->algorithm);
406 		tsig->context = tsig->algorithm->hmac_create_context(
407 			tsig->context_region);
408 		tsig->prior_mac_data = (uint8_t *) region_alloc(
409 			tsig->context_region,
410 			tsig->algorithm->maximum_digest_size);
411 	}
412 	tsig->algorithm->hmac_init_context(tsig->context,
413 					   tsig->algorithm,
414 					   tsig->key);
415 
416 	if (tsig->prior_mac_size > 0) {
417 		uint16_t mac_size = htons(tsig->prior_mac_size);
418 		tsig->algorithm->hmac_update(tsig->context,
419 					     &mac_size,
420 					     sizeof(mac_size));
421 		tsig->algorithm->hmac_update(tsig->context,
422 					     tsig->prior_mac_data,
423 					     tsig->prior_mac_size);
424 	}
425 
426 	tsig->updates_since_last_prepare = 0;
427 }
428 
429 void
430 tsig_update(tsig_record_type *tsig, buffer_type *packet, size_t length)
431 {
432 	uint16_t original_query_id = htons(tsig->original_query_id);
433 
434 	assert(length <= buffer_limit(packet));
435 
436 	tsig->algorithm->hmac_update(tsig->context,
437 				     &original_query_id,
438 				     sizeof(original_query_id));
439 	tsig->algorithm->hmac_update(
440 		tsig->context,
441 		buffer_at(packet, sizeof(original_query_id)),
442 		length - sizeof(original_query_id));
443 	if (QR(packet)) {
444 		++tsig->response_count;
445 	}
446 
447 	++tsig->updates_since_last_prepare;
448 }
449 
450 void
451 tsig_sign(tsig_record_type *tsig)
452 {
453 	uint64_t current_time = (uint64_t) time(NULL);
454 	tsig->signed_time_high = (uint16_t) (current_time >> 32);
455 	tsig->signed_time_low = (uint32_t) current_time;
456 	tsig->signed_time_fudge = 300; /* XXX; hardcoded value */
457 
458 	tsig_digest_variables(tsig, tsig->response_count > 1);
459 
460 	tsig->algorithm->hmac_final(tsig->context,
461 				    tsig->prior_mac_data,
462 				    &tsig->prior_mac_size);
463 
464 	tsig->mac_size = tsig->prior_mac_size;
465 	tsig->mac_data = tsig->prior_mac_data;
466 }
467 
468 int
469 tsig_verify(tsig_record_type *tsig)
470 {
471 	tsig_digest_variables(tsig, tsig->response_count > 1);
472 
473 	tsig->algorithm->hmac_final(tsig->context,
474 				    tsig->prior_mac_data,
475 				    &tsig->prior_mac_size);
476 
477 	if (tsig->mac_size != tsig->prior_mac_size
478 	    || memcmp(tsig->mac_data,
479 		      tsig->prior_mac_data,
480 		      tsig->mac_size) != 0)
481 	{
482 		/* Digest is incorrect, cannot authenticate.  */
483 		tsig->error_code = TSIG_ERROR_BADSIG;
484 		return 0;
485 	} else {
486 		return 1;
487 	}
488 }
489 
490 int
491 tsig_find_rr(tsig_record_type *tsig, buffer_type *packet)
492 {
493 	size_t saved_position = buffer_position(packet);
494 	size_t rrcount = (QDCOUNT(packet)
495 			  + ANCOUNT(packet)
496 			  + NSCOUNT(packet)
497 			  + ARCOUNT(packet));
498 	size_t i;
499 	int result;
500 
501 	if (ARCOUNT(packet) == 0) {
502 		tsig->status = TSIG_NOT_PRESENT;
503 		return 1;
504 	}
505 
506 	buffer_set_position(packet, QHEADERSZ);
507 
508 	/* TSIG must be the last record, so skip all others. */
509 	for (i = 0; i < rrcount - 1; ++i) {
510 		if (!packet_skip_rr(packet, i < QDCOUNT(packet))) {
511 			buffer_set_position(packet, saved_position);
512 			return 0;
513 		}
514 	}
515 
516 	result = tsig_parse_rr(tsig, packet);
517 	buffer_set_position(packet, saved_position);
518 	return result;
519 }
520 
521 int
522 tsig_parse_rr(tsig_record_type *tsig, buffer_type *packet)
523 {
524 	uint16_t type;
525 	uint16_t klass;
526 	uint32_t ttl;
527 	uint16_t rdlen;
528 
529 	tsig->status = TSIG_NOT_PRESENT;
530 	tsig->position = buffer_position(packet);
531 	tsig->key_name = NULL;
532 	tsig->algorithm_name = NULL;
533 	tsig->mac_data = NULL;
534 	tsig->other_data = NULL;
535 	region_free_all(tsig->rr_region);
536 
537 	tsig->key_name = dname_make_from_packet(tsig->rr_region, packet, 1, 1);
538 	if (!tsig->key_name) {
539 		buffer_set_position(packet, tsig->position);
540 		return 0;
541 	}
542 
543 	if (!buffer_available(packet, 10)) {
544 		buffer_set_position(packet, tsig->position);
545 		return 0;
546 	}
547 
548 	type = buffer_read_u16(packet);
549 	klass = buffer_read_u16(packet);
550 
551 	/* TSIG not present */
552 	if (type != TYPE_TSIG || klass != CLASS_ANY) {
553 		buffer_set_position(packet, tsig->position);
554 		return 1;
555 	}
556 
557 	ttl = buffer_read_u32(packet);
558 	rdlen = buffer_read_u16(packet);
559 
560 	tsig->status = TSIG_ERROR;
561 	tsig->error_code = RCODE_FORMAT;
562 	if (ttl != 0 || !buffer_available(packet, rdlen)) {
563 		buffer_set_position(packet, tsig->position);
564 		return 0;
565 	}
566 
567 	tsig->algorithm_name = dname_make_from_packet(
568 		tsig->rr_region, packet, 1, 1);
569 	if (!tsig->algorithm_name || !buffer_available(packet, 10)) {
570 		buffer_set_position(packet, tsig->position);
571 		return 0;
572 	}
573 
574 	tsig->signed_time_high = buffer_read_u16(packet);
575 	tsig->signed_time_low = buffer_read_u32(packet);
576 	tsig->signed_time_fudge = buffer_read_u16(packet);
577 	tsig->mac_size = buffer_read_u16(packet);
578 	if (!buffer_available(packet, tsig->mac_size)) {
579 		buffer_set_position(packet, tsig->position);
580 		tsig->mac_size = 0;
581 		return 0;
582 	}
583 	tsig->mac_data = (uint8_t *) region_alloc_init(
584 		tsig->rr_region, buffer_current(packet), tsig->mac_size);
585 	buffer_skip(packet, tsig->mac_size);
586 	if (!buffer_available(packet, 6)) {
587 		buffer_set_position(packet, tsig->position);
588 		return 0;
589 	}
590 	tsig->original_query_id = buffer_read_u16(packet);
591 	tsig->error_code = buffer_read_u16(packet);
592 	tsig->other_size = buffer_read_u16(packet);
593 	if (!buffer_available(packet, tsig->other_size) || tsig->other_size > 16) {
594 		tsig->other_size = 0;
595 		buffer_set_position(packet, tsig->position);
596 		return 0;
597 	}
598 	tsig->other_data = (uint8_t *) region_alloc_init(
599 		tsig->rr_region, buffer_current(packet), tsig->other_size);
600 	buffer_skip(packet, tsig->other_size);
601 	tsig->status = TSIG_OK;
602 	return 1;
603 }
604 
605 void
606 tsig_append_rr(tsig_record_type *tsig, buffer_type *packet)
607 {
608 	size_t rdlength_pos;
609 
610 	/* XXX: TODO key name compression? */
611 	if(tsig->key_name)
612 		buffer_write(packet, dname_name(tsig->key_name),
613 		     tsig->key_name->name_size);
614 	else	buffer_write_u8(packet, 0);
615 	buffer_write_u16(packet, TYPE_TSIG);
616 	buffer_write_u16(packet, CLASS_ANY);
617 	buffer_write_u32(packet, 0); /* TTL */
618 	rdlength_pos = buffer_position(packet);
619 	buffer_skip(packet, sizeof(uint16_t));
620 	if(tsig->algorithm_name)
621 		buffer_write(packet, dname_name(tsig->algorithm_name),
622 		     tsig->algorithm_name->name_size);
623 	else 	buffer_write_u8(packet, 0);
624 	buffer_write_u16(packet, tsig->signed_time_high);
625 	buffer_write_u32(packet, tsig->signed_time_low);
626 	buffer_write_u16(packet, tsig->signed_time_fudge);
627 	buffer_write_u16(packet, tsig->mac_size);
628 	buffer_write(packet, tsig->mac_data, tsig->mac_size);
629 	buffer_write_u16(packet, tsig->original_query_id);
630 	buffer_write_u16(packet, tsig->error_code);
631 	buffer_write_u16(packet, tsig->other_size);
632 	buffer_write(packet, tsig->other_data, tsig->other_size);
633 
634 	buffer_write_u16_at(packet, rdlength_pos,
635 			    buffer_position(packet) - rdlength_pos
636 			    - sizeof(uint16_t));
637 }
638 
639 size_t
640 tsig_reserved_space(tsig_record_type *tsig)
641 {
642 	if (tsig->status == TSIG_NOT_PRESENT)
643 		return 0;
644 
645 	return (
646 		(tsig->key_name?tsig->key_name->name_size:1)   /* Owner */
647 		+ sizeof(uint16_t)	    /* Type */
648 		+ sizeof(uint16_t)	    /* Class */
649 		+ sizeof(uint32_t)	    /* TTL */
650 		+ sizeof(uint16_t)	    /* RDATA length */
651 		+ (tsig->algorithm_name?tsig->algorithm_name->name_size:1)
652 		+ sizeof(uint16_t)	    /* Signed time (high) */
653 		+ sizeof(uint32_t)	    /* Signed time (low) */
654 		+ sizeof(uint16_t)	    /* Signed time fudge */
655 		+ sizeof(uint16_t)	    /* MAC size */
656 		+ max_algo_digest_size 	    /* MAC data */
657 		+ sizeof(uint16_t)	    /* Original query ID */
658 		+ sizeof(uint16_t)	    /* Error code */
659 		+ sizeof(uint16_t)	    /* Other size */
660 		+ tsig->other_size);	    /* Other data */
661 }
662 
663 void
664 tsig_error_reply(tsig_record_type *tsig)
665 {
666 	if(tsig->mac_data)
667 		memset(tsig->mac_data, 0, tsig->mac_size);
668 	tsig->mac_size = 0;
669 }
670 
671 void
672 tsig_finalize()
673 {
674 #if defined(HAVE_SSL)
675 	tsig_openssl_finalize();
676 #endif /* defined(HAVE_SSL) */
677 }
678