1c0b746e5SOllivier Robert /* 2c0b746e5SOllivier Robert * authkeys.c - routines to manage the storage of authentication keys 3c0b746e5SOllivier Robert */ 4c0b746e5SOllivier Robert #ifdef HAVE_CONFIG_H 5c0b746e5SOllivier Robert # include <config.h> 6c0b746e5SOllivier Robert #endif 7c0b746e5SOllivier Robert 82b15cb3dSCy Schubert #include <math.h> 9c0b746e5SOllivier Robert #include <stdio.h> 10c0b746e5SOllivier Robert 11c0b746e5SOllivier Robert #include "ntp.h" 122b15cb3dSCy Schubert #include "ntp_fp.h" 13c0b746e5SOllivier Robert #include "ntpd.h" 142b15cb3dSCy Schubert #include "ntp_lists.h" 15c0b746e5SOllivier Robert #include "ntp_string.h" 16c0b746e5SOllivier Robert #include "ntp_malloc.h" 17c0b746e5SOllivier Robert #include "ntp_stdlib.h" 1868ba7e87SXin LI #include "ntp_keyacc.h" 19c0b746e5SOllivier Robert 20c0b746e5SOllivier Robert /* 21c0b746e5SOllivier Robert * Structure to store keys in in the hash table. 22c0b746e5SOllivier Robert */ 232b15cb3dSCy Schubert typedef struct savekey symkey; 242b15cb3dSCy Schubert 25c0b746e5SOllivier Robert struct savekey { 262b15cb3dSCy Schubert symkey * hlink; /* next in hash bucket */ 272b15cb3dSCy Schubert DECL_DLIST_LINK(symkey, llink); /* for overall & free lists */ 282b15cb3dSCy Schubert u_char * secret; /* shared secret */ 2968ba7e87SXin LI KeyAccT * keyacclist; /* Private key access list */ 30c0b746e5SOllivier Robert u_long lifetime; /* remaining lifetime */ 312b15cb3dSCy Schubert keyid_t keyid; /* key identifier */ 322b15cb3dSCy Schubert u_short type; /* OpenSSL digest NID */ 334990d495SXin LI size_t secretsize; /* secret octets */ 342b15cb3dSCy Schubert u_short flags; /* KEY_ flags that wave */ 35c0b746e5SOllivier Robert }; 36c0b746e5SOllivier Robert 372b15cb3dSCy Schubert /* define the payload region of symkey beyond the list pointers */ 382b15cb3dSCy Schubert #define symkey_payload secret 39c0b746e5SOllivier Robert 402b15cb3dSCy Schubert #define KEY_TRUSTED 0x001 /* this key is trusted */ 412b15cb3dSCy Schubert 422b15cb3dSCy Schubert #ifdef DEBUG 432b15cb3dSCy Schubert typedef struct symkey_alloc_tag symkey_alloc; 442b15cb3dSCy Schubert 452b15cb3dSCy Schubert struct symkey_alloc_tag { 462b15cb3dSCy Schubert symkey_alloc * link; 472b15cb3dSCy Schubert void * mem; /* enable free() atexit */ 482b15cb3dSCy Schubert }; 492b15cb3dSCy Schubert 502b15cb3dSCy Schubert symkey_alloc * authallocs; 512b15cb3dSCy Schubert #endif /* DEBUG */ 522b15cb3dSCy Schubert 5368ba7e87SXin LI static u_short auth_log2(size_t); 542b15cb3dSCy Schubert static void auth_resize_hashtable(void); 554990d495SXin LI static void allocsymkey(keyid_t, u_short, 564990d495SXin LI u_short, u_long, size_t, u_char *, KeyAccT *); 574990d495SXin LI static void freesymkey(symkey *); 582b15cb3dSCy Schubert #ifdef DEBUG 592b15cb3dSCy Schubert static void free_auth_mem(void); 602b15cb3dSCy Schubert #endif 612b15cb3dSCy Schubert 622b15cb3dSCy Schubert symkey key_listhead; /* list of all in-use keys */; 63c0b746e5SOllivier Robert /* 64c0b746e5SOllivier Robert * The hash table. This is indexed by the low order bits of the 65c0b746e5SOllivier Robert * keyid. We make this fairly big for potentially busy servers. 66c0b746e5SOllivier Robert */ 672b15cb3dSCy Schubert #define DEF_AUTHHASHSIZE 64 683311ff84SXin LI /*#define HASHMASK ((HASHSIZE)-1)*/ 692b15cb3dSCy Schubert #define KEYHASH(keyid) ((keyid) & authhashmask) 70c0b746e5SOllivier Robert 712b15cb3dSCy Schubert int authhashdisabled; 722b15cb3dSCy Schubert u_short authhashbuckets = DEF_AUTHHASHSIZE; 732b15cb3dSCy Schubert u_short authhashmask = DEF_AUTHHASHSIZE - 1; 742b15cb3dSCy Schubert symkey **key_hash; 75c0b746e5SOllivier Robert 76c0b746e5SOllivier Robert u_long authkeynotfound; /* keys not found */ 77c0b746e5SOllivier Robert u_long authkeylookups; /* calls to lookup keys */ 78c0b746e5SOllivier Robert u_long authnumkeys; /* number of active keys */ 79c0b746e5SOllivier Robert u_long authkeyexpired; /* key lifetime expirations */ 80c0b746e5SOllivier Robert u_long authkeyuncached; /* cache misses */ 81c0b746e5SOllivier Robert u_long authnokey; /* calls to encrypt with no key */ 82c0b746e5SOllivier Robert u_long authencryptions; /* calls to encrypt */ 83c0b746e5SOllivier Robert u_long authdecryptions; /* calls to decrypt */ 84c0b746e5SOllivier Robert 85c0b746e5SOllivier Robert /* 862b15cb3dSCy Schubert * Storage for free symkey structures. We malloc() such things but 87c0b746e5SOllivier Robert * never free them. 88c0b746e5SOllivier Robert */ 892b15cb3dSCy Schubert symkey *authfreekeys; 90c0b746e5SOllivier Robert int authnumfreekeys; 91c0b746e5SOllivier Robert 922b15cb3dSCy Schubert #define MEMINC 16 /* number of new free ones to get */ 93c0b746e5SOllivier Robert 94c0b746e5SOllivier Robert /* 95c0b746e5SOllivier Robert * The key cache. We cache the last key we looked at here. 964990d495SXin LI * Note: this should hold the last *trusted* key. Also the 974990d495SXin LI * cache is only loaded when the digest type / MAC algorithm 984990d495SXin LI * is valid. 99c0b746e5SOllivier Robert */ 100224ba2bdSOllivier Robert keyid_t cache_keyid; /* key identifier */ 1012b15cb3dSCy Schubert u_char *cache_secret; /* secret */ 1024990d495SXin LI size_t cache_secretsize; /* secret length */ 1032b15cb3dSCy Schubert int cache_type; /* OpenSSL digest NID */ 104c0b746e5SOllivier Robert u_short cache_flags; /* flags that wave */ 10568ba7e87SXin LI KeyAccT *cache_keyacclist; /* key access list */ 106c0b746e5SOllivier Robert 1074990d495SXin LI /* -------------------------------------------------------------------- 1084990d495SXin LI * manage key access lists 1094990d495SXin LI * -------------------------------------------------------------------- 1104990d495SXin LI */ 1114990d495SXin LI /* allocate and populate new access node and pushes it on the list. 1124990d495SXin LI * Returns the new head. 1134990d495SXin LI */ 1144990d495SXin LI KeyAccT* 1154990d495SXin LI keyacc_new_push( 1164990d495SXin LI KeyAccT * head, 11709100258SXin LI const sockaddr_u * addr, 11809100258SXin LI unsigned int subnetbits 1194990d495SXin LI ) 1204990d495SXin LI { 1214990d495SXin LI KeyAccT * node = emalloc(sizeof(KeyAccT)); 1224990d495SXin LI 1234990d495SXin LI memcpy(&node->addr, addr, sizeof(sockaddr_u)); 12409100258SXin LI node->subnetbits = subnetbits; 1254990d495SXin LI node->next = head; 12609100258SXin LI 1274990d495SXin LI return node; 1284990d495SXin LI } 1294990d495SXin LI 1304990d495SXin LI /* ----------------------------------------------------------------- */ 1314990d495SXin LI /* pop and deallocate the first node of a list of access nodes, if 1324990d495SXin LI * the list is not empty. Returns the tail of the list. 1334990d495SXin LI */ 1344990d495SXin LI KeyAccT* 1354990d495SXin LI keyacc_pop_free( 1364990d495SXin LI KeyAccT *head 1374990d495SXin LI ) 1384990d495SXin LI { 1394990d495SXin LI KeyAccT * next = NULL; 1404990d495SXin LI if (head) { 1414990d495SXin LI next = head->next; 1424990d495SXin LI free(head); 1434990d495SXin LI } 1444990d495SXin LI return next; 1454990d495SXin LI } 1464990d495SXin LI 1474990d495SXin LI /* ----------------------------------------------------------------- */ 1484990d495SXin LI /* deallocate the list; returns an empty list. */ 1494990d495SXin LI KeyAccT* 1504990d495SXin LI keyacc_all_free( 1514990d495SXin LI KeyAccT * head 1524990d495SXin LI ) 1534990d495SXin LI { 1544990d495SXin LI while (head) 1554990d495SXin LI head = keyacc_pop_free(head); 1564990d495SXin LI return head; 1574990d495SXin LI } 1584990d495SXin LI 1594990d495SXin LI /* ----------------------------------------------------------------- */ 1604990d495SXin LI /* scan a list to see if it contains a given address. Return the 1614990d495SXin LI * default result value in case of an empty list. 1624990d495SXin LI */ 1634990d495SXin LI int /*BOOL*/ 1644990d495SXin LI keyacc_contains( 1654990d495SXin LI const KeyAccT *head, 1664990d495SXin LI const sockaddr_u *addr, 1674990d495SXin LI int defv) 1684990d495SXin LI { 1694990d495SXin LI if (head) { 1704990d495SXin LI do { 17109100258SXin LI if (keyacc_amatch(&head->addr, addr, 17209100258SXin LI head->subnetbits)) 1734990d495SXin LI return TRUE; 1744990d495SXin LI } while (NULL != (head = head->next)); 1754990d495SXin LI return FALSE; 1764990d495SXin LI } else { 1774990d495SXin LI return !!defv; 1784990d495SXin LI } 1794990d495SXin LI } 1804990d495SXin LI 18109100258SXin LI #if CHAR_BIT != 8 18209100258SXin LI # error "don't know how to handle bytes with that bit size" 18309100258SXin LI #endif 18409100258SXin LI 18509100258SXin LI /* ----------------------------------------------------------------- */ 18609100258SXin LI /* check two addresses for a match, taking a prefix length into account 18709100258SXin LI * when doing the compare. 18809100258SXin LI * 18909100258SXin LI * The ISC lib contains a similar function with not entirely specified 19009100258SXin LI * semantics, so it seemed somewhat cleaner to do this from scratch. 19109100258SXin LI * 19209100258SXin LI * Note 1: It *is* assumed that the addresses are stored in network byte 19309100258SXin LI * order, that is, most significant byte first! 19409100258SXin LI * 19509100258SXin LI * Note 2: "no address" compares unequal to all other addresses, even to 19609100258SXin LI * itself. This has the same semantics as NaNs have for floats: *any* 19709100258SXin LI * relational or equality operation involving a NaN returns FALSE, even 19809100258SXin LI * equality with itself. "no address" is either a NULL pointer argument 19909100258SXin LI * or an address of type AF_UNSPEC. 20009100258SXin LI */ 20109100258SXin LI int/*BOOL*/ 20209100258SXin LI keyacc_amatch( 20309100258SXin LI const sockaddr_u * a1, 20409100258SXin LI const sockaddr_u * a2, 20509100258SXin LI unsigned int mbits 20609100258SXin LI ) 20709100258SXin LI { 20809100258SXin LI const uint8_t * pm1; 20909100258SXin LI const uint8_t * pm2; 21009100258SXin LI uint8_t msk; 21109100258SXin LI unsigned int len; 21209100258SXin LI 21309100258SXin LI /* 1st check: If any address is not an address, it's inequal. */ 21409100258SXin LI if ( !a1 || (AF_UNSPEC == AF(a1)) || 21509100258SXin LI !a2 || (AF_UNSPEC == AF(a2)) ) 21609100258SXin LI return FALSE; 21709100258SXin LI 21809100258SXin LI /* We could check pointers for equality here and shortcut the 21909100258SXin LI * other checks if we find object identity. But that use case is 22009100258SXin LI * too rare to care for it. 22109100258SXin LI */ 22209100258SXin LI 22309100258SXin LI /* 2nd check: Address families must be the same. */ 22409100258SXin LI if (AF(a1) != AF(a2)) 22509100258SXin LI return FALSE; 22609100258SXin LI 22709100258SXin LI /* type check: address family determines buffer & size */ 22809100258SXin LI switch (AF(a1)) { 22909100258SXin LI case AF_INET: 23009100258SXin LI /* IPv4 is easy: clamp size, get byte pointers */ 23109100258SXin LI if (mbits > sizeof(NSRCADR(a1)) * 8) 23209100258SXin LI mbits = sizeof(NSRCADR(a1)) * 8; 23309100258SXin LI pm1 = (const void*)&NSRCADR(a1); 23409100258SXin LI pm2 = (const void*)&NSRCADR(a2); 23509100258SXin LI break; 23609100258SXin LI 23709100258SXin LI case AF_INET6: 23809100258SXin LI /* IPv6 is slightly different: Both scopes must match, 23909100258SXin LI * too, before we even consider doing a match! 24009100258SXin LI */ 24109100258SXin LI if ( ! SCOPE_EQ(a1, a2)) 24209100258SXin LI return FALSE; 24309100258SXin LI if (mbits > sizeof(NSRCADR6(a1)) * 8) 24409100258SXin LI mbits = sizeof(NSRCADR6(a1)) * 8; 24509100258SXin LI pm1 = (const void*)&NSRCADR6(a1); 24609100258SXin LI pm2 = (const void*)&NSRCADR6(a2); 24709100258SXin LI break; 24809100258SXin LI 24909100258SXin LI default: 25009100258SXin LI /* don't know how to compare that!?! */ 25109100258SXin LI return FALSE; 25209100258SXin LI } 25309100258SXin LI 25409100258SXin LI /* Split bit length into byte length and partial byte mask. 25509100258SXin LI * Note that the byte mask extends from the MSB of a byte down, 25609100258SXin LI * and that zero shift (--> mbits % 8 == 0) results in an 25709100258SXin LI * all-zero mask. 25809100258SXin LI */ 25909100258SXin LI msk = 0xFFu ^ (0xFFu >> (mbits & 7)); 26009100258SXin LI len = mbits >> 3; 26109100258SXin LI 26209100258SXin LI /* 3rd check: Do memcmp() over full bytes, if any */ 26309100258SXin LI if (len && memcmp(pm1, pm2, len)) 26409100258SXin LI return FALSE; 26509100258SXin LI 26609100258SXin LI /* 4th check: compare last incomplete byte, if any */ 26709100258SXin LI if (msk && ((pm1[len] ^ pm2[len]) & msk)) 26809100258SXin LI return FALSE; 26909100258SXin LI 27009100258SXin LI /* If none of the above failed, we're successfully through. */ 27109100258SXin LI return TRUE; 27209100258SXin LI } 273c0b746e5SOllivier Robert 274c0b746e5SOllivier Robert /* 275c0b746e5SOllivier Robert * init_auth - initialize internal data 276c0b746e5SOllivier Robert */ 277c0b746e5SOllivier Robert void 278c0b746e5SOllivier Robert init_auth(void) 279c0b746e5SOllivier Robert { 2802b15cb3dSCy Schubert size_t newalloc; 2812b15cb3dSCy Schubert 282c0b746e5SOllivier Robert /* 283c0b746e5SOllivier Robert * Initialize hash table and free list 284c0b746e5SOllivier Robert */ 2852b15cb3dSCy Schubert newalloc = authhashbuckets * sizeof(key_hash[0]); 2862b15cb3dSCy Schubert 287*e6bfd18dSCy Schubert key_hash = emalloc_zero(newalloc); 2882b15cb3dSCy Schubert 2892b15cb3dSCy Schubert INIT_DLIST(key_listhead, llink); 2902b15cb3dSCy Schubert 2912b15cb3dSCy Schubert #ifdef DEBUG 2922b15cb3dSCy Schubert atexit(&free_auth_mem); 2932b15cb3dSCy Schubert #endif 2942b15cb3dSCy Schubert } 2952b15cb3dSCy Schubert 2962b15cb3dSCy Schubert 2972b15cb3dSCy Schubert /* 2982b15cb3dSCy Schubert * free_auth_mem - assist in leak detection by freeing all dynamic 2992b15cb3dSCy Schubert * allocations from this module. 3002b15cb3dSCy Schubert */ 3012b15cb3dSCy Schubert #ifdef DEBUG 3022b15cb3dSCy Schubert static void 3032b15cb3dSCy Schubert free_auth_mem(void) 3042b15cb3dSCy Schubert { 3052b15cb3dSCy Schubert symkey * sk; 3062b15cb3dSCy Schubert symkey_alloc * alloc; 3072b15cb3dSCy Schubert symkey_alloc * next_alloc; 3082b15cb3dSCy Schubert 3092b15cb3dSCy Schubert while (NULL != (sk = HEAD_DLIST(key_listhead, llink))) { 3104990d495SXin LI freesymkey(sk); 3112b15cb3dSCy Schubert } 3122b15cb3dSCy Schubert free(key_hash); 3132b15cb3dSCy Schubert key_hash = NULL; 3142b15cb3dSCy Schubert cache_keyid = 0; 3152b15cb3dSCy Schubert cache_flags = 0; 31668ba7e87SXin LI cache_keyacclist = NULL; 3172b15cb3dSCy Schubert for (alloc = authallocs; alloc != NULL; alloc = next_alloc) { 3182b15cb3dSCy Schubert next_alloc = alloc->link; 3192b15cb3dSCy Schubert free(alloc->mem); 3202b15cb3dSCy Schubert } 3212b15cb3dSCy Schubert authfreekeys = NULL; 3222b15cb3dSCy Schubert authnumfreekeys = 0; 3232b15cb3dSCy Schubert } 3242b15cb3dSCy Schubert #endif /* DEBUG */ 3252b15cb3dSCy Schubert 3262b15cb3dSCy Schubert 3272b15cb3dSCy Schubert /* 3282b15cb3dSCy Schubert * auth_moremem - get some more free key structures 3292b15cb3dSCy Schubert */ 3302b15cb3dSCy Schubert void 3312b15cb3dSCy Schubert auth_moremem( 3322b15cb3dSCy Schubert int keycount 3332b15cb3dSCy Schubert ) 3342b15cb3dSCy Schubert { 3352b15cb3dSCy Schubert symkey * sk; 3362b15cb3dSCy Schubert int i; 3372b15cb3dSCy Schubert #ifdef DEBUG 3382b15cb3dSCy Schubert void * base; 3392b15cb3dSCy Schubert symkey_alloc * allocrec; 3402b15cb3dSCy Schubert # define MOREMEM_EXTRA_ALLOC (sizeof(*allocrec)) 3412b15cb3dSCy Schubert #else 3422b15cb3dSCy Schubert # define MOREMEM_EXTRA_ALLOC (0) 3432b15cb3dSCy Schubert #endif 3442b15cb3dSCy Schubert 3452b15cb3dSCy Schubert i = (keycount > 0) 3462b15cb3dSCy Schubert ? keycount 3472b15cb3dSCy Schubert : MEMINC; 348f0574f5cSXin LI sk = eallocarrayxz(i, sizeof(*sk), MOREMEM_EXTRA_ALLOC); 3492b15cb3dSCy Schubert #ifdef DEBUG 3502b15cb3dSCy Schubert base = sk; 3512b15cb3dSCy Schubert #endif 3522b15cb3dSCy Schubert authnumfreekeys += i; 3532b15cb3dSCy Schubert 3542b15cb3dSCy Schubert for (; i > 0; i--, sk++) { 3552b15cb3dSCy Schubert LINK_SLIST(authfreekeys, sk, llink.f); 3562b15cb3dSCy Schubert } 3572b15cb3dSCy Schubert 3582b15cb3dSCy Schubert #ifdef DEBUG 3592b15cb3dSCy Schubert allocrec = (void *)sk; 3602b15cb3dSCy Schubert allocrec->mem = base; 3612b15cb3dSCy Schubert LINK_SLIST(authallocs, allocrec, link); 3622b15cb3dSCy Schubert #endif 3632b15cb3dSCy Schubert } 3642b15cb3dSCy Schubert 3652b15cb3dSCy Schubert 3662b15cb3dSCy Schubert /* 3672b15cb3dSCy Schubert * auth_prealloc_symkeys 3682b15cb3dSCy Schubert */ 3692b15cb3dSCy Schubert void 3702b15cb3dSCy Schubert auth_prealloc_symkeys( 3712b15cb3dSCy Schubert int keycount 3722b15cb3dSCy Schubert ) 3732b15cb3dSCy Schubert { 3742b15cb3dSCy Schubert int allocated; 3752b15cb3dSCy Schubert int additional; 3762b15cb3dSCy Schubert 3772b15cb3dSCy Schubert allocated = authnumkeys + authnumfreekeys; 3782b15cb3dSCy Schubert additional = keycount - allocated; 3792b15cb3dSCy Schubert if (additional > 0) 3802b15cb3dSCy Schubert auth_moremem(additional); 3812b15cb3dSCy Schubert auth_resize_hashtable(); 3822b15cb3dSCy Schubert } 3832b15cb3dSCy Schubert 3842b15cb3dSCy Schubert 38568ba7e87SXin LI static u_short 38668ba7e87SXin LI auth_log2(size_t x) 3872b15cb3dSCy Schubert { 38868ba7e87SXin LI /* 38968ba7e87SXin LI ** bithack to calculate floor(log2(x)) 39068ba7e87SXin LI ** 39168ba7e87SXin LI ** This assumes 39268ba7e87SXin LI ** - (sizeof(size_t) is a power of two 39368ba7e87SXin LI ** - CHAR_BITS is a power of two 39468ba7e87SXin LI ** - returning zero for arguments <= 0 is OK. 39568ba7e87SXin LI ** 39668ba7e87SXin LI ** Does only shifts, masks and sums in integer arithmetic in 39768ba7e87SXin LI ** log2(CHAR_BIT*sizeof(size_t)) steps. (that is, 5/6 steps for 39868ba7e87SXin LI ** 32bit/64bit size_t) 39968ba7e87SXin LI */ 40068ba7e87SXin LI int s; 40168ba7e87SXin LI int r = 0; 40268ba7e87SXin LI size_t m = ~(size_t)0; 40368ba7e87SXin LI 40468ba7e87SXin LI for (s = sizeof(size_t) / 2 * CHAR_BIT; s != 0; s >>= 1) { 40568ba7e87SXin LI m <<= s; 40668ba7e87SXin LI if (x & m) 40768ba7e87SXin LI r += s; 40868ba7e87SXin LI else 40968ba7e87SXin LI x <<= s; 41068ba7e87SXin LI } 41168ba7e87SXin LI return (u_short)r; 4122b15cb3dSCy Schubert } 4132b15cb3dSCy Schubert 41409100258SXin LI int/*BOOL*/ 41509100258SXin LI ipaddr_match_masked(const sockaddr_u *,const sockaddr_u *, 41609100258SXin LI unsigned int mbits); 41709100258SXin LI 4184990d495SXin LI static void 4194990d495SXin LI authcache_flush_id( 4204990d495SXin LI keyid_t id 4214990d495SXin LI ) 4224990d495SXin LI { 4234990d495SXin LI if (cache_keyid == id) { 4244990d495SXin LI cache_keyid = 0; 4254990d495SXin LI cache_type = 0; 4264990d495SXin LI cache_flags = 0; 4274990d495SXin LI cache_secret = NULL; 4284990d495SXin LI cache_secretsize = 0; 4294990d495SXin LI cache_keyacclist = NULL; 4304990d495SXin LI } 4314990d495SXin LI } 4324990d495SXin LI 4332b15cb3dSCy Schubert 4342b15cb3dSCy Schubert /* 4352b15cb3dSCy Schubert * auth_resize_hashtable 4362b15cb3dSCy Schubert * 4372b15cb3dSCy Schubert * Size hash table to average 4 or fewer entries per bucket initially, 4382b15cb3dSCy Schubert * within the bounds of at least 4 and no more than 15 bits for the hash 4392b15cb3dSCy Schubert * table index. Populate the hash table. 4402b15cb3dSCy Schubert */ 4412b15cb3dSCy Schubert static void 4422b15cb3dSCy Schubert auth_resize_hashtable(void) 4432b15cb3dSCy Schubert { 4442b15cb3dSCy Schubert u_long totalkeys; 4452b15cb3dSCy Schubert u_short hashbits; 4462b15cb3dSCy Schubert u_short hash; 4472b15cb3dSCy Schubert size_t newalloc; 4482b15cb3dSCy Schubert symkey * sk; 4492b15cb3dSCy Schubert 4502b15cb3dSCy Schubert totalkeys = authnumkeys + authnumfreekeys; 45168ba7e87SXin LI hashbits = auth_log2(totalkeys / 4) + 1; 4522b15cb3dSCy Schubert hashbits = max(4, hashbits); 4532b15cb3dSCy Schubert hashbits = min(15, hashbits); 4542b15cb3dSCy Schubert 4552b15cb3dSCy Schubert authhashbuckets = 1 << hashbits; 4562b15cb3dSCy Schubert authhashmask = authhashbuckets - 1; 4572b15cb3dSCy Schubert newalloc = authhashbuckets * sizeof(key_hash[0]); 4582b15cb3dSCy Schubert 4592b15cb3dSCy Schubert key_hash = erealloc(key_hash, newalloc); 460*e6bfd18dSCy Schubert zero_mem(key_hash, newalloc); 4612b15cb3dSCy Schubert 4622b15cb3dSCy Schubert ITER_DLIST_BEGIN(key_listhead, sk, llink, symkey) 4632b15cb3dSCy Schubert hash = KEYHASH(sk->keyid); 4642b15cb3dSCy Schubert LINK_SLIST(key_hash[hash], sk, hlink); 4652b15cb3dSCy Schubert ITER_DLIST_END() 4662b15cb3dSCy Schubert } 4672b15cb3dSCy Schubert 4682b15cb3dSCy Schubert 4692b15cb3dSCy Schubert /* 4702b15cb3dSCy Schubert * allocsymkey - common code to allocate and link in symkey 4712b15cb3dSCy Schubert * 4722b15cb3dSCy Schubert * secret must be allocated with a free-compatible allocator. It is 4732b15cb3dSCy Schubert * owned by the referring symkey structure, and will be free()d by 4742b15cb3dSCy Schubert * freesymkey(). 4752b15cb3dSCy Schubert */ 4762b15cb3dSCy Schubert static void 4772b15cb3dSCy Schubert allocsymkey( 4782b15cb3dSCy Schubert keyid_t id, 4792b15cb3dSCy Schubert u_short flags, 4802b15cb3dSCy Schubert u_short type, 4812b15cb3dSCy Schubert u_long lifetime, 4824990d495SXin LI size_t secretsize, 48368ba7e87SXin LI u_char * secret, 48468ba7e87SXin LI KeyAccT * ka 4852b15cb3dSCy Schubert ) 4862b15cb3dSCy Schubert { 4872b15cb3dSCy Schubert symkey * sk; 4884990d495SXin LI symkey ** bucket; 4894990d495SXin LI 4904990d495SXin LI bucket = &key_hash[KEYHASH(id)]; 4914990d495SXin LI 4922b15cb3dSCy Schubert 4932b15cb3dSCy Schubert if (authnumfreekeys < 1) 4942b15cb3dSCy Schubert auth_moremem(-1); 4952b15cb3dSCy Schubert UNLINK_HEAD_SLIST(sk, authfreekeys, llink.f); 4962b15cb3dSCy Schubert DEBUG_ENSURE(sk != NULL); 4972b15cb3dSCy Schubert sk->keyid = id; 4982b15cb3dSCy Schubert sk->flags = flags; 4992b15cb3dSCy Schubert sk->type = type; 5002b15cb3dSCy Schubert sk->secretsize = secretsize; 5012b15cb3dSCy Schubert sk->secret = secret; 50268ba7e87SXin LI sk->keyacclist = ka; 5032b15cb3dSCy Schubert sk->lifetime = lifetime; 5042b15cb3dSCy Schubert LINK_SLIST(*bucket, sk, hlink); 5052b15cb3dSCy Schubert LINK_TAIL_DLIST(key_listhead, sk, llink); 5062b15cb3dSCy Schubert authnumfreekeys--; 5072b15cb3dSCy Schubert authnumkeys++; 5082b15cb3dSCy Schubert } 5092b15cb3dSCy Schubert 5102b15cb3dSCy Schubert 5112b15cb3dSCy Schubert /* 5122b15cb3dSCy Schubert * freesymkey - common code to remove a symkey and recycle its entry. 5132b15cb3dSCy Schubert */ 5142b15cb3dSCy Schubert static void 5152b15cb3dSCy Schubert freesymkey( 5164990d495SXin LI symkey * sk 5172b15cb3dSCy Schubert ) 5182b15cb3dSCy Schubert { 5194990d495SXin LI symkey ** bucket; 5202b15cb3dSCy Schubert symkey * unlinked; 5212b15cb3dSCy Schubert 5224990d495SXin LI if (NULL == sk) 5234990d495SXin LI return; 5244990d495SXin LI 5254990d495SXin LI authcache_flush_id(sk->keyid); 5264990d495SXin LI keyacc_all_free(sk->keyacclist); 5274990d495SXin LI 5284990d495SXin LI bucket = &key_hash[KEYHASH(sk->keyid)]; 5292b15cb3dSCy Schubert if (sk->secret != NULL) { 530*e6bfd18dSCy Schubert zero_mem(sk->secret, sk->secretsize); 5312b15cb3dSCy Schubert free(sk->secret); 5322b15cb3dSCy Schubert } 5332b15cb3dSCy Schubert UNLINK_SLIST(unlinked, *bucket, sk, hlink, symkey); 5342b15cb3dSCy Schubert DEBUG_ENSURE(sk == unlinked); 5352b15cb3dSCy Schubert UNLINK_DLIST(sk, llink); 536*e6bfd18dSCy Schubert zero_mem((char *)sk + offsetof(symkey, symkey_payload), 5372b15cb3dSCy Schubert sizeof(*sk) - offsetof(symkey, symkey_payload)); 5382b15cb3dSCy Schubert LINK_SLIST(authfreekeys, sk, llink.f); 5392b15cb3dSCy Schubert authnumkeys--; 5402b15cb3dSCy Schubert authnumfreekeys++; 541c0b746e5SOllivier Robert } 542c0b746e5SOllivier Robert 543c0b746e5SOllivier Robert 544c0b746e5SOllivier Robert /* 545c0b746e5SOllivier Robert * auth_findkey - find a key in the hash table 546c0b746e5SOllivier Robert */ 547c0b746e5SOllivier Robert struct savekey * 548c0b746e5SOllivier Robert auth_findkey( 5492b15cb3dSCy Schubert keyid_t id 550c0b746e5SOllivier Robert ) 551c0b746e5SOllivier Robert { 5522b15cb3dSCy Schubert symkey * sk; 553c0b746e5SOllivier Robert 5544990d495SXin LI for (sk = key_hash[KEYHASH(id)]; sk != NULL; sk = sk->hlink) 5554990d495SXin LI if (id == sk->keyid) 5562b15cb3dSCy Schubert return sk; 5572b15cb3dSCy Schubert return NULL; 558c0b746e5SOllivier Robert } 559c0b746e5SOllivier Robert 560c0b746e5SOllivier Robert 561c0b746e5SOllivier Robert /* 5624990d495SXin LI * auth_havekey - return TRUE if the key id is zero or known. The 5634990d495SXin LI * key needs not to be trusted. 564c0b746e5SOllivier Robert */ 565c0b746e5SOllivier Robert int 566c0b746e5SOllivier Robert auth_havekey( 5672b15cb3dSCy Schubert keyid_t id 568c0b746e5SOllivier Robert ) 569c0b746e5SOllivier Robert { 5704990d495SXin LI return 5714990d495SXin LI (0 == id) || 5724990d495SXin LI (cache_keyid == id) || 5734990d495SXin LI (NULL != auth_findkey(id)); 574c0b746e5SOllivier Robert } 575c0b746e5SOllivier Robert 576c0b746e5SOllivier Robert 577c0b746e5SOllivier Robert /* 5782b15cb3dSCy Schubert * authhavekey - return TRUE and cache the key, if zero or both known 5792b15cb3dSCy Schubert * and trusted. 580c0b746e5SOllivier Robert */ 581c0b746e5SOllivier Robert int 582c0b746e5SOllivier Robert authhavekey( 5832b15cb3dSCy Schubert keyid_t id 584c0b746e5SOllivier Robert ) 585c0b746e5SOllivier Robert { 5862b15cb3dSCy Schubert symkey * sk; 587c0b746e5SOllivier Robert 588c0b746e5SOllivier Robert authkeylookups++; 5894990d495SXin LI if (0 == id || cache_keyid == id) 5904990d495SXin LI return !!(KEY_TRUSTED & cache_flags); 591c0b746e5SOllivier Robert 592c0b746e5SOllivier Robert /* 5934990d495SXin LI * Search the bin for the key. If not found, or found but the key 5944990d495SXin LI * type is zero, somebody marked it trusted without specifying a 5954990d495SXin LI * key or key type. In this case consider the key missing. 596c0b746e5SOllivier Robert */ 5972b15cb3dSCy Schubert authkeyuncached++; 5984990d495SXin LI sk = auth_findkey(id); 5994990d495SXin LI if ((sk == NULL) || (sk->type == 0)) { 6002b15cb3dSCy Schubert authkeynotfound++; 6012b15cb3dSCy Schubert return FALSE; 602c0b746e5SOllivier Robert } 6032b15cb3dSCy Schubert 6042b15cb3dSCy Schubert /* 6054990d495SXin LI * If the key is not trusted, the key is not considered found. 6062b15cb3dSCy Schubert */ 6072b15cb3dSCy Schubert if ( ! (KEY_TRUSTED & sk->flags)) { 6082b15cb3dSCy Schubert authnokey++; 6092b15cb3dSCy Schubert return FALSE; 6102b15cb3dSCy Schubert } 6112b15cb3dSCy Schubert 6122b15cb3dSCy Schubert /* 6132b15cb3dSCy Schubert * The key is found and trusted. Initialize the key cache. 6142b15cb3dSCy Schubert */ 6152b15cb3dSCy Schubert cache_keyid = sk->keyid; 6162b15cb3dSCy Schubert cache_type = sk->type; 6172b15cb3dSCy Schubert cache_flags = sk->flags; 6182b15cb3dSCy Schubert cache_secret = sk->secret; 6192b15cb3dSCy Schubert cache_secretsize = sk->secretsize; 62068ba7e87SXin LI cache_keyacclist = sk->keyacclist; 6212b15cb3dSCy Schubert 6222b15cb3dSCy Schubert return TRUE; 623c0b746e5SOllivier Robert } 624c0b746e5SOllivier Robert 625c0b746e5SOllivier Robert 626c0b746e5SOllivier Robert /* 627c0b746e5SOllivier Robert * authtrust - declare a key to be trusted/untrusted 628c0b746e5SOllivier Robert */ 629c0b746e5SOllivier Robert void 630c0b746e5SOllivier Robert authtrust( 6312b15cb3dSCy Schubert keyid_t id, 632224ba2bdSOllivier Robert u_long trust 633c0b746e5SOllivier Robert ) 634c0b746e5SOllivier Robert { 6352b15cb3dSCy Schubert symkey * sk; 6362b15cb3dSCy Schubert u_long lifetime; 637c0b746e5SOllivier Robert 6382b15cb3dSCy Schubert /* 6392b15cb3dSCy Schubert * Search bin for key; if it does not exist and is untrusted, 6402b15cb3dSCy Schubert * forget it. 6412b15cb3dSCy Schubert */ 6424990d495SXin LI 6434990d495SXin LI sk = auth_findkey(id); 6444990d495SXin LI if (!trust && sk == NULL) 645c0b746e5SOllivier Robert return; 646c0b746e5SOllivier Robert 6472b15cb3dSCy Schubert /* 6482b15cb3dSCy Schubert * There are two conditions remaining. Either it does not 6492b15cb3dSCy Schubert * exist and is to be trusted or it does exist and is or is 6502b15cb3dSCy Schubert * not to be trusted. 6512b15cb3dSCy Schubert */ 6522b15cb3dSCy Schubert if (sk != NULL) { 6532b15cb3dSCy Schubert /* 6544990d495SXin LI * Key exists. If it is to be trusted, say so and update 6554990d495SXin LI * its lifetime. If no longer trusted, return it to the 6564990d495SXin LI * free list. Flush the cache first to be sure there are 6574990d495SXin LI * no discrepancies. 6582b15cb3dSCy Schubert */ 6594990d495SXin LI authcache_flush_id(id); 660c0b746e5SOllivier Robert if (trust > 0) { 661c0b746e5SOllivier Robert sk->flags |= KEY_TRUSTED; 662c0b746e5SOllivier Robert if (trust > 1) 663c0b746e5SOllivier Robert sk->lifetime = current_time + trust; 664c0b746e5SOllivier Robert else 665c0b746e5SOllivier Robert sk->lifetime = 0; 6664990d495SXin LI } else { 6674990d495SXin LI freesymkey(sk); 668c0b746e5SOllivier Robert } 6692b15cb3dSCy Schubert return; 6702b15cb3dSCy Schubert } 671c0b746e5SOllivier Robert 6722b15cb3dSCy Schubert /* 6732b15cb3dSCy Schubert * keyid is not present, but the is to be trusted. We allocate 6742b15cb3dSCy Schubert * a new key, but do not specify a key type or secret. 6752b15cb3dSCy Schubert */ 6762b15cb3dSCy Schubert if (trust > 1) { 6772b15cb3dSCy Schubert lifetime = current_time + trust; 678c0b746e5SOllivier Robert } else { 6792b15cb3dSCy Schubert lifetime = 0; 680c0b746e5SOllivier Robert } 6814990d495SXin LI allocsymkey(id, KEY_TRUSTED, 0, lifetime, 0, NULL, NULL); 682c0b746e5SOllivier Robert } 683c0b746e5SOllivier Robert 684c0b746e5SOllivier Robert 685c0b746e5SOllivier Robert /* 686c0b746e5SOllivier Robert * authistrusted - determine whether a key is trusted 687c0b746e5SOllivier Robert */ 688c0b746e5SOllivier Robert int 689c0b746e5SOllivier Robert authistrusted( 6904990d495SXin LI keyid_t id 691c0b746e5SOllivier Robert ) 692c0b746e5SOllivier Robert { 6932b15cb3dSCy Schubert symkey * sk; 694c0b746e5SOllivier Robert 6954990d495SXin LI if (id == cache_keyid) 6962b15cb3dSCy Schubert return !!(KEY_TRUSTED & cache_flags); 697c0b746e5SOllivier Robert 698c0b746e5SOllivier Robert authkeyuncached++; 6994990d495SXin LI sk = auth_findkey(id); 7004990d495SXin LI if (sk == NULL || !(KEY_TRUSTED & sk->flags)) { 701c0b746e5SOllivier Robert authkeynotfound++; 7022b15cb3dSCy Schubert return FALSE; 703c0b746e5SOllivier Robert } 7042b15cb3dSCy Schubert return TRUE; 705c0b746e5SOllivier Robert } 706c0b746e5SOllivier Robert 70768ba7e87SXin LI 70868ba7e87SXin LI /* 70968ba7e87SXin LI * authistrustedip - determine if the IP is OK for the keyid 71068ba7e87SXin LI */ 71168ba7e87SXin LI int 71268ba7e87SXin LI authistrustedip( 71368ba7e87SXin LI keyid_t keyno, 71468ba7e87SXin LI sockaddr_u * sau 71568ba7e87SXin LI ) 71668ba7e87SXin LI { 71768ba7e87SXin LI symkey * sk; 71868ba7e87SXin LI 7194990d495SXin LI if (keyno == cache_keyid) { 7204990d495SXin LI return (KEY_TRUSTED & cache_flags) && 7214990d495SXin LI keyacc_contains(cache_keyacclist, sau, TRUE); 72209100258SXin LI } 72309100258SXin LI 72409100258SXin LI if (NULL != (sk = auth_findkey(keyno))) { 72568ba7e87SXin LI authkeyuncached++; 7264990d495SXin LI return (KEY_TRUSTED & sk->flags) && 7274990d495SXin LI keyacc_contains(sk->keyacclist, sau, TRUE); 72868ba7e87SXin LI } 72909100258SXin LI 73009100258SXin LI authkeynotfound++; 73109100258SXin LI return FALSE; 73268ba7e87SXin LI } 73368ba7e87SXin LI 7343311ff84SXin LI /* Note: There are two locations below where 'strncpy()' is used. While 7353311ff84SXin LI * this function is a hazard by itself, it's essential that it is used 7363311ff84SXin LI * here. Bug 1243 involved that the secret was filled with NUL bytes 7373311ff84SXin LI * after the first NUL encountered, and 'strlcpy()' simply does NOT have 7383311ff84SXin LI * this behaviour. So disabling the fix and reverting to the buggy 7393311ff84SXin LI * behaviour due to compatibility issues MUST also fill with NUL and 7403311ff84SXin LI * this needs 'strncpy'. Also, the secret is managed as a byte blob of a 7413311ff84SXin LI * given size, and eventually truncating it and replacing the last byte 7423311ff84SXin LI * with a NUL would be a bug. 7433311ff84SXin LI * perlinger@ntp.org 2015-10-10 7443311ff84SXin LI */ 745c0b746e5SOllivier Robert void 746c0b746e5SOllivier Robert MD5auth_setkey( 747224ba2bdSOllivier Robert keyid_t keyno, 7482b15cb3dSCy Schubert int keytype, 749c0b746e5SOllivier Robert const u_char *key, 7504990d495SXin LI size_t secretsize, 75168ba7e87SXin LI KeyAccT *ka 752c0b746e5SOllivier Robert ) 753c0b746e5SOllivier Robert { 7542b15cb3dSCy Schubert symkey * sk; 7552b15cb3dSCy Schubert u_char * secret; 756c0b746e5SOllivier Robert 7572b15cb3dSCy Schubert DEBUG_ENSURE(keytype <= USHRT_MAX); 7584990d495SXin LI DEBUG_ENSURE(secretsize < 4 * 1024); 759c0b746e5SOllivier Robert /* 760c0b746e5SOllivier Robert * See if we already have the key. If so just stick in the 761c0b746e5SOllivier Robert * new value. 762c0b746e5SOllivier Robert */ 7634990d495SXin LI sk = auth_findkey(keyno); 7644990d495SXin LI if (sk != NULL && keyno == sk->keyid) { 7659034852cSGleb Smirnoff /* TALOS-CAN-0054: make sure we have a new buffer! */ 7669034852cSGleb Smirnoff if (NULL != sk->secret) { 7679034852cSGleb Smirnoff memset(sk->secret, 0, sk->secretsize); 7689034852cSGleb Smirnoff free(sk->secret); 7699034852cSGleb Smirnoff } 7704990d495SXin LI sk->secret = emalloc(secretsize + 1); 7712b15cb3dSCy Schubert sk->type = (u_short)keytype; 7724990d495SXin LI sk->secretsize = secretsize; 7734990d495SXin LI /* make sure access lists don't leak here! */ 7744990d495SXin LI if (ka != sk->keyacclist) { 7754990d495SXin LI keyacc_all_free(sk->keyacclist); 77668ba7e87SXin LI sk->keyacclist = ka; 7774990d495SXin LI } 7782b15cb3dSCy Schubert #ifndef DISABLE_BUG1243_FIX 7792b15cb3dSCy Schubert memcpy(sk->secret, key, secretsize); 7802b15cb3dSCy Schubert #else 7813311ff84SXin LI /* >MUST< use 'strncpy()' here! See above! */ 7823311ff84SXin LI strncpy((char *)sk->secret, (const char *)key, 7832b15cb3dSCy Schubert secretsize); 7842b15cb3dSCy Schubert #endif 7854990d495SXin LI authcache_flush_id(keyno); 786c0b746e5SOllivier Robert return; 787c0b746e5SOllivier Robert } 788c0b746e5SOllivier Robert 789c0b746e5SOllivier Robert /* 790c0b746e5SOllivier Robert * Need to allocate new structure. Do it. 791c0b746e5SOllivier Robert */ 7924990d495SXin LI secret = emalloc(secretsize + 1); 7932b15cb3dSCy Schubert #ifndef DISABLE_BUG1243_FIX 7942b15cb3dSCy Schubert memcpy(secret, key, secretsize); 7952b15cb3dSCy Schubert #else 7963311ff84SXin LI /* >MUST< use 'strncpy()' here! See above! */ 7973311ff84SXin LI strncpy((char *)secret, (const char *)key, secretsize); 7982b15cb3dSCy Schubert #endif 7994990d495SXin LI allocsymkey(keyno, 0, (u_short)keytype, 0, 8004990d495SXin LI secretsize, secret, ka); 8012b15cb3dSCy Schubert #ifdef DEBUG 802*e6bfd18dSCy Schubert if (debug >= 1) { 8032b15cb3dSCy Schubert size_t j; 8042b15cb3dSCy Schubert 8052b15cb3dSCy Schubert printf("auth_setkey: key %d type %d len %d ", (int)keyno, 8062b15cb3dSCy Schubert keytype, (int)secretsize); 8074990d495SXin LI for (j = 0; j < secretsize; j++) { 8082b15cb3dSCy Schubert printf("%02x", secret[j]); 8094990d495SXin LI } 8102b15cb3dSCy Schubert printf("\n"); 8112b15cb3dSCy Schubert } 8122b15cb3dSCy Schubert #endif 813c0b746e5SOllivier Robert } 814c0b746e5SOllivier Robert 815c0b746e5SOllivier Robert 816c0b746e5SOllivier Robert /* 8172b15cb3dSCy Schubert * auth_delkeys - delete non-autokey untrusted keys, and clear all info 8182b15cb3dSCy Schubert * except the trusted bit of non-autokey trusted keys, in 8192b15cb3dSCy Schubert * preparation for rereading the keys file. 820c0b746e5SOllivier Robert */ 821c0b746e5SOllivier Robert void 822c0b746e5SOllivier Robert auth_delkeys(void) 823c0b746e5SOllivier Robert { 8242b15cb3dSCy Schubert symkey * sk; 825c0b746e5SOllivier Robert 8262b15cb3dSCy Schubert ITER_DLIST_BEGIN(key_listhead, sk, llink, symkey) 8272b15cb3dSCy Schubert if (sk->keyid > NTP_MAXKEY) { /* autokey */ 8282b15cb3dSCy Schubert continue; 8292b15cb3dSCy Schubert } 8302b15cb3dSCy Schubert 831c0b746e5SOllivier Robert /* 8329034852cSGleb Smirnoff * Don't lose info as to which keys are trusted. Make 8339034852cSGleb Smirnoff * sure there are no dangling pointers! 834c0b746e5SOllivier Robert */ 8352b15cb3dSCy Schubert if (KEY_TRUSTED & sk->flags) { 8362b15cb3dSCy Schubert if (sk->secret != NULL) { 837*e6bfd18dSCy Schubert zero_mem(sk->secret, sk->secretsize); 8382b15cb3dSCy Schubert free(sk->secret); 8399034852cSGleb Smirnoff sk->secret = NULL; /* TALOS-CAN-0054 */ 8402b15cb3dSCy Schubert } 8414990d495SXin LI sk->keyacclist = keyacc_all_free(sk->keyacclist); 8422b15cb3dSCy Schubert sk->secretsize = 0; 843c0b746e5SOllivier Robert sk->lifetime = 0; 844c0b746e5SOllivier Robert } else { 8454990d495SXin LI freesymkey(sk); 846c0b746e5SOllivier Robert } 8472b15cb3dSCy Schubert ITER_DLIST_END() 848c0b746e5SOllivier Robert } 8492b15cb3dSCy Schubert 850c0b746e5SOllivier Robert 851c0b746e5SOllivier Robert /* 852c0b746e5SOllivier Robert * auth_agekeys - delete keys whose lifetimes have expired 853c0b746e5SOllivier Robert */ 854c0b746e5SOllivier Robert void 855c0b746e5SOllivier Robert auth_agekeys(void) 856c0b746e5SOllivier Robert { 8572b15cb3dSCy Schubert symkey * sk; 858c0b746e5SOllivier Robert 8592b15cb3dSCy Schubert ITER_DLIST_BEGIN(key_listhead, sk, llink, symkey) 8602b15cb3dSCy Schubert if (sk->lifetime > 0 && current_time > sk->lifetime) { 8614990d495SXin LI freesymkey(sk); 862c0b746e5SOllivier Robert authkeyexpired++; 863c0b746e5SOllivier Robert } 8642b15cb3dSCy Schubert ITER_DLIST_END() 8652b15cb3dSCy Schubert DPRINTF(1, ("auth_agekeys: at %lu keys %lu expired %lu\n", 8662b15cb3dSCy Schubert current_time, authnumkeys, authkeyexpired)); 867c0b746e5SOllivier Robert } 8682b15cb3dSCy Schubert 869c0b746e5SOllivier Robert 870c0b746e5SOllivier Robert /* 871c0b746e5SOllivier Robert * authencrypt - generate message authenticator 872c0b746e5SOllivier Robert * 873c0b746e5SOllivier Robert * Returns length of authenticator field, zero if key not found. 874c0b746e5SOllivier Robert */ 8753311ff84SXin LI size_t 876c0b746e5SOllivier Robert authencrypt( 877224ba2bdSOllivier Robert keyid_t keyno, 878c0b746e5SOllivier Robert u_int32 * pkt, 8793311ff84SXin LI size_t length 880c0b746e5SOllivier Robert ) 8813311ff84SXin LI { 882c0b746e5SOllivier Robert /* 883c0b746e5SOllivier Robert * A zero key identifier means the sender has not verified 884c0b746e5SOllivier Robert * the last message was correctly authenticated. The MAC 885c0b746e5SOllivier Robert * consists of a single word with value zero. 886c0b746e5SOllivier Robert */ 887c0b746e5SOllivier Robert authencryptions++; 888*e6bfd18dSCy Schubert pkt[length / KEY_MAC_LEN] = htonl(keyno); 8892b15cb3dSCy Schubert if (0 == keyno) { 890*e6bfd18dSCy Schubert return KEY_MAC_LEN; 891c0b746e5SOllivier Robert } 8922b15cb3dSCy Schubert if (!authhavekey(keyno)) { 8932b15cb3dSCy Schubert return 0; 894c0b746e5SOllivier Robert } 895c0b746e5SOllivier Robert 89609100258SXin LI return MD5authencrypt(cache_type, 89709100258SXin LI cache_secret, cache_secretsize, 89809100258SXin LI pkt, length); 8992b15cb3dSCy Schubert } 9002b15cb3dSCy Schubert 9012b15cb3dSCy Schubert 902c0b746e5SOllivier Robert /* 903c0b746e5SOllivier Robert * authdecrypt - verify message authenticator 904c0b746e5SOllivier Robert * 9052b15cb3dSCy Schubert * Returns TRUE if authenticator valid, FALSE if invalid or not found. 906c0b746e5SOllivier Robert */ 907c0b746e5SOllivier Robert int 908c0b746e5SOllivier Robert authdecrypt( 909224ba2bdSOllivier Robert keyid_t keyno, 910c0b746e5SOllivier Robert u_int32 * pkt, 9113311ff84SXin LI size_t length, 9123311ff84SXin LI size_t size 913c0b746e5SOllivier Robert ) 914c0b746e5SOllivier Robert { 915c0b746e5SOllivier Robert /* 916c0b746e5SOllivier Robert * A zero key identifier means the sender has not verified 9172b15cb3dSCy Schubert * the last message was correctly authenticated. For our 9182b15cb3dSCy Schubert * purpose this is an invalid authenticator. 919c0b746e5SOllivier Robert */ 920c0b746e5SOllivier Robert authdecryptions++; 9212b15cb3dSCy Schubert if (0 == keyno || !authhavekey(keyno) || size < 4) { 9222b15cb3dSCy Schubert return FALSE; 9232b15cb3dSCy Schubert } 924c0b746e5SOllivier Robert 92509100258SXin LI return MD5authdecrypt(cache_type, 92609100258SXin LI cache_secret, cache_secretsize, 927a466cc55SCy Schubert pkt, length, size, keyno); 928a466cc55SCy Schubert } 929a466cc55SCy Schubert 930a466cc55SCy Schubert /* password decoding helpers */ 931a466cc55SCy Schubert static size_t 932a466cc55SCy Schubert pwdecode_plain( 933a466cc55SCy Schubert u_char * dst, 934a466cc55SCy Schubert size_t dstlen, 935a466cc55SCy Schubert const char * src 936a466cc55SCy Schubert ) 937a466cc55SCy Schubert { 938a466cc55SCy Schubert size_t srclen = strlen(src); 939a466cc55SCy Schubert if (srclen > dstlen) { 940a466cc55SCy Schubert errno = ENOMEM; 941a466cc55SCy Schubert return (size_t)-1; 942a466cc55SCy Schubert } 943a466cc55SCy Schubert memcpy(dst, src, srclen); 944a466cc55SCy Schubert return srclen; 945a466cc55SCy Schubert } 946a466cc55SCy Schubert 947a466cc55SCy Schubert static size_t 948a466cc55SCy Schubert pwdecode_hex( 949a466cc55SCy Schubert u_char * dst, 950a466cc55SCy Schubert size_t dstlen, 951a466cc55SCy Schubert const char * src 952a466cc55SCy Schubert ) 953a466cc55SCy Schubert { 954a466cc55SCy Schubert static const char hex[] = "00112233445566778899AaBbCcDdEeFf"; 955a466cc55SCy Schubert 956a466cc55SCy Schubert size_t srclen = strlen(src); 957a466cc55SCy Schubert size_t reslen = (srclen >> 1) + (srclen & 1); 958a466cc55SCy Schubert u_char tmp; 959a466cc55SCy Schubert char *ptr; 960a466cc55SCy Schubert size_t j; 961a466cc55SCy Schubert 962a466cc55SCy Schubert if (reslen > dstlen) { 963a466cc55SCy Schubert errno = ENOMEM; 964a466cc55SCy Schubert reslen = (size_t)-1; 965a466cc55SCy Schubert } else { 966a466cc55SCy Schubert for (j = 0; j < srclen; ++j) { 967a466cc55SCy Schubert tmp = *(const unsigned char*)(src + j); 968a466cc55SCy Schubert ptr = strchr(hex, tmp); 969a466cc55SCy Schubert if (ptr == NULL) { 970a466cc55SCy Schubert errno = EINVAL; 971a466cc55SCy Schubert reslen = (size_t)-1; 972a466cc55SCy Schubert break; 973a466cc55SCy Schubert } 974*e6bfd18dSCy Schubert tmp = (u_char)((ptr - hex) >> 1); 975a466cc55SCy Schubert if (j & 1) 976a466cc55SCy Schubert dst[j >> 1] |= tmp; 977a466cc55SCy Schubert else 978a466cc55SCy Schubert dst[j >> 1] = tmp << 4; 979a466cc55SCy Schubert } 980a466cc55SCy Schubert } 981a466cc55SCy Schubert return reslen; 982a466cc55SCy Schubert } 983a466cc55SCy Schubert /* 984a466cc55SCy Schubert * authdecodepw - decode plaintext or hex-encoded password to binary 985a466cc55SCy Schubert * secret. Returns size of secret in bytes or -1 on error. 986a466cc55SCy Schubert */ 987a466cc55SCy Schubert size_t 988a466cc55SCy Schubert authdecodepw( 989a466cc55SCy Schubert u_char * dst, 990a466cc55SCy Schubert size_t dstlen, 991a466cc55SCy Schubert const char * src, 992a466cc55SCy Schubert enum AuthPwdEnc enc 993a466cc55SCy Schubert ) 994a466cc55SCy Schubert { 995a466cc55SCy Schubert size_t reslen; 996a466cc55SCy Schubert 997a466cc55SCy Schubert if ( !(dst && dstlen && src)) { 998a466cc55SCy Schubert errno = EINVAL; 999a466cc55SCy Schubert reslen = (size_t)-1; 1000a466cc55SCy Schubert } else { 1001a466cc55SCy Schubert switch (enc) { 1002a466cc55SCy Schubert case AUTHPWD_UNSPEC: 1003a466cc55SCy Schubert if (strlen(src) <= 20) 1004a466cc55SCy Schubert reslen = pwdecode_plain(dst, dstlen, src); 1005a466cc55SCy Schubert else 1006a466cc55SCy Schubert reslen = pwdecode_hex(dst, dstlen, src); 1007a466cc55SCy Schubert break; 1008a466cc55SCy Schubert case AUTHPWD_PLAIN: 1009a466cc55SCy Schubert reslen = pwdecode_plain(dst, dstlen, src); 1010a466cc55SCy Schubert break; 1011a466cc55SCy Schubert case AUTHPWD_HEX: 1012a466cc55SCy Schubert reslen = pwdecode_hex(dst, dstlen, src); 1013a466cc55SCy Schubert break; 1014a466cc55SCy Schubert default: 1015a466cc55SCy Schubert errno = EINVAL; 1016a466cc55SCy Schubert reslen = (size_t)-1; 1017a466cc55SCy Schubert } 1018a466cc55SCy Schubert } 1019a466cc55SCy Schubert return reslen; 1020c0b746e5SOllivier Robert } 1021