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, 1174990d495SXin LI const sockaddr_u * addr 1184990d495SXin LI ) 1194990d495SXin LI { 1204990d495SXin LI KeyAccT * node = emalloc(sizeof(KeyAccT)); 1214990d495SXin LI 1224990d495SXin LI memcpy(&node->addr, addr, sizeof(sockaddr_u)); 1234990d495SXin LI node->next = head; 1244990d495SXin LI return node; 1254990d495SXin LI } 1264990d495SXin LI 1274990d495SXin LI /* ----------------------------------------------------------------- */ 1284990d495SXin LI /* pop and deallocate the first node of a list of access nodes, if 1294990d495SXin LI * the list is not empty. Returns the tail of the list. 1304990d495SXin LI */ 1314990d495SXin LI KeyAccT* 1324990d495SXin LI keyacc_pop_free( 1334990d495SXin LI KeyAccT *head 1344990d495SXin LI ) 1354990d495SXin LI { 1364990d495SXin LI KeyAccT * next = NULL; 1374990d495SXin LI if (head) { 1384990d495SXin LI next = head->next; 1394990d495SXin LI free(head); 1404990d495SXin LI } 1414990d495SXin LI return next; 1424990d495SXin LI } 1434990d495SXin LI 1444990d495SXin LI /* ----------------------------------------------------------------- */ 1454990d495SXin LI /* deallocate the list; returns an empty list. */ 1464990d495SXin LI KeyAccT* 1474990d495SXin LI keyacc_all_free( 1484990d495SXin LI KeyAccT * head 1494990d495SXin LI ) 1504990d495SXin LI { 1514990d495SXin LI while (head) 1524990d495SXin LI head = keyacc_pop_free(head); 1534990d495SXin LI return head; 1544990d495SXin LI } 1554990d495SXin LI 1564990d495SXin LI /* ----------------------------------------------------------------- */ 1574990d495SXin LI /* scan a list to see if it contains a given address. Return the 1584990d495SXin LI * default result value in case of an empty list. 1594990d495SXin LI */ 1604990d495SXin LI int /*BOOL*/ 1614990d495SXin LI keyacc_contains( 1624990d495SXin LI const KeyAccT *head, 1634990d495SXin LI const sockaddr_u *addr, 1644990d495SXin LI int defv) 1654990d495SXin LI { 1664990d495SXin LI if (head) { 1674990d495SXin LI do { 1684990d495SXin LI if (SOCK_EQ(&head->addr, addr)) 1694990d495SXin LI return TRUE; 1704990d495SXin LI } while (NULL != (head = head->next)); 1714990d495SXin LI return FALSE; 1724990d495SXin LI } else { 1734990d495SXin LI return !!defv; 1744990d495SXin LI } 1754990d495SXin LI } 1764990d495SXin LI 177c0b746e5SOllivier Robert 178c0b746e5SOllivier Robert /* 179c0b746e5SOllivier Robert * init_auth - initialize internal data 180c0b746e5SOllivier Robert */ 181c0b746e5SOllivier Robert void 182c0b746e5SOllivier Robert init_auth(void) 183c0b746e5SOllivier Robert { 1842b15cb3dSCy Schubert size_t newalloc; 1852b15cb3dSCy Schubert 186c0b746e5SOllivier Robert /* 187c0b746e5SOllivier Robert * Initialize hash table and free list 188c0b746e5SOllivier Robert */ 1892b15cb3dSCy Schubert newalloc = authhashbuckets * sizeof(key_hash[0]); 1902b15cb3dSCy Schubert 1912b15cb3dSCy Schubert key_hash = erealloc(key_hash, newalloc); 1922b15cb3dSCy Schubert memset(key_hash, '\0', newalloc); 1932b15cb3dSCy Schubert 1942b15cb3dSCy Schubert INIT_DLIST(key_listhead, llink); 1952b15cb3dSCy Schubert 1962b15cb3dSCy Schubert #ifdef DEBUG 1972b15cb3dSCy Schubert atexit(&free_auth_mem); 1982b15cb3dSCy Schubert #endif 1992b15cb3dSCy Schubert } 2002b15cb3dSCy Schubert 2012b15cb3dSCy Schubert 2022b15cb3dSCy Schubert /* 2032b15cb3dSCy Schubert * free_auth_mem - assist in leak detection by freeing all dynamic 2042b15cb3dSCy Schubert * allocations from this module. 2052b15cb3dSCy Schubert */ 2062b15cb3dSCy Schubert #ifdef DEBUG 2072b15cb3dSCy Schubert static void 2082b15cb3dSCy Schubert free_auth_mem(void) 2092b15cb3dSCy Schubert { 2102b15cb3dSCy Schubert symkey * sk; 2112b15cb3dSCy Schubert symkey_alloc * alloc; 2122b15cb3dSCy Schubert symkey_alloc * next_alloc; 2132b15cb3dSCy Schubert 2142b15cb3dSCy Schubert while (NULL != (sk = HEAD_DLIST(key_listhead, llink))) { 2154990d495SXin LI freesymkey(sk); 2162b15cb3dSCy Schubert } 2172b15cb3dSCy Schubert free(key_hash); 2182b15cb3dSCy Schubert key_hash = NULL; 2192b15cb3dSCy Schubert cache_keyid = 0; 2202b15cb3dSCy Schubert cache_flags = 0; 22168ba7e87SXin LI cache_keyacclist = NULL; 2222b15cb3dSCy Schubert for (alloc = authallocs; alloc != NULL; alloc = next_alloc) { 2232b15cb3dSCy Schubert next_alloc = alloc->link; 2242b15cb3dSCy Schubert free(alloc->mem); 2252b15cb3dSCy Schubert } 2262b15cb3dSCy Schubert authfreekeys = NULL; 2272b15cb3dSCy Schubert authnumfreekeys = 0; 2282b15cb3dSCy Schubert } 2292b15cb3dSCy Schubert #endif /* DEBUG */ 2302b15cb3dSCy Schubert 2312b15cb3dSCy Schubert 2322b15cb3dSCy Schubert /* 2332b15cb3dSCy Schubert * auth_moremem - get some more free key structures 2342b15cb3dSCy Schubert */ 2352b15cb3dSCy Schubert void 2362b15cb3dSCy Schubert auth_moremem( 2372b15cb3dSCy Schubert int keycount 2382b15cb3dSCy Schubert ) 2392b15cb3dSCy Schubert { 2402b15cb3dSCy Schubert symkey * sk; 2412b15cb3dSCy Schubert int i; 2422b15cb3dSCy Schubert #ifdef DEBUG 2432b15cb3dSCy Schubert void * base; 2442b15cb3dSCy Schubert symkey_alloc * allocrec; 2452b15cb3dSCy Schubert # define MOREMEM_EXTRA_ALLOC (sizeof(*allocrec)) 2462b15cb3dSCy Schubert #else 2472b15cb3dSCy Schubert # define MOREMEM_EXTRA_ALLOC (0) 2482b15cb3dSCy Schubert #endif 2492b15cb3dSCy Schubert 2502b15cb3dSCy Schubert i = (keycount > 0) 2512b15cb3dSCy Schubert ? keycount 2522b15cb3dSCy Schubert : MEMINC; 253*f0574f5cSXin LI sk = eallocarrayxz(i, sizeof(*sk), MOREMEM_EXTRA_ALLOC); 2542b15cb3dSCy Schubert #ifdef DEBUG 2552b15cb3dSCy Schubert base = sk; 2562b15cb3dSCy Schubert #endif 2572b15cb3dSCy Schubert authnumfreekeys += i; 2582b15cb3dSCy Schubert 2592b15cb3dSCy Schubert for (; i > 0; i--, sk++) { 2602b15cb3dSCy Schubert LINK_SLIST(authfreekeys, sk, llink.f); 2612b15cb3dSCy Schubert } 2622b15cb3dSCy Schubert 2632b15cb3dSCy Schubert #ifdef DEBUG 2642b15cb3dSCy Schubert allocrec = (void *)sk; 2652b15cb3dSCy Schubert allocrec->mem = base; 2662b15cb3dSCy Schubert LINK_SLIST(authallocs, allocrec, link); 2672b15cb3dSCy Schubert #endif 2682b15cb3dSCy Schubert } 2692b15cb3dSCy Schubert 2702b15cb3dSCy Schubert 2712b15cb3dSCy Schubert /* 2722b15cb3dSCy Schubert * auth_prealloc_symkeys 2732b15cb3dSCy Schubert */ 2742b15cb3dSCy Schubert void 2752b15cb3dSCy Schubert auth_prealloc_symkeys( 2762b15cb3dSCy Schubert int keycount 2772b15cb3dSCy Schubert ) 2782b15cb3dSCy Schubert { 2792b15cb3dSCy Schubert int allocated; 2802b15cb3dSCy Schubert int additional; 2812b15cb3dSCy Schubert 2822b15cb3dSCy Schubert allocated = authnumkeys + authnumfreekeys; 2832b15cb3dSCy Schubert additional = keycount - allocated; 2842b15cb3dSCy Schubert if (additional > 0) 2852b15cb3dSCy Schubert auth_moremem(additional); 2862b15cb3dSCy Schubert auth_resize_hashtable(); 2872b15cb3dSCy Schubert } 2882b15cb3dSCy Schubert 2892b15cb3dSCy Schubert 29068ba7e87SXin LI static u_short 29168ba7e87SXin LI auth_log2(size_t x) 2922b15cb3dSCy Schubert { 29368ba7e87SXin LI /* 29468ba7e87SXin LI ** bithack to calculate floor(log2(x)) 29568ba7e87SXin LI ** 29668ba7e87SXin LI ** This assumes 29768ba7e87SXin LI ** - (sizeof(size_t) is a power of two 29868ba7e87SXin LI ** - CHAR_BITS is a power of two 29968ba7e87SXin LI ** - returning zero for arguments <= 0 is OK. 30068ba7e87SXin LI ** 30168ba7e87SXin LI ** Does only shifts, masks and sums in integer arithmetic in 30268ba7e87SXin LI ** log2(CHAR_BIT*sizeof(size_t)) steps. (that is, 5/6 steps for 30368ba7e87SXin LI ** 32bit/64bit size_t) 30468ba7e87SXin LI */ 30568ba7e87SXin LI int s; 30668ba7e87SXin LI int r = 0; 30768ba7e87SXin LI size_t m = ~(size_t)0; 30868ba7e87SXin LI 30968ba7e87SXin LI for (s = sizeof(size_t) / 2 * CHAR_BIT; s != 0; s >>= 1) { 31068ba7e87SXin LI m <<= s; 31168ba7e87SXin LI if (x & m) 31268ba7e87SXin LI r += s; 31368ba7e87SXin LI else 31468ba7e87SXin LI x <<= s; 31568ba7e87SXin LI } 31668ba7e87SXin LI return (u_short)r; 3172b15cb3dSCy Schubert } 3182b15cb3dSCy Schubert 3194990d495SXin LI static void 3204990d495SXin LI authcache_flush_id( 3214990d495SXin LI keyid_t id 3224990d495SXin LI ) 3234990d495SXin LI { 3244990d495SXin LI if (cache_keyid == id) { 3254990d495SXin LI cache_keyid = 0; 3264990d495SXin LI cache_type = 0; 3274990d495SXin LI cache_flags = 0; 3284990d495SXin LI cache_secret = NULL; 3294990d495SXin LI cache_secretsize = 0; 3304990d495SXin LI cache_keyacclist = NULL; 3314990d495SXin LI } 3324990d495SXin LI } 3334990d495SXin LI 3342b15cb3dSCy Schubert 3352b15cb3dSCy Schubert /* 3362b15cb3dSCy Schubert * auth_resize_hashtable 3372b15cb3dSCy Schubert * 3382b15cb3dSCy Schubert * Size hash table to average 4 or fewer entries per bucket initially, 3392b15cb3dSCy Schubert * within the bounds of at least 4 and no more than 15 bits for the hash 3402b15cb3dSCy Schubert * table index. Populate the hash table. 3412b15cb3dSCy Schubert */ 3422b15cb3dSCy Schubert static void 3432b15cb3dSCy Schubert auth_resize_hashtable(void) 3442b15cb3dSCy Schubert { 3452b15cb3dSCy Schubert u_long totalkeys; 3462b15cb3dSCy Schubert u_short hashbits; 3472b15cb3dSCy Schubert u_short hash; 3482b15cb3dSCy Schubert size_t newalloc; 3492b15cb3dSCy Schubert symkey * sk; 3502b15cb3dSCy Schubert 3512b15cb3dSCy Schubert totalkeys = authnumkeys + authnumfreekeys; 35268ba7e87SXin LI hashbits = auth_log2(totalkeys / 4) + 1; 3532b15cb3dSCy Schubert hashbits = max(4, hashbits); 3542b15cb3dSCy Schubert hashbits = min(15, hashbits); 3552b15cb3dSCy Schubert 3562b15cb3dSCy Schubert authhashbuckets = 1 << hashbits; 3572b15cb3dSCy Schubert authhashmask = authhashbuckets - 1; 3582b15cb3dSCy Schubert newalloc = authhashbuckets * sizeof(key_hash[0]); 3592b15cb3dSCy Schubert 3602b15cb3dSCy Schubert key_hash = erealloc(key_hash, newalloc); 3612b15cb3dSCy Schubert memset(key_hash, '\0', newalloc); 3622b15cb3dSCy Schubert 3632b15cb3dSCy Schubert ITER_DLIST_BEGIN(key_listhead, sk, llink, symkey) 3642b15cb3dSCy Schubert hash = KEYHASH(sk->keyid); 3652b15cb3dSCy Schubert LINK_SLIST(key_hash[hash], sk, hlink); 3662b15cb3dSCy Schubert ITER_DLIST_END() 3672b15cb3dSCy Schubert } 3682b15cb3dSCy Schubert 3692b15cb3dSCy Schubert 3702b15cb3dSCy Schubert /* 3712b15cb3dSCy Schubert * allocsymkey - common code to allocate and link in symkey 3722b15cb3dSCy Schubert * 3732b15cb3dSCy Schubert * secret must be allocated with a free-compatible allocator. It is 3742b15cb3dSCy Schubert * owned by the referring symkey structure, and will be free()d by 3752b15cb3dSCy Schubert * freesymkey(). 3762b15cb3dSCy Schubert */ 3772b15cb3dSCy Schubert static void 3782b15cb3dSCy Schubert allocsymkey( 3792b15cb3dSCy Schubert keyid_t id, 3802b15cb3dSCy Schubert u_short flags, 3812b15cb3dSCy Schubert u_short type, 3822b15cb3dSCy Schubert u_long lifetime, 3834990d495SXin LI size_t secretsize, 38468ba7e87SXin LI u_char * secret, 38568ba7e87SXin LI KeyAccT * ka 3862b15cb3dSCy Schubert ) 3872b15cb3dSCy Schubert { 3882b15cb3dSCy Schubert symkey * sk; 3894990d495SXin LI symkey ** bucket; 3904990d495SXin LI 3914990d495SXin LI bucket = &key_hash[KEYHASH(id)]; 3924990d495SXin LI 3932b15cb3dSCy Schubert 3942b15cb3dSCy Schubert if (authnumfreekeys < 1) 3952b15cb3dSCy Schubert auth_moremem(-1); 3962b15cb3dSCy Schubert UNLINK_HEAD_SLIST(sk, authfreekeys, llink.f); 3972b15cb3dSCy Schubert DEBUG_ENSURE(sk != NULL); 3982b15cb3dSCy Schubert sk->keyid = id; 3992b15cb3dSCy Schubert sk->flags = flags; 4002b15cb3dSCy Schubert sk->type = type; 4012b15cb3dSCy Schubert sk->secretsize = secretsize; 4022b15cb3dSCy Schubert sk->secret = secret; 40368ba7e87SXin LI sk->keyacclist = ka; 4042b15cb3dSCy Schubert sk->lifetime = lifetime; 4052b15cb3dSCy Schubert LINK_SLIST(*bucket, sk, hlink); 4062b15cb3dSCy Schubert LINK_TAIL_DLIST(key_listhead, sk, llink); 4072b15cb3dSCy Schubert authnumfreekeys--; 4082b15cb3dSCy Schubert authnumkeys++; 4092b15cb3dSCy Schubert } 4102b15cb3dSCy Schubert 4112b15cb3dSCy Schubert 4122b15cb3dSCy Schubert /* 4132b15cb3dSCy Schubert * freesymkey - common code to remove a symkey and recycle its entry. 4142b15cb3dSCy Schubert */ 4152b15cb3dSCy Schubert static void 4162b15cb3dSCy Schubert freesymkey( 4174990d495SXin LI symkey * sk 4182b15cb3dSCy Schubert ) 4192b15cb3dSCy Schubert { 4204990d495SXin LI symkey ** bucket; 4212b15cb3dSCy Schubert symkey * unlinked; 4222b15cb3dSCy Schubert 4234990d495SXin LI if (NULL == sk) 4244990d495SXin LI return; 4254990d495SXin LI 4264990d495SXin LI authcache_flush_id(sk->keyid); 4274990d495SXin LI keyacc_all_free(sk->keyacclist); 4284990d495SXin LI 4294990d495SXin LI bucket = &key_hash[KEYHASH(sk->keyid)]; 4302b15cb3dSCy Schubert if (sk->secret != NULL) { 4312b15cb3dSCy Schubert memset(sk->secret, '\0', sk->secretsize); 4322b15cb3dSCy Schubert free(sk->secret); 4332b15cb3dSCy Schubert } 4342b15cb3dSCy Schubert UNLINK_SLIST(unlinked, *bucket, sk, hlink, symkey); 4352b15cb3dSCy Schubert DEBUG_ENSURE(sk == unlinked); 4362b15cb3dSCy Schubert UNLINK_DLIST(sk, llink); 4372b15cb3dSCy Schubert memset((char *)sk + offsetof(symkey, symkey_payload), '\0', 4382b15cb3dSCy Schubert sizeof(*sk) - offsetof(symkey, symkey_payload)); 4392b15cb3dSCy Schubert LINK_SLIST(authfreekeys, sk, llink.f); 4402b15cb3dSCy Schubert authnumkeys--; 4412b15cb3dSCy Schubert authnumfreekeys++; 442c0b746e5SOllivier Robert } 443c0b746e5SOllivier Robert 444c0b746e5SOllivier Robert 445c0b746e5SOllivier Robert /* 446c0b746e5SOllivier Robert * auth_findkey - find a key in the hash table 447c0b746e5SOllivier Robert */ 448c0b746e5SOllivier Robert struct savekey * 449c0b746e5SOllivier Robert auth_findkey( 4502b15cb3dSCy Schubert keyid_t id 451c0b746e5SOllivier Robert ) 452c0b746e5SOllivier Robert { 4532b15cb3dSCy Schubert symkey * sk; 454c0b746e5SOllivier Robert 4554990d495SXin LI for (sk = key_hash[KEYHASH(id)]; sk != NULL; sk = sk->hlink) 4564990d495SXin LI if (id == sk->keyid) 4572b15cb3dSCy Schubert return sk; 4582b15cb3dSCy Schubert return NULL; 459c0b746e5SOllivier Robert } 460c0b746e5SOllivier Robert 461c0b746e5SOllivier Robert 462c0b746e5SOllivier Robert /* 4634990d495SXin LI * auth_havekey - return TRUE if the key id is zero or known. The 4644990d495SXin LI * key needs not to be trusted. 465c0b746e5SOllivier Robert */ 466c0b746e5SOllivier Robert int 467c0b746e5SOllivier Robert auth_havekey( 4682b15cb3dSCy Schubert keyid_t id 469c0b746e5SOllivier Robert ) 470c0b746e5SOllivier Robert { 4714990d495SXin LI return 4724990d495SXin LI (0 == id) || 4734990d495SXin LI (cache_keyid == id) || 4744990d495SXin LI (NULL != auth_findkey(id)); 475c0b746e5SOllivier Robert } 476c0b746e5SOllivier Robert 477c0b746e5SOllivier Robert 478c0b746e5SOllivier Robert /* 4792b15cb3dSCy Schubert * authhavekey - return TRUE and cache the key, if zero or both known 4802b15cb3dSCy Schubert * and trusted. 481c0b746e5SOllivier Robert */ 482c0b746e5SOllivier Robert int 483c0b746e5SOllivier Robert authhavekey( 4842b15cb3dSCy Schubert keyid_t id 485c0b746e5SOllivier Robert ) 486c0b746e5SOllivier Robert { 4872b15cb3dSCy Schubert symkey * sk; 488c0b746e5SOllivier Robert 489c0b746e5SOllivier Robert authkeylookups++; 4904990d495SXin LI if (0 == id || cache_keyid == id) 4914990d495SXin LI return !!(KEY_TRUSTED & cache_flags); 492c0b746e5SOllivier Robert 493c0b746e5SOllivier Robert /* 4944990d495SXin LI * Search the bin for the key. If not found, or found but the key 4954990d495SXin LI * type is zero, somebody marked it trusted without specifying a 4964990d495SXin LI * key or key type. In this case consider the key missing. 497c0b746e5SOllivier Robert */ 4982b15cb3dSCy Schubert authkeyuncached++; 4994990d495SXin LI sk = auth_findkey(id); 5004990d495SXin LI if ((sk == NULL) || (sk->type == 0)) { 5012b15cb3dSCy Schubert authkeynotfound++; 5022b15cb3dSCy Schubert return FALSE; 503c0b746e5SOllivier Robert } 5042b15cb3dSCy Schubert 5052b15cb3dSCy Schubert /* 5064990d495SXin LI * If the key is not trusted, the key is not considered found. 5072b15cb3dSCy Schubert */ 5082b15cb3dSCy Schubert if ( ! (KEY_TRUSTED & sk->flags)) { 5092b15cb3dSCy Schubert authnokey++; 5102b15cb3dSCy Schubert return FALSE; 5112b15cb3dSCy Schubert } 5122b15cb3dSCy Schubert 5132b15cb3dSCy Schubert /* 5142b15cb3dSCy Schubert * The key is found and trusted. Initialize the key cache. 5152b15cb3dSCy Schubert */ 5162b15cb3dSCy Schubert cache_keyid = sk->keyid; 5172b15cb3dSCy Schubert cache_type = sk->type; 5182b15cb3dSCy Schubert cache_flags = sk->flags; 5192b15cb3dSCy Schubert cache_secret = sk->secret; 5202b15cb3dSCy Schubert cache_secretsize = sk->secretsize; 52168ba7e87SXin LI cache_keyacclist = sk->keyacclist; 5222b15cb3dSCy Schubert 5232b15cb3dSCy Schubert return TRUE; 524c0b746e5SOllivier Robert } 525c0b746e5SOllivier Robert 526c0b746e5SOllivier Robert 527c0b746e5SOllivier Robert /* 528c0b746e5SOllivier Robert * authtrust - declare a key to be trusted/untrusted 529c0b746e5SOllivier Robert */ 530c0b746e5SOllivier Robert void 531c0b746e5SOllivier Robert authtrust( 5322b15cb3dSCy Schubert keyid_t id, 533224ba2bdSOllivier Robert u_long trust 534c0b746e5SOllivier Robert ) 535c0b746e5SOllivier Robert { 5362b15cb3dSCy Schubert symkey * sk; 5372b15cb3dSCy Schubert u_long lifetime; 538c0b746e5SOllivier Robert 5392b15cb3dSCy Schubert /* 5402b15cb3dSCy Schubert * Search bin for key; if it does not exist and is untrusted, 5412b15cb3dSCy Schubert * forget it. 5422b15cb3dSCy Schubert */ 5434990d495SXin LI 5444990d495SXin LI sk = auth_findkey(id); 5454990d495SXin LI if (!trust && sk == NULL) 546c0b746e5SOllivier Robert return; 547c0b746e5SOllivier Robert 5482b15cb3dSCy Schubert /* 5492b15cb3dSCy Schubert * There are two conditions remaining. Either it does not 5502b15cb3dSCy Schubert * exist and is to be trusted or it does exist and is or is 5512b15cb3dSCy Schubert * not to be trusted. 5522b15cb3dSCy Schubert */ 5532b15cb3dSCy Schubert if (sk != NULL) { 5542b15cb3dSCy Schubert /* 5554990d495SXin LI * Key exists. If it is to be trusted, say so and update 5564990d495SXin LI * its lifetime. If no longer trusted, return it to the 5574990d495SXin LI * free list. Flush the cache first to be sure there are 5584990d495SXin LI * no discrepancies. 5592b15cb3dSCy Schubert */ 5604990d495SXin LI authcache_flush_id(id); 561c0b746e5SOllivier Robert if (trust > 0) { 562c0b746e5SOllivier Robert sk->flags |= KEY_TRUSTED; 563c0b746e5SOllivier Robert if (trust > 1) 564c0b746e5SOllivier Robert sk->lifetime = current_time + trust; 565c0b746e5SOllivier Robert else 566c0b746e5SOllivier Robert sk->lifetime = 0; 5674990d495SXin LI } else { 5684990d495SXin LI freesymkey(sk); 569c0b746e5SOllivier Robert } 5702b15cb3dSCy Schubert return; 5712b15cb3dSCy Schubert } 572c0b746e5SOllivier Robert 5732b15cb3dSCy Schubert /* 5742b15cb3dSCy Schubert * keyid is not present, but the is to be trusted. We allocate 5752b15cb3dSCy Schubert * a new key, but do not specify a key type or secret. 5762b15cb3dSCy Schubert */ 5772b15cb3dSCy Schubert if (trust > 1) { 5782b15cb3dSCy Schubert lifetime = current_time + trust; 579c0b746e5SOllivier Robert } else { 5802b15cb3dSCy Schubert lifetime = 0; 581c0b746e5SOllivier Robert } 5824990d495SXin LI allocsymkey(id, KEY_TRUSTED, 0, lifetime, 0, NULL, NULL); 583c0b746e5SOllivier Robert } 584c0b746e5SOllivier Robert 585c0b746e5SOllivier Robert 586c0b746e5SOllivier Robert /* 587c0b746e5SOllivier Robert * authistrusted - determine whether a key is trusted 588c0b746e5SOllivier Robert */ 589c0b746e5SOllivier Robert int 590c0b746e5SOllivier Robert authistrusted( 5914990d495SXin LI keyid_t id 592c0b746e5SOllivier Robert ) 593c0b746e5SOllivier Robert { 5942b15cb3dSCy Schubert symkey * sk; 595c0b746e5SOllivier Robert 5964990d495SXin LI if (id == cache_keyid) 5972b15cb3dSCy Schubert return !!(KEY_TRUSTED & cache_flags); 598c0b746e5SOllivier Robert 599c0b746e5SOllivier Robert authkeyuncached++; 6004990d495SXin LI sk = auth_findkey(id); 6014990d495SXin LI if (sk == NULL || !(KEY_TRUSTED & sk->flags)) { 602c0b746e5SOllivier Robert authkeynotfound++; 6032b15cb3dSCy Schubert return FALSE; 604c0b746e5SOllivier Robert } 6052b15cb3dSCy Schubert return TRUE; 606c0b746e5SOllivier Robert } 607c0b746e5SOllivier Robert 60868ba7e87SXin LI 60968ba7e87SXin LI /* 61068ba7e87SXin LI * authistrustedip - determine if the IP is OK for the keyid 61168ba7e87SXin LI */ 61268ba7e87SXin LI int 61368ba7e87SXin LI authistrustedip( 61468ba7e87SXin LI keyid_t keyno, 61568ba7e87SXin LI sockaddr_u * sau 61668ba7e87SXin LI ) 61768ba7e87SXin LI { 61868ba7e87SXin LI symkey * sk; 61968ba7e87SXin LI 6204990d495SXin LI /* That specific key was already used to authenticate the 6214990d495SXin LI * packet. Therefore, the key *must* exist... There's a chance 6224990d495SXin LI * that is not trusted, though. 6234990d495SXin LI */ 6244990d495SXin LI if (keyno == cache_keyid) { 6254990d495SXin LI return (KEY_TRUSTED & cache_flags) && 6264990d495SXin LI keyacc_contains(cache_keyacclist, sau, TRUE); 6274990d495SXin LI } else { 62868ba7e87SXin LI authkeyuncached++; 6294990d495SXin LI sk = auth_findkey(keyno); 6304990d495SXin LI INSIST(NULL != sk); 6314990d495SXin LI return (KEY_TRUSTED & sk->flags) && 6324990d495SXin LI keyacc_contains(sk->keyacclist, sau, TRUE); 63368ba7e87SXin LI } 63468ba7e87SXin LI } 63568ba7e87SXin LI 6363311ff84SXin LI /* Note: There are two locations below where 'strncpy()' is used. While 6373311ff84SXin LI * this function is a hazard by itself, it's essential that it is used 6383311ff84SXin LI * here. Bug 1243 involved that the secret was filled with NUL bytes 6393311ff84SXin LI * after the first NUL encountered, and 'strlcpy()' simply does NOT have 6403311ff84SXin LI * this behaviour. So disabling the fix and reverting to the buggy 6413311ff84SXin LI * behaviour due to compatibility issues MUST also fill with NUL and 6423311ff84SXin LI * this needs 'strncpy'. Also, the secret is managed as a byte blob of a 6433311ff84SXin LI * given size, and eventually truncating it and replacing the last byte 6443311ff84SXin LI * with a NUL would be a bug. 6453311ff84SXin LI * perlinger@ntp.org 2015-10-10 6463311ff84SXin LI */ 647c0b746e5SOllivier Robert void 648c0b746e5SOllivier Robert MD5auth_setkey( 649224ba2bdSOllivier Robert keyid_t keyno, 6502b15cb3dSCy Schubert int keytype, 651c0b746e5SOllivier Robert const u_char *key, 6524990d495SXin LI size_t secretsize, 65368ba7e87SXin LI KeyAccT *ka 654c0b746e5SOllivier Robert ) 655c0b746e5SOllivier Robert { 6562b15cb3dSCy Schubert symkey * sk; 6572b15cb3dSCy Schubert u_char * secret; 658c0b746e5SOllivier Robert 6592b15cb3dSCy Schubert DEBUG_ENSURE(keytype <= USHRT_MAX); 6604990d495SXin LI DEBUG_ENSURE(secretsize < 4 * 1024); 661c0b746e5SOllivier Robert /* 662c0b746e5SOllivier Robert * See if we already have the key. If so just stick in the 663c0b746e5SOllivier Robert * new value. 664c0b746e5SOllivier Robert */ 6654990d495SXin LI sk = auth_findkey(keyno); 6664990d495SXin LI if (sk != NULL && keyno == sk->keyid) { 6679034852cSGleb Smirnoff /* TALOS-CAN-0054: make sure we have a new buffer! */ 6689034852cSGleb Smirnoff if (NULL != sk->secret) { 6699034852cSGleb Smirnoff memset(sk->secret, 0, sk->secretsize); 6709034852cSGleb Smirnoff free(sk->secret); 6719034852cSGleb Smirnoff } 6724990d495SXin LI sk->secret = emalloc(secretsize + 1); 6732b15cb3dSCy Schubert sk->type = (u_short)keytype; 6744990d495SXin LI sk->secretsize = secretsize; 6754990d495SXin LI /* make sure access lists don't leak here! */ 6764990d495SXin LI if (ka != sk->keyacclist) { 6774990d495SXin LI keyacc_all_free(sk->keyacclist); 67868ba7e87SXin LI sk->keyacclist = ka; 6794990d495SXin LI } 6802b15cb3dSCy Schubert #ifndef DISABLE_BUG1243_FIX 6812b15cb3dSCy Schubert memcpy(sk->secret, key, secretsize); 6822b15cb3dSCy Schubert #else 6833311ff84SXin LI /* >MUST< use 'strncpy()' here! See above! */ 6843311ff84SXin LI strncpy((char *)sk->secret, (const char *)key, 6852b15cb3dSCy Schubert secretsize); 6862b15cb3dSCy Schubert #endif 6874990d495SXin LI authcache_flush_id(keyno); 688c0b746e5SOllivier Robert return; 689c0b746e5SOllivier Robert } 690c0b746e5SOllivier Robert 691c0b746e5SOllivier Robert /* 692c0b746e5SOllivier Robert * Need to allocate new structure. Do it. 693c0b746e5SOllivier Robert */ 6944990d495SXin LI secret = emalloc(secretsize + 1); 6952b15cb3dSCy Schubert #ifndef DISABLE_BUG1243_FIX 6962b15cb3dSCy Schubert memcpy(secret, key, secretsize); 6972b15cb3dSCy Schubert #else 6983311ff84SXin LI /* >MUST< use 'strncpy()' here! See above! */ 6993311ff84SXin LI strncpy((char *)secret, (const char *)key, secretsize); 7002b15cb3dSCy Schubert #endif 7014990d495SXin LI allocsymkey(keyno, 0, (u_short)keytype, 0, 7024990d495SXin LI secretsize, secret, ka); 7032b15cb3dSCy Schubert #ifdef DEBUG 7042b15cb3dSCy Schubert if (debug >= 4) { 7052b15cb3dSCy Schubert size_t j; 7062b15cb3dSCy Schubert 7072b15cb3dSCy Schubert printf("auth_setkey: key %d type %d len %d ", (int)keyno, 7082b15cb3dSCy Schubert keytype, (int)secretsize); 7094990d495SXin LI for (j = 0; j < secretsize; j++) { 7102b15cb3dSCy Schubert printf("%02x", secret[j]); 7114990d495SXin LI } 7122b15cb3dSCy Schubert printf("\n"); 7132b15cb3dSCy Schubert } 7142b15cb3dSCy Schubert #endif 715c0b746e5SOllivier Robert } 716c0b746e5SOllivier Robert 717c0b746e5SOllivier Robert 718c0b746e5SOllivier Robert /* 7192b15cb3dSCy Schubert * auth_delkeys - delete non-autokey untrusted keys, and clear all info 7202b15cb3dSCy Schubert * except the trusted bit of non-autokey trusted keys, in 7212b15cb3dSCy Schubert * preparation for rereading the keys file. 722c0b746e5SOllivier Robert */ 723c0b746e5SOllivier Robert void 724c0b746e5SOllivier Robert auth_delkeys(void) 725c0b746e5SOllivier Robert { 7262b15cb3dSCy Schubert symkey * sk; 727c0b746e5SOllivier Robert 7282b15cb3dSCy Schubert ITER_DLIST_BEGIN(key_listhead, sk, llink, symkey) 7292b15cb3dSCy Schubert if (sk->keyid > NTP_MAXKEY) { /* autokey */ 7302b15cb3dSCy Schubert continue; 7312b15cb3dSCy Schubert } 7322b15cb3dSCy Schubert 733c0b746e5SOllivier Robert /* 7349034852cSGleb Smirnoff * Don't lose info as to which keys are trusted. Make 7359034852cSGleb Smirnoff * sure there are no dangling pointers! 736c0b746e5SOllivier Robert */ 7372b15cb3dSCy Schubert if (KEY_TRUSTED & sk->flags) { 7382b15cb3dSCy Schubert if (sk->secret != NULL) { 7399034852cSGleb Smirnoff memset(sk->secret, 0, sk->secretsize); 7402b15cb3dSCy Schubert free(sk->secret); 7419034852cSGleb Smirnoff sk->secret = NULL; /* TALOS-CAN-0054 */ 7422b15cb3dSCy Schubert } 7434990d495SXin LI sk->keyacclist = keyacc_all_free(sk->keyacclist); 7442b15cb3dSCy Schubert sk->secretsize = 0; 745c0b746e5SOllivier Robert sk->lifetime = 0; 746c0b746e5SOllivier Robert } else { 7474990d495SXin LI freesymkey(sk); 748c0b746e5SOllivier Robert } 7492b15cb3dSCy Schubert ITER_DLIST_END() 750c0b746e5SOllivier Robert } 7512b15cb3dSCy Schubert 752c0b746e5SOllivier Robert 753c0b746e5SOllivier Robert /* 754c0b746e5SOllivier Robert * auth_agekeys - delete keys whose lifetimes have expired 755c0b746e5SOllivier Robert */ 756c0b746e5SOllivier Robert void 757c0b746e5SOllivier Robert auth_agekeys(void) 758c0b746e5SOllivier Robert { 7592b15cb3dSCy Schubert symkey * sk; 760c0b746e5SOllivier Robert 7612b15cb3dSCy Schubert ITER_DLIST_BEGIN(key_listhead, sk, llink, symkey) 7622b15cb3dSCy Schubert if (sk->lifetime > 0 && current_time > sk->lifetime) { 7634990d495SXin LI freesymkey(sk); 764c0b746e5SOllivier Robert authkeyexpired++; 765c0b746e5SOllivier Robert } 7662b15cb3dSCy Schubert ITER_DLIST_END() 7672b15cb3dSCy Schubert DPRINTF(1, ("auth_agekeys: at %lu keys %lu expired %lu\n", 7682b15cb3dSCy Schubert current_time, authnumkeys, authkeyexpired)); 769c0b746e5SOllivier Robert } 7702b15cb3dSCy Schubert 771c0b746e5SOllivier Robert 772c0b746e5SOllivier Robert /* 773c0b746e5SOllivier Robert * authencrypt - generate message authenticator 774c0b746e5SOllivier Robert * 775c0b746e5SOllivier Robert * Returns length of authenticator field, zero if key not found. 776c0b746e5SOllivier Robert */ 7773311ff84SXin LI size_t 778c0b746e5SOllivier Robert authencrypt( 779224ba2bdSOllivier Robert keyid_t keyno, 780c0b746e5SOllivier Robert u_int32 * pkt, 7813311ff84SXin LI size_t length 782c0b746e5SOllivier Robert ) 7833311ff84SXin LI { 784c0b746e5SOllivier Robert /* 785c0b746e5SOllivier Robert * A zero key identifier means the sender has not verified 786c0b746e5SOllivier Robert * the last message was correctly authenticated. The MAC 787c0b746e5SOllivier Robert * consists of a single word with value zero. 788c0b746e5SOllivier Robert */ 789c0b746e5SOllivier Robert authencryptions++; 790224ba2bdSOllivier Robert pkt[length / 4] = htonl(keyno); 7912b15cb3dSCy Schubert if (0 == keyno) { 7922b15cb3dSCy Schubert return 4; 793c0b746e5SOllivier Robert } 7942b15cb3dSCy Schubert if (!authhavekey(keyno)) { 7952b15cb3dSCy Schubert return 0; 796c0b746e5SOllivier Robert } 797c0b746e5SOllivier Robert 7982b15cb3dSCy Schubert return MD5authencrypt(cache_type, cache_secret, pkt, length); 7992b15cb3dSCy Schubert } 8002b15cb3dSCy Schubert 8012b15cb3dSCy Schubert 802c0b746e5SOllivier Robert /* 803c0b746e5SOllivier Robert * authdecrypt - verify message authenticator 804c0b746e5SOllivier Robert * 8052b15cb3dSCy Schubert * Returns TRUE if authenticator valid, FALSE if invalid or not found. 806c0b746e5SOllivier Robert */ 807c0b746e5SOllivier Robert int 808c0b746e5SOllivier Robert authdecrypt( 809224ba2bdSOllivier Robert keyid_t keyno, 810c0b746e5SOllivier Robert u_int32 * pkt, 8113311ff84SXin LI size_t length, 8123311ff84SXin LI size_t size 813c0b746e5SOllivier Robert ) 814c0b746e5SOllivier Robert { 815c0b746e5SOllivier Robert /* 816c0b746e5SOllivier Robert * A zero key identifier means the sender has not verified 8172b15cb3dSCy Schubert * the last message was correctly authenticated. For our 8182b15cb3dSCy Schubert * purpose this is an invalid authenticator. 819c0b746e5SOllivier Robert */ 820c0b746e5SOllivier Robert authdecryptions++; 8212b15cb3dSCy Schubert if (0 == keyno || !authhavekey(keyno) || size < 4) { 8222b15cb3dSCy Schubert return FALSE; 8232b15cb3dSCy Schubert } 824c0b746e5SOllivier Robert 8252b15cb3dSCy Schubert return MD5authdecrypt(cache_type, cache_secret, pkt, length, 8262b15cb3dSCy Schubert size); 827c0b746e5SOllivier Robert } 828