1/* $NetBSD: authkeys.c,v 1.13 2020/05/25 20:47:24 christos Exp $ */ 2 3/* 4 * authkeys.c - routines to manage the storage of authentication keys 5 */ 6#ifdef HAVE_CONFIG_H 7# include <config.h> 8#endif 9 10#include <math.h> 11#include <stdio.h> 12 13#include "ntp.h" 14#include "ntp_fp.h" 15#include "ntpd.h" 16#include "ntp_lists.h" 17#include "ntp_string.h" 18#include "ntp_malloc.h" 19#include "ntp_stdlib.h" 20#include "ntp_keyacc.h" 21 22/* 23 * Structure to store keys in in the hash table. 24 */ 25typedef struct savekey symkey; 26 27struct savekey { 28 symkey * hlink; /* next in hash bucket */ 29 DECL_DLIST_LINK(symkey, llink); /* for overall & free lists */ 30 u_char * secret; /* shared secret */ 31 KeyAccT * keyacclist; /* Private key access list */ 32 u_long lifetime; /* remaining lifetime */ 33 keyid_t keyid; /* key identifier */ 34 u_short type; /* OpenSSL digest NID */ 35 size_t secretsize; /* secret octets */ 36 u_short flags; /* KEY_ flags that wave */ 37}; 38 39/* define the payload region of symkey beyond the list pointers */ 40#define symkey_payload secret 41 42#define KEY_TRUSTED 0x001 /* this key is trusted */ 43 44#ifdef DEBUG 45typedef struct symkey_alloc_tag symkey_alloc; 46 47struct symkey_alloc_tag { 48 symkey_alloc * link; 49 void * mem; /* enable free() atexit */ 50}; 51 52symkey_alloc * authallocs; 53#endif /* DEBUG */ 54 55static u_short auth_log2(size_t); 56static void auth_resize_hashtable(void); 57static void allocsymkey(keyid_t, u_short, 58 u_short, u_long, size_t, u_char *, KeyAccT *); 59static void freesymkey(symkey *); 60#ifdef DEBUG 61static void free_auth_mem(void); 62#endif 63 64symkey key_listhead; /* list of all in-use keys */; 65/* 66 * The hash table. This is indexed by the low order bits of the 67 * keyid. We make this fairly big for potentially busy servers. 68 */ 69#define DEF_AUTHHASHSIZE 64 70/*#define HASHMASK ((HASHSIZE)-1)*/ 71#define KEYHASH(keyid) ((keyid) & authhashmask) 72 73int authhashdisabled; 74u_short authhashbuckets = DEF_AUTHHASHSIZE; 75u_short authhashmask = DEF_AUTHHASHSIZE - 1; 76symkey **key_hash; 77 78u_long authkeynotfound; /* keys not found */ 79u_long authkeylookups; /* calls to lookup keys */ 80u_long authnumkeys; /* number of active keys */ 81u_long authkeyexpired; /* key lifetime expirations */ 82u_long authkeyuncached; /* cache misses */ 83u_long authnokey; /* calls to encrypt with no key */ 84u_long authencryptions; /* calls to encrypt */ 85u_long authdecryptions; /* calls to decrypt */ 86 87/* 88 * Storage for free symkey structures. We malloc() such things but 89 * never free them. 90 */ 91symkey *authfreekeys; 92int authnumfreekeys; 93 94#define MEMINC 16 /* number of new free ones to get */ 95 96/* 97 * The key cache. We cache the last key we looked at here. 98 * Note: this should hold the last *trusted* key. Also the 99 * cache is only loaded when the digest type / MAC algorithm 100 * is valid. 101 */ 102keyid_t cache_keyid; /* key identifier */ 103u_char *cache_secret; /* secret */ 104size_t cache_secretsize; /* secret length */ 105int cache_type; /* OpenSSL digest NID */ 106u_short cache_flags; /* flags that wave */ 107KeyAccT *cache_keyacclist; /* key access list */ 108 109/* -------------------------------------------------------------------- 110 * manage key access lists 111 * -------------------------------------------------------------------- 112 */ 113/* allocate and populate new access node and pushes it on the list. 114 * Returns the new head. 115 */ 116KeyAccT* 117keyacc_new_push( 118 KeyAccT * head, 119 const sockaddr_u * addr, 120 unsigned int subnetbits 121 ) 122{ 123 KeyAccT * node = emalloc(sizeof(KeyAccT)); 124 125 memcpy(&node->addr, addr, sizeof(sockaddr_u)); 126 node->subnetbits = subnetbits; 127 node->next = head; 128 129 return node; 130} 131 132/* ----------------------------------------------------------------- */ 133/* pop and deallocate the first node of a list of access nodes, if 134 * the list is not empty. Returns the tail of the list. 135 */ 136KeyAccT* 137keyacc_pop_free( 138 KeyAccT *head 139 ) 140{ 141 KeyAccT * next = NULL; 142 if (head) { 143 next = head->next; 144 free(head); 145 } 146 return next; 147} 148 149/* ----------------------------------------------------------------- */ 150/* deallocate the list; returns an empty list. */ 151KeyAccT* 152keyacc_all_free( 153 KeyAccT * head 154 ) 155{ 156 while (head) 157 head = keyacc_pop_free(head); 158 return head; 159} 160 161/* ----------------------------------------------------------------- */ 162/* scan a list to see if it contains a given address. Return the 163 * default result value in case of an empty list. 164 */ 165int /*BOOL*/ 166keyacc_contains( 167 const KeyAccT *head, 168 const sockaddr_u *addr, 169 int defv) 170{ 171 if (head) { 172 do { 173 if (keyacc_amatch(&head->addr, addr, 174 head->subnetbits)) 175 return TRUE; 176 } while (NULL != (head = head->next)); 177 return FALSE; 178 } else { 179 return !!defv; 180 } 181} 182 183#if CHAR_BIT != 8 184# error "don't know how to handle bytes with that bit size" 185#endif 186 187/* ----------------------------------------------------------------- */ 188/* check two addresses for a match, taking a prefix length into account 189 * when doing the compare. 190 * 191 * The ISC lib contains a similar function with not entirely specified 192 * semantics, so it seemed somewhat cleaner to do this from scratch. 193 * 194 * Note 1: It *is* assumed that the addresses are stored in network byte 195 * order, that is, most significant byte first! 196 * 197 * Note 2: "no address" compares unequal to all other addresses, even to 198 * itself. This has the same semantics as NaNs have for floats: *any* 199 * relational or equality operation involving a NaN returns FALSE, even 200 * equality with itself. "no address" is either a NULL pointer argument 201 * or an address of type AF_UNSPEC. 202 */ 203int/*BOOL*/ 204keyacc_amatch( 205 const sockaddr_u * a1, 206 const sockaddr_u * a2, 207 unsigned int mbits 208 ) 209{ 210 const uint8_t * pm1; 211 const uint8_t * pm2; 212 uint8_t msk; 213 unsigned int len; 214 215 /* 1st check: If any address is not an address, it's inequal. */ 216 if ( !a1 || (AF_UNSPEC == AF(a1)) || 217 !a2 || (AF_UNSPEC == AF(a2)) ) 218 return FALSE; 219 220 /* We could check pointers for equality here and shortcut the 221 * other checks if we find object identity. But that use case is 222 * too rare to care for it. 223 */ 224 225 /* 2nd check: Address families must be the same. */ 226 if (AF(a1) != AF(a2)) 227 return FALSE; 228 229 /* type check: address family determines buffer & size */ 230 switch (AF(a1)) { 231 case AF_INET: 232 /* IPv4 is easy: clamp size, get byte pointers */ 233 if (mbits > sizeof(NSRCADR(a1)) * 8) 234 mbits = sizeof(NSRCADR(a1)) * 8; 235 pm1 = (const void*)&NSRCADR(a1); 236 pm2 = (const void*)&NSRCADR(a2); 237 break; 238 239 case AF_INET6: 240 /* IPv6 is slightly different: Both scopes must match, 241 * too, before we even consider doing a match! 242 */ 243 if ( ! SCOPE_EQ(a1, a2)) 244 return FALSE; 245 if (mbits > sizeof(NSRCADR6(a1)) * 8) 246 mbits = sizeof(NSRCADR6(a1)) * 8; 247 pm1 = (const void*)&NSRCADR6(a1); 248 pm2 = (const void*)&NSRCADR6(a2); 249 break; 250 251 default: 252 /* don't know how to compare that!?! */ 253 return FALSE; 254 } 255 256 /* Split bit length into byte length and partial byte mask. 257 * Note that the byte mask extends from the MSB of a byte down, 258 * and that zero shift (--> mbits % 8 == 0) results in an 259 * all-zero mask. 260 */ 261 msk = 0xFFu ^ (0xFFu >> (mbits & 7)); 262 len = mbits >> 3; 263 264 /* 3rd check: Do memcmp() over full bytes, if any */ 265 if (len && memcmp(pm1, pm2, len)) 266 return FALSE; 267 268 /* 4th check: compare last incomplete byte, if any */ 269 if (msk && ((pm1[len] ^ pm2[len]) & msk)) 270 return FALSE; 271 272 /* If none of the above failed, we're successfully through. */ 273 return TRUE; 274} 275 276/* 277 * init_auth - initialize internal data 278 */ 279void 280init_auth(void) 281{ 282 size_t newalloc; 283 284 /* 285 * Initialize hash table and free list 286 */ 287 newalloc = authhashbuckets * sizeof(key_hash[0]); 288 289 key_hash = erealloc(key_hash, newalloc); 290 memset(key_hash, '\0', newalloc); 291 292 INIT_DLIST(key_listhead, llink); 293 294#ifdef DEBUG 295 atexit(&free_auth_mem); 296#endif 297} 298 299 300/* 301 * free_auth_mem - assist in leak detection by freeing all dynamic 302 * allocations from this module. 303 */ 304#ifdef DEBUG 305static void 306free_auth_mem(void) 307{ 308 symkey * sk; 309 symkey_alloc * alloc; 310 symkey_alloc * next_alloc; 311 312 while (NULL != (sk = HEAD_DLIST(key_listhead, llink))) { 313 freesymkey(sk); 314 } 315 free(key_hash); 316 key_hash = NULL; 317 cache_keyid = 0; 318 cache_flags = 0; 319 cache_keyacclist = NULL; 320 for (alloc = authallocs; alloc != NULL; alloc = next_alloc) { 321 next_alloc = alloc->link; 322 free(alloc->mem); 323 } 324 authfreekeys = NULL; 325 authnumfreekeys = 0; 326} 327#endif /* DEBUG */ 328 329 330/* 331 * auth_moremem - get some more free key structures 332 */ 333void 334auth_moremem( 335 int keycount 336 ) 337{ 338 symkey * sk; 339 int i; 340#ifdef DEBUG 341 void * base; 342 symkey_alloc * allocrec; 343# define MOREMEM_EXTRA_ALLOC (sizeof(*allocrec)) 344#else 345# define MOREMEM_EXTRA_ALLOC (0) 346#endif 347 348 i = (keycount > 0) 349 ? keycount 350 : MEMINC; 351 sk = eallocarrayxz(i, sizeof(*sk), MOREMEM_EXTRA_ALLOC); 352#ifdef DEBUG 353 base = sk; 354#endif 355 authnumfreekeys += i; 356 357 for (; i > 0; i--, sk++) { 358 LINK_SLIST(authfreekeys, sk, llink.f); 359 } 360 361#ifdef DEBUG 362 allocrec = (void *)sk; 363 allocrec->mem = base; 364 LINK_SLIST(authallocs, allocrec, link); 365#endif 366} 367 368 369/* 370 * auth_prealloc_symkeys 371 */ 372void 373auth_prealloc_symkeys( 374 int keycount 375 ) 376{ 377 int allocated; 378 int additional; 379 380 allocated = authnumkeys + authnumfreekeys; 381 additional = keycount - allocated; 382 if (additional > 0) 383 auth_moremem(additional); 384 auth_resize_hashtable(); 385} 386 387 388static u_short 389auth_log2(size_t x) 390{ 391 /* 392 ** bithack to calculate floor(log2(x)) 393 ** 394 ** This assumes 395 ** - (sizeof(size_t) is a power of two 396 ** - CHAR_BITS is a power of two 397 ** - returning zero for arguments <= 0 is OK. 398 ** 399 ** Does only shifts, masks and sums in integer arithmetic in 400 ** log2(CHAR_BIT*sizeof(size_t)) steps. (that is, 5/6 steps for 401 ** 32bit/64bit size_t) 402 */ 403 int s; 404 int r = 0; 405 size_t m = ~(size_t)0; 406 407 for (s = sizeof(size_t) / 2 * CHAR_BIT; s != 0; s >>= 1) { 408 m <<= s; 409 if (x & m) 410 r += s; 411 else 412 x <<= s; 413 } 414 return (u_short)r; 415} 416 417int/*BOOL*/ 418ipaddr_match_masked(const sockaddr_u *,const sockaddr_u *, 419 unsigned int mbits); 420 421static void 422authcache_flush_id( 423 keyid_t id 424 ) 425{ 426 if (cache_keyid == id) { 427 cache_keyid = 0; 428 cache_type = 0; 429 cache_flags = 0; 430 cache_secret = NULL; 431 cache_secretsize = 0; 432 cache_keyacclist = NULL; 433 } 434} 435 436 437/* 438 * auth_resize_hashtable 439 * 440 * Size hash table to average 4 or fewer entries per bucket initially, 441 * within the bounds of at least 4 and no more than 15 bits for the hash 442 * table index. Populate the hash table. 443 */ 444static void 445auth_resize_hashtable(void) 446{ 447 u_long totalkeys; 448 u_short hashbits; 449 u_short hash; 450 size_t newalloc; 451 symkey * sk; 452 453 totalkeys = authnumkeys + authnumfreekeys; 454 hashbits = auth_log2(totalkeys / 4) + 1; 455 hashbits = max(4, hashbits); 456 hashbits = min(15, hashbits); 457 458 authhashbuckets = 1 << hashbits; 459 authhashmask = authhashbuckets - 1; 460 newalloc = authhashbuckets * sizeof(key_hash[0]); 461 462 key_hash = erealloc(key_hash, newalloc); 463 memset(key_hash, '\0', newalloc); 464 465 ITER_DLIST_BEGIN(key_listhead, sk, llink, symkey) 466 hash = KEYHASH(sk->keyid); 467 LINK_SLIST(key_hash[hash], sk, hlink); 468 ITER_DLIST_END() 469} 470 471 472/* 473 * allocsymkey - common code to allocate and link in symkey 474 * 475 * secret must be allocated with a free-compatible allocator. It is 476 * owned by the referring symkey structure, and will be free()d by 477 * freesymkey(). 478 */ 479static void 480allocsymkey( 481 keyid_t id, 482 u_short flags, 483 u_short type, 484 u_long lifetime, 485 size_t secretsize, 486 u_char * secret, 487 KeyAccT * ka 488 ) 489{ 490 symkey * sk; 491 symkey ** bucket; 492 493 bucket = &key_hash[KEYHASH(id)]; 494 495 496 if (authnumfreekeys < 1) 497 auth_moremem(-1); 498 UNLINK_HEAD_SLIST(sk, authfreekeys, llink.f); 499 DEBUG_ENSURE(sk != NULL); 500 sk->keyid = id; 501 sk->flags = flags; 502 sk->type = type; 503 sk->secretsize = secretsize; 504 sk->secret = secret; 505 sk->keyacclist = ka; 506 sk->lifetime = lifetime; 507 LINK_SLIST(*bucket, sk, hlink); 508 LINK_TAIL_DLIST(key_listhead, sk, llink); 509 authnumfreekeys--; 510 authnumkeys++; 511} 512 513 514/* 515 * freesymkey - common code to remove a symkey and recycle its entry. 516 */ 517static void 518freesymkey( 519 symkey * sk 520 ) 521{ 522 symkey ** bucket; 523 symkey * unlinked; 524 525 if (NULL == sk) 526 return; 527 528 authcache_flush_id(sk->keyid); 529 keyacc_all_free(sk->keyacclist); 530 531 bucket = &key_hash[KEYHASH(sk->keyid)]; 532 if (sk->secret != NULL) { 533 memset(sk->secret, '\0', sk->secretsize); 534 free(sk->secret); 535 } 536 UNLINK_SLIST(unlinked, *bucket, sk, hlink, symkey); 537 DEBUG_ENSURE(sk == unlinked); 538 UNLINK_DLIST(sk, llink); 539 memset((char *)sk + offsetof(symkey, symkey_payload), '\0', 540 sizeof(*sk) - offsetof(symkey, symkey_payload)); 541 LINK_SLIST(authfreekeys, sk, llink.f); 542 authnumkeys--; 543 authnumfreekeys++; 544} 545 546 547/* 548 * auth_findkey - find a key in the hash table 549 */ 550struct savekey * 551auth_findkey( 552 keyid_t id 553 ) 554{ 555 symkey * sk; 556 557 for (sk = key_hash[KEYHASH(id)]; sk != NULL; sk = sk->hlink) 558 if (id == sk->keyid) 559 return sk; 560 return NULL; 561} 562 563 564/* 565 * auth_havekey - return TRUE if the key id is zero or known. The 566 * key needs not to be trusted. 567 */ 568int 569auth_havekey( 570 keyid_t id 571 ) 572{ 573 return 574 (0 == id) || 575 (cache_keyid == id) || 576 (NULL != auth_findkey(id)); 577} 578 579 580/* 581 * authhavekey - return TRUE and cache the key, if zero or both known 582 * and trusted. 583 */ 584int 585authhavekey( 586 keyid_t id 587 ) 588{ 589 symkey * sk; 590 591 authkeylookups++; 592 if (0 == id || cache_keyid == id) 593 return !!(KEY_TRUSTED & cache_flags); 594 595 /* 596 * Search the bin for the key. If not found, or found but the key 597 * type is zero, somebody marked it trusted without specifying a 598 * key or key type. In this case consider the key missing. 599 */ 600 authkeyuncached++; 601 sk = auth_findkey(id); 602 if ((sk == NULL) || (sk->type == 0)) { 603 authkeynotfound++; 604 return FALSE; 605 } 606 607 /* 608 * If the key is not trusted, the key is not considered found. 609 */ 610 if ( ! (KEY_TRUSTED & sk->flags)) { 611 authnokey++; 612 return FALSE; 613 } 614 615 /* 616 * The key is found and trusted. Initialize the key cache. 617 */ 618 cache_keyid = sk->keyid; 619 cache_type = sk->type; 620 cache_flags = sk->flags; 621 cache_secret = sk->secret; 622 cache_secretsize = sk->secretsize; 623 cache_keyacclist = sk->keyacclist; 624 625 return TRUE; 626} 627 628 629/* 630 * authtrust - declare a key to be trusted/untrusted 631 */ 632void 633authtrust( 634 keyid_t id, 635 u_long trust 636 ) 637{ 638 symkey * sk; 639 u_long lifetime; 640 641 /* 642 * Search bin for key; if it does not exist and is untrusted, 643 * forget it. 644 */ 645 646 sk = auth_findkey(id); 647 if (!trust && sk == NULL) 648 return; 649 650 /* 651 * There are two conditions remaining. Either it does not 652 * exist and is to be trusted or it does exist and is or is 653 * not to be trusted. 654 */ 655 if (sk != NULL) { 656 /* 657 * Key exists. If it is to be trusted, say so and update 658 * its lifetime. If no longer trusted, return it to the 659 * free list. Flush the cache first to be sure there are 660 * no discrepancies. 661 */ 662 authcache_flush_id(id); 663 if (trust > 0) { 664 sk->flags |= KEY_TRUSTED; 665 if (trust > 1) 666 sk->lifetime = current_time + trust; 667 else 668 sk->lifetime = 0; 669 } else { 670 freesymkey(sk); 671 } 672 return; 673 } 674 675 /* 676 * keyid is not present, but the is to be trusted. We allocate 677 * a new key, but do not specify a key type or secret. 678 */ 679 if (trust > 1) { 680 lifetime = current_time + trust; 681 } else { 682 lifetime = 0; 683 } 684 allocsymkey(id, KEY_TRUSTED, 0, lifetime, 0, NULL, NULL); 685} 686 687 688/* 689 * authistrusted - determine whether a key is trusted 690 */ 691int 692authistrusted( 693 keyid_t id 694 ) 695{ 696 symkey * sk; 697 698 if (id == cache_keyid) 699 return !!(KEY_TRUSTED & cache_flags); 700 701 authkeyuncached++; 702 sk = auth_findkey(id); 703 if (sk == NULL || !(KEY_TRUSTED & sk->flags)) { 704 authkeynotfound++; 705 return FALSE; 706 } 707 return TRUE; 708} 709 710 711/* 712 * authistrustedip - determine if the IP is OK for the keyid 713 */ 714 int 715 authistrustedip( 716 keyid_t keyno, 717 sockaddr_u * sau 718 ) 719{ 720 symkey * sk; 721 722 if (keyno == cache_keyid) { 723 return (KEY_TRUSTED & cache_flags) && 724 keyacc_contains(cache_keyacclist, sau, TRUE); 725 } 726 727 if (NULL != (sk = auth_findkey(keyno))) { 728 authkeyuncached++; 729 return (KEY_TRUSTED & sk->flags) && 730 keyacc_contains(sk->keyacclist, sau, TRUE); 731 } 732 733 authkeynotfound++; 734 return FALSE; 735} 736 737/* Note: There are two locations below where 'strncpy()' is used. While 738 * this function is a hazard by itself, it's essential that it is used 739 * here. Bug 1243 involved that the secret was filled with NUL bytes 740 * after the first NUL encountered, and 'strlcpy()' simply does NOT have 741 * this behaviour. So disabling the fix and reverting to the buggy 742 * behaviour due to compatibility issues MUST also fill with NUL and 743 * this needs 'strncpy'. Also, the secret is managed as a byte blob of a 744 * given size, and eventually truncating it and replacing the last byte 745 * with a NUL would be a bug. 746 * perlinger@ntp.org 2015-10-10 747 */ 748void 749MD5auth_setkey( 750 keyid_t keyno, 751 int keytype, 752 const u_char *key, 753 size_t secretsize, 754 KeyAccT *ka 755 ) 756{ 757 symkey * sk; 758 u_char * secret; 759 760 DEBUG_ENSURE(keytype <= USHRT_MAX); 761 DEBUG_ENSURE(secretsize < 4 * 1024); 762 /* 763 * See if we already have the key. If so just stick in the 764 * new value. 765 */ 766 sk = auth_findkey(keyno); 767 if (sk != NULL && keyno == sk->keyid) { 768 /* TALOS-CAN-0054: make sure we have a new buffer! */ 769 if (NULL != sk->secret) { 770 memset(sk->secret, 0, sk->secretsize); 771 free(sk->secret); 772 } 773 sk->secret = emalloc(secretsize + 1); 774 sk->type = (u_short)keytype; 775 sk->secretsize = secretsize; 776 /* make sure access lists don't leak here! */ 777 if (ka != sk->keyacclist) { 778 keyacc_all_free(sk->keyacclist); 779 sk->keyacclist = ka; 780 } 781#ifndef DISABLE_BUG1243_FIX 782 memcpy(sk->secret, key, secretsize); 783#else 784 /* >MUST< use 'strncpy()' here! See above! */ 785 strncpy((char *)sk->secret, (const char *)key, 786 secretsize); 787#endif 788 authcache_flush_id(keyno); 789 return; 790 } 791 792 /* 793 * Need to allocate new structure. Do it. 794 */ 795 secret = emalloc(secretsize + 1); 796#ifndef DISABLE_BUG1243_FIX 797 memcpy(secret, key, secretsize); 798#else 799 /* >MUST< use 'strncpy()' here! See above! */ 800 strncpy((char *)secret, (const char *)key, secretsize); 801#endif 802 allocsymkey(keyno, 0, (u_short)keytype, 0, 803 secretsize, secret, ka); 804#ifdef DEBUG 805 if (debug >= 4) { 806 size_t j; 807 808 printf("auth_setkey: key %d type %d len %d ", (int)keyno, 809 keytype, (int)secretsize); 810 for (j = 0; j < secretsize; j++) { 811 printf("%02x", secret[j]); 812 } 813 printf("\n"); 814 } 815#endif 816} 817 818 819/* 820 * auth_delkeys - delete non-autokey untrusted keys, and clear all info 821 * except the trusted bit of non-autokey trusted keys, in 822 * preparation for rereading the keys file. 823 */ 824void 825auth_delkeys(void) 826{ 827 symkey * sk; 828 829 ITER_DLIST_BEGIN(key_listhead, sk, llink, symkey) 830 if (sk->keyid > NTP_MAXKEY) { /* autokey */ 831 continue; 832 } 833 834 /* 835 * Don't lose info as to which keys are trusted. Make 836 * sure there are no dangling pointers! 837 */ 838 if (KEY_TRUSTED & sk->flags) { 839 if (sk->secret != NULL) { 840 memset(sk->secret, 0, sk->secretsize); 841 free(sk->secret); 842 sk->secret = NULL; /* TALOS-CAN-0054 */ 843 } 844 sk->keyacclist = keyacc_all_free(sk->keyacclist); 845 sk->secretsize = 0; 846 sk->lifetime = 0; 847 } else { 848 freesymkey(sk); 849 } 850 ITER_DLIST_END() 851} 852 853 854/* 855 * auth_agekeys - delete keys whose lifetimes have expired 856 */ 857void 858auth_agekeys(void) 859{ 860 symkey * sk; 861 862 ITER_DLIST_BEGIN(key_listhead, sk, llink, symkey) 863 if (sk->lifetime > 0 && current_time > sk->lifetime) { 864 freesymkey(sk); 865 authkeyexpired++; 866 } 867 ITER_DLIST_END() 868 DPRINTF(1, ("auth_agekeys: at %lu keys %lu expired %lu\n", 869 current_time, authnumkeys, authkeyexpired)); 870} 871 872 873/* 874 * authencrypt - generate message authenticator 875 * 876 * Returns length of authenticator field, zero if key not found. 877 */ 878size_t 879authencrypt( 880 keyid_t keyno, 881 u_int32 * pkt, 882 size_t length 883 ) 884{ 885 /* 886 * A zero key identifier means the sender has not verified 887 * the last message was correctly authenticated. The MAC 888 * consists of a single word with value zero. 889 */ 890 authencryptions++; 891 pkt[length / 4] = htonl(keyno); 892 if (0 == keyno) { 893 return 4; 894 } 895 if (!authhavekey(keyno)) { 896 return 0; 897 } 898 899 return MD5authencrypt(cache_type, 900 cache_secret, cache_secretsize, 901 pkt, length); 902} 903 904 905/* 906 * authdecrypt - verify message authenticator 907 * 908 * Returns TRUE if authenticator valid, FALSE if invalid or not found. 909 */ 910int 911authdecrypt( 912 keyid_t keyno, 913 u_int32 * pkt, 914 size_t length, 915 size_t size 916 ) 917{ 918 /* 919 * A zero key identifier means the sender has not verified 920 * the last message was correctly authenticated. For our 921 * purpose this is an invalid authenticator. 922 */ 923 authdecryptions++; 924 if (0 == keyno || !authhavekey(keyno) || size < 4) { 925 return FALSE; 926 } 927 928 return MD5authdecrypt(cache_type, 929 cache_secret, cache_secretsize, 930 pkt, length, size); 931} 932