authkeys.c revision 294905
1139826Simp/*
262587Sitojun * authkeys.c - routines to manage the storage of authentication keys
362587Sitojun */
4120941Sume#ifdef HAVE_CONFIG_H
562587Sitojun# include <config.h>
662587Sitojun#endif
762587Sitojun
862587Sitojun#include <math.h>
962587Sitojun#include <stdio.h>
1062587Sitojun
1162587Sitojun#include "ntp.h"
1262587Sitojun#include "ntp_fp.h"
1362587Sitojun#include "ntpd.h"
1462587Sitojun#include "ntp_lists.h"
1562587Sitojun#include "ntp_string.h"
16120941Sume#include "ntp_malloc.h"
1762587Sitojun#include "ntp_stdlib.h"
1862587Sitojun#include "ntp_keyacc.h"
1962587Sitojun
2062587Sitojun/*
2162587Sitojun * Structure to store keys in in the hash table.
2262587Sitojun */
2362587Sitojuntypedef struct savekey symkey;
2462587Sitojun
2562587Sitojunstruct savekey {
2662587Sitojun	symkey *	hlink;		/* next in hash bucket */
2762587Sitojun	DECL_DLIST_LINK(symkey, llink);	/* for overall & free lists */
28174510Sobrien	u_char *	secret;		/* shared secret */
29174510Sobrien	KeyAccT *	keyacclist;	/* Private key access list */
3062587Sitojun	u_long		lifetime;	/* remaining lifetime */
3162587Sitojun	keyid_t		keyid;		/* key identifier */
32174510Sobrien	u_short		type;		/* OpenSSL digest NID */
33174510Sobrien	u_short		secretsize;	/* secret octets */
34174510Sobrien	u_short		flags;		/* KEY_ flags that wave */
3562587Sitojun};
3662587Sitojun
3762587Sitojun/* define the payload region of symkey beyond the list pointers */
3862587Sitojun#define symkey_payload	secret
3962587Sitojun
4078064Sume#define	KEY_TRUSTED	0x001	/* this key is trusted */
41148385Sume
4262587Sitojun#ifdef DEBUG
4362587Sitojuntypedef struct symkey_alloc_tag symkey_alloc;
44185571Sbz
4562587Sitojunstruct symkey_alloc_tag {
4662587Sitojun	symkey_alloc *	link;
47185571Sbz	void *		mem;		/* enable free() atexit */
48183550Szec};
4962587Sitojun
50195699Srwatsonsymkey_alloc *	authallocs;
5162587Sitojun#endif	/* DEBUG */
5262587Sitojun
53207369Sbzstatic u_short	auth_log2(size_t);
54207369Sbzstatic void	auth_resize_hashtable(void);
55207369Sbzstatic void	allocsymkey(symkey **, keyid_t,	u_short, u_short,
56207369Sbz			    u_long, u_short, u_char *, KeyAccT *);
57207369Sbzstatic void	freesymkey(symkey *, symkey **);
58148385Sume#ifdef DEBUG
59121343Sumestatic void	free_auth_mem(void);
60138184Sgnn#endif
61138184Sgnn
62121343Sumesymkey	key_listhead;		/* list of all in-use keys */;
63121343Sume/*
64121343Sume * The hash table. This is indexed by the low order bits of the
65121343Sume * keyid. We make this fairly big for potentially busy servers.
66121343Sume */
67121343Sume#define	DEF_AUTHHASHSIZE	64
68121343Sume/*#define	HASHMASK	((HASHSIZE)-1)*/
69215701Sdim#define	KEYHASH(keyid)	((keyid) & authhashmask)
70195727Srwatson
71195699Srwatsonint	authhashdisabled;
72121161Sumeu_short	authhashbuckets = DEF_AUTHHASHSIZE;
73121161Sumeu_short authhashmask = DEF_AUTHHASHSIZE - 1;
7462587Sitojunsymkey **key_hash;
7562587Sitojun
76171259Sdelphiju_long authkeynotfound;		/* keys not found */
77121161Sumeu_long authkeylookups;		/* calls to lookup keys */
78121161Sumeu_long authnumkeys;		/* number of active keys */
79190787Szecu_long authkeyexpired;		/* key lifetime expirations */
80190787Szecu_long authkeyuncached;		/* cache misses */
81190787Szecu_long authnokey;		/* calls to encrypt with no key */
82190787Szecu_long authencryptions;		/* calls to encrypt */
83190787Szecu_long authdecryptions;		/* calls to decrypt */
84121343Sume
85121161Sume/*
86121161Sume * Storage for free symkey structures.  We malloc() such things but
87121161Sume * never free them.
88171259Sdelphij */
8962587Sitojunsymkey *authfreekeys;
90121161Sumeint authnumfreekeys;
9162587Sitojun
92121161Sume#define	MEMINC	16		/* number of new free ones to get */
93121161Sume
9462587Sitojun/*
9562587Sitojun * The key cache. We cache the last key we looked at here.
9662587Sitojun */
9762587Sitojunkeyid_t	cache_keyid;		/* key identifier */
9862587Sitojunu_char *cache_secret;		/* secret */
99121315Sumeu_short	cache_secretsize;	/* secret length */
100121161Sumeint	cache_type;		/* OpenSSL digest NID */
10162587Sitojunu_short cache_flags;		/* flags that wave */
10262587SitojunKeyAccT *cache_keyacclist;	/* key access list */
103121161Sume
104121161Sume
10562587Sitojun/*
10662587Sitojun * init_auth - initialize internal data
107121161Sume */
10862587Sitojunvoid
10962587Sitojuninit_auth(void)
110121161Sume{
111171259Sdelphij	size_t newalloc;
112121161Sume
113121161Sume	/*
114121161Sume	 * Initialize hash table and free list
115121161Sume	 */
116121161Sume	newalloc = authhashbuckets * sizeof(key_hash[0]);
11762587Sitojun
118171259Sdelphij	key_hash = erealloc(key_hash, newalloc);
11962587Sitojun	memset(key_hash, '\0', newalloc);
120138184Sgnn
12162587Sitojun	INIT_DLIST(key_listhead, llink);
122138184Sgnn
12362587Sitojun#ifdef DEBUG
124243382Sae	atexit(&free_auth_mem);
125138184Sgnn#endif
126138184Sgnn}
127138184Sgnn
128243382Sae
129120856Sume/*
130138184Sgnn * free_auth_mem - assist in leak detection by freeing all dynamic
13162587Sitojun *		   allocations from this module.
13262587Sitojun */
13362587Sitojun#ifdef DEBUG
13462587Sitojunstatic void
13562587Sitojunfree_auth_mem(void)
13662587Sitojun{
13762587Sitojun	symkey *	sk;
13862587Sitojun	symkey_alloc *	alloc;
139120941Sume	symkey_alloc *	next_alloc;
14062587Sitojun
14162587Sitojun	while (NULL != (sk = HEAD_DLIST(key_listhead, llink))) {
14262587Sitojun		freesymkey(sk, &key_hash[KEYHASH(sk->keyid)]);
143121161Sume	}
144121161Sume	free(key_hash);
145121315Sume	key_hash = NULL;
146121315Sume	cache_keyid = 0;
147121315Sume	cache_flags = 0;
148121315Sume	cache_keyacclist = NULL;
149121315Sume	for (alloc = authallocs; alloc != NULL; alloc = next_alloc) {
150121315Sume		next_alloc = alloc->link;
151243382Sae		free(alloc->mem);
152121315Sume	}
153121315Sume	authfreekeys = NULL;
154121315Sume	authnumfreekeys = 0;
15562587Sitojun}
156181803Sbz#endif	/* DEBUG */
15762587Sitojun
15862587Sitojun
15962587Sitojun/*
16062587Sitojun * auth_moremem - get some more free key structures
16162587Sitojun */
16262587Sitojunvoid
163243382Saeauth_moremem(
164120856Sume	int	keycount
16562587Sitojun	)
16662587Sitojun{
16762587Sitojun	symkey *	sk;
16862587Sitojun	int		i;
16962587Sitojun#ifdef DEBUG
17062587Sitojun	void *		base;
17162587Sitojun	symkey_alloc *	allocrec;
172121161Sume# define MOREMEM_EXTRA_ALLOC	(sizeof(*allocrec))
17362587Sitojun#else
17462587Sitojun# define MOREMEM_EXTRA_ALLOC	(0)
175243382Sae#endif
17662587Sitojun
177120856Sume	i = (keycount > 0)
17862587Sitojun		? keycount
17962587Sitojun		: MEMINC;
18062587Sitojun	sk = emalloc_zero(i * sizeof(*sk) + MOREMEM_EXTRA_ALLOC);
181171259Sdelphij#ifdef DEBUG
18262587Sitojun	base = sk;
183243382Sae#endif
184243382Sae	authnumfreekeys += i;
185138184Sgnn
186243382Sae	for (; i > 0; i--, sk++) {
187243382Sae		LINK_SLIST(authfreekeys, sk, llink.f);
188138184Sgnn	}
189243382Sae
190120856Sume#ifdef DEBUG
191138184Sgnn	allocrec = (void *)sk;
19262587Sitojun	allocrec->mem = base;
193121161Sume	LINK_SLIST(authallocs, allocrec, link);
19462587Sitojun#endif
195243382Sae}
196120856Sume
19762587Sitojun
19862587Sitojun/*
19962587Sitojun * auth_prealloc_symkeys
20062587Sitojun */
20162587Sitojunvoid
20262587Sitojunauth_prealloc_symkeys(
20362587Sitojun	int	keycount
204171259Sdelphij	)
20562587Sitojun{
20662587Sitojun	int	allocated;
20762587Sitojun	int	additional;
208121315Sume
209121315Sume	allocated = authnumkeys + authnumfreekeys;
21062587Sitojun	additional = keycount - allocated;
21162587Sitojun	if (additional > 0)
21262587Sitojun		auth_moremem(additional);
21362587Sitojun	auth_resize_hashtable();
21462587Sitojun}
21562587Sitojun
21662587Sitojun
21762587Sitojunstatic u_short
21862587Sitojunauth_log2(size_t x)
21962587Sitojun{
22062587Sitojun	/*
22162587Sitojun	** bithack to calculate floor(log2(x))
22262587Sitojun	**
22362587Sitojun	** This assumes
22462587Sitojun	**   - (sizeof(size_t) is a power of two
225121315Sume	**   - CHAR_BITS is a power of two
226121315Sume	**   - returning zero for arguments <= 0 is OK.
22762587Sitojun	**
22862587Sitojun	** Does only shifts, masks and sums in integer arithmetic in
22962587Sitojun	** log2(CHAR_BIT*sizeof(size_t)) steps. (that is, 5/6 steps for
23062587Sitojun	** 32bit/64bit size_t)
23162587Sitojun	*/
23262587Sitojun	int	s;
233121315Sume	int	r = 0;
234121315Sume	size_t  m = ~(size_t)0;
23562587Sitojun
23662587Sitojun	for (s = sizeof(size_t) / 2 * CHAR_BIT; s != 0; s >>= 1) {
23762587Sitojun		m <<= s;
23862587Sitojun		if (x & m)
23962587Sitojun			r += s;
24062587Sitojun		else
24162587Sitojun			x <<= s;
24262587Sitojun	}
24362587Sitojun	return (u_short)r;
24462587Sitojun}
24562587Sitojun
24662587Sitojun
24762587Sitojun/*
248121315Sume * auth_resize_hashtable
249121315Sume *
250121315Sume * Size hash table to average 4 or fewer entries per bucket initially,
251121315Sume * within the bounds of at least 4 and no more than 15 bits for the hash
25293128Sume * table index.  Populate the hash table.
253121315Sume */
25462587Sitojunstatic void
255121315Sumeauth_resize_hashtable(void)
256121315Sume{
25762587Sitojun	u_long		totalkeys;
25862587Sitojun	u_short		hashbits;
25962587Sitojun	u_short		hash;
26062587Sitojun	size_t		newalloc;
26162587Sitojun	symkey *	sk;
262171259Sdelphij
263171259Sdelphij	totalkeys = authnumkeys + authnumfreekeys;
264171259Sdelphij	hashbits = auth_log2(totalkeys / 4) + 1;
265171259Sdelphij	hashbits = max(4, hashbits);
26662587Sitojun	hashbits = min(15, hashbits);
267171259Sdelphij
26862587Sitojun	authhashbuckets = 1 << hashbits;
269183550Szec	authhashmask = authhashbuckets - 1;
27062587Sitojun	newalloc = authhashbuckets * sizeof(key_hash[0]);
271138184Sgnn
272121161Sume	key_hash = erealloc(key_hash, newalloc);
27362587Sitojun	memset(key_hash, '\0', newalloc);
27462587Sitojun
27562587Sitojun	ITER_DLIST_BEGIN(key_listhead, sk, llink, symkey)
276121343Sume		hash = KEYHASH(sk->keyid);
27762587Sitojun		LINK_SLIST(key_hash[hash], sk, hlink);
278181803Sbz	ITER_DLIST_END()
27962587Sitojun}
280181803Sbz
281121161Sume
282120941Sume/*
283181803Sbz * allocsymkey - common code to allocate and link in symkey
284181803Sbz *
28562587Sitojun * secret must be allocated with a free-compatible allocator.  It is
286121343Sume * owned by the referring symkey structure, and will be free()d by
28762587Sitojun * freesymkey().
28862587Sitojun */
28962587Sitojunstatic void
290171259Sdelphijallocsymkey(
29162587Sitojun	symkey **	bucket,
292121343Sume	keyid_t		id,
293121343Sume	u_short		flags,
294181803Sbz	u_short		type,
295121343Sume	u_long		lifetime,
29662587Sitojun	u_short		secretsize,
297120856Sume	u_char *	secret,
29862587Sitojun	KeyAccT *	ka
29962587Sitojun	)
30062587Sitojun{
301171259Sdelphij	symkey *	sk;
30262587Sitojun
303121343Sume	if (authnumfreekeys < 1)
304121343Sume		auth_moremem(-1);
305121161Sume	UNLINK_HEAD_SLIST(sk, authfreekeys, llink.f);
306121161Sume	DEBUG_ENSURE(sk != NULL);
307121161Sume	sk->keyid = id;
308121161Sume	sk->flags = flags;
309121161Sume	sk->type = type;
310121161Sume	sk->secretsize = secretsize;
311121161Sume	sk->secret = secret;
312121343Sume	sk->keyacclist = ka;
313121343Sume	sk->lifetime = lifetime;
314121343Sume	LINK_SLIST(*bucket, sk, hlink);
315121343Sume	LINK_TAIL_DLIST(key_listhead, sk, llink);
316121343Sume	authnumfreekeys--;
317181803Sbz	authnumkeys++;
318121343Sume}
319121343Sume
32062587Sitojun
321148385Sume/*
322148385Sume * freesymkey - common code to remove a symkey and recycle its entry.
323148385Sume */
324148385Sumestatic void
325148385Sumefreesymkey(
326148385Sume	symkey *	sk,
327148385Sume	symkey **	bucket
328148385Sume	)
329148385Sume{
330148385Sume	symkey *	unlinked;
331171259Sdelphij
332148385Sume	if (sk->secret != NULL) {
333148385Sume		memset(sk->secret, '\0', sk->secretsize);
334148385Sume		free(sk->secret);
335148385Sume	}
336148385Sume	UNLINK_SLIST(unlinked, *bucket, sk, hlink, symkey);
337148385Sume	DEBUG_ENSURE(sk == unlinked);
338148385Sume	UNLINK_DLIST(sk, llink);
339148385Sume	memset((char *)sk + offsetof(symkey, symkey_payload), '\0',
340148385Sume	       sizeof(*sk) - offsetof(symkey, symkey_payload));
341148385Sume	LINK_SLIST(authfreekeys, sk, llink.f);
342148385Sume	authnumkeys--;
343148385Sume	authnumfreekeys++;
344148385Sume}
345148385Sume
346148385Sume
347148385Sume/*
348181803Sbz * auth_findkey - find a key in the hash table
349148385Sume */
350148385Sumestruct savekey *
351148385Sumeauth_findkey(
352148385Sume	keyid_t		id
353148385Sume	)
354148385Sume{
355148385Sume	symkey *	sk;
356148385Sume
357148385Sume	for (sk = key_hash[KEYHASH(id)]; sk != NULL; sk = sk->hlink) {
358148385Sume		if (id == sk->keyid) {
359148385Sume			return sk;
360148385Sume		}
361148385Sume	}
362148385Sume
363148385Sume	return NULL;
364148385Sume}
365148385Sume
366148385Sume
367171259Sdelphij/*
368148385Sume * auth_havekey - return TRUE if the key id is zero or known
369165118Sbz */
370148385Sumeint
371148385Sumeauth_havekey(
372148385Sume	keyid_t		id
373148385Sume	)
374148385Sume{
375165118Sbz	symkey *	sk;
376148385Sume
377148385Sume	if (0 == id || cache_keyid == id) {
378148385Sume		return TRUE;
379148385Sume	}
380148385Sume
381148385Sume	for (sk = key_hash[KEYHASH(id)]; sk != NULL; sk = sk->hlink) {
382148385Sume		if (id == sk->keyid) {
383148385Sume			return TRUE;
384148385Sume		}
385148385Sume	}
386243382Sae
387148385Sume	return FALSE;
388148385Sume}
389148385Sume
390148385Sume
391148385Sume/*
392148385Sume * authhavekey - return TRUE and cache the key, if zero or both known
393148385Sume *		 and trusted.
394148385Sume */
395148385Sumeint
396148385Sumeauthhavekey(
397148385Sume	keyid_t		id
398148385Sume	)
399148385Sume{
400148385Sume	symkey *	sk;
401148385Sume
402171259Sdelphij	authkeylookups++;
403171259Sdelphij	if (0 == id || cache_keyid == id) {
404148385Sume		return TRUE;
405148385Sume	}
406171259Sdelphij
407148385Sume	/*
408148385Sume	 * Seach the bin for the key. If found and the key type
409148385Sume	 * is zero, somebody marked it trusted without specifying
410148396Sume	 * a key or key type. In this case consider the key missing.
411148385Sume	 */
412243382Sae	authkeyuncached++;
413148396Sume	for (sk = key_hash[KEYHASH(id)]; sk != NULL; sk = sk->hlink) {
414148396Sume		if (id == sk->keyid) {
415148396Sume			if (0 == sk->type) {
416148385Sume				authkeynotfound++;
417148385Sume				return FALSE;
418148385Sume			}
419148385Sume			break;
420148385Sume		}
421148385Sume	}
422148385Sume
423148385Sume	/*
424148385Sume	 * If the key is not found, or if it is found but not trusted,
425148385Sume	 * the key is not considered found.
426148385Sume	 */
427148385Sume	if (NULL == sk) {
428148399Sume		authkeynotfound++;
429243382Sae		return FALSE;
430148385Sume	}
431148399Sume	if (!(KEY_TRUSTED & sk->flags)) {
432148385Sume		authnokey++;
433148385Sume		return FALSE;
434243382Sae	}
435148385Sume
436148385Sume	/*
437148385Sume	 * The key is found and trusted. Initialize the key cache.
438148385Sume	 */
439148385Sume	cache_keyid = sk->keyid;
440148385Sume	cache_type = sk->type;
441148385Sume	cache_flags = sk->flags;
442148385Sume	cache_secret = sk->secret;
443148385Sume	cache_secretsize = sk->secretsize;
444148385Sume	cache_keyacclist = sk->keyacclist;
445148385Sume
446148385Sume	return TRUE;
447148385Sume}
448148385Sume
449148385Sume
450148385Sume/*
451148385Sume * authtrust - declare a key to be trusted/untrusted
452148385Sume */
453148385Sumevoid
454148385Sumeauthtrust(
455148385Sume	keyid_t		id,
456148385Sume	u_long		trust
457148385Sume	)
458148385Sume{
459148385Sume	symkey **	bucket;
460148385Sume	symkey *	sk;
461243382Sae	u_long		lifetime;
462148385Sume
463148385Sume	/*
464148385Sume	 * Search bin for key; if it does not exist and is untrusted,
465148385Sume	 * forget it.
466148385Sume	 */
467148385Sume	bucket = &key_hash[KEYHASH(id)];
468148385Sume	for (sk = *bucket; sk != NULL; sk = sk->hlink) {
469148385Sume		if (id == sk->keyid)
470148385Sume			break;
471148385Sume	}
472148385Sume	if (!trust && NULL == sk)
473148385Sume		return;
474148385Sume
475148385Sume	/*
476148385Sume	 * There are two conditions remaining. Either it does not
477171259Sdelphij	 * exist and is to be trusted or it does exist and is or is
478148385Sume	 * not to be trusted.
479148385Sume	 */
480148385Sume	if (sk != NULL) {
481148385Sume		if (cache_keyid == id) {
482148385Sume			cache_flags = 0;
483148385Sume			cache_keyid = 0;
484148385Sume			cache_keyacclist = NULL;
485148385Sume		}
486148385Sume
487148385Sume		/*
488148385Sume		 * Key exists. If it is to be trusted, say so and
489238224Sbz		 * update its lifetime.
490238224Sbz		 */
491238224Sbz		if (trust > 0) {
492238224Sbz			sk->flags |= KEY_TRUSTED;
493238224Sbz			if (trust > 1)
494238224Sbz				sk->lifetime = current_time + trust;
495238224Sbz			else
496238224Sbz				sk->lifetime = 0;
497238224Sbz			return;
498238224Sbz		}
499238224Sbz
500238224Sbz		/* No longer trusted, return it to the free list. */
501238224Sbz		freesymkey(sk, bucket);
502		return;
503	}
504
505	/*
506	 * keyid is not present, but the is to be trusted.  We allocate
507	 * a new key, but do not specify a key type or secret.
508	 */
509	if (trust > 1) {
510		lifetime = current_time + trust;
511	} else {
512		lifetime = 0;
513	}
514	allocsymkey(bucket, id, KEY_TRUSTED, 0, lifetime, 0, NULL, NULL);
515}
516
517
518/*
519 * authistrusted - determine whether a key is trusted
520 */
521int
522authistrusted(
523	keyid_t		keyno
524	)
525{
526	symkey *	sk;
527	symkey **	bucket;
528
529	if (keyno == cache_keyid)
530		return !!(KEY_TRUSTED & cache_flags);
531
532	authkeyuncached++;
533	bucket = &key_hash[KEYHASH(keyno)];
534	for (sk = *bucket; sk != NULL; sk = sk->hlink) {
535		if (keyno == sk->keyid)
536			break;
537	}
538	if (NULL == sk || !(KEY_TRUSTED & sk->flags)) {
539		authkeynotfound++;
540		return FALSE;
541	}
542	return TRUE;
543}
544
545
546/*
547 * authistrustedip - determine if the IP is OK for the keyid
548 */
549 int
550 authistrustedip(
551 	keyid_t		keyno,
552	sockaddr_u *	sau
553	)
554{
555	symkey *	sk;
556	symkey **	bucket;
557	KeyAccT *	kal;
558	KeyAccT *	k;
559
560	if (keyno == cache_keyid)
561		kal = cache_keyacclist;
562	else {
563		authkeyuncached++;
564		bucket = &key_hash[KEYHASH(keyno)];
565		for (sk = *bucket; sk != NULL; sk = sk->hlink) {
566			if (keyno == sk->keyid)
567				break;
568		}
569		if (NULL == sk || !(KEY_TRUSTED & sk->flags)) {
570			INSIST(!"authistrustedip: keyid not found/trusted!");
571			return FALSE;
572		}
573		kal = sk->keyacclist;
574	}
575
576	if (NULL == kal)
577		return TRUE;
578
579	for (k = kal; k; k = k->next) {
580		if (SOCK_EQ(&k->addr, sau))
581			return TRUE;
582	}
583
584	return FALSE;
585}
586
587
588/* Note: There are two locations below where 'strncpy()' is used. While
589 * this function is a hazard by itself, it's essential that it is used
590 * here. Bug 1243 involved that the secret was filled with NUL bytes
591 * after the first NUL encountered, and 'strlcpy()' simply does NOT have
592 * this behaviour. So disabling the fix and reverting to the buggy
593 * behaviour due to compatibility issues MUST also fill with NUL and
594 * this needs 'strncpy'. Also, the secret is managed as a byte blob of a
595 * given size, and eventually truncating it and replacing the last byte
596 * with a NUL would be a bug.
597 * perlinger@ntp.org 2015-10-10
598 */
599void
600MD5auth_setkey(
601	keyid_t keyno,
602	int	keytype,
603	const u_char *key,
604	size_t	len,
605	KeyAccT *ka
606	)
607{
608	symkey *	sk;
609	symkey **	bucket;
610	u_char *	secret;
611	size_t		secretsize;
612
613	DEBUG_ENSURE(keytype <= USHRT_MAX);
614	DEBUG_ENSURE(len < 4 * 1024);
615	/*
616	 * See if we already have the key.  If so just stick in the
617	 * new value.
618	 */
619	bucket = &key_hash[KEYHASH(keyno)];
620	for (sk = *bucket; sk != NULL; sk = sk->hlink) {
621		if (keyno == sk->keyid) {
622			/* TALOS-CAN-0054: make sure we have a new buffer! */
623			if (NULL != sk->secret) {
624				memset(sk->secret, 0, sk->secretsize);
625				free(sk->secret);
626			}
627			sk->secret = emalloc(len);
628			sk->type = (u_short)keytype;
629			secretsize = len;
630			sk->secretsize = (u_short)secretsize;
631			sk->keyacclist = ka;
632#ifndef DISABLE_BUG1243_FIX
633			memcpy(sk->secret, key, secretsize);
634#else
635			/* >MUST< use 'strncpy()' here! See above! */
636			strncpy((char *)sk->secret, (const char *)key,
637				secretsize);
638#endif
639			if (cache_keyid == keyno) {
640				cache_flags = 0;
641				cache_keyid = 0;
642				cache_keyacclist = NULL;
643			}
644			return;
645		}
646	}
647
648	/*
649	 * Need to allocate new structure.  Do it.
650	 */
651	secretsize = len;
652	secret = emalloc(secretsize);
653#ifndef DISABLE_BUG1243_FIX
654	memcpy(secret, key, secretsize);
655#else
656	/* >MUST< use 'strncpy()' here! See above! */
657	strncpy((char *)secret, (const char *)key, secretsize);
658#endif
659	allocsymkey(bucket, keyno, 0, (u_short)keytype, 0,
660		    (u_short)secretsize, secret, ka);
661#ifdef DEBUG
662	if (debug >= 4) {
663		size_t	j;
664
665		printf("auth_setkey: key %d type %d len %d ", (int)keyno,
666		    keytype, (int)secretsize);
667		for (j = 0; j < secretsize; j++)
668			printf("%02x", secret[j]);
669		printf("\n");
670	}
671#endif
672}
673
674
675/*
676 * auth_delkeys - delete non-autokey untrusted keys, and clear all info
677 *                except the trusted bit of non-autokey trusted keys, in
678 *		  preparation for rereading the keys file.
679 */
680void
681auth_delkeys(void)
682{
683	symkey *	sk;
684
685	ITER_DLIST_BEGIN(key_listhead, sk, llink, symkey)
686		if (sk->keyid > NTP_MAXKEY) {	/* autokey */
687			continue;
688		}
689
690		/*
691		 * Don't lose info as to which keys are trusted. Make
692		 * sure there are no dangling pointers!
693		 */
694		if (KEY_TRUSTED & sk->flags) {
695			if (sk->secret != NULL) {
696				memset(sk->secret, 0, sk->secretsize);
697				free(sk->secret);
698				sk->secret = NULL; /* TALOS-CAN-0054 */
699			}
700			sk->secretsize = 0;
701			sk->lifetime = 0;
702		} else {
703			freesymkey(sk, &key_hash[KEYHASH(sk->keyid)]);
704		}
705	ITER_DLIST_END()
706}
707
708
709/*
710 * auth_agekeys - delete keys whose lifetimes have expired
711 */
712void
713auth_agekeys(void)
714{
715	symkey *	sk;
716
717	ITER_DLIST_BEGIN(key_listhead, sk, llink, symkey)
718		if (sk->lifetime > 0 && current_time > sk->lifetime) {
719			freesymkey(sk, &key_hash[KEYHASH(sk->keyid)]);
720			authkeyexpired++;
721		}
722	ITER_DLIST_END()
723	DPRINTF(1, ("auth_agekeys: at %lu keys %lu expired %lu\n",
724		    current_time, authnumkeys, authkeyexpired));
725}
726
727
728/*
729 * authencrypt - generate message authenticator
730 *
731 * Returns length of authenticator field, zero if key not found.
732 */
733size_t
734authencrypt(
735	keyid_t		keyno,
736	u_int32 *	pkt,
737	size_t		length
738	)
739{
740	/*
741	 * A zero key identifier means the sender has not verified
742	 * the last message was correctly authenticated. The MAC
743	 * consists of a single word with value zero.
744	 */
745	authencryptions++;
746	pkt[length / 4] = htonl(keyno);
747	if (0 == keyno) {
748		return 4;
749	}
750	if (!authhavekey(keyno)) {
751		return 0;
752	}
753
754	return MD5authencrypt(cache_type, cache_secret, pkt, length);
755}
756
757
758/*
759 * authdecrypt - verify message authenticator
760 *
761 * Returns TRUE if authenticator valid, FALSE if invalid or not found.
762 */
763int
764authdecrypt(
765	keyid_t		keyno,
766	u_int32 *	pkt,
767	size_t		length,
768	size_t		size
769	)
770{
771	/*
772	 * A zero key identifier means the sender has not verified
773	 * the last message was correctly authenticated.  For our
774	 * purpose this is an invalid authenticator.
775	 */
776	authdecryptions++;
777	if (0 == keyno || !authhavekey(keyno) || size < 4) {
778		return FALSE;
779	}
780
781	return MD5authdecrypt(cache_type, cache_secret, pkt, length,
782			      size);
783}
784