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