1/* 2 * authkeys.c - routines to manage the storage of authentication keys 3 */ 4#ifdef HAVE_CONFIG_H 5# include <config.h> 6#endif 7 8#include <math.h> 9#include <stdio.h> 10 11#include "ntp.h" 12#include "ntp_fp.h" 13#include "ntpd.h" 14#include "ntp_lists.h" 15#include "ntp_string.h" 16#include "ntp_malloc.h" 17#include "ntp_stdlib.h" 18#include "ntp_keyacc.h" 19 20/* 21 * Structure to store keys in in the hash table. 22 */ 23typedef struct savekey symkey; 24 25struct savekey { 26 symkey * hlink; /* next in hash bucket */ 27 DECL_DLIST_LINK(symkey, llink); /* for overall & free lists */ 28 u_char * secret; /* shared secret */ 29 KeyAccT * keyacclist; /* Private key access list */ 30 u_long lifetime; /* remaining lifetime */ 31 keyid_t keyid; /* key identifier */ 32 u_short type; /* OpenSSL digest NID */ 33 size_t secretsize; /* secret octets */ 34 u_short flags; /* KEY_ flags that wave */ 35}; 36 37/* define the payload region of symkey beyond the list pointers */ 38#define symkey_payload secret 39 40#define KEY_TRUSTED 0x001 /* this key is trusted */ 41 42#ifdef DEBUG 43typedef struct symkey_alloc_tag symkey_alloc; 44 45struct symkey_alloc_tag { 46 symkey_alloc * link; 47 void * mem; /* enable free() atexit */ 48}; 49 50symkey_alloc * authallocs; 51#endif /* DEBUG */ 52 53static u_short auth_log2(size_t); 54static void auth_resize_hashtable(void); 55static void allocsymkey(keyid_t, u_short, 56 u_short, u_long, size_t, u_char *, KeyAccT *); 57static void freesymkey(symkey *); 58#ifdef DEBUG 59static void free_auth_mem(void); 60#endif 61 62symkey key_listhead; /* list of all in-use keys */; 63/* 64 * The hash table. This is indexed by the low order bits of the 65 * keyid. We make this fairly big for potentially busy servers. 66 */ 67#define DEF_AUTHHASHSIZE 64 68/*#define HASHMASK ((HASHSIZE)-1)*/ 69#define KEYHASH(keyid) ((keyid) & authhashmask) 70 71int authhashdisabled; 72u_short authhashbuckets = DEF_AUTHHASHSIZE; 73u_short authhashmask = DEF_AUTHHASHSIZE - 1; 74symkey **key_hash; 75 76u_long authkeynotfound; /* keys not found */ 77u_long authkeylookups; /* calls to lookup keys */ 78u_long authnumkeys; /* number of active keys */ 79u_long authkeyexpired; /* key lifetime expirations */ 80u_long authkeyuncached; /* cache misses */ 81u_long authnokey; /* calls to encrypt with no key */ 82u_long authencryptions; /* calls to encrypt */ 83u_long authdecryptions; /* calls to decrypt */ 84 85/* 86 * Storage for free symkey structures. We malloc() such things but 87 * never free them. 88 */ 89symkey *authfreekeys; 90int authnumfreekeys; 91 92#define MEMINC 16 /* number of new free ones to get */ 93 94/* 95 * The key cache. We cache the last key we looked at here. 96 * Note: this should hold the last *trusted* key. Also the 97 * cache is only loaded when the digest type / MAC algorithm 98 * is valid. 99 */ 100keyid_t cache_keyid; /* key identifier */ 101u_char *cache_secret; /* secret */ 102size_t cache_secretsize; /* secret length */ 103int cache_type; /* OpenSSL digest NID */ 104u_short cache_flags; /* flags that wave */ 105KeyAccT *cache_keyacclist; /* key access list */ 106 107/* -------------------------------------------------------------------- 108 * manage key access lists 109 * -------------------------------------------------------------------- 110 */ 111/* allocate and populate new access node and pushes it on the list. 112 * Returns the new head. 113 */ 114KeyAccT* 115keyacc_new_push( 116 KeyAccT * head, 117 const sockaddr_u * addr, 118 unsigned int subnetbits 119 ) 120{ 121 KeyAccT * node = emalloc(sizeof(KeyAccT)); 122 123 memcpy(&node->addr, addr, sizeof(sockaddr_u)); 124 node->subnetbits = subnetbits; 125 node->next = head; 126 127 return node; 128} 129 130/* ----------------------------------------------------------------- */ 131/* pop and deallocate the first node of a list of access nodes, if 132 * the list is not empty. Returns the tail of the list. 133 */ 134KeyAccT* 135keyacc_pop_free( 136 KeyAccT *head 137 ) 138{ 139 KeyAccT * next = NULL; 140 if (head) { 141 next = head->next; 142 free(head); 143 } 144 return next; 145} 146 147/* ----------------------------------------------------------------- */ 148/* deallocate the list; returns an empty list. */ 149KeyAccT* 150keyacc_all_free( 151 KeyAccT * head 152 ) 153{ 154 while (head) 155 head = keyacc_pop_free(head); 156 return head; 157} 158 159/* ----------------------------------------------------------------- */ 160/* scan a list to see if it contains a given address. Return the 161 * default result value in case of an empty list. 162 */ 163int /*BOOL*/ 164keyacc_contains( 165 const KeyAccT *head, 166 const sockaddr_u *addr, 167 int defv) 168{ 169 if (head) { 170 do { 171 if (keyacc_amatch(&head->addr, addr, 172 head->subnetbits)) 173 return TRUE; 174 } while (NULL != (head = head->next)); 175 return FALSE; 176 } else { 177 return !!defv; 178 } 179} 180 181#if CHAR_BIT != 8 182# error "don't know how to handle bytes with that bit size" 183#endif 184 185/* ----------------------------------------------------------------- */ 186/* check two addresses for a match, taking a prefix length into account 187 * when doing the compare. 188 * 189 * The ISC lib contains a similar function with not entirely specified 190 * semantics, so it seemed somewhat cleaner to do this from scratch. 191 * 192 * Note 1: It *is* assumed that the addresses are stored in network byte 193 * order, that is, most significant byte first! 194 * 195 * Note 2: "no address" compares unequal to all other addresses, even to 196 * itself. This has the same semantics as NaNs have for floats: *any* 197 * relational or equality operation involving a NaN returns FALSE, even 198 * equality with itself. "no address" is either a NULL pointer argument 199 * or an address of type AF_UNSPEC. 200 */ 201int/*BOOL*/ 202keyacc_amatch( 203 const sockaddr_u * a1, 204 const sockaddr_u * a2, 205 unsigned int mbits 206 ) 207{ 208 const uint8_t * pm1; 209 const uint8_t * pm2; 210 uint8_t msk; 211 unsigned int len; 212 213 /* 1st check: If any address is not an address, it's inequal. */ 214 if ( !a1 || (AF_UNSPEC == AF(a1)) || 215 !a2 || (AF_UNSPEC == AF(a2)) ) 216 return FALSE; 217 218 /* We could check pointers for equality here and shortcut the 219 * other checks if we find object identity. But that use case is 220 * too rare to care for it. 221 */ 222 223 /* 2nd check: Address families must be the same. */ 224 if (AF(a1) != AF(a2)) 225 return FALSE; 226 227 /* type check: address family determines buffer & size */ 228 switch (AF(a1)) { 229 case AF_INET: 230 /* IPv4 is easy: clamp size, get byte pointers */ 231 if (mbits > sizeof(NSRCADR(a1)) * 8) 232 mbits = sizeof(NSRCADR(a1)) * 8; 233 pm1 = (const void*)&NSRCADR(a1); 234 pm2 = (const void*)&NSRCADR(a2); 235 break; 236 237 case AF_INET6: 238 /* IPv6 is slightly different: Both scopes must match, 239 * too, before we even consider doing a match! 240 */ 241 if ( ! SCOPE_EQ(a1, a2)) 242 return FALSE; 243 if (mbits > sizeof(NSRCADR6(a1)) * 8) 244 mbits = sizeof(NSRCADR6(a1)) * 8; 245 pm1 = (const void*)&NSRCADR6(a1); 246 pm2 = (const void*)&NSRCADR6(a2); 247 break; 248 249 default: 250 /* don't know how to compare that!?! */ 251 return FALSE; 252 } 253 254 /* Split bit length into byte length and partial byte mask. 255 * Note that the byte mask extends from the MSB of a byte down, 256 * and that zero shift (--> mbits % 8 == 0) results in an 257 * all-zero mask. 258 */ 259 msk = 0xFFu ^ (0xFFu >> (mbits & 7)); 260 len = mbits >> 3; 261 262 /* 3rd check: Do memcmp() over full bytes, if any */ 263 if (len && memcmp(pm1, pm2, len)) 264 return FALSE; 265 266 /* 4th check: compare last incomplete byte, if any */ 267 if (msk && ((pm1[len] ^ pm2[len]) & msk)) 268 return FALSE; 269 270 /* If none of the above failed, we're successfully through. */ 271 return TRUE; 272} 273 274/* 275 * init_auth - initialize internal data 276 */ 277void 278init_auth(void) 279{ 280 size_t newalloc; 281 282 /* 283 * Initialize hash table and free list 284 */ 285 newalloc = authhashbuckets * sizeof(key_hash[0]); 286 287 key_hash = emalloc_zero(newalloc); 288 289 INIT_DLIST(key_listhead, llink); 290 291#ifdef DEBUG 292 atexit(&free_auth_mem); 293#endif 294} 295 296 297/* 298 * free_auth_mem - assist in leak detection by freeing all dynamic 299 * allocations from this module. 300 */ 301#ifdef DEBUG 302static void 303free_auth_mem(void) 304{ 305 symkey * sk; 306 symkey_alloc * alloc; 307 symkey_alloc * next_alloc; 308 309 while (NULL != (sk = HEAD_DLIST(key_listhead, llink))) { 310 freesymkey(sk); 311 } 312 free(key_hash); 313 key_hash = NULL; 314 cache_keyid = 0; 315 cache_flags = 0; 316 cache_keyacclist = NULL; 317 for (alloc = authallocs; alloc != NULL; alloc = next_alloc) { 318 next_alloc = alloc->link; 319 free(alloc->mem); 320 } 321 authfreekeys = NULL; 322 authnumfreekeys = 0; 323} 324#endif /* DEBUG */ 325 326 327/* 328 * auth_moremem - get some more free key structures 329 */ 330void 331auth_moremem( 332 int keycount 333 ) 334{ 335 symkey * sk; 336 int i; 337#ifdef DEBUG 338 void * base; 339 symkey_alloc * allocrec; 340# define MOREMEM_EXTRA_ALLOC (sizeof(*allocrec)) 341#else 342# define MOREMEM_EXTRA_ALLOC (0) 343#endif 344 345 i = (keycount > 0) 346 ? keycount 347 : MEMINC; 348 sk = eallocarrayxz(i, sizeof(*sk), MOREMEM_EXTRA_ALLOC); 349#ifdef DEBUG 350 base = sk; 351#endif 352 authnumfreekeys += i; 353 354 for (; i > 0; i--, sk++) { 355 LINK_SLIST(authfreekeys, sk, llink.f); 356 } 357 358#ifdef DEBUG 359 allocrec = (void *)sk; 360 allocrec->mem = base; 361 LINK_SLIST(authallocs, allocrec, link); 362#endif 363} 364 365 366/* 367 * auth_prealloc_symkeys 368 */ 369void 370auth_prealloc_symkeys( 371 int keycount 372 ) 373{ 374 int allocated; 375 int additional; 376 377 allocated = authnumkeys + authnumfreekeys; 378 additional = keycount - allocated; 379 if (additional > 0) 380 auth_moremem(additional); 381 auth_resize_hashtable(); 382} 383 384 385static u_short 386auth_log2(size_t x) 387{ 388 /* 389 ** bithack to calculate floor(log2(x)) 390 ** 391 ** This assumes 392 ** - (sizeof(size_t) is a power of two 393 ** - CHAR_BITS is a power of two 394 ** - returning zero for arguments <= 0 is OK. 395 ** 396 ** Does only shifts, masks and sums in integer arithmetic in 397 ** log2(CHAR_BIT*sizeof(size_t)) steps. (that is, 5/6 steps for 398 ** 32bit/64bit size_t) 399 */ 400 int s; 401 int r = 0; 402 size_t m = ~(size_t)0; 403 404 for (s = sizeof(size_t) / 2 * CHAR_BIT; s != 0; s >>= 1) { 405 m <<= s; 406 if (x & m) 407 r += s; 408 else 409 x <<= s; 410 } 411 return (u_short)r; 412} 413 414int/*BOOL*/ 415ipaddr_match_masked(const sockaddr_u *,const sockaddr_u *, 416 unsigned int mbits); 417 418static void 419authcache_flush_id( 420 keyid_t id 421 ) 422{ 423 if (cache_keyid == id) { 424 cache_keyid = 0; 425 cache_type = 0; 426 cache_flags = 0; 427 cache_secret = NULL; 428 cache_secretsize = 0; 429 cache_keyacclist = NULL; 430 } 431} 432 433 434/* 435 * auth_resize_hashtable 436 * 437 * Size hash table to average 4 or fewer entries per bucket initially, 438 * within the bounds of at least 4 and no more than 15 bits for the hash 439 * table index. Populate the hash table. 440 */ 441static void 442auth_resize_hashtable(void) 443{ 444 u_long totalkeys; 445 u_short hashbits; 446 u_short hash; 447 size_t newalloc; 448 symkey * sk; 449 450 totalkeys = authnumkeys + authnumfreekeys; 451 hashbits = auth_log2(totalkeys / 4) + 1; 452 hashbits = max(4, hashbits); 453 hashbits = min(15, hashbits); 454 455 authhashbuckets = 1 << hashbits; 456 authhashmask = authhashbuckets - 1; 457 newalloc = authhashbuckets * sizeof(key_hash[0]); 458 459 key_hash = erealloc(key_hash, newalloc); 460 zero_mem(key_hash, newalloc); 461 462 ITER_DLIST_BEGIN(key_listhead, sk, llink, symkey) 463 hash = KEYHASH(sk->keyid); 464 LINK_SLIST(key_hash[hash], sk, hlink); 465 ITER_DLIST_END() 466} 467 468 469/* 470 * allocsymkey - common code to allocate and link in symkey 471 * 472 * secret must be allocated with a free-compatible allocator. It is 473 * owned by the referring symkey structure, and will be free()d by 474 * freesymkey(). 475 */ 476static void 477allocsymkey( 478 keyid_t id, 479 u_short flags, 480 u_short type, 481 u_long lifetime, 482 size_t secretsize, 483 u_char * secret, 484 KeyAccT * ka 485 ) 486{ 487 symkey * sk; 488 symkey ** bucket; 489 490 bucket = &key_hash[KEYHASH(id)]; 491 492 493 if (authnumfreekeys < 1) 494 auth_moremem(-1); 495 UNLINK_HEAD_SLIST(sk, authfreekeys, llink.f); 496 DEBUG_ENSURE(sk != NULL); 497 sk->keyid = id; 498 sk->flags = flags; 499 sk->type = type; 500 sk->secretsize = secretsize; 501 sk->secret = secret; 502 sk->keyacclist = ka; 503 sk->lifetime = lifetime; 504 LINK_SLIST(*bucket, sk, hlink); 505 LINK_TAIL_DLIST(key_listhead, sk, llink); 506 authnumfreekeys--; 507 authnumkeys++; 508} 509 510 511/* 512 * freesymkey - common code to remove a symkey and recycle its entry. 513 */ 514static void 515freesymkey( 516 symkey * sk 517 ) 518{ 519 symkey ** bucket; 520 symkey * unlinked; 521 522 if (NULL == sk) 523 return; 524 525 authcache_flush_id(sk->keyid); 526 keyacc_all_free(sk->keyacclist); 527 528 bucket = &key_hash[KEYHASH(sk->keyid)]; 529 if (sk->secret != NULL) { 530 zero_mem(sk->secret, sk->secretsize); 531 free(sk->secret); 532 } 533 UNLINK_SLIST(unlinked, *bucket, sk, hlink, symkey); 534 DEBUG_ENSURE(sk == unlinked); 535 UNLINK_DLIST(sk, llink); 536 zero_mem((char *)sk + offsetof(symkey, symkey_payload), 537 sizeof(*sk) - offsetof(symkey, symkey_payload)); 538 LINK_SLIST(authfreekeys, sk, llink.f); 539 authnumkeys--; 540 authnumfreekeys++; 541} 542 543 544/* 545 * auth_findkey - find a key in the hash table 546 */ 547struct savekey * 548auth_findkey( 549 keyid_t id 550 ) 551{ 552 symkey * sk; 553 554 for (sk = key_hash[KEYHASH(id)]; sk != NULL; sk = sk->hlink) 555 if (id == sk->keyid) 556 return sk; 557 return NULL; 558} 559 560 561/* 562 * auth_havekey - return TRUE if the key id is zero or known. The 563 * key needs not to be trusted. 564 */ 565int 566auth_havekey( 567 keyid_t id 568 ) 569{ 570 return 571 (0 == id) || 572 (cache_keyid == id) || 573 (NULL != auth_findkey(id)); 574} 575 576 577/* 578 * authhavekey - return TRUE and cache the key, if zero or both known 579 * and trusted. 580 */ 581int 582authhavekey( 583 keyid_t id 584 ) 585{ 586 symkey * sk; 587 588 authkeylookups++; 589 if (0 == id || cache_keyid == id) 590 return !!(KEY_TRUSTED & cache_flags); 591 592 /* 593 * Search the bin for the key. If not found, or found but the key 594 * type is zero, somebody marked it trusted without specifying a 595 * key or key type. In this case consider the key missing. 596 */ 597 authkeyuncached++; 598 sk = auth_findkey(id); 599 if ((sk == NULL) || (sk->type == 0)) { 600 authkeynotfound++; 601 return FALSE; 602 } 603 604 /* 605 * If the key is not trusted, the key is not considered found. 606 */ 607 if ( ! (KEY_TRUSTED & sk->flags)) { 608 authnokey++; 609 return FALSE; 610 } 611 612 /* 613 * The key is found and trusted. Initialize the key cache. 614 * The cache really should be a struct savekey to streamline 615 * this code. Using a sk pointer would be even faster but more 616 * fragile around pointing to freed memory. 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 >= 1) { 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 zero_mem(sk->secret, 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 / KEY_MAC_LEN] = htonl(keyno); 892 if (0 == keyno) { 893 return KEY_MAC_LEN; 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, keyno); 931} 932 933 934/* password decoding helpers */ 935static size_t 936pwdecode_plain( 937 u_char * dst, 938 size_t dstlen, 939 const char * src 940 ) 941{ 942 size_t srclen = strlen(src); 943 if (srclen > dstlen) { 944 errno = ENOMEM; 945 return (size_t)-1; 946 } 947 memcpy(dst, src, srclen); 948 return srclen; 949} 950 951static size_t 952pwdecode_hex( 953 u_char * dst, 954 size_t dstlen, 955 const char * src 956 ) 957{ 958 static const char hex[] = "00112233445566778899AaBbCcDdEeFf"; 959 960 size_t srclen = strlen(src); 961 size_t reslen = (srclen >> 1) + (srclen & 1); 962 u_char tmp; 963 char *ptr; 964 size_t j; 965 966 if (reslen > dstlen) { 967 errno = ENOMEM; 968 reslen = (size_t)-1; 969 } else { 970 for (j = 0; j < srclen; ++j) { 971 tmp = *(const unsigned char*)(src + j); 972 ptr = strchr(hex, tmp); 973 if (ptr == NULL) { 974 errno = EINVAL; 975 reslen = (size_t)-1; 976 break; 977 } 978 tmp = (u_char)((ptr - hex) >> 1); 979 if (j & 1) 980 dst[j >> 1] |= tmp; 981 else 982 dst[j >> 1] = tmp << 4; 983 } 984 } 985 return reslen; 986} 987/* 988 * authdecodepw - decode plaintext or hex-encoded password to binary 989 * secret. Returns size of secret in bytes or -1 on error. 990 */ 991size_t 992authdecodepw( 993 u_char * dst, 994 size_t dstlen, 995 const char * src, 996 enum AuthPwdEnc enc 997 ) 998{ 999 size_t reslen; 1000 1001 if ( !(dst && dstlen && src)) { 1002 errno = EINVAL; 1003 reslen = (size_t)-1; 1004 } else { 1005 switch (enc) { 1006 case AUTHPWD_UNSPEC: 1007 if (strlen(src) <= 20) 1008 reslen = pwdecode_plain(dst, dstlen, src); 1009 else 1010 reslen = pwdecode_hex(dst, dstlen, src); 1011 break; 1012 case AUTHPWD_PLAIN: 1013 reslen = pwdecode_plain(dst, dstlen, src); 1014 break; 1015 case AUTHPWD_HEX: 1016 reslen = pwdecode_hex(dst, dstlen, src); 1017 break; 1018 default: 1019 errno = EINVAL; 1020 reslen = (size_t)-1; 1021 } 1022 } 1023 return reslen; 1024} 1025