1c0b746e5SOllivier Robert /* 2c0b746e5SOllivier Robert * authkeys.c - routines to manage the storage of authentication keys 3c0b746e5SOllivier Robert */ 4c0b746e5SOllivier Robert 5c0b746e5SOllivier Robert #ifdef HAVE_CONFIG_H 6c0b746e5SOllivier Robert # include <config.h> 7c0b746e5SOllivier Robert #endif 8c0b746e5SOllivier Robert 9c0b746e5SOllivier Robert #include <stdio.h> 10c0b746e5SOllivier Robert 11c0b746e5SOllivier Robert #include "ntp_types.h" 12c0b746e5SOllivier Robert #include "ntp_fp.h" 13c0b746e5SOllivier Robert #include "ntp.h" 14c0b746e5SOllivier Robert #include "ntpd.h" 15c0b746e5SOllivier Robert #include "ntp_string.h" 16c0b746e5SOllivier Robert #include "ntp_malloc.h" 17c0b746e5SOllivier Robert #include "ntp_stdlib.h" 18c0b746e5SOllivier Robert 19c0b746e5SOllivier Robert /* 20c0b746e5SOllivier Robert * Structure to store keys in in the hash table. 21c0b746e5SOllivier Robert */ 22c0b746e5SOllivier Robert struct savekey { 23c0b746e5SOllivier Robert struct savekey *next; 24c0b746e5SOllivier Robert union { 25c0b746e5SOllivier Robert long bogon; /* Make sure nonempty */ 26c0b746e5SOllivier Robert #ifdef DES 27c0b746e5SOllivier Robert u_int32 DES_key[2]; /* DES key */ 28c0b746e5SOllivier Robert #endif 29c0b746e5SOllivier Robert u_char MD5_key[32]; /* MD5 key */ 30c0b746e5SOllivier Robert } k; 31224ba2bdSOllivier Robert keyid_t keyid; /* key identifier */ 32c0b746e5SOllivier Robert u_short flags; /* flags that wave */ 33c0b746e5SOllivier Robert u_long lifetime; /* remaining lifetime */ 34c0b746e5SOllivier Robert int keylen; /* key length */ 35c0b746e5SOllivier Robert }; 36c0b746e5SOllivier Robert 37c0b746e5SOllivier Robert #define KEY_TRUSTED 0x001 /* this key is trusted */ 38c0b746e5SOllivier Robert #define KEY_DES 0x100 /* this is a DES type key */ 39c0b746e5SOllivier Robert #define KEY_MD5 0x200 /* this is a MD5 type key */ 40c0b746e5SOllivier Robert 41c0b746e5SOllivier Robert /* 42c0b746e5SOllivier Robert * The hash table. This is indexed by the low order bits of the 43c0b746e5SOllivier Robert * keyid. We make this fairly big for potentially busy servers. 44c0b746e5SOllivier Robert */ 45c0b746e5SOllivier Robert #define HASHSIZE 64 46c0b746e5SOllivier Robert #define HASHMASK ((HASHSIZE)-1) 47c0b746e5SOllivier Robert #define KEYHASH(keyid) ((keyid) & HASHMASK) 48c0b746e5SOllivier Robert 49c0b746e5SOllivier Robert struct savekey *key_hash[HASHSIZE]; 50c0b746e5SOllivier Robert 51c0b746e5SOllivier Robert u_long authkeynotfound; /* keys not found */ 52c0b746e5SOllivier Robert u_long authkeylookups; /* calls to lookup keys */ 53c0b746e5SOllivier Robert u_long authnumkeys; /* number of active keys */ 54c0b746e5SOllivier Robert u_long authkeyexpired; /* key lifetime expirations */ 55c0b746e5SOllivier Robert u_long authkeyuncached; /* cache misses */ 56c0b746e5SOllivier Robert u_long authnokey; /* calls to encrypt with no key */ 57c0b746e5SOllivier Robert u_long authencryptions; /* calls to encrypt */ 58c0b746e5SOllivier Robert u_long authdecryptions; /* calls to decrypt */ 59c0b746e5SOllivier Robert 60c0b746e5SOllivier Robert /* 61c0b746e5SOllivier Robert * Storage for free key structures. We malloc() such things but 62c0b746e5SOllivier Robert * never free them. 63c0b746e5SOllivier Robert */ 64c0b746e5SOllivier Robert struct savekey *authfreekeys; 65c0b746e5SOllivier Robert int authnumfreekeys; 66c0b746e5SOllivier Robert 67c0b746e5SOllivier Robert #define MEMINC 12 /* number of new free ones to get */ 68c0b746e5SOllivier Robert 69c0b746e5SOllivier Robert /* 70c0b746e5SOllivier Robert * The key cache. We cache the last key we looked at here. 71c0b746e5SOllivier Robert */ 72224ba2bdSOllivier Robert keyid_t cache_keyid; /* key identifier */ 73c0b746e5SOllivier Robert u_char *cache_key; /* key pointer */ 74c0b746e5SOllivier Robert u_int cache_keylen; /* key length */ 75c0b746e5SOllivier Robert u_short cache_flags; /* flags that wave */ 76c0b746e5SOllivier Robert 77c0b746e5SOllivier Robert 78c0b746e5SOllivier Robert /* 79c0b746e5SOllivier Robert * init_auth - initialize internal data 80c0b746e5SOllivier Robert */ 81c0b746e5SOllivier Robert void 82c0b746e5SOllivier Robert init_auth(void) 83c0b746e5SOllivier Robert { 84c0b746e5SOllivier Robert /* 85c0b746e5SOllivier Robert * Initialize hash table and free list 86c0b746e5SOllivier Robert */ 87c0b746e5SOllivier Robert memset((char *)key_hash, 0, sizeof key_hash); 88c0b746e5SOllivier Robert } 89c0b746e5SOllivier Robert 90c0b746e5SOllivier Robert 91c0b746e5SOllivier Robert /* 92c0b746e5SOllivier Robert * auth_findkey - find a key in the hash table 93c0b746e5SOllivier Robert */ 94c0b746e5SOllivier Robert struct savekey * 95c0b746e5SOllivier Robert auth_findkey( 96224ba2bdSOllivier Robert keyid_t keyno 97c0b746e5SOllivier Robert ) 98c0b746e5SOllivier Robert { 99c0b746e5SOllivier Robert struct savekey *sk; 100c0b746e5SOllivier Robert 101c0b746e5SOllivier Robert sk = key_hash[KEYHASH(keyno)]; 102c0b746e5SOllivier Robert while (sk != 0) { 103c0b746e5SOllivier Robert if (keyno == sk->keyid) 104c0b746e5SOllivier Robert return (sk); 105c0b746e5SOllivier Robert 106c0b746e5SOllivier Robert sk = sk->next; 107c0b746e5SOllivier Robert } 108c0b746e5SOllivier Robert return (0); 109c0b746e5SOllivier Robert } 110c0b746e5SOllivier Robert 111c0b746e5SOllivier Robert 112c0b746e5SOllivier Robert /* 113c0b746e5SOllivier Robert * auth_havekey - return one if the key is known 114c0b746e5SOllivier Robert */ 115c0b746e5SOllivier Robert int 116c0b746e5SOllivier Robert auth_havekey( 117224ba2bdSOllivier Robert keyid_t keyno 118c0b746e5SOllivier Robert ) 119c0b746e5SOllivier Robert { 120c0b746e5SOllivier Robert struct savekey *sk; 121c0b746e5SOllivier Robert 122c0b746e5SOllivier Robert if (keyno == 0 || (keyno == cache_keyid)) 123c0b746e5SOllivier Robert return (1); 124c0b746e5SOllivier Robert 125c0b746e5SOllivier Robert sk = key_hash[KEYHASH(keyno)]; 126c0b746e5SOllivier Robert while (sk != 0) { 127c0b746e5SOllivier Robert if (keyno == sk->keyid) 128c0b746e5SOllivier Robert return (1); 129c0b746e5SOllivier Robert 130c0b746e5SOllivier Robert sk = sk->next; 131c0b746e5SOllivier Robert } 132c0b746e5SOllivier Robert return (0); 133c0b746e5SOllivier Robert } 134c0b746e5SOllivier Robert 135c0b746e5SOllivier Robert 136c0b746e5SOllivier Robert /* 137c0b746e5SOllivier Robert * authhavekey - return one and cache the key, if known and trusted. 138c0b746e5SOllivier Robert */ 139c0b746e5SOllivier Robert int 140c0b746e5SOllivier Robert authhavekey( 141224ba2bdSOllivier Robert keyid_t keyno 142c0b746e5SOllivier Robert ) 143c0b746e5SOllivier Robert { 144c0b746e5SOllivier Robert struct savekey *sk; 145c0b746e5SOllivier Robert 146c0b746e5SOllivier Robert authkeylookups++; 147c0b746e5SOllivier Robert if (keyno == 0 || keyno == cache_keyid) 148c0b746e5SOllivier Robert return (1); 149c0b746e5SOllivier Robert 150c0b746e5SOllivier Robert authkeyuncached++; 151c0b746e5SOllivier Robert sk = key_hash[KEYHASH(keyno)]; 152c0b746e5SOllivier Robert while (sk != 0) { 153c0b746e5SOllivier Robert if (keyno == sk->keyid) 154c0b746e5SOllivier Robert break; 155c0b746e5SOllivier Robert sk = sk->next; 156c0b746e5SOllivier Robert } 157c0b746e5SOllivier Robert if (sk == 0) { 158c0b746e5SOllivier Robert authkeynotfound++; 159c0b746e5SOllivier Robert return (0); 160c0b746e5SOllivier Robert } else if (!(sk->flags & KEY_TRUSTED)) { 161c0b746e5SOllivier Robert authnokey++; 162c0b746e5SOllivier Robert return (0); 163c0b746e5SOllivier Robert } 164c0b746e5SOllivier Robert cache_keyid = sk->keyid; 165c0b746e5SOllivier Robert cache_flags = sk->flags; 166c0b746e5SOllivier Robert if (sk->flags & KEY_MD5) { 167c0b746e5SOllivier Robert cache_key = sk->k.MD5_key; 168c0b746e5SOllivier Robert cache_keylen = sk->keylen; 169c0b746e5SOllivier Robert return (1); 170c0b746e5SOllivier Robert } 171c0b746e5SOllivier Robert #ifdef DES 172c0b746e5SOllivier Robert if (sk->flags & KEY_DES) { 173c0b746e5SOllivier Robert cache_key = (u_char *)sk->k.DES_key; 174c0b746e5SOllivier Robert return (1); 175c0b746e5SOllivier Robert } 176c0b746e5SOllivier Robert #endif 177c0b746e5SOllivier Robert return (0); 178c0b746e5SOllivier Robert } 179c0b746e5SOllivier Robert 180c0b746e5SOllivier Robert 181c0b746e5SOllivier Robert /* 182c0b746e5SOllivier Robert * auth_moremem - get some more free key structures 183c0b746e5SOllivier Robert */ 184c0b746e5SOllivier Robert int 185c0b746e5SOllivier Robert auth_moremem(void) 186c0b746e5SOllivier Robert { 187c0b746e5SOllivier Robert struct savekey *sk; 188c0b746e5SOllivier Robert int i; 189c0b746e5SOllivier Robert 190a151a66cSOllivier Robert sk = (struct savekey *)calloc(MEMINC, sizeof(struct savekey)); 191c0b746e5SOllivier Robert if (sk == 0) 192c0b746e5SOllivier Robert return (0); 193c0b746e5SOllivier Robert 194c0b746e5SOllivier Robert for (i = MEMINC; i > 0; i--) { 195c0b746e5SOllivier Robert sk->next = authfreekeys; 196c0b746e5SOllivier Robert authfreekeys = sk++; 197c0b746e5SOllivier Robert } 198c0b746e5SOllivier Robert authnumfreekeys += MEMINC; 199c0b746e5SOllivier Robert return (authnumfreekeys); 200c0b746e5SOllivier Robert } 201c0b746e5SOllivier Robert 202c0b746e5SOllivier Robert 203c0b746e5SOllivier Robert /* 204c0b746e5SOllivier Robert * authtrust - declare a key to be trusted/untrusted 205c0b746e5SOllivier Robert */ 206c0b746e5SOllivier Robert void 207c0b746e5SOllivier Robert authtrust( 208224ba2bdSOllivier Robert keyid_t keyno, 209224ba2bdSOllivier Robert u_long trust 210c0b746e5SOllivier Robert ) 211c0b746e5SOllivier Robert { 212c0b746e5SOllivier Robert struct savekey *sk; 213c0b746e5SOllivier Robert 214c0b746e5SOllivier Robert #ifdef DEBUG 215224ba2bdSOllivier Robert if (debug > 2) 216224ba2bdSOllivier Robert printf("authtrust: keyid %08x life %lu\n", keyno, trust); 217c0b746e5SOllivier Robert #endif 218c0b746e5SOllivier Robert sk = key_hash[KEYHASH(keyno)]; 219c0b746e5SOllivier Robert while (sk != 0) { 220c0b746e5SOllivier Robert if (keyno == sk->keyid) 221c0b746e5SOllivier Robert break; 222c0b746e5SOllivier Robert sk = sk->next; 223c0b746e5SOllivier Robert } 224c0b746e5SOllivier Robert 225c0b746e5SOllivier Robert if (sk == 0 && !trust) 226c0b746e5SOllivier Robert return; 227c0b746e5SOllivier Robert 228c0b746e5SOllivier Robert if (sk != 0) { 229c0b746e5SOllivier Robert if (cache_keyid == keyno) { 230c0b746e5SOllivier Robert cache_flags = 0; 231c0b746e5SOllivier Robert cache_keyid = 0; 232c0b746e5SOllivier Robert } 233c0b746e5SOllivier Robert 234c0b746e5SOllivier Robert if (trust > 0) { 235c0b746e5SOllivier Robert sk->flags |= KEY_TRUSTED; 236c0b746e5SOllivier Robert if (trust > 1) 237c0b746e5SOllivier Robert sk->lifetime = current_time + trust; 238c0b746e5SOllivier Robert else 239c0b746e5SOllivier Robert sk->lifetime = 0; 240c0b746e5SOllivier Robert return; 241c0b746e5SOllivier Robert } 242c0b746e5SOllivier Robert 243c0b746e5SOllivier Robert sk->flags &= ~KEY_TRUSTED; { 244c0b746e5SOllivier Robert struct savekey *skp; 245c0b746e5SOllivier Robert 246c0b746e5SOllivier Robert skp = key_hash[KEYHASH(keyno)]; 247c0b746e5SOllivier Robert if (skp == sk) { 248c0b746e5SOllivier Robert key_hash[KEYHASH(keyno)] = sk->next; 249c0b746e5SOllivier Robert } else { 250c0b746e5SOllivier Robert while (skp->next != sk) 251c0b746e5SOllivier Robert skp = skp->next; 252c0b746e5SOllivier Robert skp->next = sk->next; 253c0b746e5SOllivier Robert } 254c0b746e5SOllivier Robert authnumkeys--; 255c0b746e5SOllivier Robert 256c0b746e5SOllivier Robert sk->next = authfreekeys; 257c0b746e5SOllivier Robert authfreekeys = sk; 258c0b746e5SOllivier Robert authnumfreekeys++; 259c0b746e5SOllivier Robert } 260c0b746e5SOllivier Robert return; 261c0b746e5SOllivier Robert } 262c0b746e5SOllivier Robert 263c0b746e5SOllivier Robert if (authnumfreekeys == 0) 264c0b746e5SOllivier Robert if (auth_moremem() == 0) 265c0b746e5SOllivier Robert return; 266c0b746e5SOllivier Robert 267c0b746e5SOllivier Robert sk = authfreekeys; 268c0b746e5SOllivier Robert authfreekeys = sk->next; 269c0b746e5SOllivier Robert authnumfreekeys--; 270c0b746e5SOllivier Robert 271c0b746e5SOllivier Robert sk->keyid = keyno; 272c0b746e5SOllivier Robert sk->flags = KEY_TRUSTED; 273c0b746e5SOllivier Robert sk->next = key_hash[KEYHASH(keyno)]; 274c0b746e5SOllivier Robert key_hash[KEYHASH(keyno)] = sk; 275c0b746e5SOllivier Robert authnumkeys++; 276c0b746e5SOllivier Robert return; 277c0b746e5SOllivier Robert } 278c0b746e5SOllivier Robert 279c0b746e5SOllivier Robert 280c0b746e5SOllivier Robert /* 281c0b746e5SOllivier Robert * authistrusted - determine whether a key is trusted 282c0b746e5SOllivier Robert */ 283c0b746e5SOllivier Robert int 284c0b746e5SOllivier Robert authistrusted( 285224ba2bdSOllivier Robert keyid_t keyno 286c0b746e5SOllivier Robert ) 287c0b746e5SOllivier Robert { 288c0b746e5SOllivier Robert struct savekey *sk; 289c0b746e5SOllivier Robert 290c0b746e5SOllivier Robert if (keyno == cache_keyid) 291c0b746e5SOllivier Robert return ((cache_flags & KEY_TRUSTED) != 0); 292c0b746e5SOllivier Robert 293c0b746e5SOllivier Robert authkeyuncached++; 294c0b746e5SOllivier Robert sk = key_hash[KEYHASH(keyno)]; 295c0b746e5SOllivier Robert while (sk != 0) { 296c0b746e5SOllivier Robert if (keyno == sk->keyid) 297c0b746e5SOllivier Robert break; 298c0b746e5SOllivier Robert sk = sk->next; 299c0b746e5SOllivier Robert } 300c0b746e5SOllivier Robert if (sk == 0) { 301c0b746e5SOllivier Robert authkeynotfound++; 302c0b746e5SOllivier Robert return (0); 303c0b746e5SOllivier Robert } else if (!(sk->flags & KEY_TRUSTED)) { 304c0b746e5SOllivier Robert authkeynotfound++; 305c0b746e5SOllivier Robert return (0); 306c0b746e5SOllivier Robert } 307c0b746e5SOllivier Robert return (1); 308c0b746e5SOllivier Robert } 309c0b746e5SOllivier Robert 310c0b746e5SOllivier Robert 311c0b746e5SOllivier Robert 312c0b746e5SOllivier Robert #ifdef DES 313c0b746e5SOllivier Robert /* 314c0b746e5SOllivier Robert * DESauth_setkey - set a key into the key array 315c0b746e5SOllivier Robert */ 316c0b746e5SOllivier Robert void 317c0b746e5SOllivier Robert DESauth_setkey( 318224ba2bdSOllivier Robert keyid_t keyno, 319c0b746e5SOllivier Robert const u_int32 *key 320c0b746e5SOllivier Robert ) 321c0b746e5SOllivier Robert { 322c0b746e5SOllivier Robert struct savekey *sk; 323c0b746e5SOllivier Robert 324c0b746e5SOllivier Robert /* 325c0b746e5SOllivier Robert * See if we already have the key. If so just stick in the 326c0b746e5SOllivier Robert * new value. 327c0b746e5SOllivier Robert */ 328c0b746e5SOllivier Robert sk = key_hash[KEYHASH(keyno)]; 329c0b746e5SOllivier Robert while (sk != 0) { 330c0b746e5SOllivier Robert if (keyno == sk->keyid) { 331c0b746e5SOllivier Robert sk->k.DES_key[0] = key[0]; 332c0b746e5SOllivier Robert sk->k.DES_key[1] = key[1]; 333c0b746e5SOllivier Robert sk->flags |= KEY_DES; 334c0b746e5SOllivier Robert if (cache_keyid == keyno) 335c0b746e5SOllivier Robert cache_flags = 0; 336c0b746e5SOllivier Robert cache_keyid = 0; 337c0b746e5SOllivier Robert return; 338c0b746e5SOllivier Robert } 339c0b746e5SOllivier Robert sk = sk->next; 340c0b746e5SOllivier Robert } 341c0b746e5SOllivier Robert 342c0b746e5SOllivier Robert /* 343c0b746e5SOllivier Robert * Need to allocate new structure. Do it. 344c0b746e5SOllivier Robert */ 345c0b746e5SOllivier Robert if (authnumfreekeys == 0) { 346c0b746e5SOllivier Robert if (auth_moremem() == 0) 347c0b746e5SOllivier Robert return; 348c0b746e5SOllivier Robert } 349c0b746e5SOllivier Robert sk = authfreekeys; 350c0b746e5SOllivier Robert authfreekeys = sk->next; 351c0b746e5SOllivier Robert authnumfreekeys--; 352c0b746e5SOllivier Robert 353c0b746e5SOllivier Robert sk->k.DES_key[0] = key[0]; 354c0b746e5SOllivier Robert sk->k.DES_key[1] = key[1]; 355c0b746e5SOllivier Robert sk->keyid = keyno; 356c0b746e5SOllivier Robert sk->flags = KEY_DES; 357c0b746e5SOllivier Robert sk->lifetime = 0; 358c0b746e5SOllivier Robert sk->next = key_hash[KEYHASH(keyno)]; 359c0b746e5SOllivier Robert key_hash[KEYHASH(keyno)] = sk; 360c0b746e5SOllivier Robert authnumkeys++; 361c0b746e5SOllivier Robert return; 362c0b746e5SOllivier Robert } 363c0b746e5SOllivier Robert #endif 364c0b746e5SOllivier Robert 365c0b746e5SOllivier Robert void 366c0b746e5SOllivier Robert MD5auth_setkey( 367224ba2bdSOllivier Robert keyid_t keyno, 368c0b746e5SOllivier Robert const u_char *key, 369c0b746e5SOllivier Robert const int len 370c0b746e5SOllivier Robert ) 371c0b746e5SOllivier Robert { 372c0b746e5SOllivier Robert struct savekey *sk; 373c0b746e5SOllivier Robert 374c0b746e5SOllivier Robert /* 375c0b746e5SOllivier Robert * See if we already have the key. If so just stick in the 376c0b746e5SOllivier Robert * new value. 377c0b746e5SOllivier Robert */ 378c0b746e5SOllivier Robert sk = key_hash[KEYHASH(keyno)]; 379c0b746e5SOllivier Robert while (sk != 0) { 380c0b746e5SOllivier Robert if (keyno == sk->keyid) { 381c0b746e5SOllivier Robert strncpy((char *)sk->k.MD5_key, (const char *)key, 382c0b746e5SOllivier Robert sizeof(sk->k.MD5_key)); 383c0b746e5SOllivier Robert if ((sk->keylen = len) > sizeof(sk->k.MD5_key)) 384c0b746e5SOllivier Robert sk->keylen = sizeof(sk->k.MD5_key); 385c0b746e5SOllivier Robert 386c0b746e5SOllivier Robert sk->flags |= KEY_MD5; 387c0b746e5SOllivier Robert if (cache_keyid == keyno) { 388c0b746e5SOllivier Robert cache_flags = 0; 389c0b746e5SOllivier Robert cache_keyid = 0; 390c0b746e5SOllivier Robert } 391c0b746e5SOllivier Robert return; 392c0b746e5SOllivier Robert } 393c0b746e5SOllivier Robert sk = sk->next; 394c0b746e5SOllivier Robert } 395c0b746e5SOllivier Robert 396c0b746e5SOllivier Robert /* 397c0b746e5SOllivier Robert * Need to allocate new structure. Do it. 398c0b746e5SOllivier Robert */ 399c0b746e5SOllivier Robert if (authnumfreekeys == 0) { 400c0b746e5SOllivier Robert if (auth_moremem() == 0) 401c0b746e5SOllivier Robert return; 402c0b746e5SOllivier Robert } 403c0b746e5SOllivier Robert 404c0b746e5SOllivier Robert sk = authfreekeys; 405c0b746e5SOllivier Robert authfreekeys = sk->next; 406c0b746e5SOllivier Robert authnumfreekeys--; 407c0b746e5SOllivier Robert 408c0b746e5SOllivier Robert strncpy((char *)sk->k.MD5_key, (const char *)key, 409c0b746e5SOllivier Robert sizeof(sk->k.MD5_key)); 410c0b746e5SOllivier Robert if ((sk->keylen = len) > sizeof(sk->k.MD5_key)) 411c0b746e5SOllivier Robert sk->keylen = sizeof(sk->k.MD5_key); 412c0b746e5SOllivier Robert 413c0b746e5SOllivier Robert sk->keyid = keyno; 414c0b746e5SOllivier Robert sk->flags = KEY_MD5; 415c0b746e5SOllivier Robert sk->lifetime = 0; 416c0b746e5SOllivier Robert sk->next = key_hash[KEYHASH(keyno)]; 417c0b746e5SOllivier Robert key_hash[KEYHASH(keyno)] = sk; 418c0b746e5SOllivier Robert authnumkeys++; 419c0b746e5SOllivier Robert return; 420c0b746e5SOllivier Robert } 421c0b746e5SOllivier Robert 422c0b746e5SOllivier Robert /* 423c0b746e5SOllivier Robert * auth_delkeys - delete all known keys, in preparation for rereading 424c0b746e5SOllivier Robert * the keys file (presumably) 425c0b746e5SOllivier Robert */ 426c0b746e5SOllivier Robert void 427c0b746e5SOllivier Robert auth_delkeys(void) 428c0b746e5SOllivier Robert { 429c0b746e5SOllivier Robert struct savekey *sk; 430c0b746e5SOllivier Robert struct savekey **skp; 431c0b746e5SOllivier Robert int i; 432c0b746e5SOllivier Robert 433c0b746e5SOllivier Robert for (i = 0; i < HASHSIZE; i++) { 434c0b746e5SOllivier Robert skp = &(key_hash[i]); 435c0b746e5SOllivier Robert sk = key_hash[i]; 436c0b746e5SOllivier Robert /* 437c0b746e5SOllivier Robert * Leave autokey keys alone. 438c0b746e5SOllivier Robert */ 439c0b746e5SOllivier Robert while (sk != 0 && sk->keyid <= NTP_MAXKEY) { 440c0b746e5SOllivier Robert /* 441c0b746e5SOllivier Robert * Don't loose info which keys are trusted. 442c0b746e5SOllivier Robert */ 443c0b746e5SOllivier Robert if (sk->flags & KEY_TRUSTED) { 444c0b746e5SOllivier Robert memset(&sk->k, 0, sizeof(sk->k)); 445c0b746e5SOllivier Robert sk->lifetime = 0; 446c0b746e5SOllivier Robert sk->keylen = 0; 447c0b746e5SOllivier Robert sk = sk->next; 448c0b746e5SOllivier Robert } else { 449c0b746e5SOllivier Robert *skp = sk->next; 450c0b746e5SOllivier Robert authnumkeys--; 451c0b746e5SOllivier Robert sk->next = authfreekeys; 452c0b746e5SOllivier Robert authfreekeys = sk; 453c0b746e5SOllivier Robert authnumfreekeys++; 454c0b746e5SOllivier Robert sk = *skp; 455c0b746e5SOllivier Robert } 456c0b746e5SOllivier Robert } 457c0b746e5SOllivier Robert } 458c0b746e5SOllivier Robert } 459c0b746e5SOllivier Robert 460c0b746e5SOllivier Robert /* 461c0b746e5SOllivier Robert * auth_agekeys - delete keys whose lifetimes have expired 462c0b746e5SOllivier Robert */ 463c0b746e5SOllivier Robert void 464c0b746e5SOllivier Robert auth_agekeys(void) 465c0b746e5SOllivier Robert { 466c0b746e5SOllivier Robert struct savekey *sk; 467c0b746e5SOllivier Robert struct savekey *skp; 468c0b746e5SOllivier Robert int i; 469c0b746e5SOllivier Robert 470c0b746e5SOllivier Robert for (i = 0; i < HASHSIZE; i++) { 471c0b746e5SOllivier Robert sk = skp = key_hash[i]; 472c0b746e5SOllivier Robert while (sk != 0) { 473c0b746e5SOllivier Robert skp = sk->next; 474c0b746e5SOllivier Robert if (sk->lifetime > 0 && current_time > 475c0b746e5SOllivier Robert sk->lifetime) { 476c0b746e5SOllivier Robert authtrust(sk->keyid, 0); 477c0b746e5SOllivier Robert authkeyexpired++; 478c0b746e5SOllivier Robert } 479c0b746e5SOllivier Robert sk = skp; 480c0b746e5SOllivier Robert } 481c0b746e5SOllivier Robert } 482c0b746e5SOllivier Robert #ifdef DEBUG 483c0b746e5SOllivier Robert if (debug) 484c0b746e5SOllivier Robert printf("auth_agekeys: at %lu keys %lu expired %lu\n", 485c0b746e5SOllivier Robert current_time, authnumkeys, authkeyexpired); 486c0b746e5SOllivier Robert #endif 487c0b746e5SOllivier Robert } 488c0b746e5SOllivier Robert 489c0b746e5SOllivier Robert /* 490c0b746e5SOllivier Robert * authencrypt - generate message authenticator 491c0b746e5SOllivier Robert * 492c0b746e5SOllivier Robert * Returns length of authenticator field, zero if key not found. 493c0b746e5SOllivier Robert */ 494c0b746e5SOllivier Robert int 495c0b746e5SOllivier Robert authencrypt( 496224ba2bdSOllivier Robert keyid_t keyno, 497c0b746e5SOllivier Robert u_int32 *pkt, 498c0b746e5SOllivier Robert int length 499c0b746e5SOllivier Robert ) 500c0b746e5SOllivier Robert { 501c0b746e5SOllivier Robert 502c0b746e5SOllivier Robert /* 503c0b746e5SOllivier Robert * A zero key identifier means the sender has not verified 504c0b746e5SOllivier Robert * the last message was correctly authenticated. The MAC 505c0b746e5SOllivier Robert * consists of a single word with value zero. 506c0b746e5SOllivier Robert */ 507c0b746e5SOllivier Robert authencryptions++; 508224ba2bdSOllivier Robert pkt[length / 4] = htonl(keyno); 509c0b746e5SOllivier Robert if (keyno == 0) { 510c0b746e5SOllivier Robert return (4); 511c0b746e5SOllivier Robert } 512c0b746e5SOllivier Robert if (!authhavekey(keyno)) 513c0b746e5SOllivier Robert return (0); 514c0b746e5SOllivier Robert 515c0b746e5SOllivier Robert #ifdef DES 516c0b746e5SOllivier Robert if (cache_flags & KEY_DES) 517c0b746e5SOllivier Robert return (DESauthencrypt(cache_key, pkt, length)); 518c0b746e5SOllivier Robert #endif 519c0b746e5SOllivier Robert 520c0b746e5SOllivier Robert if (cache_flags & KEY_MD5) 521c0b746e5SOllivier Robert return (MD5authencrypt(cache_key, pkt, length)); 522224ba2bdSOllivier Robert 523c0b746e5SOllivier Robert return (0); 524c0b746e5SOllivier Robert } 525c0b746e5SOllivier Robert 526c0b746e5SOllivier Robert /* 527c0b746e5SOllivier Robert * authdecrypt - verify message authenticator 528c0b746e5SOllivier Robert * 529c0b746e5SOllivier Robert * Returns one if authenticator valid, zero if invalid or key not found. 530c0b746e5SOllivier Robert */ 531c0b746e5SOllivier Robert int 532c0b746e5SOllivier Robert authdecrypt( 533224ba2bdSOllivier Robert keyid_t keyno, 534c0b746e5SOllivier Robert u_int32 *pkt, 535c0b746e5SOllivier Robert int length, 536c0b746e5SOllivier Robert int size 537c0b746e5SOllivier Robert ) 538c0b746e5SOllivier Robert { 539c0b746e5SOllivier Robert 540c0b746e5SOllivier Robert /* 541c0b746e5SOllivier Robert * A zero key identifier means the sender has not verified 542c0b746e5SOllivier Robert * the last message was correctly authenticated. Nevertheless, 543c0b746e5SOllivier Robert * the authenticator itself is considered valid. 544c0b746e5SOllivier Robert */ 545c0b746e5SOllivier Robert authdecryptions++; 546c0b746e5SOllivier Robert if (keyno == 0) 547224ba2bdSOllivier Robert return (0); 548c0b746e5SOllivier Robert 549c0b746e5SOllivier Robert if (!authhavekey(keyno) || size < 4) 550c0b746e5SOllivier Robert return (0); 551c0b746e5SOllivier Robert 552c0b746e5SOllivier Robert #ifdef DES 553c0b746e5SOllivier Robert if (cache_flags & KEY_DES) 554c0b746e5SOllivier Robert return (DESauthdecrypt(cache_key, pkt, length, size)); 555c0b746e5SOllivier Robert #endif 556c0b746e5SOllivier Robert 557c0b746e5SOllivier Robert if (cache_flags & KEY_MD5) 558c0b746e5SOllivier Robert return (MD5authdecrypt(cache_key, pkt, length, size)); 559c0b746e5SOllivier Robert 560c0b746e5SOllivier Robert return (0); 561c0b746e5SOllivier Robert } 562