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 287e6bfd18dSCy 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); 460e6bfd18dSCy 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) { 530e6bfd18dSCy 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); 536e6bfd18dSCy 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. 614*f5f40dd6SCy Schubert * The cache really should be a struct savekey to streamline 615*f5f40dd6SCy Schubert * this code. Using a sk pointer would be even faster but more 616*f5f40dd6SCy Schubert * fragile around pointing to freed memory. 6172b15cb3dSCy Schubert */ 6182b15cb3dSCy Schubert cache_keyid = sk->keyid; 6192b15cb3dSCy Schubert cache_type = sk->type; 6202b15cb3dSCy Schubert cache_flags = sk->flags; 6212b15cb3dSCy Schubert cache_secret = sk->secret; 6222b15cb3dSCy Schubert cache_secretsize = sk->secretsize; 62368ba7e87SXin LI cache_keyacclist = sk->keyacclist; 6242b15cb3dSCy Schubert 6252b15cb3dSCy Schubert return TRUE; 626c0b746e5SOllivier Robert } 627c0b746e5SOllivier Robert 628c0b746e5SOllivier Robert 629c0b746e5SOllivier Robert /* 630c0b746e5SOllivier Robert * authtrust - declare a key to be trusted/untrusted 631c0b746e5SOllivier Robert */ 632c0b746e5SOllivier Robert void 633c0b746e5SOllivier Robert authtrust( 6342b15cb3dSCy Schubert keyid_t id, 635224ba2bdSOllivier Robert u_long trust 636c0b746e5SOllivier Robert ) 637c0b746e5SOllivier Robert { 6382b15cb3dSCy Schubert symkey * sk; 6392b15cb3dSCy Schubert u_long lifetime; 640c0b746e5SOllivier Robert 6412b15cb3dSCy Schubert /* 6422b15cb3dSCy Schubert * Search bin for key; if it does not exist and is untrusted, 6432b15cb3dSCy Schubert * forget it. 6442b15cb3dSCy Schubert */ 6454990d495SXin LI 6464990d495SXin LI sk = auth_findkey(id); 6474990d495SXin LI if (!trust && sk == NULL) 648c0b746e5SOllivier Robert return; 649c0b746e5SOllivier Robert 6502b15cb3dSCy Schubert /* 6512b15cb3dSCy Schubert * There are two conditions remaining. Either it does not 6522b15cb3dSCy Schubert * exist and is to be trusted or it does exist and is or is 6532b15cb3dSCy Schubert * not to be trusted. 6542b15cb3dSCy Schubert */ 6552b15cb3dSCy Schubert if (sk != NULL) { 6562b15cb3dSCy Schubert /* 6574990d495SXin LI * Key exists. If it is to be trusted, say so and update 6584990d495SXin LI * its lifetime. If no longer trusted, return it to the 6594990d495SXin LI * free list. Flush the cache first to be sure there are 6604990d495SXin LI * no discrepancies. 6612b15cb3dSCy Schubert */ 6624990d495SXin LI authcache_flush_id(id); 663c0b746e5SOllivier Robert if (trust > 0) { 664c0b746e5SOllivier Robert sk->flags |= KEY_TRUSTED; 665c0b746e5SOllivier Robert if (trust > 1) 666c0b746e5SOllivier Robert sk->lifetime = current_time + trust; 667c0b746e5SOllivier Robert else 668c0b746e5SOllivier Robert sk->lifetime = 0; 6694990d495SXin LI } else { 6704990d495SXin LI freesymkey(sk); 671c0b746e5SOllivier Robert } 6722b15cb3dSCy Schubert return; 6732b15cb3dSCy Schubert } 674c0b746e5SOllivier Robert 6752b15cb3dSCy Schubert /* 6762b15cb3dSCy Schubert * keyid is not present, but the is to be trusted. We allocate 6772b15cb3dSCy Schubert * a new key, but do not specify a key type or secret. 6782b15cb3dSCy Schubert */ 6792b15cb3dSCy Schubert if (trust > 1) { 6802b15cb3dSCy Schubert lifetime = current_time + trust; 681c0b746e5SOllivier Robert } else { 6822b15cb3dSCy Schubert lifetime = 0; 683c0b746e5SOllivier Robert } 6844990d495SXin LI allocsymkey(id, KEY_TRUSTED, 0, lifetime, 0, NULL, NULL); 685c0b746e5SOllivier Robert } 686c0b746e5SOllivier Robert 687c0b746e5SOllivier Robert 688c0b746e5SOllivier Robert /* 689c0b746e5SOllivier Robert * authistrusted - determine whether a key is trusted 690c0b746e5SOllivier Robert */ 691c0b746e5SOllivier Robert int 692c0b746e5SOllivier Robert authistrusted( 6934990d495SXin LI keyid_t id 694c0b746e5SOllivier Robert ) 695c0b746e5SOllivier Robert { 6962b15cb3dSCy Schubert symkey * sk; 697c0b746e5SOllivier Robert 6984990d495SXin LI if (id == cache_keyid) 6992b15cb3dSCy Schubert return !!(KEY_TRUSTED & cache_flags); 700c0b746e5SOllivier Robert 701c0b746e5SOllivier Robert authkeyuncached++; 7024990d495SXin LI sk = auth_findkey(id); 7034990d495SXin LI if (sk == NULL || !(KEY_TRUSTED & sk->flags)) { 704c0b746e5SOllivier Robert authkeynotfound++; 7052b15cb3dSCy Schubert return FALSE; 706c0b746e5SOllivier Robert } 7072b15cb3dSCy Schubert return TRUE; 708c0b746e5SOllivier Robert } 709c0b746e5SOllivier Robert 71068ba7e87SXin LI 71168ba7e87SXin LI /* 71268ba7e87SXin LI * authistrustedip - determine if the IP is OK for the keyid 71368ba7e87SXin LI */ 71468ba7e87SXin LI int 71568ba7e87SXin LI authistrustedip( 71668ba7e87SXin LI keyid_t keyno, 71768ba7e87SXin LI sockaddr_u * sau 71868ba7e87SXin LI ) 71968ba7e87SXin LI { 72068ba7e87SXin LI symkey * sk; 72168ba7e87SXin LI 7224990d495SXin LI if (keyno == cache_keyid) { 7234990d495SXin LI return (KEY_TRUSTED & cache_flags) && 7244990d495SXin LI keyacc_contains(cache_keyacclist, sau, TRUE); 72509100258SXin LI } 72609100258SXin LI 72709100258SXin LI if (NULL != (sk = auth_findkey(keyno))) { 72868ba7e87SXin LI authkeyuncached++; 7294990d495SXin LI return (KEY_TRUSTED & sk->flags) && 7304990d495SXin LI keyacc_contains(sk->keyacclist, sau, TRUE); 73168ba7e87SXin LI } 73209100258SXin LI 73309100258SXin LI authkeynotfound++; 73409100258SXin LI return FALSE; 73568ba7e87SXin LI } 73668ba7e87SXin LI 7373311ff84SXin LI /* Note: There are two locations below where 'strncpy()' is used. While 7383311ff84SXin LI * this function is a hazard by itself, it's essential that it is used 7393311ff84SXin LI * here. Bug 1243 involved that the secret was filled with NUL bytes 7403311ff84SXin LI * after the first NUL encountered, and 'strlcpy()' simply does NOT have 7413311ff84SXin LI * this behaviour. So disabling the fix and reverting to the buggy 7423311ff84SXin LI * behaviour due to compatibility issues MUST also fill with NUL and 7433311ff84SXin LI * this needs 'strncpy'. Also, the secret is managed as a byte blob of a 7443311ff84SXin LI * given size, and eventually truncating it and replacing the last byte 7453311ff84SXin LI * with a NUL would be a bug. 7463311ff84SXin LI * perlinger@ntp.org 2015-10-10 7473311ff84SXin LI */ 748c0b746e5SOllivier Robert void 749c0b746e5SOllivier Robert MD5auth_setkey( 750224ba2bdSOllivier Robert keyid_t keyno, 7512b15cb3dSCy Schubert int keytype, 752c0b746e5SOllivier Robert const u_char *key, 7534990d495SXin LI size_t secretsize, 75468ba7e87SXin LI KeyAccT *ka 755c0b746e5SOllivier Robert ) 756c0b746e5SOllivier Robert { 7572b15cb3dSCy Schubert symkey * sk; 7582b15cb3dSCy Schubert u_char * secret; 759c0b746e5SOllivier Robert 7602b15cb3dSCy Schubert DEBUG_ENSURE(keytype <= USHRT_MAX); 7614990d495SXin LI DEBUG_ENSURE(secretsize < 4 * 1024); 762c0b746e5SOllivier Robert /* 763c0b746e5SOllivier Robert * See if we already have the key. If so just stick in the 764c0b746e5SOllivier Robert * new value. 765c0b746e5SOllivier Robert */ 7664990d495SXin LI sk = auth_findkey(keyno); 7674990d495SXin LI if (sk != NULL && keyno == sk->keyid) { 7689034852cSGleb Smirnoff /* TALOS-CAN-0054: make sure we have a new buffer! */ 7699034852cSGleb Smirnoff if (NULL != sk->secret) { 7709034852cSGleb Smirnoff memset(sk->secret, 0, sk->secretsize); 7719034852cSGleb Smirnoff free(sk->secret); 7729034852cSGleb Smirnoff } 7734990d495SXin LI sk->secret = emalloc(secretsize + 1); 7742b15cb3dSCy Schubert sk->type = (u_short)keytype; 7754990d495SXin LI sk->secretsize = secretsize; 7764990d495SXin LI /* make sure access lists don't leak here! */ 7774990d495SXin LI if (ka != sk->keyacclist) { 7784990d495SXin LI keyacc_all_free(sk->keyacclist); 77968ba7e87SXin LI sk->keyacclist = ka; 7804990d495SXin LI } 7812b15cb3dSCy Schubert #ifndef DISABLE_BUG1243_FIX 7822b15cb3dSCy Schubert memcpy(sk->secret, key, secretsize); 7832b15cb3dSCy Schubert #else 7843311ff84SXin LI /* >MUST< use 'strncpy()' here! See above! */ 7853311ff84SXin LI strncpy((char *)sk->secret, (const char *)key, 7862b15cb3dSCy Schubert secretsize); 7872b15cb3dSCy Schubert #endif 7884990d495SXin LI authcache_flush_id(keyno); 789c0b746e5SOllivier Robert return; 790c0b746e5SOllivier Robert } 791c0b746e5SOllivier Robert 792c0b746e5SOllivier Robert /* 793c0b746e5SOllivier Robert * Need to allocate new structure. Do it. 794c0b746e5SOllivier Robert */ 7954990d495SXin LI secret = emalloc(secretsize + 1); 7962b15cb3dSCy Schubert #ifndef DISABLE_BUG1243_FIX 7972b15cb3dSCy Schubert memcpy(secret, key, secretsize); 7982b15cb3dSCy Schubert #else 7993311ff84SXin LI /* >MUST< use 'strncpy()' here! See above! */ 8003311ff84SXin LI strncpy((char *)secret, (const char *)key, secretsize); 8012b15cb3dSCy Schubert #endif 8024990d495SXin LI allocsymkey(keyno, 0, (u_short)keytype, 0, 8034990d495SXin LI secretsize, secret, ka); 8042b15cb3dSCy Schubert #ifdef DEBUG 805e6bfd18dSCy Schubert if (debug >= 1) { 8062b15cb3dSCy Schubert size_t j; 8072b15cb3dSCy Schubert 8082b15cb3dSCy Schubert printf("auth_setkey: key %d type %d len %d ", (int)keyno, 8092b15cb3dSCy Schubert keytype, (int)secretsize); 8104990d495SXin LI for (j = 0; j < secretsize; j++) { 8112b15cb3dSCy Schubert printf("%02x", secret[j]); 8124990d495SXin LI } 8132b15cb3dSCy Schubert printf("\n"); 8142b15cb3dSCy Schubert } 8152b15cb3dSCy Schubert #endif 816c0b746e5SOllivier Robert } 817c0b746e5SOllivier Robert 818c0b746e5SOllivier Robert 819c0b746e5SOllivier Robert /* 8202b15cb3dSCy Schubert * auth_delkeys - delete non-autokey untrusted keys, and clear all info 8212b15cb3dSCy Schubert * except the trusted bit of non-autokey trusted keys, in 8222b15cb3dSCy Schubert * preparation for rereading the keys file. 823c0b746e5SOllivier Robert */ 824c0b746e5SOllivier Robert void 825c0b746e5SOllivier Robert auth_delkeys(void) 826c0b746e5SOllivier Robert { 8272b15cb3dSCy Schubert symkey * sk; 828c0b746e5SOllivier Robert 8292b15cb3dSCy Schubert ITER_DLIST_BEGIN(key_listhead, sk, llink, symkey) 8302b15cb3dSCy Schubert if (sk->keyid > NTP_MAXKEY) { /* autokey */ 8312b15cb3dSCy Schubert continue; 8322b15cb3dSCy Schubert } 8332b15cb3dSCy Schubert 834c0b746e5SOllivier Robert /* 8359034852cSGleb Smirnoff * Don't lose info as to which keys are trusted. Make 8369034852cSGleb Smirnoff * sure there are no dangling pointers! 837c0b746e5SOllivier Robert */ 8382b15cb3dSCy Schubert if (KEY_TRUSTED & sk->flags) { 8392b15cb3dSCy Schubert if (sk->secret != NULL) { 840e6bfd18dSCy Schubert zero_mem(sk->secret, sk->secretsize); 8412b15cb3dSCy Schubert free(sk->secret); 8429034852cSGleb Smirnoff sk->secret = NULL; /* TALOS-CAN-0054 */ 8432b15cb3dSCy Schubert } 8444990d495SXin LI sk->keyacclist = keyacc_all_free(sk->keyacclist); 8452b15cb3dSCy Schubert sk->secretsize = 0; 846c0b746e5SOllivier Robert sk->lifetime = 0; 847c0b746e5SOllivier Robert } else { 8484990d495SXin LI freesymkey(sk); 849c0b746e5SOllivier Robert } 8502b15cb3dSCy Schubert ITER_DLIST_END() 851c0b746e5SOllivier Robert } 8522b15cb3dSCy Schubert 853c0b746e5SOllivier Robert 854c0b746e5SOllivier Robert /* 855c0b746e5SOllivier Robert * auth_agekeys - delete keys whose lifetimes have expired 856c0b746e5SOllivier Robert */ 857c0b746e5SOllivier Robert void 858c0b746e5SOllivier Robert auth_agekeys(void) 859c0b746e5SOllivier Robert { 8602b15cb3dSCy Schubert symkey * sk; 861c0b746e5SOllivier Robert 8622b15cb3dSCy Schubert ITER_DLIST_BEGIN(key_listhead, sk, llink, symkey) 8632b15cb3dSCy Schubert if (sk->lifetime > 0 && current_time > sk->lifetime) { 8644990d495SXin LI freesymkey(sk); 865c0b746e5SOllivier Robert authkeyexpired++; 866c0b746e5SOllivier Robert } 8672b15cb3dSCy Schubert ITER_DLIST_END() 8682b15cb3dSCy Schubert DPRINTF(1, ("auth_agekeys: at %lu keys %lu expired %lu\n", 8692b15cb3dSCy Schubert current_time, authnumkeys, authkeyexpired)); 870c0b746e5SOllivier Robert } 8712b15cb3dSCy Schubert 872c0b746e5SOllivier Robert 873c0b746e5SOllivier Robert /* 874c0b746e5SOllivier Robert * authencrypt - generate message authenticator 875c0b746e5SOllivier Robert * 876c0b746e5SOllivier Robert * Returns length of authenticator field, zero if key not found. 877c0b746e5SOllivier Robert */ 8783311ff84SXin LI size_t 879c0b746e5SOllivier Robert authencrypt( 880224ba2bdSOllivier Robert keyid_t keyno, 881c0b746e5SOllivier Robert u_int32 * pkt, 8823311ff84SXin LI size_t length 883c0b746e5SOllivier Robert ) 8843311ff84SXin LI { 885c0b746e5SOllivier Robert /* 886c0b746e5SOllivier Robert * A zero key identifier means the sender has not verified 887c0b746e5SOllivier Robert * the last message was correctly authenticated. The MAC 888c0b746e5SOllivier Robert * consists of a single word with value zero. 889c0b746e5SOllivier Robert */ 890c0b746e5SOllivier Robert authencryptions++; 891e6bfd18dSCy Schubert pkt[length / KEY_MAC_LEN] = htonl(keyno); 8922b15cb3dSCy Schubert if (0 == keyno) { 893e6bfd18dSCy Schubert return KEY_MAC_LEN; 894c0b746e5SOllivier Robert } 8952b15cb3dSCy Schubert if (!authhavekey(keyno)) { 8962b15cb3dSCy Schubert return 0; 897c0b746e5SOllivier Robert } 898c0b746e5SOllivier Robert 89909100258SXin LI return MD5authencrypt(cache_type, 90009100258SXin LI cache_secret, cache_secretsize, 90109100258SXin LI pkt, length); 9022b15cb3dSCy Schubert } 9032b15cb3dSCy Schubert 9042b15cb3dSCy Schubert 905c0b746e5SOllivier Robert /* 906c0b746e5SOllivier Robert * authdecrypt - verify message authenticator 907c0b746e5SOllivier Robert * 9082b15cb3dSCy Schubert * Returns TRUE if authenticator valid, FALSE if invalid or not found. 909c0b746e5SOllivier Robert */ 910c0b746e5SOllivier Robert int 911c0b746e5SOllivier Robert authdecrypt( 912224ba2bdSOllivier Robert keyid_t keyno, 913c0b746e5SOllivier Robert u_int32 * pkt, 9143311ff84SXin LI size_t length, 9153311ff84SXin LI size_t size 916c0b746e5SOllivier Robert ) 917c0b746e5SOllivier Robert { 918c0b746e5SOllivier Robert /* 919c0b746e5SOllivier Robert * A zero key identifier means the sender has not verified 9202b15cb3dSCy Schubert * the last message was correctly authenticated. For our 9212b15cb3dSCy Schubert * purpose this is an invalid authenticator. 922c0b746e5SOllivier Robert */ 923c0b746e5SOllivier Robert authdecryptions++; 9242b15cb3dSCy Schubert if (0 == keyno || !authhavekey(keyno) || size < 4) { 9252b15cb3dSCy Schubert return FALSE; 9262b15cb3dSCy Schubert } 927c0b746e5SOllivier Robert 92809100258SXin LI return MD5authdecrypt(cache_type, 92909100258SXin LI cache_secret, cache_secretsize, 930a466cc55SCy Schubert pkt, length, size, keyno); 931a466cc55SCy Schubert } 932a466cc55SCy Schubert 933*f5f40dd6SCy Schubert 934a466cc55SCy Schubert /* password decoding helpers */ 935a466cc55SCy Schubert static size_t 936a466cc55SCy Schubert pwdecode_plain( 937a466cc55SCy Schubert u_char * dst, 938a466cc55SCy Schubert size_t dstlen, 939a466cc55SCy Schubert const char * src 940a466cc55SCy Schubert ) 941a466cc55SCy Schubert { 942a466cc55SCy Schubert size_t srclen = strlen(src); 943a466cc55SCy Schubert if (srclen > dstlen) { 944a466cc55SCy Schubert errno = ENOMEM; 945a466cc55SCy Schubert return (size_t)-1; 946a466cc55SCy Schubert } 947a466cc55SCy Schubert memcpy(dst, src, srclen); 948a466cc55SCy Schubert return srclen; 949a466cc55SCy Schubert } 950a466cc55SCy Schubert 951a466cc55SCy Schubert static size_t 952a466cc55SCy Schubert pwdecode_hex( 953a466cc55SCy Schubert u_char * dst, 954a466cc55SCy Schubert size_t dstlen, 955a466cc55SCy Schubert const char * src 956a466cc55SCy Schubert ) 957a466cc55SCy Schubert { 958a466cc55SCy Schubert static const char hex[] = "00112233445566778899AaBbCcDdEeFf"; 959a466cc55SCy Schubert 960a466cc55SCy Schubert size_t srclen = strlen(src); 961a466cc55SCy Schubert size_t reslen = (srclen >> 1) + (srclen & 1); 962a466cc55SCy Schubert u_char tmp; 963a466cc55SCy Schubert char *ptr; 964a466cc55SCy Schubert size_t j; 965a466cc55SCy Schubert 966a466cc55SCy Schubert if (reslen > dstlen) { 967a466cc55SCy Schubert errno = ENOMEM; 968a466cc55SCy Schubert reslen = (size_t)-1; 969a466cc55SCy Schubert } else { 970a466cc55SCy Schubert for (j = 0; j < srclen; ++j) { 971a466cc55SCy Schubert tmp = *(const unsigned char*)(src + j); 972a466cc55SCy Schubert ptr = strchr(hex, tmp); 973a466cc55SCy Schubert if (ptr == NULL) { 974a466cc55SCy Schubert errno = EINVAL; 975a466cc55SCy Schubert reslen = (size_t)-1; 976a466cc55SCy Schubert break; 977a466cc55SCy Schubert } 978e6bfd18dSCy Schubert tmp = (u_char)((ptr - hex) >> 1); 979a466cc55SCy Schubert if (j & 1) 980a466cc55SCy Schubert dst[j >> 1] |= tmp; 981a466cc55SCy Schubert else 982a466cc55SCy Schubert dst[j >> 1] = tmp << 4; 983a466cc55SCy Schubert } 984a466cc55SCy Schubert } 985a466cc55SCy Schubert return reslen; 986a466cc55SCy Schubert } 987a466cc55SCy Schubert /* 988a466cc55SCy Schubert * authdecodepw - decode plaintext or hex-encoded password to binary 989a466cc55SCy Schubert * secret. Returns size of secret in bytes or -1 on error. 990a466cc55SCy Schubert */ 991a466cc55SCy Schubert size_t 992a466cc55SCy Schubert authdecodepw( 993a466cc55SCy Schubert u_char * dst, 994a466cc55SCy Schubert size_t dstlen, 995a466cc55SCy Schubert const char * src, 996a466cc55SCy Schubert enum AuthPwdEnc enc 997a466cc55SCy Schubert ) 998a466cc55SCy Schubert { 999a466cc55SCy Schubert size_t reslen; 1000a466cc55SCy Schubert 1001a466cc55SCy Schubert if ( !(dst && dstlen && src)) { 1002a466cc55SCy Schubert errno = EINVAL; 1003a466cc55SCy Schubert reslen = (size_t)-1; 1004a466cc55SCy Schubert } else { 1005a466cc55SCy Schubert switch (enc) { 1006a466cc55SCy Schubert case AUTHPWD_UNSPEC: 1007a466cc55SCy Schubert if (strlen(src) <= 20) 1008a466cc55SCy Schubert reslen = pwdecode_plain(dst, dstlen, src); 1009a466cc55SCy Schubert else 1010a466cc55SCy Schubert reslen = pwdecode_hex(dst, dstlen, src); 1011a466cc55SCy Schubert break; 1012a466cc55SCy Schubert case AUTHPWD_PLAIN: 1013a466cc55SCy Schubert reslen = pwdecode_plain(dst, dstlen, src); 1014a466cc55SCy Schubert break; 1015a466cc55SCy Schubert case AUTHPWD_HEX: 1016a466cc55SCy Schubert reslen = pwdecode_hex(dst, dstlen, src); 1017a466cc55SCy Schubert break; 1018a466cc55SCy Schubert default: 1019a466cc55SCy Schubert errno = EINVAL; 1020a466cc55SCy Schubert reslen = (size_t)-1; 1021a466cc55SCy Schubert } 1022a466cc55SCy Schubert } 1023a466cc55SCy Schubert return reslen; 1024c0b746e5SOllivier Robert } 1025