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