154359Sroberto/*
254359Sroberto * authkeys.c - routines to manage the storage of authentication keys
354359Sroberto */
454359Sroberto#ifdef HAVE_CONFIG_H
554359Sroberto# include <config.h>
654359Sroberto#endif
754359Sroberto
8285612Sdelphij#include <math.h>
954359Sroberto#include <stdio.h>
1054359Sroberto
11285612Sdelphij#include "ntp.h"
1254359Sroberto#include "ntp_fp.h"
1354359Sroberto#include "ntpd.h"
14285612Sdelphij#include "ntp_lists.h"
1554359Sroberto#include "ntp_string.h"
1654359Sroberto#include "ntp_malloc.h"
1754359Sroberto#include "ntp_stdlib.h"
18294569Sdelphij#include "ntp_keyacc.h"
1954359Sroberto
2054359Sroberto/*
2154359Sroberto * Structure to store keys in in the hash table.
2254359Sroberto */
23285612Sdelphijtypedef struct savekey symkey;
24285612Sdelphij
2554359Srobertostruct savekey {
26285612Sdelphij	symkey *	hlink;		/* next in hash bucket */
27285612Sdelphij	DECL_DLIST_LINK(symkey, llink);	/* for overall & free lists */
28285612Sdelphij	u_char *	secret;		/* shared secret */
29294569Sdelphij	KeyAccT *	keyacclist;	/* Private key access list */
30285612Sdelphij	u_long		lifetime;	/* remaining lifetime */
31285612Sdelphij	keyid_t		keyid;		/* key identifier */
32285612Sdelphij	u_short		type;		/* OpenSSL digest NID */
33298699Sdelphij	size_t		secretsize;	/* secret octets */
34285612Sdelphij	u_short		flags;		/* KEY_ flags that wave */
3554359Sroberto};
3654359Sroberto
37285612Sdelphij/* define the payload region of symkey beyond the list pointers */
38285612Sdelphij#define symkey_payload	secret
39285612Sdelphij
4054359Sroberto#define	KEY_TRUSTED	0x001	/* this key is trusted */
4154359Sroberto
42285612Sdelphij#ifdef DEBUG
43285612Sdelphijtypedef struct symkey_alloc_tag symkey_alloc;
44285612Sdelphij
45285612Sdelphijstruct symkey_alloc_tag {
46285612Sdelphij	symkey_alloc *	link;
47285612Sdelphij	void *		mem;		/* enable free() atexit */
48285612Sdelphij};
49285612Sdelphij
50285612Sdelphijsymkey_alloc *	authallocs;
51285612Sdelphij#endif	/* DEBUG */
52285612Sdelphij
53294569Sdelphijstatic u_short	auth_log2(size_t);
54298699Sdelphijstatic void		auth_resize_hashtable(void);
55298699Sdelphijstatic void		allocsymkey(keyid_t,	u_short,
56298699Sdelphij				    u_short, u_long, size_t, u_char *, KeyAccT *);
57298699Sdelphijstatic void		freesymkey(symkey *);
58285612Sdelphij#ifdef DEBUG
59298699Sdelphijstatic void		free_auth_mem(void);
60285612Sdelphij#endif
61285612Sdelphij
62285612Sdelphijsymkey	key_listhead;		/* list of all in-use keys */;
6354359Sroberto/*
6454359Sroberto * The hash table. This is indexed by the low order bits of the
6554359Sroberto * keyid. We make this fairly big for potentially busy servers.
6654359Sroberto */
67285612Sdelphij#define	DEF_AUTHHASHSIZE	64
68293650Sglebius/*#define	HASHMASK	((HASHSIZE)-1)*/
69285612Sdelphij#define	KEYHASH(keyid)	((keyid) & authhashmask)
7054359Sroberto
71285612Sdelphijint	authhashdisabled;
72285612Sdelphiju_short	authhashbuckets = DEF_AUTHHASHSIZE;
73285612Sdelphiju_short authhashmask = DEF_AUTHHASHSIZE - 1;
74285612Sdelphijsymkey **key_hash;
7554359Sroberto
7654359Srobertou_long authkeynotfound;		/* keys not found */
7754359Srobertou_long authkeylookups;		/* calls to lookup keys */
7854359Srobertou_long authnumkeys;		/* number of active keys */
7954359Srobertou_long authkeyexpired;		/* key lifetime expirations */
8054359Srobertou_long authkeyuncached;		/* cache misses */
8154359Srobertou_long authnokey;		/* calls to encrypt with no key */
8254359Srobertou_long authencryptions;		/* calls to encrypt */
8354359Srobertou_long authdecryptions;		/* calls to decrypt */
8454359Sroberto
8554359Sroberto/*
86285612Sdelphij * Storage for free symkey structures.  We malloc() such things but
8754359Sroberto * never free them.
8854359Sroberto */
89285612Sdelphijsymkey *authfreekeys;
9054359Srobertoint authnumfreekeys;
9154359Sroberto
92285612Sdelphij#define	MEMINC	16		/* number of new free ones to get */
9354359Sroberto
9454359Sroberto/*
9554359Sroberto * The key cache. We cache the last key we looked at here.
96298699Sdelphij * Note: this should hold the last *trusted* key. Also the
97298699Sdelphij * cache is only loaded when the digest type / MAC algorithm
98298699Sdelphij * is valid.
9954359Sroberto */
10082498Srobertokeyid_t	cache_keyid;		/* key identifier */
101285612Sdelphiju_char *cache_secret;		/* secret */
102298699Sdelphijsize_t	cache_secretsize;	/* secret length */
103285612Sdelphijint	cache_type;		/* OpenSSL digest NID */
10454359Srobertou_short cache_flags;		/* flags that wave */
105294569SdelphijKeyAccT *cache_keyacclist;	/* key access list */
10654359Sroberto
107298699Sdelphij/* --------------------------------------------------------------------
108298699Sdelphij * manage key access lists
109298699Sdelphij * --------------------------------------------------------------------
110298699Sdelphij */
111298699Sdelphij/* allocate and populate new access node and pushes it on the list.
112298699Sdelphij * Returns the new head.
113298699Sdelphij */
114298699SdelphijKeyAccT*
115298699Sdelphijkeyacc_new_push(
116298699Sdelphij	KeyAccT          * head,
117330141Sdelphij	const sockaddr_u * addr,
118330141Sdelphij	unsigned int	   subnetbits
119298699Sdelphij	)
120298699Sdelphij{
121298699Sdelphij	KeyAccT *	node = emalloc(sizeof(KeyAccT));
122298699Sdelphij
123298699Sdelphij	memcpy(&node->addr, addr, sizeof(sockaddr_u));
124330141Sdelphij	node->subnetbits = subnetbits;
125298699Sdelphij	node->next = head;
126330141Sdelphij
127298699Sdelphij	return node;
128298699Sdelphij}
12954359Sroberto
130298699Sdelphij/* ----------------------------------------------------------------- */
131298699Sdelphij/* pop and deallocate the first node of a list of access nodes, if
132298699Sdelphij * the list is not empty. Returns the tail of the list.
133298699Sdelphij */
134298699SdelphijKeyAccT*
135298699Sdelphijkeyacc_pop_free(
136298699Sdelphij	KeyAccT *head
137298699Sdelphij	)
138298699Sdelphij{
139298699Sdelphij	KeyAccT *	next = NULL;
140298699Sdelphij	if (head) {
141298699Sdelphij		next = head->next;
142298699Sdelphij		free(head);
143298699Sdelphij	}
144298699Sdelphij	return next;
145298699Sdelphij}
146298699Sdelphij
147298699Sdelphij/* ----------------------------------------------------------------- */
148298699Sdelphij/* deallocate the list; returns an empty list. */
149298699SdelphijKeyAccT*
150298699Sdelphijkeyacc_all_free(
151298699Sdelphij	KeyAccT * head
152298699Sdelphij	)
153298699Sdelphij{
154298699Sdelphij	while (head)
155298699Sdelphij		head = keyacc_pop_free(head);
156298699Sdelphij	return head;
157298699Sdelphij}
158298699Sdelphij
159298699Sdelphij/* ----------------------------------------------------------------- */
160298699Sdelphij/* scan a list to see if it contains a given address. Return the
161298699Sdelphij * default result value in case of an empty list.
162298699Sdelphij */
163298699Sdelphijint /*BOOL*/
164298699Sdelphijkeyacc_contains(
165298699Sdelphij	const KeyAccT    *head,
166298699Sdelphij	const sockaddr_u *addr,
167298699Sdelphij	int               defv)
168298699Sdelphij{
169298699Sdelphij	if (head) {
170298699Sdelphij		do {
171330141Sdelphij			if (keyacc_amatch(&head->addr, addr,
172330141Sdelphij					  head->subnetbits))
173298699Sdelphij				return TRUE;
174298699Sdelphij		} while (NULL != (head = head->next));
175298699Sdelphij		return FALSE;
176298699Sdelphij	} else {
177298699Sdelphij		return !!defv;
178298699Sdelphij	}
179298699Sdelphij}
180298699Sdelphij
181330141Sdelphij#if CHAR_BIT != 8
182330141Sdelphij# error "don't know how to handle bytes with that bit size"
183330141Sdelphij#endif
184298699Sdelphij
185330141Sdelphij/* ----------------------------------------------------------------- */
186330141Sdelphij/* check two addresses for a match, taking a prefix length into account
187330141Sdelphij * when doing the compare.
188330141Sdelphij *
189330141Sdelphij * The ISC lib contains a similar function with not entirely specified
190330141Sdelphij * semantics, so it seemed somewhat cleaner to do this from scratch.
191330141Sdelphij *
192330141Sdelphij * Note 1: It *is* assumed that the addresses are stored in network byte
193330141Sdelphij * order, that is, most significant byte first!
194330141Sdelphij *
195330141Sdelphij * Note 2: "no address" compares unequal to all other addresses, even to
196330141Sdelphij * itself. This has the same semantics as NaNs have for floats: *any*
197330141Sdelphij * relational or equality operation involving a NaN returns FALSE, even
198330141Sdelphij * equality with itself. "no address" is either a NULL pointer argument
199330141Sdelphij * or an address of type AF_UNSPEC.
200330141Sdelphij */
201330141Sdelphijint/*BOOL*/
202330141Sdelphijkeyacc_amatch(
203330141Sdelphij	const sockaddr_u *	a1,
204330141Sdelphij	const sockaddr_u *	a2,
205330141Sdelphij	unsigned int		mbits
206330141Sdelphij	)
207330141Sdelphij{
208330141Sdelphij	const uint8_t * pm1;
209330141Sdelphij	const uint8_t * pm2;
210330141Sdelphij	uint8_t         msk;
211330141Sdelphij	unsigned int    len;
212330141Sdelphij
213330141Sdelphij	/* 1st check: If any address is not an address, it's inequal. */
214330141Sdelphij	if ( !a1 || (AF_UNSPEC == AF(a1)) ||
215330141Sdelphij	     !a2 || (AF_UNSPEC == AF(a2))  )
216330141Sdelphij		return FALSE;
217330141Sdelphij
218330141Sdelphij	/* We could check pointers for equality here and shortcut the
219330141Sdelphij	 * other checks if we find object identity. But that use case is
220330141Sdelphij	 * too rare to care for it.
221330141Sdelphij	 */
222330141Sdelphij
223330141Sdelphij	/* 2nd check: Address families must be the same. */
224330141Sdelphij	if (AF(a1) != AF(a2))
225330141Sdelphij		return FALSE;
226330141Sdelphij
227330141Sdelphij	/* type check: address family determines buffer & size */
228330141Sdelphij	switch (AF(a1)) {
229330141Sdelphij	case AF_INET:
230330141Sdelphij		/* IPv4 is easy: clamp size, get byte pointers */
231330141Sdelphij		if (mbits > sizeof(NSRCADR(a1)) * 8)
232330141Sdelphij			mbits = sizeof(NSRCADR(a1)) * 8;
233330141Sdelphij		pm1 = (const void*)&NSRCADR(a1);
234330141Sdelphij		pm2 = (const void*)&NSRCADR(a2);
235330141Sdelphij		break;
236330141Sdelphij
237330141Sdelphij	case AF_INET6:
238330141Sdelphij		/* IPv6 is slightly different: Both scopes must match,
239330141Sdelphij		 * too, before we even consider doing a match!
240330141Sdelphij		 */
241330141Sdelphij		if ( ! SCOPE_EQ(a1, a2))
242330141Sdelphij			return FALSE;
243330141Sdelphij		if (mbits > sizeof(NSRCADR6(a1)) * 8)
244330141Sdelphij			mbits = sizeof(NSRCADR6(a1)) * 8;
245330141Sdelphij		pm1 = (const void*)&NSRCADR6(a1);
246330141Sdelphij		pm2 = (const void*)&NSRCADR6(a2);
247330141Sdelphij		break;
248330141Sdelphij
249330141Sdelphij	default:
250330141Sdelphij		/* don't know how to compare that!?! */
251330141Sdelphij		return FALSE;
252330141Sdelphij	}
253330141Sdelphij
254330141Sdelphij	/* Split bit length into byte length and partial byte mask.
255330141Sdelphij	 * Note that the byte mask extends from the MSB of a byte down,
256330141Sdelphij	 * and that zero shift (--> mbits % 8 == 0) results in an
257330141Sdelphij	 * all-zero mask.
258330141Sdelphij	 */
259330141Sdelphij	msk = 0xFFu ^ (0xFFu >> (mbits & 7));
260330141Sdelphij	len = mbits >> 3;
261330141Sdelphij
262330141Sdelphij	/* 3rd check: Do memcmp() over full bytes, if any */
263330141Sdelphij	if (len && memcmp(pm1, pm2, len))
264330141Sdelphij		return FALSE;
265330141Sdelphij
266330141Sdelphij	/* 4th check: compare last incomplete byte, if any */
267330141Sdelphij	if (msk && ((pm1[len] ^ pm2[len]) & msk))
268330141Sdelphij		return FALSE;
269330141Sdelphij
270330141Sdelphij	/* If none of the above failed, we're successfully through. */
271330141Sdelphij	return TRUE;
272330141Sdelphij}
273330141Sdelphij
27454359Sroberto/*
27554359Sroberto * init_auth - initialize internal data
27654359Sroberto */
27754359Srobertovoid
27854359Srobertoinit_auth(void)
27954359Sroberto{
280285612Sdelphij	size_t newalloc;
281285612Sdelphij
28254359Sroberto	/*
28354359Sroberto	 * Initialize hash table and free list
28454359Sroberto	 */
285285612Sdelphij	newalloc = authhashbuckets * sizeof(key_hash[0]);
286285612Sdelphij
287285612Sdelphij	key_hash = erealloc(key_hash, newalloc);
288285612Sdelphij	memset(key_hash, '\0', newalloc);
289285612Sdelphij
290285612Sdelphij	INIT_DLIST(key_listhead, llink);
291285612Sdelphij
292285612Sdelphij#ifdef DEBUG
293285612Sdelphij	atexit(&free_auth_mem);
294285612Sdelphij#endif
29554359Sroberto}
29654359Sroberto
29754359Sroberto
29854359Sroberto/*
299285612Sdelphij * free_auth_mem - assist in leak detection by freeing all dynamic
300285612Sdelphij *		   allocations from this module.
301285612Sdelphij */
302285612Sdelphij#ifdef DEBUG
303285612Sdelphijstatic void
304285612Sdelphijfree_auth_mem(void)
305285612Sdelphij{
306285612Sdelphij	symkey *	sk;
307285612Sdelphij	symkey_alloc *	alloc;
308285612Sdelphij	symkey_alloc *	next_alloc;
309285612Sdelphij
310285612Sdelphij	while (NULL != (sk = HEAD_DLIST(key_listhead, llink))) {
311298699Sdelphij		freesymkey(sk);
312285612Sdelphij	}
313285612Sdelphij	free(key_hash);
314285612Sdelphij	key_hash = NULL;
315285612Sdelphij	cache_keyid = 0;
316285612Sdelphij	cache_flags = 0;
317294569Sdelphij	cache_keyacclist = NULL;
318285612Sdelphij	for (alloc = authallocs; alloc != NULL; alloc = next_alloc) {
319285612Sdelphij		next_alloc = alloc->link;
320285612Sdelphij		free(alloc->mem);
321285612Sdelphij	}
322285612Sdelphij	authfreekeys = NULL;
323285612Sdelphij	authnumfreekeys = 0;
324285612Sdelphij}
325285612Sdelphij#endif	/* DEBUG */
326285612Sdelphij
327285612Sdelphij
328285612Sdelphij/*
329285612Sdelphij * auth_moremem - get some more free key structures
330285612Sdelphij */
331285612Sdelphijvoid
332285612Sdelphijauth_moremem(
333285612Sdelphij	int	keycount
334285612Sdelphij	)
335285612Sdelphij{
336285612Sdelphij	symkey *	sk;
337285612Sdelphij	int		i;
338285612Sdelphij#ifdef DEBUG
339285612Sdelphij	void *		base;
340285612Sdelphij	symkey_alloc *	allocrec;
341285612Sdelphij# define MOREMEM_EXTRA_ALLOC	(sizeof(*allocrec))
342285612Sdelphij#else
343285612Sdelphij# define MOREMEM_EXTRA_ALLOC	(0)
344285612Sdelphij#endif
345285612Sdelphij
346285612Sdelphij	i = (keycount > 0)
347285612Sdelphij		? keycount
348285612Sdelphij		: MEMINC;
349316069Sdelphij	sk = eallocarrayxz(i, sizeof(*sk), MOREMEM_EXTRA_ALLOC);
350285612Sdelphij#ifdef DEBUG
351285612Sdelphij	base = sk;
352285612Sdelphij#endif
353285612Sdelphij	authnumfreekeys += i;
354285612Sdelphij
355285612Sdelphij	for (; i > 0; i--, sk++) {
356285612Sdelphij		LINK_SLIST(authfreekeys, sk, llink.f);
357285612Sdelphij	}
358285612Sdelphij
359285612Sdelphij#ifdef DEBUG
360285612Sdelphij	allocrec = (void *)sk;
361285612Sdelphij	allocrec->mem = base;
362285612Sdelphij	LINK_SLIST(authallocs, allocrec, link);
363285612Sdelphij#endif
364285612Sdelphij}
365285612Sdelphij
366285612Sdelphij
367285612Sdelphij/*
368285612Sdelphij * auth_prealloc_symkeys
369285612Sdelphij */
370285612Sdelphijvoid
371285612Sdelphijauth_prealloc_symkeys(
372285612Sdelphij	int	keycount
373285612Sdelphij	)
374285612Sdelphij{
375285612Sdelphij	int	allocated;
376285612Sdelphij	int	additional;
377285612Sdelphij
378285612Sdelphij	allocated = authnumkeys + authnumfreekeys;
379285612Sdelphij	additional = keycount - allocated;
380285612Sdelphij	if (additional > 0)
381285612Sdelphij		auth_moremem(additional);
382285612Sdelphij	auth_resize_hashtable();
383285612Sdelphij}
384285612Sdelphij
385285612Sdelphij
386294569Sdelphijstatic u_short
387294569Sdelphijauth_log2(size_t x)
388285612Sdelphij{
389294569Sdelphij	/*
390294569Sdelphij	** bithack to calculate floor(log2(x))
391294569Sdelphij	**
392294569Sdelphij	** This assumes
393294569Sdelphij	**   - (sizeof(size_t) is a power of two
394294569Sdelphij	**   - CHAR_BITS is a power of two
395294569Sdelphij	**   - returning zero for arguments <= 0 is OK.
396294569Sdelphij	**
397294569Sdelphij	** Does only shifts, masks and sums in integer arithmetic in
398294569Sdelphij	** log2(CHAR_BIT*sizeof(size_t)) steps. (that is, 5/6 steps for
399294569Sdelphij	** 32bit/64bit size_t)
400294569Sdelphij	*/
401294569Sdelphij	int	s;
402294569Sdelphij	int	r = 0;
403294569Sdelphij	size_t  m = ~(size_t)0;
404294569Sdelphij
405294569Sdelphij	for (s = sizeof(size_t) / 2 * CHAR_BIT; s != 0; s >>= 1) {
406294569Sdelphij		m <<= s;
407294569Sdelphij		if (x & m)
408294569Sdelphij			r += s;
409294569Sdelphij		else
410294569Sdelphij			x <<= s;
411294569Sdelphij	}
412294569Sdelphij	return (u_short)r;
413285612Sdelphij}
414285612Sdelphij
415330141Sdelphijint/*BOOL*/
416330141Sdelphijipaddr_match_masked(const sockaddr_u *,const sockaddr_u *,
417330141Sdelphij		    unsigned int mbits);
418330141Sdelphij
419298699Sdelphijstatic void
420298699Sdelphijauthcache_flush_id(
421298699Sdelphij	keyid_t id
422298699Sdelphij	)
423298699Sdelphij{
424298699Sdelphij	if (cache_keyid == id) {
425298699Sdelphij		cache_keyid = 0;
426298699Sdelphij		cache_type = 0;
427298699Sdelphij		cache_flags = 0;
428298699Sdelphij		cache_secret = NULL;
429298699Sdelphij		cache_secretsize = 0;
430298699Sdelphij		cache_keyacclist = NULL;
431298699Sdelphij	}
432298699Sdelphij}
433285612Sdelphij
434298699Sdelphij
435285612Sdelphij/*
436285612Sdelphij * auth_resize_hashtable
437285612Sdelphij *
438285612Sdelphij * Size hash table to average 4 or fewer entries per bucket initially,
439285612Sdelphij * within the bounds of at least 4 and no more than 15 bits for the hash
440285612Sdelphij * table index.  Populate the hash table.
441285612Sdelphij */
442285612Sdelphijstatic void
443285612Sdelphijauth_resize_hashtable(void)
444285612Sdelphij{
445285612Sdelphij	u_long		totalkeys;
446285612Sdelphij	u_short		hashbits;
447285612Sdelphij	u_short		hash;
448285612Sdelphij	size_t		newalloc;
449285612Sdelphij	symkey *	sk;
450285612Sdelphij
451285612Sdelphij	totalkeys = authnumkeys + authnumfreekeys;
452294569Sdelphij	hashbits = auth_log2(totalkeys / 4) + 1;
453285612Sdelphij	hashbits = max(4, hashbits);
454285612Sdelphij	hashbits = min(15, hashbits);
455285612Sdelphij
456285612Sdelphij	authhashbuckets = 1 << hashbits;
457285612Sdelphij	authhashmask = authhashbuckets - 1;
458285612Sdelphij	newalloc = authhashbuckets * sizeof(key_hash[0]);
459285612Sdelphij
460285612Sdelphij	key_hash = erealloc(key_hash, newalloc);
461285612Sdelphij	memset(key_hash, '\0', newalloc);
462285612Sdelphij
463285612Sdelphij	ITER_DLIST_BEGIN(key_listhead, sk, llink, symkey)
464285612Sdelphij		hash = KEYHASH(sk->keyid);
465285612Sdelphij		LINK_SLIST(key_hash[hash], sk, hlink);
466285612Sdelphij	ITER_DLIST_END()
467285612Sdelphij}
468285612Sdelphij
469285612Sdelphij
470285612Sdelphij/*
471285612Sdelphij * allocsymkey - common code to allocate and link in symkey
472285612Sdelphij *
473285612Sdelphij * secret must be allocated with a free-compatible allocator.  It is
474285612Sdelphij * owned by the referring symkey structure, and will be free()d by
475285612Sdelphij * freesymkey().
476285612Sdelphij */
477285612Sdelphijstatic void
478285612Sdelphijallocsymkey(
479285612Sdelphij	keyid_t		id,
480285612Sdelphij	u_short		flags,
481285612Sdelphij	u_short		type,
482285612Sdelphij	u_long		lifetime,
483298699Sdelphij	size_t		secretsize,
484294569Sdelphij	u_char *	secret,
485294569Sdelphij	KeyAccT *	ka
486285612Sdelphij	)
487285612Sdelphij{
488285612Sdelphij	symkey *	sk;
489298699Sdelphij	symkey **	bucket;
490285612Sdelphij
491298699Sdelphij	bucket = &key_hash[KEYHASH(id)];
492298699Sdelphij
493298699Sdelphij
494285612Sdelphij	if (authnumfreekeys < 1)
495285612Sdelphij		auth_moremem(-1);
496285612Sdelphij	UNLINK_HEAD_SLIST(sk, authfreekeys, llink.f);
497285612Sdelphij	DEBUG_ENSURE(sk != NULL);
498285612Sdelphij	sk->keyid = id;
499285612Sdelphij	sk->flags = flags;
500285612Sdelphij	sk->type = type;
501285612Sdelphij	sk->secretsize = secretsize;
502285612Sdelphij	sk->secret = secret;
503294569Sdelphij	sk->keyacclist = ka;
504285612Sdelphij	sk->lifetime = lifetime;
505285612Sdelphij	LINK_SLIST(*bucket, sk, hlink);
506285612Sdelphij	LINK_TAIL_DLIST(key_listhead, sk, llink);
507285612Sdelphij	authnumfreekeys--;
508285612Sdelphij	authnumkeys++;
509285612Sdelphij}
510285612Sdelphij
511285612Sdelphij
512285612Sdelphij/*
513285612Sdelphij * freesymkey - common code to remove a symkey and recycle its entry.
514285612Sdelphij */
515285612Sdelphijstatic void
516285612Sdelphijfreesymkey(
517298699Sdelphij	symkey *	sk
518285612Sdelphij	)
519285612Sdelphij{
520298699Sdelphij	symkey **	bucket;
521285612Sdelphij	symkey *	unlinked;
522285612Sdelphij
523298699Sdelphij	if (NULL == sk)
524298699Sdelphij		return;
525298699Sdelphij
526298699Sdelphij	authcache_flush_id(sk->keyid);
527298699Sdelphij	keyacc_all_free(sk->keyacclist);
528298699Sdelphij
529298699Sdelphij	bucket = &key_hash[KEYHASH(sk->keyid)];
530285612Sdelphij	if (sk->secret != NULL) {
531285612Sdelphij		memset(sk->secret, '\0', sk->secretsize);
532285612Sdelphij		free(sk->secret);
533285612Sdelphij	}
534285612Sdelphij	UNLINK_SLIST(unlinked, *bucket, sk, hlink, symkey);
535285612Sdelphij	DEBUG_ENSURE(sk == unlinked);
536285612Sdelphij	UNLINK_DLIST(sk, llink);
537285612Sdelphij	memset((char *)sk + offsetof(symkey, symkey_payload), '\0',
538285612Sdelphij	       sizeof(*sk) - offsetof(symkey, symkey_payload));
539285612Sdelphij	LINK_SLIST(authfreekeys, sk, llink.f);
540285612Sdelphij	authnumkeys--;
541285612Sdelphij	authnumfreekeys++;
542285612Sdelphij}
543285612Sdelphij
544285612Sdelphij
545285612Sdelphij/*
54654359Sroberto * auth_findkey - find a key in the hash table
54754359Sroberto */
54854359Srobertostruct savekey *
54954359Srobertoauth_findkey(
550285612Sdelphij	keyid_t		id
55154359Sroberto	)
55254359Sroberto{
553285612Sdelphij	symkey *	sk;
55454359Sroberto
555298699Sdelphij	for (sk = key_hash[KEYHASH(id)]; sk != NULL; sk = sk->hlink)
556298699Sdelphij		if (id == sk->keyid)
557285612Sdelphij			return sk;
558285612Sdelphij	return NULL;
55954359Sroberto}
56054359Sroberto
56154359Sroberto
56254359Sroberto/*
563298699Sdelphij * auth_havekey - return TRUE if the key id is zero or known. The
564298699Sdelphij * key needs not to be trusted.
56554359Sroberto */
56654359Srobertoint
56754359Srobertoauth_havekey(
568285612Sdelphij	keyid_t		id
56954359Sroberto	)
57054359Sroberto{
571298699Sdelphij	return
572298699Sdelphij	    (0           == id) ||
573298699Sdelphij	    (cache_keyid == id) ||
574298699Sdelphij	    (NULL        != auth_findkey(id));
57554359Sroberto}
57654359Sroberto
57754359Sroberto
57854359Sroberto/*
579285612Sdelphij * authhavekey - return TRUE and cache the key, if zero or both known
580285612Sdelphij *		 and trusted.
58154359Sroberto */
58254359Srobertoint
58354359Srobertoauthhavekey(
584285612Sdelphij	keyid_t		id
58554359Sroberto	)
58654359Sroberto{
587285612Sdelphij	symkey *	sk;
58854359Sroberto
58954359Sroberto	authkeylookups++;
590298699Sdelphij	if (0 == id || cache_keyid == id)
591298699Sdelphij		return !!(KEY_TRUSTED & cache_flags);
59254359Sroberto
593285612Sdelphij	/*
594298699Sdelphij	 * Search the bin for the key. If not found, or found but the key
595298699Sdelphij	 * type is zero, somebody marked it trusted without specifying a
596298699Sdelphij	 * key or key type. In this case consider the key missing.
597285612Sdelphij	 */
59854359Sroberto	authkeyuncached++;
599298699Sdelphij	sk = auth_findkey(id);
600298699Sdelphij	if ((sk == NULL) || (sk->type == 0)) {
601298699Sdelphij		authkeynotfound++;
602298699Sdelphij		return FALSE;
60354359Sroberto	}
604285612Sdelphij
605285612Sdelphij	/*
606298699Sdelphij	 * If the key is not trusted, the key is not considered found.
607285612Sdelphij	 */
608298699Sdelphij	if ( ! (KEY_TRUSTED & sk->flags)) {
60954359Sroberto		authnokey++;
610285612Sdelphij		return FALSE;
61154359Sroberto	}
612285612Sdelphij
613285612Sdelphij	/*
614285612Sdelphij	 * The key is found and trusted. Initialize the key cache.
615285612Sdelphij	 */
61654359Sroberto	cache_keyid = sk->keyid;
617285612Sdelphij	cache_type = sk->type;
61854359Sroberto	cache_flags = sk->flags;
619285612Sdelphij	cache_secret = sk->secret;
620285612Sdelphij	cache_secretsize = sk->secretsize;
621294569Sdelphij	cache_keyacclist = sk->keyacclist;
62254359Sroberto
623285612Sdelphij	return TRUE;
62454359Sroberto}
62554359Sroberto
62654359Sroberto
62754359Sroberto/*
62854359Sroberto * authtrust - declare a key to be trusted/untrusted
62954359Sroberto */
63054359Srobertovoid
63154359Srobertoauthtrust(
632285612Sdelphij	keyid_t		id,
633285612Sdelphij	u_long		trust
63454359Sroberto	)
63554359Sroberto{
636285612Sdelphij	symkey *	sk;
637285612Sdelphij	u_long		lifetime;
63854359Sroberto
639285612Sdelphij	/*
640285612Sdelphij	 * Search bin for key; if it does not exist and is untrusted,
641285612Sdelphij	 * forget it.
642285612Sdelphij	 */
643298699Sdelphij
644298699Sdelphij	sk = auth_findkey(id);
645298699Sdelphij	if (!trust && sk == NULL)
646285612Sdelphij		return;
64754359Sroberto
648285612Sdelphij	/*
649285612Sdelphij	 * There are two conditions remaining. Either it does not
650285612Sdelphij	 * exist and is to be trusted or it does exist and is or is
651285612Sdelphij	 * not to be trusted.
652285612Sdelphij	 */
653285612Sdelphij	if (sk != NULL) {
654285612Sdelphij		/*
655298699Sdelphij		 * Key exists. If it is to be trusted, say so and update
656298699Sdelphij		 * its lifetime. If no longer trusted, return it to the
657298699Sdelphij		 * free list. Flush the cache first to be sure there are
658298699Sdelphij		 * no discrepancies.
659285612Sdelphij		 */
660298699Sdelphij		authcache_flush_id(id);
66154359Sroberto		if (trust > 0) {
66254359Sroberto			sk->flags |= KEY_TRUSTED;
66354359Sroberto			if (trust > 1)
66454359Sroberto				sk->lifetime = current_time + trust;
66554359Sroberto			else
66654359Sroberto				sk->lifetime = 0;
667298699Sdelphij		} else {
668298699Sdelphij			freesymkey(sk);
66954359Sroberto		}
67054359Sroberto		return;
67154359Sroberto	}
67254359Sroberto
673285612Sdelphij	/*
674285612Sdelphij	 * keyid is not present, but the is to be trusted.  We allocate
675285612Sdelphij	 * a new key, but do not specify a key type or secret.
676285612Sdelphij	 */
677285612Sdelphij	if (trust > 1) {
678285612Sdelphij		lifetime = current_time + trust;
679285612Sdelphij	} else {
680285612Sdelphij		lifetime = 0;
681285612Sdelphij	}
682298699Sdelphij	allocsymkey(id, KEY_TRUSTED, 0, lifetime, 0, NULL, NULL);
68354359Sroberto}
68454359Sroberto
68554359Sroberto
68654359Sroberto/*
68754359Sroberto * authistrusted - determine whether a key is trusted
68854359Sroberto */
68954359Srobertoint
69054359Srobertoauthistrusted(
691298699Sdelphij	keyid_t		id
69254359Sroberto	)
69354359Sroberto{
694285612Sdelphij	symkey *	sk;
69554359Sroberto
696298699Sdelphij	if (id == cache_keyid)
697285612Sdelphij		return !!(KEY_TRUSTED & cache_flags);
69854359Sroberto
69954359Sroberto	authkeyuncached++;
700298699Sdelphij	sk = auth_findkey(id);
701298699Sdelphij	if (sk == NULL || !(KEY_TRUSTED & sk->flags)) {
70254359Sroberto		authkeynotfound++;
703285612Sdelphij		return FALSE;
70454359Sroberto	}
705285612Sdelphij	return TRUE;
70654359Sroberto}
70754359Sroberto
708294569Sdelphij
709294569Sdelphij/*
710294569Sdelphij * authistrustedip - determine if the IP is OK for the keyid
711294569Sdelphij */
712294569Sdelphij int
713294569Sdelphij authistrustedip(
714294569Sdelphij 	keyid_t		keyno,
715294569Sdelphij	sockaddr_u *	sau
716294569Sdelphij	)
717294569Sdelphij{
718294569Sdelphij	symkey *	sk;
719294569Sdelphij
720298699Sdelphij	if (keyno == cache_keyid) {
721298699Sdelphij		return (KEY_TRUSTED & cache_flags) &&
722298699Sdelphij		    keyacc_contains(cache_keyacclist, sau, TRUE);
723330141Sdelphij	}
724330141Sdelphij
725330141Sdelphij	if (NULL != (sk = auth_findkey(keyno))) {
726294569Sdelphij		authkeyuncached++;
727298699Sdelphij		return (KEY_TRUSTED & sk->flags) &&
728298699Sdelphij		    keyacc_contains(sk->keyacclist, sau, TRUE);
729294569Sdelphij	}
730330141Sdelphij
731330141Sdelphij	authkeynotfound++;
732330141Sdelphij	return FALSE;
733294569Sdelphij}
734294569Sdelphij
735293650Sglebius/* Note: There are two locations below where 'strncpy()' is used. While
736293650Sglebius * this function is a hazard by itself, it's essential that it is used
737293650Sglebius * here. Bug 1243 involved that the secret was filled with NUL bytes
738293650Sglebius * after the first NUL encountered, and 'strlcpy()' simply does NOT have
739293650Sglebius * this behaviour. So disabling the fix and reverting to the buggy
740293650Sglebius * behaviour due to compatibility issues MUST also fill with NUL and
741293650Sglebius * this needs 'strncpy'. Also, the secret is managed as a byte blob of a
742293650Sglebius * given size, and eventually truncating it and replacing the last byte
743293650Sglebius * with a NUL would be a bug.
744293650Sglebius * perlinger@ntp.org 2015-10-10
745293650Sglebius */
74654359Srobertovoid
74754359SrobertoMD5auth_setkey(
74882498Sroberto	keyid_t keyno,
749285612Sdelphij	int	keytype,
75054359Sroberto	const u_char *key,
751298699Sdelphij	size_t secretsize,
752294569Sdelphij	KeyAccT *ka
75354359Sroberto	)
75454359Sroberto{
755285612Sdelphij	symkey *	sk;
756285612Sdelphij	u_char *	secret;
75754359Sroberto
758285612Sdelphij	DEBUG_ENSURE(keytype <= USHRT_MAX);
759298699Sdelphij	DEBUG_ENSURE(secretsize < 4 * 1024);
76054359Sroberto	/*
76154359Sroberto	 * See if we already have the key.  If so just stick in the
76254359Sroberto	 * new value.
76354359Sroberto	 */
764298699Sdelphij	sk = auth_findkey(keyno);
765298699Sdelphij	if (sk != NULL && keyno == sk->keyid) {
766289997Sglebius			/* TALOS-CAN-0054: make sure we have a new buffer! */
767298699Sdelphij		if (NULL != sk->secret) {
768298699Sdelphij			memset(sk->secret, 0, sk->secretsize);
769298699Sdelphij			free(sk->secret);
770298699Sdelphij		}
771298699Sdelphij		sk->secret = emalloc(secretsize + 1);
772298699Sdelphij		sk->type = (u_short)keytype;
773298699Sdelphij		sk->secretsize = secretsize;
774298699Sdelphij		/* make sure access lists don't leak here! */
775298699Sdelphij		if (ka != sk->keyacclist) {
776298699Sdelphij			keyacc_all_free(sk->keyacclist);
777294569Sdelphij			sk->keyacclist = ka;
778298699Sdelphij		}
779285612Sdelphij#ifndef DISABLE_BUG1243_FIX
780298699Sdelphij		memcpy(sk->secret, key, secretsize);
781285612Sdelphij#else
782298699Sdelphij		/* >MUST< use 'strncpy()' here! See above! */
783298699Sdelphij		strncpy((char *)sk->secret, (const char *)key,
784298699Sdelphij			secretsize);
785285612Sdelphij#endif
786298699Sdelphij		authcache_flush_id(keyno);
787298699Sdelphij		return;
78854359Sroberto	}
78954359Sroberto
79054359Sroberto	/*
79154359Sroberto	 * Need to allocate new structure.  Do it.
79254359Sroberto	 */
793298699Sdelphij	secret = emalloc(secretsize + 1);
794285612Sdelphij#ifndef DISABLE_BUG1243_FIX
795285612Sdelphij	memcpy(secret, key, secretsize);
796285612Sdelphij#else
797293650Sglebius	/* >MUST< use 'strncpy()' here! See above! */
798293650Sglebius	strncpy((char *)secret, (const char *)key, secretsize);
799285612Sdelphij#endif
800298699Sdelphij	allocsymkey(keyno, 0, (u_short)keytype, 0,
801298699Sdelphij		    secretsize, secret, ka);
802285612Sdelphij#ifdef DEBUG
803285612Sdelphij	if (debug >= 4) {
804285612Sdelphij		size_t	j;
80554359Sroberto
806285612Sdelphij		printf("auth_setkey: key %d type %d len %d ", (int)keyno,
807285612Sdelphij		    keytype, (int)secretsize);
808298699Sdelphij		for (j = 0; j < secretsize; j++) {
809285612Sdelphij			printf("%02x", secret[j]);
810298699Sdelphij		}
811285612Sdelphij		printf("\n");
812285612Sdelphij	}
813285612Sdelphij#endif
814285612Sdelphij}
81554359Sroberto
81654359Sroberto
81754359Sroberto/*
818285612Sdelphij * auth_delkeys - delete non-autokey untrusted keys, and clear all info
819285612Sdelphij *                except the trusted bit of non-autokey trusted keys, in
820285612Sdelphij *		  preparation for rereading the keys file.
82154359Sroberto */
82254359Srobertovoid
82354359Srobertoauth_delkeys(void)
82454359Sroberto{
825285612Sdelphij	symkey *	sk;
82654359Sroberto
827285612Sdelphij	ITER_DLIST_BEGIN(key_listhead, sk, llink, symkey)
828285612Sdelphij		if (sk->keyid > NTP_MAXKEY) {	/* autokey */
829285612Sdelphij			continue;
830285612Sdelphij		}
831285612Sdelphij
83254359Sroberto		/*
833289997Sglebius		 * Don't lose info as to which keys are trusted. Make
834289997Sglebius		 * sure there are no dangling pointers!
83554359Sroberto		 */
836285612Sdelphij		if (KEY_TRUSTED & sk->flags) {
837285612Sdelphij			if (sk->secret != NULL) {
838289997Sglebius				memset(sk->secret, 0, sk->secretsize);
839285612Sdelphij				free(sk->secret);
840289997Sglebius				sk->secret = NULL; /* TALOS-CAN-0054 */
84154359Sroberto			}
842298699Sdelphij			sk->keyacclist = keyacc_all_free(sk->keyacclist);
843285612Sdelphij			sk->secretsize = 0;
844285612Sdelphij			sk->lifetime = 0;
845285612Sdelphij		} else {
846298699Sdelphij			freesymkey(sk);
84754359Sroberto		}
848285612Sdelphij	ITER_DLIST_END()
84954359Sroberto}
85054359Sroberto
851285612Sdelphij
85254359Sroberto/*
85354359Sroberto * auth_agekeys - delete keys whose lifetimes have expired
85454359Sroberto */
85554359Srobertovoid
85654359Srobertoauth_agekeys(void)
85754359Sroberto{
858285612Sdelphij	symkey *	sk;
85954359Sroberto
860285612Sdelphij	ITER_DLIST_BEGIN(key_listhead, sk, llink, symkey)
861285612Sdelphij		if (sk->lifetime > 0 && current_time > sk->lifetime) {
862298699Sdelphij			freesymkey(sk);
863285612Sdelphij			authkeyexpired++;
86454359Sroberto		}
865285612Sdelphij	ITER_DLIST_END()
866285612Sdelphij	DPRINTF(1, ("auth_agekeys: at %lu keys %lu expired %lu\n",
867285612Sdelphij		    current_time, authnumkeys, authkeyexpired));
86854359Sroberto}
86954359Sroberto
870285612Sdelphij
87154359Sroberto/*
87254359Sroberto * authencrypt - generate message authenticator
87354359Sroberto *
87454359Sroberto * Returns length of authenticator field, zero if key not found.
87554359Sroberto */
876293650Sglebiussize_t
87754359Srobertoauthencrypt(
878285612Sdelphij	keyid_t		keyno,
879285612Sdelphij	u_int32 *	pkt,
880293650Sglebius	size_t		length
88154359Sroberto	)
882293650Sglebius{
88354359Sroberto	/*
88454359Sroberto	 * A zero key identifier means the sender has not verified
88554359Sroberto	 * the last message was correctly authenticated. The MAC
88654359Sroberto	 * consists of a single word with value zero.
88754359Sroberto	 */
88854359Sroberto	authencryptions++;
88982498Sroberto	pkt[length / 4] = htonl(keyno);
890285612Sdelphij	if (0 == keyno) {
891285612Sdelphij		return 4;
89254359Sroberto	}
893285612Sdelphij	if (!authhavekey(keyno)) {
894285612Sdelphij		return 0;
895285612Sdelphij	}
89654359Sroberto
897330141Sdelphij	return MD5authencrypt(cache_type,
898330141Sdelphij			      cache_secret, cache_secretsize,
899330141Sdelphij			      pkt, length);
90054359Sroberto}
90154359Sroberto
902285612Sdelphij
90354359Sroberto/*
90454359Sroberto * authdecrypt - verify message authenticator
90554359Sroberto *
906285612Sdelphij * Returns TRUE if authenticator valid, FALSE if invalid or not found.
90754359Sroberto */
90854359Srobertoint
90954359Srobertoauthdecrypt(
910285612Sdelphij	keyid_t		keyno,
911285612Sdelphij	u_int32 *	pkt,
912293650Sglebius	size_t		length,
913293650Sglebius	size_t		size
91454359Sroberto	)
91554359Sroberto{
91654359Sroberto	/*
91754359Sroberto	 * A zero key identifier means the sender has not verified
918285612Sdelphij	 * the last message was correctly authenticated.  For our
919285612Sdelphij	 * purpose this is an invalid authenticator.
92054359Sroberto	 */
92154359Sroberto	authdecryptions++;
922285612Sdelphij	if (0 == keyno || !authhavekey(keyno) || size < 4) {
923285612Sdelphij		return FALSE;
924285612Sdelphij	}
92554359Sroberto
926330141Sdelphij	return MD5authdecrypt(cache_type,
927330141Sdelphij			      cache_secret, cache_secretsize,
928330141Sdelphij			      pkt, length, size);
92954359Sroberto}
930