Sync usage with man page.
[netbsd-mini2440.git] / dist / ntp / libntp / authkeys.c
blob3f8c5e717ae6f021950e99c79a9493c433e75a86
1 /* $NetBSD$ */
3 /*
4 * authkeys.c - routines to manage the storage of authentication keys
5 */
7 #ifdef HAVE_CONFIG_H
8 # include <config.h>
9 #endif
11 #include <stdio.h>
13 #include "ntp_types.h"
14 #include "ntp_fp.h"
15 #include "ntp.h"
16 #include "ntpd.h"
17 #include "ntp_string.h"
18 #include "ntp_malloc.h"
19 #include "ntp_stdlib.h"
22 * Structure to store keys in in the hash table.
24 struct savekey {
25 struct savekey *next;
26 union {
27 long bogon; /* Make sure nonempty */
28 u_char MD5_key[32]; /* MD5 key */
29 } k;
30 keyid_t keyid; /* key identifier */
31 u_short flags; /* flags that wave */
32 u_long lifetime; /* remaining lifetime */
33 int keylen; /* key length */
36 #define KEY_TRUSTED 0x001 /* this key is trusted */
37 #define KEY_MD5 0x200 /* this is a MD5 type key */
40 * The hash table. This is indexed by the low order bits of the
41 * keyid. We make this fairly big for potentially busy servers.
43 #define HASHSIZE 64
44 #define HASHMASK ((HASHSIZE)-1)
45 #define KEYHASH(keyid) ((keyid) & HASHMASK)
47 struct savekey *key_hash[HASHSIZE];
49 u_long authkeynotfound; /* keys not found */
50 u_long authkeylookups; /* calls to lookup keys */
51 u_long authnumkeys; /* number of active keys */
52 u_long authkeyexpired; /* key lifetime expirations */
53 u_long authkeyuncached; /* cache misses */
54 u_long authnokey; /* calls to encrypt with no key */
55 u_long authencryptions; /* calls to encrypt */
56 u_long authdecryptions; /* calls to decrypt */
59 * Storage for free key structures. We malloc() such things but
60 * never free them.
62 struct savekey *authfreekeys;
63 int authnumfreekeys;
65 #define MEMINC 12 /* number of new free ones to get */
68 * The key cache. We cache the last key we looked at here.
70 keyid_t cache_keyid; /* key identifier */
71 u_char *cache_key; /* key pointer */
72 u_int cache_keylen; /* key length */
73 u_short cache_flags; /* flags that wave */
77 * init_auth - initialize internal data
79 void
80 init_auth(void)
83 * Initialize hash table and free list
85 memset((char *)key_hash, 0, sizeof key_hash);
90 * auth_findkey - find a key in the hash table
92 struct savekey *
93 auth_findkey(
94 keyid_t keyno
97 struct savekey *sk;
99 sk = key_hash[KEYHASH(keyno)];
100 while (sk != 0) {
101 if (keyno == sk->keyid)
102 return (sk);
104 sk = sk->next;
106 return (0);
111 * auth_havekey - return one if the key is known
114 auth_havekey(
115 keyid_t keyno
118 struct savekey *sk;
120 if (keyno == 0 || (keyno == cache_keyid))
121 return (1);
123 sk = key_hash[KEYHASH(keyno)];
124 while (sk != 0) {
125 if (keyno == sk->keyid)
126 return (1);
128 sk = sk->next;
130 return (0);
135 * authhavekey - return one and cache the key, if known and trusted.
138 authhavekey(
139 keyid_t keyno
142 struct savekey *sk;
144 authkeylookups++;
145 if (keyno == 0 || keyno == cache_keyid)
146 return (1);
148 authkeyuncached++;
149 sk = key_hash[KEYHASH(keyno)];
150 while (sk != 0) {
151 if (keyno == sk->keyid)
152 break;
153 sk = sk->next;
155 if (sk == 0) {
156 authkeynotfound++;
157 return (0);
158 } else if (!(sk->flags & KEY_TRUSTED)) {
159 authnokey++;
160 return (0);
162 cache_keyid = sk->keyid;
163 cache_flags = sk->flags;
164 if (sk->flags & KEY_MD5) {
165 cache_key = sk->k.MD5_key;
166 cache_keylen = sk->keylen;
167 return (1);
169 return (0);
174 * auth_moremem - get some more free key structures
177 auth_moremem(void)
179 struct savekey *sk;
180 int i;
182 sk = (struct savekey *)calloc(MEMINC, sizeof(struct savekey));
183 if (sk == 0)
184 return (0);
186 for (i = MEMINC; i > 0; i--) {
187 sk->next = authfreekeys;
188 authfreekeys = sk++;
190 authnumfreekeys += MEMINC;
191 return (authnumfreekeys);
196 * authtrust - declare a key to be trusted/untrusted
198 void
199 authtrust(
200 keyid_t keyno,
201 u_long trust
204 struct savekey *sk;
206 #ifdef DEBUG
207 if (debug > 2)
208 printf("authtrust: keyid %08x life %lu\n", keyno, trust);
209 #endif
210 sk = key_hash[KEYHASH(keyno)];
211 while (sk != 0) {
212 if (keyno == sk->keyid)
213 break;
214 sk = sk->next;
217 if (sk == 0 && !trust)
218 return;
220 if (sk != 0) {
221 if (cache_keyid == keyno) {
222 cache_flags = 0;
223 cache_keyid = 0;
226 if (trust > 0) {
227 sk->flags |= KEY_TRUSTED;
228 if (trust > 1)
229 sk->lifetime = current_time + trust;
230 else
231 sk->lifetime = 0;
232 return;
235 sk->flags &= ~KEY_TRUSTED; {
236 struct savekey *skp;
238 skp = key_hash[KEYHASH(keyno)];
239 if (skp == sk) {
240 key_hash[KEYHASH(keyno)] = sk->next;
241 } else {
242 while (skp->next != sk)
243 skp = skp->next;
244 skp->next = sk->next;
246 authnumkeys--;
248 sk->next = authfreekeys;
249 authfreekeys = sk;
250 authnumfreekeys++;
252 return;
255 if (authnumfreekeys == 0)
256 if (auth_moremem() == 0)
257 return;
259 sk = authfreekeys;
260 authfreekeys = sk->next;
261 authnumfreekeys--;
263 sk->keyid = keyno;
264 sk->flags = KEY_TRUSTED;
265 sk->next = key_hash[KEYHASH(keyno)];
266 key_hash[KEYHASH(keyno)] = sk;
267 authnumkeys++;
268 return;
273 * authistrusted - determine whether a key is trusted
276 authistrusted(
277 keyid_t keyno
280 struct savekey *sk;
282 if (keyno == cache_keyid)
283 return ((cache_flags & KEY_TRUSTED) != 0);
285 authkeyuncached++;
286 sk = key_hash[KEYHASH(keyno)];
287 while (sk != 0) {
288 if (keyno == sk->keyid)
289 break;
290 sk = sk->next;
292 if (sk == 0) {
293 authkeynotfound++;
294 return (0);
295 } else if (!(sk->flags & KEY_TRUSTED)) {
296 authkeynotfound++;
297 return (0);
299 return (1);
303 void
304 MD5auth_setkey(
305 keyid_t keyno,
306 const u_char *key,
307 const int len
310 struct savekey *sk;
313 * See if we already have the key. If so just stick in the
314 * new value.
316 sk = key_hash[KEYHASH(keyno)];
317 while (sk != 0) {
318 if (keyno == sk->keyid) {
319 strncpy((char *)sk->k.MD5_key, (const char *)key,
320 sizeof(sk->k.MD5_key));
321 if ((sk->keylen = len) > sizeof(sk->k.MD5_key))
322 sk->keylen = sizeof(sk->k.MD5_key);
324 sk->flags |= KEY_MD5;
325 if (cache_keyid == keyno) {
326 cache_flags = 0;
327 cache_keyid = 0;
329 return;
331 sk = sk->next;
335 * Need to allocate new structure. Do it.
337 if (authnumfreekeys == 0) {
338 if (auth_moremem() == 0)
339 return;
342 sk = authfreekeys;
343 authfreekeys = sk->next;
344 authnumfreekeys--;
346 strncpy((char *)sk->k.MD5_key, (const char *)key,
347 sizeof(sk->k.MD5_key));
348 if ((sk->keylen = len) > sizeof(sk->k.MD5_key))
349 sk->keylen = sizeof(sk->k.MD5_key);
351 sk->keyid = keyno;
352 sk->flags = KEY_MD5;
353 sk->lifetime = 0;
354 sk->next = key_hash[KEYHASH(keyno)];
355 key_hash[KEYHASH(keyno)] = sk;
356 authnumkeys++;
357 return;
361 * auth_delkeys - delete all known keys, in preparation for rereading
362 * the keys file (presumably)
364 void
365 auth_delkeys(void)
367 struct savekey *sk;
368 struct savekey **skp;
369 int i;
371 for (i = 0; i < HASHSIZE; i++) {
372 skp = &(key_hash[i]);
373 sk = key_hash[i];
375 * Leave autokey keys alone.
377 while (sk != 0 && sk->keyid <= NTP_MAXKEY) {
379 * Don't lose info as to which keys are trusted.
381 if (sk->flags & KEY_TRUSTED) {
382 skp = &(sk->next);
383 memset(&sk->k, 0, sizeof(sk->k));
384 sk->lifetime = 0;
385 sk->keylen = 0;
386 sk = sk->next;
387 } else {
388 *skp = sk->next;
389 authnumkeys--;
390 sk->next = authfreekeys;
391 authfreekeys = sk;
392 authnumfreekeys++;
393 sk = *skp;
400 * auth_agekeys - delete keys whose lifetimes have expired
402 void
403 auth_agekeys(void)
405 struct savekey *sk;
406 struct savekey *skp;
407 int i;
409 for (i = 0; i < HASHSIZE; i++) {
410 sk = skp = key_hash[i];
411 while (sk != 0) {
412 skp = sk->next;
413 if (sk->lifetime > 0 && current_time >
414 sk->lifetime) {
415 authtrust(sk->keyid, 0);
416 authkeyexpired++;
418 sk = skp;
421 #ifdef DEBUG
422 if (debug)
423 printf("auth_agekeys: at %lu keys %lu expired %lu\n",
424 current_time, authnumkeys, authkeyexpired);
425 #endif
429 * authencrypt - generate message authenticator
431 * Returns length of authenticator field, zero if key not found.
434 authencrypt(
435 keyid_t keyno,
436 u_int32 *pkt,
437 int length
442 * A zero key identifier means the sender has not verified
443 * the last message was correctly authenticated. The MAC
444 * consists of a single word with value zero.
446 authencryptions++;
447 pkt[length / 4] = htonl(keyno);
448 if (keyno == 0) {
449 return (4);
451 if (!authhavekey(keyno))
452 return (0);
454 if (cache_flags & KEY_MD5)
455 return (MD5authencrypt(cache_key, pkt, length));
457 return (0);
461 * authdecrypt - verify message authenticator
463 * Returns one if authenticator valid, zero if invalid or key not found.
466 authdecrypt(
467 keyid_t keyno,
468 u_int32 *pkt,
469 int length,
470 int size
475 * A zero key identifier means the sender has not verified
476 * the last message was correctly authenticated. Nevertheless,
477 * the authenticator itself is considered valid.
479 authdecryptions++;
480 if (keyno == 0)
481 return (0);
483 if (!authhavekey(keyno) || size < 4)
484 return (0);
486 if (cache_flags & KEY_MD5)
487 return (MD5authdecrypt(cache_key, pkt, length, size));
489 return (0);