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