xref: /netbsd-src/external/bsd/ntp/dist/libntp/authkeys.c (revision b1c86f5f087524e68db12794ee9c3e3da1ab17a0)
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