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 */
22 struct 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
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 u_short cache_flags; /* flags that wave */
72
73
74 /*
75 * init_auth - initialize internal data
76 */
77 void
init_auth(void)78 init_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 */
90 struct savekey *
auth_findkey(keyid_t keyno)91 auth_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 */
111 int
auth_havekey(keyid_t keyno)112 auth_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 */
135 int
authhavekey(keyid_t keyno)136 authhavekey(
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 */
174 int
auth_moremem(void)175 auth_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 */
196 void
authtrust(keyid_t keyno,u_long trust)197 authtrust(
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 */
273 int
authistrusted(keyid_t keyno)274 authistrusted(
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
301 void
MD5auth_setkey(keyid_t keyno,const u_char * key,const int len)302 MD5auth_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 */
362 void
auth_delkeys(void)363 auth_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 */
400 void
auth_agekeys(void)401 auth_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 */
431 int
authencrypt(keyid_t keyno,u_int32 * pkt,int length)432 authencrypt(
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 */
463 int
authdecrypt(keyid_t keyno,u_int32 * pkt,int length,int size)464 authdecrypt(
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