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