xref: /netbsd-src/external/bsd/ntp/dist/libntp/authkeys.c (revision 3117ece4fc4a4ca4489ba793710b60b0d26bab6c)
1 /*	$NetBSD: authkeys.c,v 1.14 2024/08/18 20:47:13 christos Exp $	*/
2 
3 /*
4  * authkeys.c - routines to manage the storage of authentication keys
5  */
6 #ifdef HAVE_CONFIG_H
7 # include <config.h>
8 #endif
9 
10 #include <math.h>
11 #include <stdio.h>
12 
13 #include "ntp.h"
14 #include "ntp_fp.h"
15 #include "ntpd.h"
16 #include "ntp_lists.h"
17 #include "ntp_string.h"
18 #include "ntp_malloc.h"
19 #include "ntp_stdlib.h"
20 #include "ntp_keyacc.h"
21 
22 /*
23  * Structure to store keys in in the hash table.
24  */
25 typedef struct savekey symkey;
26 
27 struct savekey {
28 	symkey *	hlink;		/* next in hash bucket */
29 	DECL_DLIST_LINK(symkey, llink);	/* for overall & free lists */
30 	u_char *	secret;		/* shared secret */
31 	KeyAccT *	keyacclist;	/* Private key access list */
32 	u_long		lifetime;	/* remaining lifetime */
33 	keyid_t		keyid;		/* key identifier */
34 	u_short		type;		/* OpenSSL digest NID */
35 	size_t		secretsize;	/* secret octets */
36 	u_short		flags;		/* KEY_ flags that wave */
37 };
38 
39 /* define the payload region of symkey beyond the list pointers */
40 #define symkey_payload	secret
41 
42 #define	KEY_TRUSTED	0x001	/* this key is trusted */
43 
44 #ifdef DEBUG
45 typedef struct symkey_alloc_tag symkey_alloc;
46 
47 struct symkey_alloc_tag {
48 	symkey_alloc *	link;
49 	void *		mem;		/* enable free() atexit */
50 };
51 
52 symkey_alloc *	authallocs;
53 #endif	/* DEBUG */
54 
55 static u_short	auth_log2(size_t);
56 static void		auth_resize_hashtable(void);
57 static void		allocsymkey(keyid_t,	u_short,
58 				    u_short, u_long, size_t, u_char *, KeyAccT *);
59 static void		freesymkey(symkey *);
60 #ifdef DEBUG
61 static void		free_auth_mem(void);
62 #endif
63 
64 symkey	key_listhead;		/* list of all in-use keys */;
65 /*
66  * The hash table. This is indexed by the low order bits of the
67  * keyid. We make this fairly big for potentially busy servers.
68  */
69 #define	DEF_AUTHHASHSIZE	64
70 /*#define	HASHMASK	((HASHSIZE)-1)*/
71 #define	KEYHASH(keyid)	((keyid) & authhashmask)
72 
73 int	authhashdisabled;
74 u_short	authhashbuckets = DEF_AUTHHASHSIZE;
75 u_short authhashmask = DEF_AUTHHASHSIZE - 1;
76 symkey **key_hash;
77 
78 u_long authkeynotfound;		/* keys not found */
79 u_long authkeylookups;		/* calls to lookup keys */
80 u_long authnumkeys;		/* number of active keys */
81 u_long authkeyexpired;		/* key lifetime expirations */
82 u_long authkeyuncached;		/* cache misses */
83 u_long authnokey;		/* calls to encrypt with no key */
84 u_long authencryptions;		/* calls to encrypt */
85 u_long authdecryptions;		/* calls to decrypt */
86 
87 /*
88  * Storage for free symkey structures.  We malloc() such things but
89  * never free them.
90  */
91 symkey *authfreekeys;
92 int authnumfreekeys;
93 
94 #define	MEMINC	16		/* number of new free ones to get */
95 
96 /*
97  * The key cache. We cache the last key we looked at here.
98  * Note: this should hold the last *trusted* key. Also the
99  * cache is only loaded when the digest type / MAC algorithm
100  * is valid.
101  */
102 keyid_t	cache_keyid;		/* key identifier */
103 u_char *cache_secret;		/* secret */
104 size_t	cache_secretsize;	/* secret length */
105 int	cache_type;		/* OpenSSL digest NID */
106 u_short cache_flags;		/* flags that wave */
107 KeyAccT *cache_keyacclist;	/* key access list */
108 
109 /* --------------------------------------------------------------------
110  * manage key access lists
111  * --------------------------------------------------------------------
112  */
113 /* allocate and populate new access node and pushes it on the list.
114  * Returns the new head.
115  */
116 KeyAccT*
117 keyacc_new_push(
118 	KeyAccT          * head,
119 	const sockaddr_u * addr,
120 	unsigned int	   subnetbits
121 	)
122 {
123 	KeyAccT *	node = emalloc(sizeof(KeyAccT));
124 
125 	memcpy(&node->addr, addr, sizeof(sockaddr_u));
126 	node->subnetbits = subnetbits;
127 	node->next = head;
128 
129 	return node;
130 }
131 
132 /* ----------------------------------------------------------------- */
133 /* pop and deallocate the first node of a list of access nodes, if
134  * the list is not empty. Returns the tail of the list.
135  */
136 KeyAccT*
137 keyacc_pop_free(
138 	KeyAccT *head
139 	)
140 {
141 	KeyAccT *	next = NULL;
142 	if (head) {
143 		next = head->next;
144 		free(head);
145 	}
146 	return next;
147 }
148 
149 /* ----------------------------------------------------------------- */
150 /* deallocate the list; returns an empty list. */
151 KeyAccT*
152 keyacc_all_free(
153 	KeyAccT * head
154 	)
155 {
156 	while (head)
157 		head = keyacc_pop_free(head);
158 	return head;
159 }
160 
161 /* ----------------------------------------------------------------- */
162 /* scan a list to see if it contains a given address. Return the
163  * default result value in case of an empty list.
164  */
165 int /*BOOL*/
166 keyacc_contains(
167 	const KeyAccT    *head,
168 	const sockaddr_u *addr,
169 	int               defv)
170 {
171 	if (head) {
172 		do {
173 			if (keyacc_amatch(&head->addr, addr,
174 					  head->subnetbits))
175 				return TRUE;
176 		} while (NULL != (head = head->next));
177 		return FALSE;
178 	} else {
179 		return !!defv;
180 	}
181 }
182 
183 #if CHAR_BIT != 8
184 # error "don't know how to handle bytes with that bit size"
185 #endif
186 
187 /* ----------------------------------------------------------------- */
188 /* check two addresses for a match, taking a prefix length into account
189  * when doing the compare.
190  *
191  * The ISC lib contains a similar function with not entirely specified
192  * semantics, so it seemed somewhat cleaner to do this from scratch.
193  *
194  * Note 1: It *is* assumed that the addresses are stored in network byte
195  * order, that is, most significant byte first!
196  *
197  * Note 2: "no address" compares unequal to all other addresses, even to
198  * itself. This has the same semantics as NaNs have for floats: *any*
199  * relational or equality operation involving a NaN returns FALSE, even
200  * equality with itself. "no address" is either a NULL pointer argument
201  * or an address of type AF_UNSPEC.
202  */
203 int/*BOOL*/
204 keyacc_amatch(
205 	const sockaddr_u *	a1,
206 	const sockaddr_u *	a2,
207 	unsigned int		mbits
208 	)
209 {
210 	const uint8_t * pm1;
211 	const uint8_t * pm2;
212 	uint8_t         msk;
213 	unsigned int    len;
214 
215 	/* 1st check: If any address is not an address, it's inequal. */
216 	if ( !a1 || (AF_UNSPEC == AF(a1)) ||
217 	     !a2 || (AF_UNSPEC == AF(a2))  )
218 		return FALSE;
219 
220 	/* We could check pointers for equality here and shortcut the
221 	 * other checks if we find object identity. But that use case is
222 	 * too rare to care for it.
223 	 */
224 
225 	/* 2nd check: Address families must be the same. */
226 	if (AF(a1) != AF(a2))
227 		return FALSE;
228 
229 	/* type check: address family determines buffer & size */
230 	switch (AF(a1)) {
231 	case AF_INET:
232 		/* IPv4 is easy: clamp size, get byte pointers */
233 		if (mbits > sizeof(NSRCADR(a1)) * 8)
234 			mbits = sizeof(NSRCADR(a1)) * 8;
235 		pm1 = (const void*)&NSRCADR(a1);
236 		pm2 = (const void*)&NSRCADR(a2);
237 		break;
238 
239 	case AF_INET6:
240 		/* IPv6 is slightly different: Both scopes must match,
241 		 * too, before we even consider doing a match!
242 		 */
243 		if ( ! SCOPE_EQ(a1, a2))
244 			return FALSE;
245 		if (mbits > sizeof(NSRCADR6(a1)) * 8)
246 			mbits = sizeof(NSRCADR6(a1)) * 8;
247 		pm1 = (const void*)&NSRCADR6(a1);
248 		pm2 = (const void*)&NSRCADR6(a2);
249 		break;
250 
251 	default:
252 		/* don't know how to compare that!?! */
253 		return FALSE;
254 	}
255 
256 	/* Split bit length into byte length and partial byte mask.
257 	 * Note that the byte mask extends from the MSB of a byte down,
258 	 * and that zero shift (--> mbits % 8 == 0) results in an
259 	 * all-zero mask.
260 	 */
261 	msk = 0xFFu ^ (0xFFu >> (mbits & 7));
262 	len = mbits >> 3;
263 
264 	/* 3rd check: Do memcmp() over full bytes, if any */
265 	if (len && memcmp(pm1, pm2, len))
266 		return FALSE;
267 
268 	/* 4th check: compare last incomplete byte, if any */
269 	if (msk && ((pm1[len] ^ pm2[len]) & msk))
270 		return FALSE;
271 
272 	/* If none of the above failed, we're successfully through. */
273 	return TRUE;
274 }
275 
276 /*
277  * init_auth - initialize internal data
278  */
279 void
280 init_auth(void)
281 {
282 	size_t newalloc;
283 
284 	/*
285 	 * Initialize hash table and free list
286 	 */
287 	newalloc = authhashbuckets * sizeof(key_hash[0]);
288 
289 	key_hash = emalloc_zero(newalloc);
290 
291 	INIT_DLIST(key_listhead, llink);
292 
293 #ifdef DEBUG
294 	atexit(&free_auth_mem);
295 #endif
296 }
297 
298 
299 /*
300  * free_auth_mem - assist in leak detection by freeing all dynamic
301  *		   allocations from this module.
302  */
303 #ifdef DEBUG
304 static void
305 free_auth_mem(void)
306 {
307 	symkey *	sk;
308 	symkey_alloc *	alloc;
309 	symkey_alloc *	next_alloc;
310 
311 	while (NULL != (sk = HEAD_DLIST(key_listhead, llink))) {
312 		freesymkey(sk);
313 	}
314 	free(key_hash);
315 	key_hash = NULL;
316 	cache_keyid = 0;
317 	cache_flags = 0;
318 	cache_keyacclist = NULL;
319 	for (alloc = authallocs; alloc != NULL; alloc = next_alloc) {
320 		next_alloc = alloc->link;
321 		free(alloc->mem);
322 	}
323 	authfreekeys = NULL;
324 	authnumfreekeys = 0;
325 }
326 #endif	/* DEBUG */
327 
328 
329 /*
330  * auth_moremem - get some more free key structures
331  */
332 void
333 auth_moremem(
334 	int	keycount
335 	)
336 {
337 	symkey *	sk;
338 	int		i;
339 #ifdef DEBUG
340 	void *		base;
341 	symkey_alloc *	allocrec;
342 # define MOREMEM_EXTRA_ALLOC	(sizeof(*allocrec))
343 #else
344 # define MOREMEM_EXTRA_ALLOC	(0)
345 #endif
346 
347 	i = (keycount > 0)
348 		? keycount
349 		: MEMINC;
350 	sk = eallocarrayxz(i, sizeof(*sk), MOREMEM_EXTRA_ALLOC);
351 #ifdef DEBUG
352 	base = sk;
353 #endif
354 	authnumfreekeys += i;
355 
356 	for (; i > 0; i--, sk++) {
357 		LINK_SLIST(authfreekeys, sk, llink.f);
358 	}
359 
360 #ifdef DEBUG
361 	allocrec = (void *)sk;
362 	allocrec->mem = base;
363 	LINK_SLIST(authallocs, allocrec, link);
364 #endif
365 }
366 
367 
368 /*
369  * auth_prealloc_symkeys
370  */
371 void
372 auth_prealloc_symkeys(
373 	int	keycount
374 	)
375 {
376 	int	allocated;
377 	int	additional;
378 
379 	allocated = authnumkeys + authnumfreekeys;
380 	additional = keycount - allocated;
381 	if (additional > 0)
382 		auth_moremem(additional);
383 	auth_resize_hashtable();
384 }
385 
386 
387 static u_short
388 auth_log2(size_t x)
389 {
390 	/*
391 	** bithack to calculate floor(log2(x))
392 	**
393 	** This assumes
394 	**   - (sizeof(size_t) is a power of two
395 	**   - CHAR_BITS is a power of two
396 	**   - returning zero for arguments <= 0 is OK.
397 	**
398 	** Does only shifts, masks and sums in integer arithmetic in
399 	** log2(CHAR_BIT*sizeof(size_t)) steps. (that is, 5/6 steps for
400 	** 32bit/64bit size_t)
401 	*/
402 	int	s;
403 	int	r = 0;
404 	size_t  m = ~(size_t)0;
405 
406 	for (s = sizeof(size_t) / 2 * CHAR_BIT; s != 0; s >>= 1) {
407 		m <<= s;
408 		if (x & m)
409 			r += s;
410 		else
411 			x <<= s;
412 	}
413 	return (u_short)r;
414 }
415 
416 int/*BOOL*/
417 ipaddr_match_masked(const sockaddr_u *,const sockaddr_u *,
418 		    unsigned int mbits);
419 
420 static void
421 authcache_flush_id(
422 	keyid_t id
423 	)
424 {
425 	if (cache_keyid == id) {
426 		cache_keyid = 0;
427 		cache_type = 0;
428 		cache_flags = 0;
429 		cache_secret = NULL;
430 		cache_secretsize = 0;
431 		cache_keyacclist = NULL;
432 	}
433 }
434 
435 
436 /*
437  * auth_resize_hashtable
438  *
439  * Size hash table to average 4 or fewer entries per bucket initially,
440  * within the bounds of at least 4 and no more than 15 bits for the hash
441  * table index.  Populate the hash table.
442  */
443 static void
444 auth_resize_hashtable(void)
445 {
446 	u_long		totalkeys;
447 	u_short		hashbits;
448 	u_short		hash;
449 	size_t		newalloc;
450 	symkey *	sk;
451 
452 	totalkeys = authnumkeys + authnumfreekeys;
453 	hashbits = auth_log2(totalkeys / 4) + 1;
454 	hashbits = max(4, hashbits);
455 	hashbits = min(15, hashbits);
456 
457 	authhashbuckets = 1 << hashbits;
458 	authhashmask = authhashbuckets - 1;
459 	newalloc = authhashbuckets * sizeof(key_hash[0]);
460 
461 	key_hash = erealloc(key_hash, newalloc);
462 	zero_mem(key_hash, newalloc);
463 
464 	ITER_DLIST_BEGIN(key_listhead, sk, llink, symkey)
465 		hash = KEYHASH(sk->keyid);
466 		LINK_SLIST(key_hash[hash], sk, hlink);
467 	ITER_DLIST_END()
468 }
469 
470 
471 /*
472  * allocsymkey - common code to allocate and link in symkey
473  *
474  * secret must be allocated with a free-compatible allocator.  It is
475  * owned by the referring symkey structure, and will be free()d by
476  * freesymkey().
477  */
478 static void
479 allocsymkey(
480 	keyid_t		id,
481 	u_short		flags,
482 	u_short		type,
483 	u_long		lifetime,
484 	size_t		secretsize,
485 	u_char *	secret,
486 	KeyAccT *	ka
487 	)
488 {
489 	symkey *	sk;
490 	symkey **	bucket;
491 
492 	bucket = &key_hash[KEYHASH(id)];
493 
494 
495 	if (authnumfreekeys < 1)
496 		auth_moremem(-1);
497 	UNLINK_HEAD_SLIST(sk, authfreekeys, llink.f);
498 	DEBUG_ENSURE(sk != NULL);
499 	sk->keyid = id;
500 	sk->flags = flags;
501 	sk->type = type;
502 	sk->secretsize = secretsize;
503 	sk->secret = secret;
504 	sk->keyacclist = ka;
505 	sk->lifetime = lifetime;
506 	LINK_SLIST(*bucket, sk, hlink);
507 	LINK_TAIL_DLIST(key_listhead, sk, llink);
508 	authnumfreekeys--;
509 	authnumkeys++;
510 }
511 
512 
513 /*
514  * freesymkey - common code to remove a symkey and recycle its entry.
515  */
516 static void
517 freesymkey(
518 	symkey *	sk
519 	)
520 {
521 	symkey **	bucket;
522 	symkey *	unlinked;
523 
524 	if (NULL == sk)
525 		return;
526 
527 	authcache_flush_id(sk->keyid);
528 	keyacc_all_free(sk->keyacclist);
529 
530 	bucket = &key_hash[KEYHASH(sk->keyid)];
531 	if (sk->secret != NULL) {
532 		zero_mem(sk->secret, sk->secretsize);
533 		free(sk->secret);
534 	}
535 	UNLINK_SLIST(unlinked, *bucket, sk, hlink, symkey);
536 	DEBUG_ENSURE(sk == unlinked);
537 	UNLINK_DLIST(sk, llink);
538 	zero_mem((char *)sk + offsetof(symkey, symkey_payload),
539 		 sizeof(*sk) - offsetof(symkey, symkey_payload));
540 	LINK_SLIST(authfreekeys, sk, llink.f);
541 	authnumkeys--;
542 	authnumfreekeys++;
543 }
544 
545 
546 /*
547  * auth_findkey - find a key in the hash table
548  */
549 struct savekey *
550 auth_findkey(
551 	keyid_t		id
552 	)
553 {
554 	symkey *	sk;
555 
556 	for (sk = key_hash[KEYHASH(id)]; sk != NULL; sk = sk->hlink)
557 		if (id == sk->keyid)
558 			return sk;
559 	return NULL;
560 }
561 
562 
563 /*
564  * auth_havekey - return TRUE if the key id is zero or known. The
565  * key needs not to be trusted.
566  */
567 int
568 auth_havekey(
569 	keyid_t		id
570 	)
571 {
572 	return
573 	    (0           == id) ||
574 	    (cache_keyid == id) ||
575 	    (NULL        != auth_findkey(id));
576 }
577 
578 
579 /*
580  * authhavekey - return TRUE and cache the key, if zero or both known
581  *		 and trusted.
582  */
583 int
584 authhavekey(
585 	keyid_t		id
586 	)
587 {
588 	symkey *	sk;
589 
590 	authkeylookups++;
591 	if (0 == id || cache_keyid == id)
592 		return !!(KEY_TRUSTED & cache_flags);
593 
594 	/*
595 	 * Search the bin for the key. If not found, or found but the key
596 	 * type is zero, somebody marked it trusted without specifying a
597 	 * key or key type. In this case consider the key missing.
598 	 */
599 	authkeyuncached++;
600 	sk = auth_findkey(id);
601 	if ((sk == NULL) || (sk->type == 0)) {
602 		authkeynotfound++;
603 		return FALSE;
604 	}
605 
606 	/*
607 	 * If the key is not trusted, the key is not considered found.
608 	 */
609 	if ( ! (KEY_TRUSTED & sk->flags)) {
610 		authnokey++;
611 		return FALSE;
612 	}
613 
614 	/*
615 	 * The key is found and trusted. Initialize the key cache.
616 	 * The cache really should be a struct savekey to streamline
617 	 * this code.  Using a sk pointer would be even faster but more
618 	 * fragile around pointing to freed memory.
619 	 */
620 	cache_keyid = sk->keyid;
621 	cache_type = sk->type;
622 	cache_flags = sk->flags;
623 	cache_secret = sk->secret;
624 	cache_secretsize = sk->secretsize;
625 	cache_keyacclist = sk->keyacclist;
626 
627 	return TRUE;
628 }
629 
630 
631 /*
632  * authtrust - declare a key to be trusted/untrusted
633  */
634 void
635 authtrust(
636 	keyid_t		id,
637 	u_long		trust
638 	)
639 {
640 	symkey *	sk;
641 	u_long		lifetime;
642 
643 	/*
644 	 * Search bin for key; if it does not exist and is untrusted,
645 	 * forget it.
646 	 */
647 
648 	sk = auth_findkey(id);
649 	if (!trust && sk == NULL)
650 		return;
651 
652 	/*
653 	 * There are two conditions remaining. Either it does not
654 	 * exist and is to be trusted or it does exist and is or is
655 	 * not to be trusted.
656 	 */
657 	if (sk != NULL) {
658 		/*
659 		 * Key exists. If it is to be trusted, say so and update
660 		 * its lifetime. If no longer trusted, return it to the
661 		 * free list. Flush the cache first to be sure there are
662 		 * no discrepancies.
663 		 */
664 		authcache_flush_id(id);
665 		if (trust > 0) {
666 			sk->flags |= KEY_TRUSTED;
667 			if (trust > 1)
668 				sk->lifetime = current_time + trust;
669 			else
670 				sk->lifetime = 0;
671 		} else {
672 			freesymkey(sk);
673 		}
674 		return;
675 	}
676 
677 	/*
678 	 * keyid is not present, but the is to be trusted.  We allocate
679 	 * a new key, but do not specify a key type or secret.
680 	 */
681 	if (trust > 1) {
682 		lifetime = current_time + trust;
683 	} else {
684 		lifetime = 0;
685 	}
686 	allocsymkey(id, KEY_TRUSTED, 0, lifetime, 0, NULL, NULL);
687 }
688 
689 
690 /*
691  * authistrusted - determine whether a key is trusted
692  */
693 int
694 authistrusted(
695 	keyid_t		id
696 	)
697 {
698 	symkey *	sk;
699 
700 	if (id == cache_keyid)
701 		return !!(KEY_TRUSTED & cache_flags);
702 
703 	authkeyuncached++;
704 	sk = auth_findkey(id);
705 	if (sk == NULL || !(KEY_TRUSTED & sk->flags)) {
706 		authkeynotfound++;
707 		return FALSE;
708 	}
709 	return TRUE;
710 }
711 
712 
713 /*
714  * authistrustedip - determine if the IP is OK for the keyid
715  */
716  int
717  authistrustedip(
718  	keyid_t		keyno,
719 	sockaddr_u *	sau
720 	)
721 {
722 	symkey *	sk;
723 
724 	if (keyno == cache_keyid) {
725 		return (KEY_TRUSTED & cache_flags) &&
726 			keyacc_contains(cache_keyacclist, sau, TRUE);
727 	}
728 
729 	if (NULL != (sk = auth_findkey(keyno))) {
730 		authkeyuncached++;
731 		return (KEY_TRUSTED & sk->flags) &&
732 			keyacc_contains(sk->keyacclist, sau, TRUE);
733 	}
734 
735 	authkeynotfound++;
736 	return FALSE;
737 }
738 
739 /* Note: There are two locations below where 'strncpy()' is used. While
740  * this function is a hazard by itself, it's essential that it is used
741  * here. Bug 1243 involved that the secret was filled with NUL bytes
742  * after the first NUL encountered, and 'strlcpy()' simply does NOT have
743  * this behaviour. So disabling the fix and reverting to the buggy
744  * behaviour due to compatibility issues MUST also fill with NUL and
745  * this needs 'strncpy'. Also, the secret is managed as a byte blob of a
746  * given size, and eventually truncating it and replacing the last byte
747  * with a NUL would be a bug.
748  * perlinger@ntp.org 2015-10-10
749  */
750 void
751 MD5auth_setkey(
752 	keyid_t keyno,
753 	int	keytype,
754 	const u_char *key,
755 	size_t secretsize,
756 	KeyAccT *ka
757 	)
758 {
759 	symkey *	sk;
760 	u_char *	secret;
761 
762 	DEBUG_ENSURE(keytype <= USHRT_MAX);
763 	DEBUG_ENSURE(secretsize < 4 * 1024);
764 	/*
765 	 * See if we already have the key.  If so just stick in the
766 	 * new value.
767 	 */
768 	sk = auth_findkey(keyno);
769 	if (sk != NULL && keyno == sk->keyid) {
770 			/* TALOS-CAN-0054: make sure we have a new buffer! */
771 		if (NULL != sk->secret) {
772 			memset(sk->secret, 0, sk->secretsize);
773 			free(sk->secret);
774 		}
775 		sk->secret = emalloc(secretsize + 1);
776 		sk->type = (u_short)keytype;
777 		sk->secretsize = secretsize;
778 		/* make sure access lists don't leak here! */
779 		if (ka != sk->keyacclist) {
780 			keyacc_all_free(sk->keyacclist);
781 			sk->keyacclist = ka;
782 		}
783 #ifndef DISABLE_BUG1243_FIX
784 		memcpy(sk->secret, key, secretsize);
785 #else
786 		/* >MUST< use 'strncpy()' here! See above! */
787 		strncpy((char *)sk->secret, (const char *)key,
788 			secretsize);
789 #endif
790 		authcache_flush_id(keyno);
791 		return;
792 	}
793 
794 	/*
795 	 * Need to allocate new structure.  Do it.
796 	 */
797 	secret = emalloc(secretsize + 1);
798 #ifndef DISABLE_BUG1243_FIX
799 	memcpy(secret, key, secretsize);
800 #else
801 	/* >MUST< use 'strncpy()' here! See above! */
802 	strncpy((char *)secret, (const char *)key, secretsize);
803 #endif
804 	allocsymkey(keyno, 0, (u_short)keytype, 0,
805 		    secretsize, secret, ka);
806 #ifdef DEBUG
807 	if (debug >= 1) {
808 		size_t	j;
809 
810 		printf("auth_setkey: key %d type %d len %d ", (int)keyno,
811 		    keytype, (int)secretsize);
812 		for (j = 0; j < secretsize; j++) {
813 			printf("%02x", secret[j]);
814 		}
815 		printf("\n");
816 	}
817 #endif
818 }
819 
820 
821 /*
822  * auth_delkeys - delete non-autokey untrusted keys, and clear all info
823  *		  except the trusted bit of non-autokey trusted keys, in
824  *		  preparation for rereading the keys file.
825  */
826 void
827 auth_delkeys(void)
828 {
829 	symkey *	sk;
830 
831 	ITER_DLIST_BEGIN(key_listhead, sk, llink, symkey)
832 		if (sk->keyid > NTP_MAXKEY) {	/* autokey */
833 			continue;
834 		}
835 
836 		/*
837 		 * Don't lose info as to which keys are trusted. Make
838 		 * sure there are no dangling pointers!
839 		 */
840 		if (KEY_TRUSTED & sk->flags) {
841 			if (sk->secret != NULL) {
842 				zero_mem(sk->secret, sk->secretsize);
843 				free(sk->secret);
844 				sk->secret = NULL; /* TALOS-CAN-0054 */
845 			}
846 			sk->keyacclist = keyacc_all_free(sk->keyacclist);
847 			sk->secretsize = 0;
848 			sk->lifetime = 0;
849 		} else {
850 			freesymkey(sk);
851 		}
852 	ITER_DLIST_END()
853 }
854 
855 
856 /*
857  * auth_agekeys - delete keys whose lifetimes have expired
858  */
859 void
860 auth_agekeys(void)
861 {
862 	symkey *	sk;
863 
864 	ITER_DLIST_BEGIN(key_listhead, sk, llink, symkey)
865 		if (sk->lifetime > 0 && current_time > sk->lifetime) {
866 			freesymkey(sk);
867 			authkeyexpired++;
868 		}
869 	ITER_DLIST_END()
870 	DPRINTF(1, ("auth_agekeys: at %lu keys %lu expired %lu\n",
871 		    current_time, authnumkeys, authkeyexpired));
872 }
873 
874 
875 /*
876  * authencrypt - generate message authenticator
877  *
878  * Returns length of authenticator field, zero if key not found.
879  */
880 size_t
881 authencrypt(
882 	keyid_t		keyno,
883 	u_int32 *	pkt,
884 	size_t		length
885 	)
886 {
887 	/*
888 	 * A zero key identifier means the sender has not verified
889 	 * the last message was correctly authenticated. The MAC
890 	 * consists of a single word with value zero.
891 	 */
892 	authencryptions++;
893 	pkt[length / KEY_MAC_LEN] = htonl(keyno);
894 	if (0 == keyno) {
895 		return KEY_MAC_LEN;
896 	}
897 	if (!authhavekey(keyno)) {
898 		return 0;
899 	}
900 
901 	return MD5authencrypt(cache_type,
902 			      cache_secret, cache_secretsize,
903 			      pkt, length);
904 }
905 
906 
907 /*
908  * authdecrypt - verify message authenticator
909  *
910  * Returns TRUE if authenticator valid, FALSE if invalid or not found.
911  */
912 int
913 authdecrypt(
914 	keyid_t		keyno,
915 	u_int32 *	pkt,
916 	size_t		length,
917 	size_t		size
918 	)
919 {
920 	/*
921 	 * A zero key identifier means the sender has not verified
922 	 * the last message was correctly authenticated.  For our
923 	 * purpose this is an invalid authenticator.
924 	 */
925 	authdecryptions++;
926 	if (0 == keyno || !authhavekey(keyno) || size < 4) {
927 		return FALSE;
928 	}
929 
930 	return MD5authdecrypt(cache_type,
931 			      cache_secret, cache_secretsize,
932 			      pkt, length, size, keyno);
933 }
934 
935 
936 /* password decoding helpers */
937 static size_t
938 pwdecode_plain(
939 	u_char *	dst,
940 	size_t 		dstlen,
941 	const char *	src
942 	)
943 {
944 	size_t		srclen = strlen(src);
945 	if (srclen > dstlen) {
946 		errno = ENOMEM;
947 		return (size_t)-1;
948 	}
949 	memcpy(dst, src, srclen);
950 	return srclen;
951 }
952 
953 static size_t
954 pwdecode_hex(
955 	u_char *	dst,
956 	size_t 		dstlen,
957 	const char *	src
958 	)
959 {
960 	static const char hex[] = "00112233445566778899AaBbCcDdEeFf";
961 
962 	size_t		srclen = strlen(src);
963 	size_t		reslen = (srclen >> 1) + (srclen & 1);
964 	u_char		tmp;
965 	char		*ptr;
966 	size_t		j;
967 
968 	if (reslen > dstlen) {
969 		errno = ENOMEM;
970 		reslen = (size_t)-1;
971 	} else {
972 		for (j = 0; j < srclen; ++j) {
973 			tmp = *(const unsigned char*)(src + j);
974 			ptr = strchr(hex, tmp);
975 			if (ptr == NULL) {
976 				errno = EINVAL;
977 				reslen = (size_t)-1;
978 				break;
979 			}
980 			tmp = (u_char)((ptr - hex) >> 1);
981 			if (j & 1)
982 				dst[j >> 1] |= tmp;
983 			else
984 				dst[j >> 1] = tmp << 4;
985 		}
986 	}
987 	return reslen;
988 }
989 /*
990  * authdecodepw - decode plaintext or hex-encoded password to binary
991  * secret.  Returns size of secret in bytes or -1 on error.
992  */
993 size_t
994 authdecodepw(
995 	u_char *	dst,
996 	size_t 		dstlen,
997 	const char *	src,
998 	enum AuthPwdEnc	enc
999 	)
1000 {
1001 	size_t		reslen;
1002 
1003 	if ( !(dst && dstlen && src)) {
1004 		errno  = EINVAL;
1005 		reslen = (size_t)-1;
1006 	} else {
1007 		switch (enc) {
1008 		case AUTHPWD_UNSPEC:
1009 			if (strlen(src) <= 20)
1010 				reslen = pwdecode_plain(dst, dstlen, src);
1011 			else
1012 				reslen = pwdecode_hex(dst, dstlen, src);
1013 			break;
1014 		case AUTHPWD_PLAIN:
1015 			reslen = pwdecode_plain(dst, dstlen, src);
1016 			break;
1017 		case AUTHPWD_HEX:
1018 			reslen = pwdecode_hex(dst, dstlen, src);
1019 			break;
1020 		default:
1021 			errno = EINVAL;
1022 			reslen = (size_t)-1;
1023 		}
1024 	}
1025 	return reslen;
1026 }
1027