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