xref: /freebsd/contrib/ntp/libntp/authkeys.c (revision a466cc55373fc3cf86837f09da729535b57e69a1)
1c0b746e5SOllivier Robert /*
2c0b746e5SOllivier Robert  * authkeys.c - routines to manage the storage of authentication keys
3c0b746e5SOllivier Robert  */
4c0b746e5SOllivier Robert #ifdef HAVE_CONFIG_H
5c0b746e5SOllivier Robert # include <config.h>
6c0b746e5SOllivier Robert #endif
7c0b746e5SOllivier Robert 
82b15cb3dSCy Schubert #include <math.h>
9c0b746e5SOllivier Robert #include <stdio.h>
10c0b746e5SOllivier Robert 
11c0b746e5SOllivier Robert #include "ntp.h"
122b15cb3dSCy Schubert #include "ntp_fp.h"
13c0b746e5SOllivier Robert #include "ntpd.h"
142b15cb3dSCy Schubert #include "ntp_lists.h"
15c0b746e5SOllivier Robert #include "ntp_string.h"
16c0b746e5SOllivier Robert #include "ntp_malloc.h"
17c0b746e5SOllivier Robert #include "ntp_stdlib.h"
1868ba7e87SXin LI #include "ntp_keyacc.h"
19c0b746e5SOllivier Robert 
20c0b746e5SOllivier Robert /*
21c0b746e5SOllivier Robert  * Structure to store keys in in the hash table.
22c0b746e5SOllivier Robert  */
232b15cb3dSCy Schubert typedef struct savekey symkey;
242b15cb3dSCy Schubert 
25c0b746e5SOllivier Robert struct savekey {
262b15cb3dSCy Schubert 	symkey *	hlink;		/* next in hash bucket */
272b15cb3dSCy Schubert 	DECL_DLIST_LINK(symkey, llink);	/* for overall & free lists */
282b15cb3dSCy Schubert 	u_char *	secret;		/* shared secret */
2968ba7e87SXin LI 	KeyAccT *	keyacclist;	/* Private key access list */
30c0b746e5SOllivier Robert 	u_long		lifetime;	/* remaining lifetime */
312b15cb3dSCy Schubert 	keyid_t		keyid;		/* key identifier */
322b15cb3dSCy Schubert 	u_short		type;		/* OpenSSL digest NID */
334990d495SXin LI 	size_t		secretsize;	/* secret octets */
342b15cb3dSCy Schubert 	u_short		flags;		/* KEY_ flags that wave */
35c0b746e5SOllivier Robert };
36c0b746e5SOllivier Robert 
372b15cb3dSCy Schubert /* define the payload region of symkey beyond the list pointers */
382b15cb3dSCy Schubert #define symkey_payload	secret
39c0b746e5SOllivier Robert 
402b15cb3dSCy Schubert #define	KEY_TRUSTED	0x001	/* this key is trusted */
412b15cb3dSCy Schubert 
422b15cb3dSCy Schubert #ifdef DEBUG
432b15cb3dSCy Schubert typedef struct symkey_alloc_tag symkey_alloc;
442b15cb3dSCy Schubert 
452b15cb3dSCy Schubert struct symkey_alloc_tag {
462b15cb3dSCy Schubert 	symkey_alloc *	link;
472b15cb3dSCy Schubert 	void *		mem;		/* enable free() atexit */
482b15cb3dSCy Schubert };
492b15cb3dSCy Schubert 
502b15cb3dSCy Schubert symkey_alloc *	authallocs;
512b15cb3dSCy Schubert #endif	/* DEBUG */
522b15cb3dSCy Schubert 
5368ba7e87SXin LI static u_short	auth_log2(size_t);
542b15cb3dSCy Schubert static void		auth_resize_hashtable(void);
554990d495SXin LI static void		allocsymkey(keyid_t,	u_short,
564990d495SXin LI 				    u_short, u_long, size_t, u_char *, KeyAccT *);
574990d495SXin LI static void		freesymkey(symkey *);
582b15cb3dSCy Schubert #ifdef DEBUG
592b15cb3dSCy Schubert static void		free_auth_mem(void);
602b15cb3dSCy Schubert #endif
612b15cb3dSCy Schubert 
622b15cb3dSCy Schubert symkey	key_listhead;		/* list of all in-use keys */;
63c0b746e5SOllivier Robert /*
64c0b746e5SOllivier Robert  * The hash table. This is indexed by the low order bits of the
65c0b746e5SOllivier Robert  * keyid. We make this fairly big for potentially busy servers.
66c0b746e5SOllivier Robert  */
672b15cb3dSCy Schubert #define	DEF_AUTHHASHSIZE	64
683311ff84SXin LI /*#define	HASHMASK	((HASHSIZE)-1)*/
692b15cb3dSCy Schubert #define	KEYHASH(keyid)	((keyid) & authhashmask)
70c0b746e5SOllivier Robert 
712b15cb3dSCy Schubert int	authhashdisabled;
722b15cb3dSCy Schubert u_short	authhashbuckets = DEF_AUTHHASHSIZE;
732b15cb3dSCy Schubert u_short authhashmask = DEF_AUTHHASHSIZE - 1;
742b15cb3dSCy Schubert symkey **key_hash;
75c0b746e5SOllivier Robert 
76c0b746e5SOllivier Robert u_long authkeynotfound;		/* keys not found */
77c0b746e5SOllivier Robert u_long authkeylookups;		/* calls to lookup keys */
78c0b746e5SOllivier Robert u_long authnumkeys;		/* number of active keys */
79c0b746e5SOllivier Robert u_long authkeyexpired;		/* key lifetime expirations */
80c0b746e5SOllivier Robert u_long authkeyuncached;		/* cache misses */
81c0b746e5SOllivier Robert u_long authnokey;		/* calls to encrypt with no key */
82c0b746e5SOllivier Robert u_long authencryptions;		/* calls to encrypt */
83c0b746e5SOllivier Robert u_long authdecryptions;		/* calls to decrypt */
84c0b746e5SOllivier Robert 
85c0b746e5SOllivier Robert /*
862b15cb3dSCy Schubert  * Storage for free symkey structures.  We malloc() such things but
87c0b746e5SOllivier Robert  * never free them.
88c0b746e5SOllivier Robert  */
892b15cb3dSCy Schubert symkey *authfreekeys;
90c0b746e5SOllivier Robert int authnumfreekeys;
91c0b746e5SOllivier Robert 
922b15cb3dSCy Schubert #define	MEMINC	16		/* number of new free ones to get */
93c0b746e5SOllivier Robert 
94c0b746e5SOllivier Robert /*
95c0b746e5SOllivier Robert  * The key cache. We cache the last key we looked at here.
964990d495SXin LI  * Note: this should hold the last *trusted* key. Also the
974990d495SXin LI  * cache is only loaded when the digest type / MAC algorithm
984990d495SXin LI  * is valid.
99c0b746e5SOllivier Robert  */
100224ba2bdSOllivier Robert keyid_t	cache_keyid;		/* key identifier */
1012b15cb3dSCy Schubert u_char *cache_secret;		/* secret */
1024990d495SXin LI size_t	cache_secretsize;	/* secret length */
1032b15cb3dSCy Schubert int	cache_type;		/* OpenSSL digest NID */
104c0b746e5SOllivier Robert u_short cache_flags;		/* flags that wave */
10568ba7e87SXin LI KeyAccT *cache_keyacclist;	/* key access list */
106c0b746e5SOllivier Robert 
1074990d495SXin LI /* --------------------------------------------------------------------
1084990d495SXin LI  * manage key access lists
1094990d495SXin LI  * --------------------------------------------------------------------
1104990d495SXin LI  */
1114990d495SXin LI /* allocate and populate new access node and pushes it on the list.
1124990d495SXin LI  * Returns the new head.
1134990d495SXin LI  */
1144990d495SXin LI KeyAccT*
1154990d495SXin LI keyacc_new_push(
1164990d495SXin LI 	KeyAccT          * head,
11709100258SXin LI 	const sockaddr_u * addr,
11809100258SXin LI 	unsigned int	   subnetbits
1194990d495SXin LI 	)
1204990d495SXin LI {
1214990d495SXin LI 	KeyAccT *	node = emalloc(sizeof(KeyAccT));
1224990d495SXin LI 
1234990d495SXin LI 	memcpy(&node->addr, addr, sizeof(sockaddr_u));
12409100258SXin LI 	node->subnetbits = subnetbits;
1254990d495SXin LI 	node->next = head;
12609100258SXin LI 
1274990d495SXin LI 	return node;
1284990d495SXin LI }
1294990d495SXin LI 
1304990d495SXin LI /* ----------------------------------------------------------------- */
1314990d495SXin LI /* pop and deallocate the first node of a list of access nodes, if
1324990d495SXin LI  * the list is not empty. Returns the tail of the list.
1334990d495SXin LI  */
1344990d495SXin LI KeyAccT*
1354990d495SXin LI keyacc_pop_free(
1364990d495SXin LI 	KeyAccT *head
1374990d495SXin LI 	)
1384990d495SXin LI {
1394990d495SXin LI 	KeyAccT *	next = NULL;
1404990d495SXin LI 	if (head) {
1414990d495SXin LI 		next = head->next;
1424990d495SXin LI 		free(head);
1434990d495SXin LI 	}
1444990d495SXin LI 	return next;
1454990d495SXin LI }
1464990d495SXin LI 
1474990d495SXin LI /* ----------------------------------------------------------------- */
1484990d495SXin LI /* deallocate the list; returns an empty list. */
1494990d495SXin LI KeyAccT*
1504990d495SXin LI keyacc_all_free(
1514990d495SXin LI 	KeyAccT * head
1524990d495SXin LI 	)
1534990d495SXin LI {
1544990d495SXin LI 	while (head)
1554990d495SXin LI 		head = keyacc_pop_free(head);
1564990d495SXin LI 	return head;
1574990d495SXin LI }
1584990d495SXin LI 
1594990d495SXin LI /* ----------------------------------------------------------------- */
1604990d495SXin LI /* scan a list to see if it contains a given address. Return the
1614990d495SXin LI  * default result value in case of an empty list.
1624990d495SXin LI  */
1634990d495SXin LI int /*BOOL*/
1644990d495SXin LI keyacc_contains(
1654990d495SXin LI 	const KeyAccT    *head,
1664990d495SXin LI 	const sockaddr_u *addr,
1674990d495SXin LI 	int               defv)
1684990d495SXin LI {
1694990d495SXin LI 	if (head) {
1704990d495SXin LI 		do {
17109100258SXin LI 			if (keyacc_amatch(&head->addr, addr,
17209100258SXin LI 					  head->subnetbits))
1734990d495SXin LI 				return TRUE;
1744990d495SXin LI 		} while (NULL != (head = head->next));
1754990d495SXin LI 		return FALSE;
1764990d495SXin LI 	} else {
1774990d495SXin LI 		return !!defv;
1784990d495SXin LI 	}
1794990d495SXin LI }
1804990d495SXin LI 
18109100258SXin LI #if CHAR_BIT != 8
18209100258SXin LI # error "don't know how to handle bytes with that bit size"
18309100258SXin LI #endif
18409100258SXin LI 
18509100258SXin LI /* ----------------------------------------------------------------- */
18609100258SXin LI /* check two addresses for a match, taking a prefix length into account
18709100258SXin LI  * when doing the compare.
18809100258SXin LI  *
18909100258SXin LI  * The ISC lib contains a similar function with not entirely specified
19009100258SXin LI  * semantics, so it seemed somewhat cleaner to do this from scratch.
19109100258SXin LI  *
19209100258SXin LI  * Note 1: It *is* assumed that the addresses are stored in network byte
19309100258SXin LI  * order, that is, most significant byte first!
19409100258SXin LI  *
19509100258SXin LI  * Note 2: "no address" compares unequal to all other addresses, even to
19609100258SXin LI  * itself. This has the same semantics as NaNs have for floats: *any*
19709100258SXin LI  * relational or equality operation involving a NaN returns FALSE, even
19809100258SXin LI  * equality with itself. "no address" is either a NULL pointer argument
19909100258SXin LI  * or an address of type AF_UNSPEC.
20009100258SXin LI  */
20109100258SXin LI int/*BOOL*/
20209100258SXin LI keyacc_amatch(
20309100258SXin LI 	const sockaddr_u *	a1,
20409100258SXin LI 	const sockaddr_u *	a2,
20509100258SXin LI 	unsigned int		mbits
20609100258SXin LI 	)
20709100258SXin LI {
20809100258SXin LI 	const uint8_t * pm1;
20909100258SXin LI 	const uint8_t * pm2;
21009100258SXin LI 	uint8_t         msk;
21109100258SXin LI 	unsigned int    len;
21209100258SXin LI 
21309100258SXin LI 	/* 1st check: If any address is not an address, it's inequal. */
21409100258SXin LI 	if ( !a1 || (AF_UNSPEC == AF(a1)) ||
21509100258SXin LI 	     !a2 || (AF_UNSPEC == AF(a2))  )
21609100258SXin LI 		return FALSE;
21709100258SXin LI 
21809100258SXin LI 	/* We could check pointers for equality here and shortcut the
21909100258SXin LI 	 * other checks if we find object identity. But that use case is
22009100258SXin LI 	 * too rare to care for it.
22109100258SXin LI 	 */
22209100258SXin LI 
22309100258SXin LI 	/* 2nd check: Address families must be the same. */
22409100258SXin LI 	if (AF(a1) != AF(a2))
22509100258SXin LI 		return FALSE;
22609100258SXin LI 
22709100258SXin LI 	/* type check: address family determines buffer & size */
22809100258SXin LI 	switch (AF(a1)) {
22909100258SXin LI 	case AF_INET:
23009100258SXin LI 		/* IPv4 is easy: clamp size, get byte pointers */
23109100258SXin LI 		if (mbits > sizeof(NSRCADR(a1)) * 8)
23209100258SXin LI 			mbits = sizeof(NSRCADR(a1)) * 8;
23309100258SXin LI 		pm1 = (const void*)&NSRCADR(a1);
23409100258SXin LI 		pm2 = (const void*)&NSRCADR(a2);
23509100258SXin LI 		break;
23609100258SXin LI 
23709100258SXin LI 	case AF_INET6:
23809100258SXin LI 		/* IPv6 is slightly different: Both scopes must match,
23909100258SXin LI 		 * too, before we even consider doing a match!
24009100258SXin LI 		 */
24109100258SXin LI 		if ( ! SCOPE_EQ(a1, a2))
24209100258SXin LI 			return FALSE;
24309100258SXin LI 		if (mbits > sizeof(NSRCADR6(a1)) * 8)
24409100258SXin LI 			mbits = sizeof(NSRCADR6(a1)) * 8;
24509100258SXin LI 		pm1 = (const void*)&NSRCADR6(a1);
24609100258SXin LI 		pm2 = (const void*)&NSRCADR6(a2);
24709100258SXin LI 		break;
24809100258SXin LI 
24909100258SXin LI 	default:
25009100258SXin LI 		/* don't know how to compare that!?! */
25109100258SXin LI 		return FALSE;
25209100258SXin LI 	}
25309100258SXin LI 
25409100258SXin LI 	/* Split bit length into byte length and partial byte mask.
25509100258SXin LI 	 * Note that the byte mask extends from the MSB of a byte down,
25609100258SXin LI 	 * and that zero shift (--> mbits % 8 == 0) results in an
25709100258SXin LI 	 * all-zero mask.
25809100258SXin LI 	 */
25909100258SXin LI 	msk = 0xFFu ^ (0xFFu >> (mbits & 7));
26009100258SXin LI 	len = mbits >> 3;
26109100258SXin LI 
26209100258SXin LI 	/* 3rd check: Do memcmp() over full bytes, if any */
26309100258SXin LI 	if (len && memcmp(pm1, pm2, len))
26409100258SXin LI 		return FALSE;
26509100258SXin LI 
26609100258SXin LI 	/* 4th check: compare last incomplete byte, if any */
26709100258SXin LI 	if (msk && ((pm1[len] ^ pm2[len]) & msk))
26809100258SXin LI 		return FALSE;
26909100258SXin LI 
27009100258SXin LI 	/* If none of the above failed, we're successfully through. */
27109100258SXin LI 	return TRUE;
27209100258SXin LI }
273c0b746e5SOllivier Robert 
274c0b746e5SOllivier Robert /*
275c0b746e5SOllivier Robert  * init_auth - initialize internal data
276c0b746e5SOllivier Robert  */
277c0b746e5SOllivier Robert void
278c0b746e5SOllivier Robert init_auth(void)
279c0b746e5SOllivier Robert {
2802b15cb3dSCy Schubert 	size_t newalloc;
2812b15cb3dSCy Schubert 
282c0b746e5SOllivier Robert 	/*
283c0b746e5SOllivier Robert 	 * Initialize hash table and free list
284c0b746e5SOllivier Robert 	 */
2852b15cb3dSCy Schubert 	newalloc = authhashbuckets * sizeof(key_hash[0]);
2862b15cb3dSCy Schubert 
2872b15cb3dSCy Schubert 	key_hash = erealloc(key_hash, newalloc);
2882b15cb3dSCy Schubert 	memset(key_hash, '\0', newalloc);
2892b15cb3dSCy Schubert 
2902b15cb3dSCy Schubert 	INIT_DLIST(key_listhead, llink);
2912b15cb3dSCy Schubert 
2922b15cb3dSCy Schubert #ifdef DEBUG
2932b15cb3dSCy Schubert 	atexit(&free_auth_mem);
2942b15cb3dSCy Schubert #endif
2952b15cb3dSCy Schubert }
2962b15cb3dSCy Schubert 
2972b15cb3dSCy Schubert 
2982b15cb3dSCy Schubert /*
2992b15cb3dSCy Schubert  * free_auth_mem - assist in leak detection by freeing all dynamic
3002b15cb3dSCy Schubert  *		   allocations from this module.
3012b15cb3dSCy Schubert  */
3022b15cb3dSCy Schubert #ifdef DEBUG
3032b15cb3dSCy Schubert static void
3042b15cb3dSCy Schubert free_auth_mem(void)
3052b15cb3dSCy Schubert {
3062b15cb3dSCy Schubert 	symkey *	sk;
3072b15cb3dSCy Schubert 	symkey_alloc *	alloc;
3082b15cb3dSCy Schubert 	symkey_alloc *	next_alloc;
3092b15cb3dSCy Schubert 
3102b15cb3dSCy Schubert 	while (NULL != (sk = HEAD_DLIST(key_listhead, llink))) {
3114990d495SXin LI 		freesymkey(sk);
3122b15cb3dSCy Schubert 	}
3132b15cb3dSCy Schubert 	free(key_hash);
3142b15cb3dSCy Schubert 	key_hash = NULL;
3152b15cb3dSCy Schubert 	cache_keyid = 0;
3162b15cb3dSCy Schubert 	cache_flags = 0;
31768ba7e87SXin LI 	cache_keyacclist = NULL;
3182b15cb3dSCy Schubert 	for (alloc = authallocs; alloc != NULL; alloc = next_alloc) {
3192b15cb3dSCy Schubert 		next_alloc = alloc->link;
3202b15cb3dSCy Schubert 		free(alloc->mem);
3212b15cb3dSCy Schubert 	}
3222b15cb3dSCy Schubert 	authfreekeys = NULL;
3232b15cb3dSCy Schubert 	authnumfreekeys = 0;
3242b15cb3dSCy Schubert }
3252b15cb3dSCy Schubert #endif	/* DEBUG */
3262b15cb3dSCy Schubert 
3272b15cb3dSCy Schubert 
3282b15cb3dSCy Schubert /*
3292b15cb3dSCy Schubert  * auth_moremem - get some more free key structures
3302b15cb3dSCy Schubert  */
3312b15cb3dSCy Schubert void
3322b15cb3dSCy Schubert auth_moremem(
3332b15cb3dSCy Schubert 	int	keycount
3342b15cb3dSCy Schubert 	)
3352b15cb3dSCy Schubert {
3362b15cb3dSCy Schubert 	symkey *	sk;
3372b15cb3dSCy Schubert 	int		i;
3382b15cb3dSCy Schubert #ifdef DEBUG
3392b15cb3dSCy Schubert 	void *		base;
3402b15cb3dSCy Schubert 	symkey_alloc *	allocrec;
3412b15cb3dSCy Schubert # define MOREMEM_EXTRA_ALLOC	(sizeof(*allocrec))
3422b15cb3dSCy Schubert #else
3432b15cb3dSCy Schubert # define MOREMEM_EXTRA_ALLOC	(0)
3442b15cb3dSCy Schubert #endif
3452b15cb3dSCy Schubert 
3462b15cb3dSCy Schubert 	i = (keycount > 0)
3472b15cb3dSCy Schubert 		? keycount
3482b15cb3dSCy Schubert 		: MEMINC;
349f0574f5cSXin LI 	sk = eallocarrayxz(i, sizeof(*sk), MOREMEM_EXTRA_ALLOC);
3502b15cb3dSCy Schubert #ifdef DEBUG
3512b15cb3dSCy Schubert 	base = sk;
3522b15cb3dSCy Schubert #endif
3532b15cb3dSCy Schubert 	authnumfreekeys += i;
3542b15cb3dSCy Schubert 
3552b15cb3dSCy Schubert 	for (; i > 0; i--, sk++) {
3562b15cb3dSCy Schubert 		LINK_SLIST(authfreekeys, sk, llink.f);
3572b15cb3dSCy Schubert 	}
3582b15cb3dSCy Schubert 
3592b15cb3dSCy Schubert #ifdef DEBUG
3602b15cb3dSCy Schubert 	allocrec = (void *)sk;
3612b15cb3dSCy Schubert 	allocrec->mem = base;
3622b15cb3dSCy Schubert 	LINK_SLIST(authallocs, allocrec, link);
3632b15cb3dSCy Schubert #endif
3642b15cb3dSCy Schubert }
3652b15cb3dSCy Schubert 
3662b15cb3dSCy Schubert 
3672b15cb3dSCy Schubert /*
3682b15cb3dSCy Schubert  * auth_prealloc_symkeys
3692b15cb3dSCy Schubert  */
3702b15cb3dSCy Schubert void
3712b15cb3dSCy Schubert auth_prealloc_symkeys(
3722b15cb3dSCy Schubert 	int	keycount
3732b15cb3dSCy Schubert 	)
3742b15cb3dSCy Schubert {
3752b15cb3dSCy Schubert 	int	allocated;
3762b15cb3dSCy Schubert 	int	additional;
3772b15cb3dSCy Schubert 
3782b15cb3dSCy Schubert 	allocated = authnumkeys + authnumfreekeys;
3792b15cb3dSCy Schubert 	additional = keycount - allocated;
3802b15cb3dSCy Schubert 	if (additional > 0)
3812b15cb3dSCy Schubert 		auth_moremem(additional);
3822b15cb3dSCy Schubert 	auth_resize_hashtable();
3832b15cb3dSCy Schubert }
3842b15cb3dSCy Schubert 
3852b15cb3dSCy Schubert 
38668ba7e87SXin LI static u_short
38768ba7e87SXin LI auth_log2(size_t x)
3882b15cb3dSCy Schubert {
38968ba7e87SXin LI 	/*
39068ba7e87SXin LI 	** bithack to calculate floor(log2(x))
39168ba7e87SXin LI 	**
39268ba7e87SXin LI 	** This assumes
39368ba7e87SXin LI 	**   - (sizeof(size_t) is a power of two
39468ba7e87SXin LI 	**   - CHAR_BITS is a power of two
39568ba7e87SXin LI 	**   - returning zero for arguments <= 0 is OK.
39668ba7e87SXin LI 	**
39768ba7e87SXin LI 	** Does only shifts, masks and sums in integer arithmetic in
39868ba7e87SXin LI 	** log2(CHAR_BIT*sizeof(size_t)) steps. (that is, 5/6 steps for
39968ba7e87SXin LI 	** 32bit/64bit size_t)
40068ba7e87SXin LI 	*/
40168ba7e87SXin LI 	int	s;
40268ba7e87SXin LI 	int	r = 0;
40368ba7e87SXin LI 	size_t  m = ~(size_t)0;
40468ba7e87SXin LI 
40568ba7e87SXin LI 	for (s = sizeof(size_t) / 2 * CHAR_BIT; s != 0; s >>= 1) {
40668ba7e87SXin LI 		m <<= s;
40768ba7e87SXin LI 		if (x & m)
40868ba7e87SXin LI 			r += s;
40968ba7e87SXin LI 		else
41068ba7e87SXin LI 			x <<= s;
41168ba7e87SXin LI 	}
41268ba7e87SXin LI 	return (u_short)r;
4132b15cb3dSCy Schubert }
4142b15cb3dSCy Schubert 
41509100258SXin LI int/*BOOL*/
41609100258SXin LI ipaddr_match_masked(const sockaddr_u *,const sockaddr_u *,
41709100258SXin LI 		    unsigned int mbits);
41809100258SXin LI 
4194990d495SXin LI static void
4204990d495SXin LI authcache_flush_id(
4214990d495SXin LI 	keyid_t id
4224990d495SXin LI 	)
4234990d495SXin LI {
4244990d495SXin LI 	if (cache_keyid == id) {
4254990d495SXin LI 		cache_keyid = 0;
4264990d495SXin LI 		cache_type = 0;
4274990d495SXin LI 		cache_flags = 0;
4284990d495SXin LI 		cache_secret = NULL;
4294990d495SXin LI 		cache_secretsize = 0;
4304990d495SXin LI 		cache_keyacclist = NULL;
4314990d495SXin LI 	}
4324990d495SXin LI }
4334990d495SXin LI 
4342b15cb3dSCy Schubert 
4352b15cb3dSCy Schubert /*
4362b15cb3dSCy Schubert  * auth_resize_hashtable
4372b15cb3dSCy Schubert  *
4382b15cb3dSCy Schubert  * Size hash table to average 4 or fewer entries per bucket initially,
4392b15cb3dSCy Schubert  * within the bounds of at least 4 and no more than 15 bits for the hash
4402b15cb3dSCy Schubert  * table index.  Populate the hash table.
4412b15cb3dSCy Schubert  */
4422b15cb3dSCy Schubert static void
4432b15cb3dSCy Schubert auth_resize_hashtable(void)
4442b15cb3dSCy Schubert {
4452b15cb3dSCy Schubert 	u_long		totalkeys;
4462b15cb3dSCy Schubert 	u_short		hashbits;
4472b15cb3dSCy Schubert 	u_short		hash;
4482b15cb3dSCy Schubert 	size_t		newalloc;
4492b15cb3dSCy Schubert 	symkey *	sk;
4502b15cb3dSCy Schubert 
4512b15cb3dSCy Schubert 	totalkeys = authnumkeys + authnumfreekeys;
45268ba7e87SXin LI 	hashbits = auth_log2(totalkeys / 4) + 1;
4532b15cb3dSCy Schubert 	hashbits = max(4, hashbits);
4542b15cb3dSCy Schubert 	hashbits = min(15, hashbits);
4552b15cb3dSCy Schubert 
4562b15cb3dSCy Schubert 	authhashbuckets = 1 << hashbits;
4572b15cb3dSCy Schubert 	authhashmask = authhashbuckets - 1;
4582b15cb3dSCy Schubert 	newalloc = authhashbuckets * sizeof(key_hash[0]);
4592b15cb3dSCy Schubert 
4602b15cb3dSCy Schubert 	key_hash = erealloc(key_hash, newalloc);
4612b15cb3dSCy Schubert 	memset(key_hash, '\0', newalloc);
4622b15cb3dSCy Schubert 
4632b15cb3dSCy Schubert 	ITER_DLIST_BEGIN(key_listhead, sk, llink, symkey)
4642b15cb3dSCy Schubert 		hash = KEYHASH(sk->keyid);
4652b15cb3dSCy Schubert 		LINK_SLIST(key_hash[hash], sk, hlink);
4662b15cb3dSCy Schubert 	ITER_DLIST_END()
4672b15cb3dSCy Schubert }
4682b15cb3dSCy Schubert 
4692b15cb3dSCy Schubert 
4702b15cb3dSCy Schubert /*
4712b15cb3dSCy Schubert  * allocsymkey - common code to allocate and link in symkey
4722b15cb3dSCy Schubert  *
4732b15cb3dSCy Schubert  * secret must be allocated with a free-compatible allocator.  It is
4742b15cb3dSCy Schubert  * owned by the referring symkey structure, and will be free()d by
4752b15cb3dSCy Schubert  * freesymkey().
4762b15cb3dSCy Schubert  */
4772b15cb3dSCy Schubert static void
4782b15cb3dSCy Schubert allocsymkey(
4792b15cb3dSCy Schubert 	keyid_t		id,
4802b15cb3dSCy Schubert 	u_short		flags,
4812b15cb3dSCy Schubert 	u_short		type,
4822b15cb3dSCy Schubert 	u_long		lifetime,
4834990d495SXin LI 	size_t		secretsize,
48468ba7e87SXin LI 	u_char *	secret,
48568ba7e87SXin LI 	KeyAccT *	ka
4862b15cb3dSCy Schubert 	)
4872b15cb3dSCy Schubert {
4882b15cb3dSCy Schubert 	symkey *	sk;
4894990d495SXin LI 	symkey **	bucket;
4904990d495SXin LI 
4914990d495SXin LI 	bucket = &key_hash[KEYHASH(id)];
4924990d495SXin LI 
4932b15cb3dSCy Schubert 
4942b15cb3dSCy Schubert 	if (authnumfreekeys < 1)
4952b15cb3dSCy Schubert 		auth_moremem(-1);
4962b15cb3dSCy Schubert 	UNLINK_HEAD_SLIST(sk, authfreekeys, llink.f);
4972b15cb3dSCy Schubert 	DEBUG_ENSURE(sk != NULL);
4982b15cb3dSCy Schubert 	sk->keyid = id;
4992b15cb3dSCy Schubert 	sk->flags = flags;
5002b15cb3dSCy Schubert 	sk->type = type;
5012b15cb3dSCy Schubert 	sk->secretsize = secretsize;
5022b15cb3dSCy Schubert 	sk->secret = secret;
50368ba7e87SXin LI 	sk->keyacclist = ka;
5042b15cb3dSCy Schubert 	sk->lifetime = lifetime;
5052b15cb3dSCy Schubert 	LINK_SLIST(*bucket, sk, hlink);
5062b15cb3dSCy Schubert 	LINK_TAIL_DLIST(key_listhead, sk, llink);
5072b15cb3dSCy Schubert 	authnumfreekeys--;
5082b15cb3dSCy Schubert 	authnumkeys++;
5092b15cb3dSCy Schubert }
5102b15cb3dSCy Schubert 
5112b15cb3dSCy Schubert 
5122b15cb3dSCy Schubert /*
5132b15cb3dSCy Schubert  * freesymkey - common code to remove a symkey and recycle its entry.
5142b15cb3dSCy Schubert  */
5152b15cb3dSCy Schubert static void
5162b15cb3dSCy Schubert freesymkey(
5174990d495SXin LI 	symkey *	sk
5182b15cb3dSCy Schubert 	)
5192b15cb3dSCy Schubert {
5204990d495SXin LI 	symkey **	bucket;
5212b15cb3dSCy Schubert 	symkey *	unlinked;
5222b15cb3dSCy Schubert 
5234990d495SXin LI 	if (NULL == sk)
5244990d495SXin LI 		return;
5254990d495SXin LI 
5264990d495SXin LI 	authcache_flush_id(sk->keyid);
5274990d495SXin LI 	keyacc_all_free(sk->keyacclist);
5284990d495SXin LI 
5294990d495SXin LI 	bucket = &key_hash[KEYHASH(sk->keyid)];
5302b15cb3dSCy Schubert 	if (sk->secret != NULL) {
5312b15cb3dSCy Schubert 		memset(sk->secret, '\0', sk->secretsize);
5322b15cb3dSCy Schubert 		free(sk->secret);
5332b15cb3dSCy Schubert 	}
5342b15cb3dSCy Schubert 	UNLINK_SLIST(unlinked, *bucket, sk, hlink, symkey);
5352b15cb3dSCy Schubert 	DEBUG_ENSURE(sk == unlinked);
5362b15cb3dSCy Schubert 	UNLINK_DLIST(sk, llink);
5372b15cb3dSCy Schubert 	memset((char *)sk + offsetof(symkey, symkey_payload), '\0',
5382b15cb3dSCy Schubert 	       sizeof(*sk) - offsetof(symkey, symkey_payload));
5392b15cb3dSCy Schubert 	LINK_SLIST(authfreekeys, sk, llink.f);
5402b15cb3dSCy Schubert 	authnumkeys--;
5412b15cb3dSCy Schubert 	authnumfreekeys++;
542c0b746e5SOllivier Robert }
543c0b746e5SOllivier Robert 
544c0b746e5SOllivier Robert 
545c0b746e5SOllivier Robert /*
546c0b746e5SOllivier Robert  * auth_findkey - find a key in the hash table
547c0b746e5SOllivier Robert  */
548c0b746e5SOllivier Robert struct savekey *
549c0b746e5SOllivier Robert auth_findkey(
5502b15cb3dSCy Schubert 	keyid_t		id
551c0b746e5SOllivier Robert 	)
552c0b746e5SOllivier Robert {
5532b15cb3dSCy Schubert 	symkey *	sk;
554c0b746e5SOllivier Robert 
5554990d495SXin LI 	for (sk = key_hash[KEYHASH(id)]; sk != NULL; sk = sk->hlink)
5564990d495SXin LI 		if (id == sk->keyid)
5572b15cb3dSCy Schubert 			return sk;
5582b15cb3dSCy Schubert 	return NULL;
559c0b746e5SOllivier Robert }
560c0b746e5SOllivier Robert 
561c0b746e5SOllivier Robert 
562c0b746e5SOllivier Robert /*
5634990d495SXin LI  * auth_havekey - return TRUE if the key id is zero or known. The
5644990d495SXin LI  * key needs not to be trusted.
565c0b746e5SOllivier Robert  */
566c0b746e5SOllivier Robert int
567c0b746e5SOllivier Robert auth_havekey(
5682b15cb3dSCy Schubert 	keyid_t		id
569c0b746e5SOllivier Robert 	)
570c0b746e5SOllivier Robert {
5714990d495SXin LI 	return
5724990d495SXin LI 	    (0           == id) ||
5734990d495SXin LI 	    (cache_keyid == id) ||
5744990d495SXin LI 	    (NULL        != auth_findkey(id));
575c0b746e5SOllivier Robert }
576c0b746e5SOllivier Robert 
577c0b746e5SOllivier Robert 
578c0b746e5SOllivier Robert /*
5792b15cb3dSCy Schubert  * authhavekey - return TRUE and cache the key, if zero or both known
5802b15cb3dSCy Schubert  *		 and trusted.
581c0b746e5SOllivier Robert  */
582c0b746e5SOllivier Robert int
583c0b746e5SOllivier Robert authhavekey(
5842b15cb3dSCy Schubert 	keyid_t		id
585c0b746e5SOllivier Robert 	)
586c0b746e5SOllivier Robert {
5872b15cb3dSCy Schubert 	symkey *	sk;
588c0b746e5SOllivier Robert 
589c0b746e5SOllivier Robert 	authkeylookups++;
5904990d495SXin LI 	if (0 == id || cache_keyid == id)
5914990d495SXin LI 		return !!(KEY_TRUSTED & cache_flags);
592c0b746e5SOllivier Robert 
593c0b746e5SOllivier Robert 	/*
5944990d495SXin LI 	 * Search the bin for the key. If not found, or found but the key
5954990d495SXin LI 	 * type is zero, somebody marked it trusted without specifying a
5964990d495SXin LI 	 * key or key type. In this case consider the key missing.
597c0b746e5SOllivier Robert 	 */
5982b15cb3dSCy Schubert 	authkeyuncached++;
5994990d495SXin LI 	sk = auth_findkey(id);
6004990d495SXin LI 	if ((sk == NULL) || (sk->type == 0)) {
6012b15cb3dSCy Schubert 		authkeynotfound++;
6022b15cb3dSCy Schubert 		return FALSE;
603c0b746e5SOllivier Robert 	}
6042b15cb3dSCy Schubert 
6052b15cb3dSCy Schubert 	/*
6064990d495SXin LI 	 * If the key is not trusted, the key is not considered found.
6072b15cb3dSCy Schubert 	 */
6082b15cb3dSCy Schubert 	if ( ! (KEY_TRUSTED & sk->flags)) {
6092b15cb3dSCy Schubert 		authnokey++;
6102b15cb3dSCy Schubert 		return FALSE;
6112b15cb3dSCy Schubert 	}
6122b15cb3dSCy Schubert 
6132b15cb3dSCy Schubert 	/*
6142b15cb3dSCy Schubert 	 * The key is found and trusted. Initialize the key cache.
6152b15cb3dSCy Schubert 	 */
6162b15cb3dSCy Schubert 	cache_keyid = sk->keyid;
6172b15cb3dSCy Schubert 	cache_type = sk->type;
6182b15cb3dSCy Schubert 	cache_flags = sk->flags;
6192b15cb3dSCy Schubert 	cache_secret = sk->secret;
6202b15cb3dSCy Schubert 	cache_secretsize = sk->secretsize;
62168ba7e87SXin LI 	cache_keyacclist = sk->keyacclist;
6222b15cb3dSCy Schubert 
6232b15cb3dSCy Schubert 	return TRUE;
624c0b746e5SOllivier Robert }
625c0b746e5SOllivier Robert 
626c0b746e5SOllivier Robert 
627c0b746e5SOllivier Robert /*
628c0b746e5SOllivier Robert  * authtrust - declare a key to be trusted/untrusted
629c0b746e5SOllivier Robert  */
630c0b746e5SOllivier Robert void
631c0b746e5SOllivier Robert authtrust(
6322b15cb3dSCy Schubert 	keyid_t		id,
633224ba2bdSOllivier Robert 	u_long		trust
634c0b746e5SOllivier Robert 	)
635c0b746e5SOllivier Robert {
6362b15cb3dSCy Schubert 	symkey *	sk;
6372b15cb3dSCy Schubert 	u_long		lifetime;
638c0b746e5SOllivier Robert 
6392b15cb3dSCy Schubert 	/*
6402b15cb3dSCy Schubert 	 * Search bin for key; if it does not exist and is untrusted,
6412b15cb3dSCy Schubert 	 * forget it.
6422b15cb3dSCy Schubert 	 */
6434990d495SXin LI 
6444990d495SXin LI 	sk = auth_findkey(id);
6454990d495SXin LI 	if (!trust && sk == NULL)
646c0b746e5SOllivier Robert 		return;
647c0b746e5SOllivier Robert 
6482b15cb3dSCy Schubert 	/*
6492b15cb3dSCy Schubert 	 * There are two conditions remaining. Either it does not
6502b15cb3dSCy Schubert 	 * exist and is to be trusted or it does exist and is or is
6512b15cb3dSCy Schubert 	 * not to be trusted.
6522b15cb3dSCy Schubert 	 */
6532b15cb3dSCy Schubert 	if (sk != NULL) {
6542b15cb3dSCy Schubert 		/*
6554990d495SXin LI 		 * Key exists. If it is to be trusted, say so and update
6564990d495SXin LI 		 * its lifetime. If no longer trusted, return it to the
6574990d495SXin LI 		 * free list. Flush the cache first to be sure there are
6584990d495SXin LI 		 * no discrepancies.
6592b15cb3dSCy Schubert 		 */
6604990d495SXin LI 		authcache_flush_id(id);
661c0b746e5SOllivier Robert 		if (trust > 0) {
662c0b746e5SOllivier Robert 			sk->flags |= KEY_TRUSTED;
663c0b746e5SOllivier Robert 			if (trust > 1)
664c0b746e5SOllivier Robert 				sk->lifetime = current_time + trust;
665c0b746e5SOllivier Robert 			else
666c0b746e5SOllivier Robert 				sk->lifetime = 0;
6674990d495SXin LI 		} else {
6684990d495SXin LI 			freesymkey(sk);
669c0b746e5SOllivier Robert 		}
6702b15cb3dSCy Schubert 		return;
6712b15cb3dSCy Schubert 	}
672c0b746e5SOllivier Robert 
6732b15cb3dSCy Schubert 	/*
6742b15cb3dSCy Schubert 	 * keyid is not present, but the is to be trusted.  We allocate
6752b15cb3dSCy Schubert 	 * a new key, but do not specify a key type or secret.
6762b15cb3dSCy Schubert 	 */
6772b15cb3dSCy Schubert 	if (trust > 1) {
6782b15cb3dSCy Schubert 		lifetime = current_time + trust;
679c0b746e5SOllivier Robert 	} else {
6802b15cb3dSCy Schubert 		lifetime = 0;
681c0b746e5SOllivier Robert 	}
6824990d495SXin LI 	allocsymkey(id, KEY_TRUSTED, 0, lifetime, 0, NULL, NULL);
683c0b746e5SOllivier Robert }
684c0b746e5SOllivier Robert 
685c0b746e5SOllivier Robert 
686c0b746e5SOllivier Robert /*
687c0b746e5SOllivier Robert  * authistrusted - determine whether a key is trusted
688c0b746e5SOllivier Robert  */
689c0b746e5SOllivier Robert int
690c0b746e5SOllivier Robert authistrusted(
6914990d495SXin LI 	keyid_t		id
692c0b746e5SOllivier Robert 	)
693c0b746e5SOllivier Robert {
6942b15cb3dSCy Schubert 	symkey *	sk;
695c0b746e5SOllivier Robert 
6964990d495SXin LI 	if (id == cache_keyid)
6972b15cb3dSCy Schubert 		return !!(KEY_TRUSTED & cache_flags);
698c0b746e5SOllivier Robert 
699c0b746e5SOllivier Robert 	authkeyuncached++;
7004990d495SXin LI 	sk = auth_findkey(id);
7014990d495SXin LI 	if (sk == NULL || !(KEY_TRUSTED & sk->flags)) {
702c0b746e5SOllivier Robert 		authkeynotfound++;
7032b15cb3dSCy Schubert 		return FALSE;
704c0b746e5SOllivier Robert 	}
7052b15cb3dSCy Schubert 	return TRUE;
706c0b746e5SOllivier Robert }
707c0b746e5SOllivier Robert 
70868ba7e87SXin LI 
70968ba7e87SXin LI /*
71068ba7e87SXin LI  * authistrustedip - determine if the IP is OK for the keyid
71168ba7e87SXin LI  */
71268ba7e87SXin LI  int
71368ba7e87SXin LI  authistrustedip(
71468ba7e87SXin LI  	keyid_t		keyno,
71568ba7e87SXin LI 	sockaddr_u *	sau
71668ba7e87SXin LI 	)
71768ba7e87SXin LI {
71868ba7e87SXin LI 	symkey *	sk;
71968ba7e87SXin LI 
7204990d495SXin LI 	if (keyno == cache_keyid) {
7214990d495SXin LI 		return (KEY_TRUSTED & cache_flags) &&
7224990d495SXin LI 		    keyacc_contains(cache_keyacclist, sau, TRUE);
72309100258SXin LI 	}
72409100258SXin LI 
72509100258SXin LI 	if (NULL != (sk = auth_findkey(keyno))) {
72668ba7e87SXin LI 		authkeyuncached++;
7274990d495SXin LI 		return (KEY_TRUSTED & sk->flags) &&
7284990d495SXin LI 		    keyacc_contains(sk->keyacclist, sau, TRUE);
72968ba7e87SXin LI 	}
73009100258SXin LI 
73109100258SXin LI 	authkeynotfound++;
73209100258SXin LI 	return FALSE;
73368ba7e87SXin LI }
73468ba7e87SXin LI 
7353311ff84SXin LI /* Note: There are two locations below where 'strncpy()' is used. While
7363311ff84SXin LI  * this function is a hazard by itself, it's essential that it is used
7373311ff84SXin LI  * here. Bug 1243 involved that the secret was filled with NUL bytes
7383311ff84SXin LI  * after the first NUL encountered, and 'strlcpy()' simply does NOT have
7393311ff84SXin LI  * this behaviour. So disabling the fix and reverting to the buggy
7403311ff84SXin LI  * behaviour due to compatibility issues MUST also fill with NUL and
7413311ff84SXin LI  * this needs 'strncpy'. Also, the secret is managed as a byte blob of a
7423311ff84SXin LI  * given size, and eventually truncating it and replacing the last byte
7433311ff84SXin LI  * with a NUL would be a bug.
7443311ff84SXin LI  * perlinger@ntp.org 2015-10-10
7453311ff84SXin LI  */
746c0b746e5SOllivier Robert void
747c0b746e5SOllivier Robert MD5auth_setkey(
748224ba2bdSOllivier Robert 	keyid_t keyno,
7492b15cb3dSCy Schubert 	int	keytype,
750c0b746e5SOllivier Robert 	const u_char *key,
7514990d495SXin LI 	size_t secretsize,
75268ba7e87SXin LI 	KeyAccT *ka
753c0b746e5SOllivier Robert 	)
754c0b746e5SOllivier Robert {
7552b15cb3dSCy Schubert 	symkey *	sk;
7562b15cb3dSCy Schubert 	u_char *	secret;
757c0b746e5SOllivier Robert 
7582b15cb3dSCy Schubert 	DEBUG_ENSURE(keytype <= USHRT_MAX);
7594990d495SXin LI 	DEBUG_ENSURE(secretsize < 4 * 1024);
760c0b746e5SOllivier Robert 	/*
761c0b746e5SOllivier Robert 	 * See if we already have the key.  If so just stick in the
762c0b746e5SOllivier Robert 	 * new value.
763c0b746e5SOllivier Robert 	 */
7644990d495SXin LI 	sk = auth_findkey(keyno);
7654990d495SXin LI 	if (sk != NULL && keyno == sk->keyid) {
7669034852cSGleb Smirnoff 			/* TALOS-CAN-0054: make sure we have a new buffer! */
7679034852cSGleb Smirnoff 		if (NULL != sk->secret) {
7689034852cSGleb Smirnoff 			memset(sk->secret, 0, sk->secretsize);
7699034852cSGleb Smirnoff 			free(sk->secret);
7709034852cSGleb Smirnoff 		}
7714990d495SXin LI 		sk->secret = emalloc(secretsize + 1);
7722b15cb3dSCy Schubert 		sk->type = (u_short)keytype;
7734990d495SXin LI 		sk->secretsize = secretsize;
7744990d495SXin LI 		/* make sure access lists don't leak here! */
7754990d495SXin LI 		if (ka != sk->keyacclist) {
7764990d495SXin LI 			keyacc_all_free(sk->keyacclist);
77768ba7e87SXin LI 			sk->keyacclist = ka;
7784990d495SXin LI 		}
7792b15cb3dSCy Schubert #ifndef DISABLE_BUG1243_FIX
7802b15cb3dSCy Schubert 		memcpy(sk->secret, key, secretsize);
7812b15cb3dSCy Schubert #else
7823311ff84SXin LI 		/* >MUST< use 'strncpy()' here! See above! */
7833311ff84SXin LI 		strncpy((char *)sk->secret, (const char *)key,
7842b15cb3dSCy Schubert 			secretsize);
7852b15cb3dSCy Schubert #endif
7864990d495SXin LI 		authcache_flush_id(keyno);
787c0b746e5SOllivier Robert 		return;
788c0b746e5SOllivier Robert 	}
789c0b746e5SOllivier Robert 
790c0b746e5SOllivier Robert 	/*
791c0b746e5SOllivier Robert 	 * Need to allocate new structure.  Do it.
792c0b746e5SOllivier Robert 	 */
7934990d495SXin LI 	secret = emalloc(secretsize + 1);
7942b15cb3dSCy Schubert #ifndef DISABLE_BUG1243_FIX
7952b15cb3dSCy Schubert 	memcpy(secret, key, secretsize);
7962b15cb3dSCy Schubert #else
7973311ff84SXin LI 	/* >MUST< use 'strncpy()' here! See above! */
7983311ff84SXin LI 	strncpy((char *)secret, (const char *)key, secretsize);
7992b15cb3dSCy Schubert #endif
8004990d495SXin LI 	allocsymkey(keyno, 0, (u_short)keytype, 0,
8014990d495SXin LI 		    secretsize, secret, ka);
8022b15cb3dSCy Schubert #ifdef DEBUG
8032b15cb3dSCy Schubert 	if (debug >= 4) {
8042b15cb3dSCy Schubert 		size_t	j;
8052b15cb3dSCy Schubert 
8062b15cb3dSCy Schubert 		printf("auth_setkey: key %d type %d len %d ", (int)keyno,
8072b15cb3dSCy Schubert 		    keytype, (int)secretsize);
8084990d495SXin LI 		for (j = 0; j < secretsize; j++) {
8092b15cb3dSCy Schubert 			printf("%02x", secret[j]);
8104990d495SXin LI 		}
8112b15cb3dSCy Schubert 		printf("\n");
8122b15cb3dSCy Schubert 	}
8132b15cb3dSCy Schubert #endif
814c0b746e5SOllivier Robert }
815c0b746e5SOllivier Robert 
816c0b746e5SOllivier Robert 
817c0b746e5SOllivier Robert /*
8182b15cb3dSCy Schubert  * auth_delkeys - delete non-autokey untrusted keys, and clear all info
8192b15cb3dSCy Schubert  *                except the trusted bit of non-autokey trusted keys, in
8202b15cb3dSCy Schubert  *		  preparation for rereading the keys file.
821c0b746e5SOllivier Robert  */
822c0b746e5SOllivier Robert void
823c0b746e5SOllivier Robert auth_delkeys(void)
824c0b746e5SOllivier Robert {
8252b15cb3dSCy Schubert 	symkey *	sk;
826c0b746e5SOllivier Robert 
8272b15cb3dSCy Schubert 	ITER_DLIST_BEGIN(key_listhead, sk, llink, symkey)
8282b15cb3dSCy Schubert 		if (sk->keyid > NTP_MAXKEY) {	/* autokey */
8292b15cb3dSCy Schubert 			continue;
8302b15cb3dSCy Schubert 		}
8312b15cb3dSCy Schubert 
832c0b746e5SOllivier Robert 		/*
8339034852cSGleb Smirnoff 		 * Don't lose info as to which keys are trusted. Make
8349034852cSGleb Smirnoff 		 * sure there are no dangling pointers!
835c0b746e5SOllivier Robert 		 */
8362b15cb3dSCy Schubert 		if (KEY_TRUSTED & sk->flags) {
8372b15cb3dSCy Schubert 			if (sk->secret != NULL) {
8389034852cSGleb Smirnoff 				memset(sk->secret, 0, sk->secretsize);
8392b15cb3dSCy Schubert 				free(sk->secret);
8409034852cSGleb Smirnoff 				sk->secret = NULL; /* TALOS-CAN-0054 */
8412b15cb3dSCy Schubert 			}
8424990d495SXin LI 			sk->keyacclist = keyacc_all_free(sk->keyacclist);
8432b15cb3dSCy Schubert 			sk->secretsize = 0;
844c0b746e5SOllivier Robert 			sk->lifetime = 0;
845c0b746e5SOllivier Robert 		} else {
8464990d495SXin LI 			freesymkey(sk);
847c0b746e5SOllivier Robert 		}
8482b15cb3dSCy Schubert 	ITER_DLIST_END()
849c0b746e5SOllivier Robert }
8502b15cb3dSCy Schubert 
851c0b746e5SOllivier Robert 
852c0b746e5SOllivier Robert /*
853c0b746e5SOllivier Robert  * auth_agekeys - delete keys whose lifetimes have expired
854c0b746e5SOllivier Robert  */
855c0b746e5SOllivier Robert void
856c0b746e5SOllivier Robert auth_agekeys(void)
857c0b746e5SOllivier Robert {
8582b15cb3dSCy Schubert 	symkey *	sk;
859c0b746e5SOllivier Robert 
8602b15cb3dSCy Schubert 	ITER_DLIST_BEGIN(key_listhead, sk, llink, symkey)
8612b15cb3dSCy Schubert 		if (sk->lifetime > 0 && current_time > sk->lifetime) {
8624990d495SXin LI 			freesymkey(sk);
863c0b746e5SOllivier Robert 			authkeyexpired++;
864c0b746e5SOllivier Robert 		}
8652b15cb3dSCy Schubert 	ITER_DLIST_END()
8662b15cb3dSCy Schubert 	DPRINTF(1, ("auth_agekeys: at %lu keys %lu expired %lu\n",
8672b15cb3dSCy Schubert 		    current_time, authnumkeys, authkeyexpired));
868c0b746e5SOllivier Robert }
8692b15cb3dSCy Schubert 
870c0b746e5SOllivier Robert 
871c0b746e5SOllivier Robert /*
872c0b746e5SOllivier Robert  * authencrypt - generate message authenticator
873c0b746e5SOllivier Robert  *
874c0b746e5SOllivier Robert  * Returns length of authenticator field, zero if key not found.
875c0b746e5SOllivier Robert  */
8763311ff84SXin LI size_t
877c0b746e5SOllivier Robert authencrypt(
878224ba2bdSOllivier Robert 	keyid_t		keyno,
879c0b746e5SOllivier Robert 	u_int32 *	pkt,
8803311ff84SXin LI 	size_t		length
881c0b746e5SOllivier Robert 	)
8823311ff84SXin LI {
883c0b746e5SOllivier Robert 	/*
884c0b746e5SOllivier Robert 	 * A zero key identifier means the sender has not verified
885c0b746e5SOllivier Robert 	 * the last message was correctly authenticated. The MAC
886c0b746e5SOllivier Robert 	 * consists of a single word with value zero.
887c0b746e5SOllivier Robert 	 */
888c0b746e5SOllivier Robert 	authencryptions++;
889224ba2bdSOllivier Robert 	pkt[length / 4] = htonl(keyno);
8902b15cb3dSCy Schubert 	if (0 == keyno) {
8912b15cb3dSCy Schubert 		return 4;
892c0b746e5SOllivier Robert 	}
8932b15cb3dSCy Schubert 	if (!authhavekey(keyno)) {
8942b15cb3dSCy Schubert 		return 0;
895c0b746e5SOllivier Robert 	}
896c0b746e5SOllivier Robert 
89709100258SXin LI 	return MD5authencrypt(cache_type,
89809100258SXin LI 			      cache_secret, cache_secretsize,
89909100258SXin LI 			      pkt, length);
9002b15cb3dSCy Schubert }
9012b15cb3dSCy Schubert 
9022b15cb3dSCy Schubert 
903c0b746e5SOllivier Robert /*
904c0b746e5SOllivier Robert  * authdecrypt - verify message authenticator
905c0b746e5SOllivier Robert  *
9062b15cb3dSCy Schubert  * Returns TRUE if authenticator valid, FALSE if invalid or not found.
907c0b746e5SOllivier Robert  */
908c0b746e5SOllivier Robert int
909c0b746e5SOllivier Robert authdecrypt(
910224ba2bdSOllivier Robert 	keyid_t		keyno,
911c0b746e5SOllivier Robert 	u_int32 *	pkt,
9123311ff84SXin LI 	size_t		length,
9133311ff84SXin LI 	size_t		size
914c0b746e5SOllivier Robert 	)
915c0b746e5SOllivier Robert {
916c0b746e5SOllivier Robert 	/*
917c0b746e5SOllivier Robert 	 * A zero key identifier means the sender has not verified
9182b15cb3dSCy Schubert 	 * the last message was correctly authenticated.  For our
9192b15cb3dSCy Schubert 	 * purpose this is an invalid authenticator.
920c0b746e5SOllivier Robert 	 */
921c0b746e5SOllivier Robert 	authdecryptions++;
9222b15cb3dSCy Schubert 	if (0 == keyno || !authhavekey(keyno) || size < 4) {
9232b15cb3dSCy Schubert 		return FALSE;
9242b15cb3dSCy Schubert 	}
925c0b746e5SOllivier Robert 
92609100258SXin LI 	return MD5authdecrypt(cache_type,
92709100258SXin LI 			      cache_secret, cache_secretsize,
928*a466cc55SCy Schubert 			      pkt, length, size, keyno);
929*a466cc55SCy Schubert }
930*a466cc55SCy Schubert 
931*a466cc55SCy Schubert /* password decoding helpers */
932*a466cc55SCy Schubert static size_t
933*a466cc55SCy Schubert pwdecode_plain(
934*a466cc55SCy Schubert 	u_char *	dst,
935*a466cc55SCy Schubert 	size_t 		dstlen,
936*a466cc55SCy Schubert 	const char *	src
937*a466cc55SCy Schubert 	)
938*a466cc55SCy Schubert {
939*a466cc55SCy Schubert 	size_t		srclen = strlen(src);
940*a466cc55SCy Schubert 	if (srclen > dstlen) {
941*a466cc55SCy Schubert 		errno = ENOMEM;
942*a466cc55SCy Schubert 		return (size_t)-1;
943*a466cc55SCy Schubert 	}
944*a466cc55SCy Schubert 	memcpy(dst, src, srclen);
945*a466cc55SCy Schubert 	return srclen;
946*a466cc55SCy Schubert }
947*a466cc55SCy Schubert 
948*a466cc55SCy Schubert static size_t
949*a466cc55SCy Schubert pwdecode_hex(
950*a466cc55SCy Schubert 	u_char *	dst,
951*a466cc55SCy Schubert 	size_t 		dstlen,
952*a466cc55SCy Schubert 	const char *	src
953*a466cc55SCy Schubert 	)
954*a466cc55SCy Schubert {
955*a466cc55SCy Schubert 	static const char hex[] = "00112233445566778899AaBbCcDdEeFf";
956*a466cc55SCy Schubert 
957*a466cc55SCy Schubert 	size_t		srclen = strlen(src);
958*a466cc55SCy Schubert 	size_t		reslen = (srclen >> 1) + (srclen & 1);
959*a466cc55SCy Schubert 	u_char		tmp;
960*a466cc55SCy Schubert 	char		*ptr;
961*a466cc55SCy Schubert 	size_t		j;
962*a466cc55SCy Schubert 
963*a466cc55SCy Schubert 	if (reslen > dstlen) {
964*a466cc55SCy Schubert 		errno = ENOMEM;
965*a466cc55SCy Schubert 		reslen = (size_t)-1;
966*a466cc55SCy Schubert 	} else {
967*a466cc55SCy Schubert 		for (j = 0; j < srclen; ++j) {
968*a466cc55SCy Schubert 			tmp = *(const unsigned char*)(src + j);
969*a466cc55SCy Schubert 			ptr = strchr(hex, tmp);
970*a466cc55SCy Schubert 			if (ptr == NULL) {
971*a466cc55SCy Schubert 				errno = EINVAL;
972*a466cc55SCy Schubert 				reslen = (size_t)-1;
973*a466cc55SCy Schubert 				break;
974*a466cc55SCy Schubert 			}
975*a466cc55SCy Schubert 			tmp = (u_char)((ptr - hex) > 1);
976*a466cc55SCy Schubert 			if (j & 1)
977*a466cc55SCy Schubert 				dst[j >> 1] |= tmp;
978*a466cc55SCy Schubert 			else
979*a466cc55SCy Schubert 				dst[j >> 1] = tmp << 4;
980*a466cc55SCy Schubert 		}
981*a466cc55SCy Schubert 	}
982*a466cc55SCy Schubert 	return reslen;
983*a466cc55SCy Schubert }
984*a466cc55SCy Schubert /*
985*a466cc55SCy Schubert  * authdecodepw - decode plaintext or hex-encoded password to binary
986*a466cc55SCy Schubert  * secret.  Returns size of secret in bytes or -1 on error.
987*a466cc55SCy Schubert  */
988*a466cc55SCy Schubert size_t
989*a466cc55SCy Schubert authdecodepw(
990*a466cc55SCy Schubert 	u_char *	dst,
991*a466cc55SCy Schubert 	size_t 		dstlen,
992*a466cc55SCy Schubert 	const char *	src,
993*a466cc55SCy Schubert 	enum AuthPwdEnc	enc
994*a466cc55SCy Schubert 	)
995*a466cc55SCy Schubert {
996*a466cc55SCy Schubert 	size_t		reslen;
997*a466cc55SCy Schubert 
998*a466cc55SCy Schubert 	if ( !(dst && dstlen && src)) {
999*a466cc55SCy Schubert 		errno  = EINVAL;
1000*a466cc55SCy Schubert 		reslen = (size_t)-1;
1001*a466cc55SCy Schubert 	} else {
1002*a466cc55SCy Schubert 		switch (enc) {
1003*a466cc55SCy Schubert 		case AUTHPWD_UNSPEC:
1004*a466cc55SCy Schubert 			if (strlen(src) <= 20)
1005*a466cc55SCy Schubert 				reslen = pwdecode_plain(dst, dstlen, src);
1006*a466cc55SCy Schubert 			else
1007*a466cc55SCy Schubert 				reslen = pwdecode_hex(dst, dstlen, src);
1008*a466cc55SCy Schubert 			break;
1009*a466cc55SCy Schubert 		case AUTHPWD_PLAIN:
1010*a466cc55SCy Schubert 			reslen = pwdecode_plain(dst, dstlen, src);
1011*a466cc55SCy Schubert 			break;
1012*a466cc55SCy Schubert 		case AUTHPWD_HEX:
1013*a466cc55SCy Schubert 			reslen = pwdecode_hex(dst, dstlen, src);
1014*a466cc55SCy Schubert 			break;
1015*a466cc55SCy Schubert 		default:
1016*a466cc55SCy Schubert 			errno = EINVAL;
1017*a466cc55SCy Schubert 			reslen = (size_t)-1;
1018*a466cc55SCy Schubert 		}
1019*a466cc55SCy Schubert 	}
1020*a466cc55SCy Schubert 	return reslen;
1021c0b746e5SOllivier Robert }
1022