]> CyberLeo.Net >> Repos - FreeBSD/releng/10.3.git/blob - contrib/ntp/libntp/authkeys.c
Fix multiple vulnerabilities in ntp. [SA-18:02.ntp]
[FreeBSD/releng/10.3.git] / contrib / ntp / libntp / authkeys.c
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 <math.h>
9 #include <stdio.h>
10
11 #include "ntp.h"
12 #include "ntp_fp.h"
13 #include "ntpd.h"
14 #include "ntp_lists.h"
15 #include "ntp_string.h"
16 #include "ntp_malloc.h"
17 #include "ntp_stdlib.h"
18 #include "ntp_keyacc.h"
19
20 /*
21  * Structure to store keys in in the hash table.
22  */
23 typedef struct savekey symkey;
24
25 struct savekey {
26         symkey *        hlink;          /* next in hash bucket */
27         DECL_DLIST_LINK(symkey, llink); /* for overall & free lists */
28         u_char *        secret;         /* shared secret */
29         KeyAccT *       keyacclist;     /* Private key access list */
30         u_long          lifetime;       /* remaining lifetime */
31         keyid_t         keyid;          /* key identifier */
32         u_short         type;           /* OpenSSL digest NID */
33         size_t          secretsize;     /* secret octets */
34         u_short         flags;          /* KEY_ flags that wave */
35 };
36
37 /* define the payload region of symkey beyond the list pointers */
38 #define symkey_payload  secret
39
40 #define KEY_TRUSTED     0x001   /* this key is trusted */
41
42 #ifdef DEBUG
43 typedef struct symkey_alloc_tag symkey_alloc;
44
45 struct symkey_alloc_tag {
46         symkey_alloc *  link;
47         void *          mem;            /* enable free() atexit */
48 };
49
50 symkey_alloc *  authallocs;
51 #endif  /* DEBUG */
52
53 static u_short  auth_log2(size_t);
54 static void             auth_resize_hashtable(void);
55 static void             allocsymkey(keyid_t,    u_short,
56                                     u_short, u_long, size_t, u_char *, KeyAccT *);
57 static void             freesymkey(symkey *);
58 #ifdef DEBUG
59 static void             free_auth_mem(void);
60 #endif
61
62 symkey  key_listhead;           /* list of all in-use keys */;
63 /*
64  * The hash table. This is indexed by the low order bits of the
65  * keyid. We make this fairly big for potentially busy servers.
66  */
67 #define DEF_AUTHHASHSIZE        64
68 /*#define       HASHMASK        ((HASHSIZE)-1)*/
69 #define KEYHASH(keyid)  ((keyid) & authhashmask)
70
71 int     authhashdisabled;
72 u_short authhashbuckets = DEF_AUTHHASHSIZE;
73 u_short authhashmask = DEF_AUTHHASHSIZE - 1;
74 symkey **key_hash;
75
76 u_long authkeynotfound;         /* keys not found */
77 u_long authkeylookups;          /* calls to lookup keys */
78 u_long authnumkeys;             /* number of active keys */
79 u_long authkeyexpired;          /* key lifetime expirations */
80 u_long authkeyuncached;         /* cache misses */
81 u_long authnokey;               /* calls to encrypt with no key */
82 u_long authencryptions;         /* calls to encrypt */
83 u_long authdecryptions;         /* calls to decrypt */
84
85 /*
86  * Storage for free symkey structures.  We malloc() such things but
87  * never free them.
88  */
89 symkey *authfreekeys;
90 int authnumfreekeys;
91
92 #define MEMINC  16              /* number of new free ones to get */
93
94 /*
95  * The key cache. We cache the last key we looked at here.
96  * Note: this should hold the last *trusted* key. Also the
97  * cache is only loaded when the digest type / MAC algorithm
98  * is valid.
99  */
100 keyid_t cache_keyid;            /* key identifier */
101 u_char *cache_secret;           /* secret */
102 size_t  cache_secretsize;       /* secret length */
103 int     cache_type;             /* OpenSSL digest NID */
104 u_short cache_flags;            /* flags that wave */
105 KeyAccT *cache_keyacclist;      /* key access list */
106
107 /* --------------------------------------------------------------------
108  * manage key access lists
109  * --------------------------------------------------------------------
110  */
111 /* allocate and populate new access node and pushes it on the list.
112  * Returns the new head.
113  */
114 KeyAccT*
115 keyacc_new_push(
116         KeyAccT          * head,
117         const sockaddr_u * addr,
118         unsigned int       subnetbits
119         )
120 {
121         KeyAccT *       node = emalloc(sizeof(KeyAccT));
122         
123         memcpy(&node->addr, addr, sizeof(sockaddr_u));
124         node->subnetbits = subnetbits;
125         node->next = head;
126
127         return node;
128 }
129
130 /* ----------------------------------------------------------------- */
131 /* pop and deallocate the first node of a list of access nodes, if
132  * the list is not empty. Returns the tail of the list.
133  */
134 KeyAccT*
135 keyacc_pop_free(
136         KeyAccT *head
137         )
138 {
139         KeyAccT *       next = NULL;
140         if (head) {
141                 next = head->next;
142                 free(head);
143         }
144         return next;
145 }
146
147 /* ----------------------------------------------------------------- */
148 /* deallocate the list; returns an empty list. */
149 KeyAccT*
150 keyacc_all_free(
151         KeyAccT * head
152         )
153 {
154         while (head)
155                 head = keyacc_pop_free(head);
156         return head;
157 }
158
159 /* ----------------------------------------------------------------- */
160 /* scan a list to see if it contains a given address. Return the
161  * default result value in case of an empty list.
162  */
163 int /*BOOL*/
164 keyacc_contains(
165         const KeyAccT    *head,
166         const sockaddr_u *addr,
167         int               defv)
168 {
169         if (head) {
170                 do {
171                         if (keyacc_amatch(&head->addr, addr,
172                                           head->subnetbits))
173                                 return TRUE;
174                 } while (NULL != (head = head->next));
175                 return FALSE;
176         } else {
177                 return !!defv;
178         }
179 }
180
181 #if CHAR_BIT != 8
182 # error "don't know how to handle bytes with that bit size"
183 #endif
184
185 /* ----------------------------------------------------------------- */
186 /* check two addresses for a match, taking a prefix length into account
187  * when doing the compare.
188  *
189  * The ISC lib contains a similar function with not entirely specified
190  * semantics, so it seemed somewhat cleaner to do this from scratch.
191  *
192  * Note 1: It *is* assumed that the addresses are stored in network byte
193  * order, that is, most significant byte first!
194  *
195  * Note 2: "no address" compares unequal to all other addresses, even to
196  * itself. This has the same semantics as NaNs have for floats: *any*
197  * relational or equality operation involving a NaN returns FALSE, even
198  * equality with itself. "no address" is either a NULL pointer argument
199  * or an address of type AF_UNSPEC.
200  */
201 int/*BOOL*/
202 keyacc_amatch(
203         const sockaddr_u *      a1,
204         const sockaddr_u *      a2,
205         unsigned int            mbits
206         )
207 {
208         const uint8_t * pm1;
209         const uint8_t * pm2;
210         uint8_t         msk;
211         unsigned int    len;
212
213         /* 1st check: If any address is not an address, it's inequal. */
214         if ( !a1 || (AF_UNSPEC == AF(a1)) ||
215              !a2 || (AF_UNSPEC == AF(a2))  )
216                 return FALSE;
217
218         /* We could check pointers for equality here and shortcut the
219          * other checks if we find object identity. But that use case is
220          * too rare to care for it.
221          */
222         
223         /* 2nd check: Address families must be the same. */
224         if (AF(a1) != AF(a2))
225                 return FALSE;
226
227         /* type check: address family determines buffer & size */
228         switch (AF(a1)) {
229         case AF_INET:
230                 /* IPv4 is easy: clamp size, get byte pointers */
231                 if (mbits > sizeof(NSRCADR(a1)) * 8)
232                         mbits = sizeof(NSRCADR(a1)) * 8;
233                 pm1 = (const void*)&NSRCADR(a1);
234                 pm2 = (const void*)&NSRCADR(a2);
235                 break;
236
237         case AF_INET6:
238                 /* IPv6 is slightly different: Both scopes must match,
239                  * too, before we even consider doing a match!
240                  */
241                 if ( ! SCOPE_EQ(a1, a2))
242                         return FALSE;
243                 if (mbits > sizeof(NSRCADR6(a1)) * 8)
244                         mbits = sizeof(NSRCADR6(a1)) * 8;
245                 pm1 = (const void*)&NSRCADR6(a1);
246                 pm2 = (const void*)&NSRCADR6(a2);
247                 break;
248
249         default:
250                 /* don't know how to compare that!?! */
251                 return FALSE;
252         }
253
254         /* Split bit length into byte length and partial byte mask.
255          * Note that the byte mask extends from the MSB of a byte down,
256          * and that zero shift (--> mbits % 8 == 0) results in an
257          * all-zero mask.
258          */
259         msk = 0xFFu ^ (0xFFu >> (mbits & 7));
260         len = mbits >> 3;
261
262         /* 3rd check: Do memcmp() over full bytes, if any */
263         if (len && memcmp(pm1, pm2, len))
264                 return FALSE;
265
266         /* 4th check: compare last incomplete byte, if any */
267         if (msk && ((pm1[len] ^ pm2[len]) & msk))
268                 return FALSE;
269
270         /* If none of the above failed, we're successfully through. */
271         return TRUE;
272 }
273
274 /*
275  * init_auth - initialize internal data
276  */
277 void
278 init_auth(void)
279 {
280         size_t newalloc;
281
282         /*
283          * Initialize hash table and free list
284          */
285         newalloc = authhashbuckets * sizeof(key_hash[0]);
286
287         key_hash = erealloc(key_hash, newalloc);
288         memset(key_hash, '\0', newalloc);
289
290         INIT_DLIST(key_listhead, llink);
291
292 #ifdef DEBUG
293         atexit(&free_auth_mem);
294 #endif
295 }
296
297
298 /*
299  * free_auth_mem - assist in leak detection by freeing all dynamic
300  *                 allocations from this module.
301  */
302 #ifdef DEBUG
303 static void
304 free_auth_mem(void)
305 {
306         symkey *        sk;
307         symkey_alloc *  alloc;
308         symkey_alloc *  next_alloc;
309
310         while (NULL != (sk = HEAD_DLIST(key_listhead, llink))) {
311                 freesymkey(sk);
312         }
313         free(key_hash);
314         key_hash = NULL;
315         cache_keyid = 0;
316         cache_flags = 0;
317         cache_keyacclist = NULL;
318         for (alloc = authallocs; alloc != NULL; alloc = next_alloc) {
319                 next_alloc = alloc->link;
320                 free(alloc->mem);       
321         }
322         authfreekeys = NULL;
323         authnumfreekeys = 0;
324 }
325 #endif  /* DEBUG */
326
327
328 /*
329  * auth_moremem - get some more free key structures
330  */
331 void
332 auth_moremem(
333         int     keycount
334         )
335 {
336         symkey *        sk;
337         int             i;
338 #ifdef DEBUG
339         void *          base;
340         symkey_alloc *  allocrec;
341 # define MOREMEM_EXTRA_ALLOC    (sizeof(*allocrec))
342 #else
343 # define MOREMEM_EXTRA_ALLOC    (0)
344 #endif
345
346         i = (keycount > 0)
347                 ? keycount
348                 : MEMINC;
349         sk = eallocarrayxz(i, sizeof(*sk), MOREMEM_EXTRA_ALLOC);
350 #ifdef DEBUG
351         base = sk;
352 #endif
353         authnumfreekeys += i;
354
355         for (; i > 0; i--, sk++) {
356                 LINK_SLIST(authfreekeys, sk, llink.f);
357         }
358
359 #ifdef DEBUG
360         allocrec = (void *)sk;
361         allocrec->mem = base;
362         LINK_SLIST(authallocs, allocrec, link);
363 #endif
364 }
365
366
367 /*
368  * auth_prealloc_symkeys
369  */
370 void
371 auth_prealloc_symkeys(
372         int     keycount
373         )
374 {
375         int     allocated;
376         int     additional;
377
378         allocated = authnumkeys + authnumfreekeys;
379         additional = keycount - allocated;
380         if (additional > 0)
381                 auth_moremem(additional);
382         auth_resize_hashtable();
383 }
384
385
386 static u_short
387 auth_log2(size_t x)
388 {
389         /*
390         ** bithack to calculate floor(log2(x))
391         **
392         ** This assumes
393         **   - (sizeof(size_t) is a power of two
394         **   - CHAR_BITS is a power of two
395         **   - returning zero for arguments <= 0 is OK.
396         **
397         ** Does only shifts, masks and sums in integer arithmetic in
398         ** log2(CHAR_BIT*sizeof(size_t)) steps. (that is, 5/6 steps for
399         ** 32bit/64bit size_t)
400         */
401         int     s;
402         int     r = 0;
403         size_t  m = ~(size_t)0;
404
405         for (s = sizeof(size_t) / 2 * CHAR_BIT; s != 0; s >>= 1) {
406                 m <<= s;
407                 if (x & m)
408                         r += s;
409                 else
410                         x <<= s;
411         }
412         return (u_short)r;
413 }
414
415 int/*BOOL*/
416 ipaddr_match_masked(const sockaddr_u *,const sockaddr_u *,
417                     unsigned int mbits);
418
419 static void
420 authcache_flush_id(
421         keyid_t id
422         )
423 {
424         if (cache_keyid == id) {
425                 cache_keyid = 0;
426                 cache_type = 0;
427                 cache_flags = 0;
428                 cache_secret = NULL;
429                 cache_secretsize = 0;
430                 cache_keyacclist = NULL;
431         }
432 }
433
434
435 /*
436  * auth_resize_hashtable
437  *
438  * Size hash table to average 4 or fewer entries per bucket initially,
439  * within the bounds of at least 4 and no more than 15 bits for the hash
440  * table index.  Populate the hash table.
441  */
442 static void
443 auth_resize_hashtable(void)
444 {
445         u_long          totalkeys;
446         u_short         hashbits;
447         u_short         hash;
448         size_t          newalloc;
449         symkey *        sk;
450
451         totalkeys = authnumkeys + authnumfreekeys;
452         hashbits = auth_log2(totalkeys / 4) + 1;
453         hashbits = max(4, hashbits);
454         hashbits = min(15, hashbits);
455
456         authhashbuckets = 1 << hashbits;
457         authhashmask = authhashbuckets - 1;
458         newalloc = authhashbuckets * sizeof(key_hash[0]);
459
460         key_hash = erealloc(key_hash, newalloc);
461         memset(key_hash, '\0', newalloc);
462
463         ITER_DLIST_BEGIN(key_listhead, sk, llink, symkey)
464                 hash = KEYHASH(sk->keyid);
465                 LINK_SLIST(key_hash[hash], sk, hlink);
466         ITER_DLIST_END()
467 }
468
469
470 /*
471  * allocsymkey - common code to allocate and link in symkey
472  *
473  * secret must be allocated with a free-compatible allocator.  It is
474  * owned by the referring symkey structure, and will be free()d by
475  * freesymkey().
476  */
477 static void
478 allocsymkey(
479         keyid_t         id,
480         u_short         flags,
481         u_short         type,
482         u_long          lifetime,
483         size_t          secretsize,
484         u_char *        secret,
485         KeyAccT *       ka
486         )
487 {
488         symkey *        sk;
489         symkey **       bucket;
490
491         bucket = &key_hash[KEYHASH(id)];
492
493
494         if (authnumfreekeys < 1)
495                 auth_moremem(-1);
496         UNLINK_HEAD_SLIST(sk, authfreekeys, llink.f);
497         DEBUG_ENSURE(sk != NULL);
498         sk->keyid = id;
499         sk->flags = flags;
500         sk->type = type;
501         sk->secretsize = secretsize;
502         sk->secret = secret;
503         sk->keyacclist = ka;
504         sk->lifetime = lifetime;
505         LINK_SLIST(*bucket, sk, hlink);
506         LINK_TAIL_DLIST(key_listhead, sk, llink);
507         authnumfreekeys--;
508         authnumkeys++;
509 }
510
511
512 /*
513  * freesymkey - common code to remove a symkey and recycle its entry.
514  */
515 static void
516 freesymkey(
517         symkey *        sk
518         )
519 {
520         symkey **       bucket;
521         symkey *        unlinked;
522
523         if (NULL == sk)
524                 return;
525
526         authcache_flush_id(sk->keyid);
527         keyacc_all_free(sk->keyacclist);
528         
529         bucket = &key_hash[KEYHASH(sk->keyid)];
530         if (sk->secret != NULL) {
531                 memset(sk->secret, '\0', sk->secretsize);
532                 free(sk->secret);
533         }
534         UNLINK_SLIST(unlinked, *bucket, sk, hlink, symkey);
535         DEBUG_ENSURE(sk == unlinked);
536         UNLINK_DLIST(sk, llink);
537         memset((char *)sk + offsetof(symkey, symkey_payload), '\0',
538                sizeof(*sk) - offsetof(symkey, symkey_payload));
539         LINK_SLIST(authfreekeys, sk, llink.f);
540         authnumkeys--;
541         authnumfreekeys++;
542 }
543
544
545 /*
546  * auth_findkey - find a key in the hash table
547  */
548 struct savekey *
549 auth_findkey(
550         keyid_t         id
551         )
552 {
553         symkey *        sk;
554
555         for (sk = key_hash[KEYHASH(id)]; sk != NULL; sk = sk->hlink)
556                 if (id == sk->keyid)
557                         return sk;
558         return NULL;
559 }
560
561
562 /*
563  * auth_havekey - return TRUE if the key id is zero or known. The
564  * key needs not to be trusted.
565  */
566 int
567 auth_havekey(
568         keyid_t         id
569         )
570 {
571         return
572             (0           == id) ||
573             (cache_keyid == id) ||
574             (NULL        != auth_findkey(id));
575 }
576
577
578 /*
579  * authhavekey - return TRUE and cache the key, if zero or both known
580  *               and trusted.
581  */
582 int
583 authhavekey(
584         keyid_t         id
585         )
586 {
587         symkey *        sk;
588
589         authkeylookups++;
590         if (0 == id || cache_keyid == id)
591                 return !!(KEY_TRUSTED & cache_flags);
592
593         /*
594          * Search the bin for the key. If not found, or found but the key
595          * type is zero, somebody marked it trusted without specifying a
596          * key or key type. In this case consider the key missing.
597          */
598         authkeyuncached++;
599         sk = auth_findkey(id);
600         if ((sk == NULL) || (sk->type == 0)) {
601                 authkeynotfound++;
602                 return FALSE;
603         }
604
605         /*
606          * If the key is not trusted, the key is not considered found.
607          */
608         if ( ! (KEY_TRUSTED & sk->flags)) {
609                 authnokey++;
610                 return FALSE;
611         }
612
613         /*
614          * The key is found and trusted. Initialize the key cache.
615          */
616         cache_keyid = sk->keyid;
617         cache_type = sk->type;
618         cache_flags = sk->flags;
619         cache_secret = sk->secret;
620         cache_secretsize = sk->secretsize;
621         cache_keyacclist = sk->keyacclist;
622
623         return TRUE;
624 }
625
626
627 /*
628  * authtrust - declare a key to be trusted/untrusted
629  */
630 void
631 authtrust(
632         keyid_t         id,
633         u_long          trust
634         )
635 {
636         symkey *        sk;
637         u_long          lifetime;
638
639         /*
640          * Search bin for key; if it does not exist and is untrusted,
641          * forget it.
642          */
643
644         sk = auth_findkey(id);
645         if (!trust && sk == NULL)
646                 return;
647
648         /*
649          * There are two conditions remaining. Either it does not
650          * exist and is to be trusted or it does exist and is or is
651          * not to be trusted.
652          */     
653         if (sk != NULL) {
654                 /*
655                  * Key exists. If it is to be trusted, say so and update
656                  * its lifetime. If no longer trusted, return it to the
657                  * free list. Flush the cache first to be sure there are
658                  * no discrepancies.
659                  */
660                 authcache_flush_id(id);
661                 if (trust > 0) {
662                         sk->flags |= KEY_TRUSTED;
663                         if (trust > 1)
664                                 sk->lifetime = current_time + trust;
665                         else
666                                 sk->lifetime = 0;
667                 } else {
668                         freesymkey(sk);
669                 }
670                 return;
671         }
672
673         /*
674          * keyid is not present, but the is to be trusted.  We allocate
675          * a new key, but do not specify a key type or secret.
676          */
677         if (trust > 1) {
678                 lifetime = current_time + trust;
679         } else {
680                 lifetime = 0;
681         }
682         allocsymkey(id, KEY_TRUSTED, 0, lifetime, 0, NULL, NULL);
683 }
684
685
686 /*
687  * authistrusted - determine whether a key is trusted
688  */
689 int
690 authistrusted(
691         keyid_t         id
692         )
693 {
694         symkey *        sk;
695
696         if (id == cache_keyid)
697                 return !!(KEY_TRUSTED & cache_flags);
698
699         authkeyuncached++;
700         sk = auth_findkey(id);
701         if (sk == NULL || !(KEY_TRUSTED & sk->flags)) {
702                 authkeynotfound++;
703                 return FALSE;
704         }
705         return TRUE;
706 }
707
708
709 /*
710  * authistrustedip - determine if the IP is OK for the keyid
711  */
712  int
713  authistrustedip(
714         keyid_t         keyno,
715         sockaddr_u *    sau
716         )
717 {
718         symkey *        sk;
719
720         if (keyno == cache_keyid) {
721                 return (KEY_TRUSTED & cache_flags) &&
722                     keyacc_contains(cache_keyacclist, sau, TRUE);
723         }
724
725         if (NULL != (sk = auth_findkey(keyno))) {
726                 authkeyuncached++;
727                 return (KEY_TRUSTED & sk->flags) &&
728                     keyacc_contains(sk->keyacclist, sau, TRUE);
729         }
730         
731         authkeynotfound++;
732         return FALSE;    
733 }
734
735 /* Note: There are two locations below where 'strncpy()' is used. While
736  * this function is a hazard by itself, it's essential that it is used
737  * here. Bug 1243 involved that the secret was filled with NUL bytes
738  * after the first NUL encountered, and 'strlcpy()' simply does NOT have
739  * this behaviour. So disabling the fix and reverting to the buggy
740  * behaviour due to compatibility issues MUST also fill with NUL and
741  * this needs 'strncpy'. Also, the secret is managed as a byte blob of a
742  * given size, and eventually truncating it and replacing the last byte
743  * with a NUL would be a bug.
744  * perlinger@ntp.org 2015-10-10
745  */
746 void
747 MD5auth_setkey(
748         keyid_t keyno,
749         int     keytype,
750         const u_char *key,
751         size_t secretsize,
752         KeyAccT *ka
753         )
754 {
755         symkey *        sk;
756         u_char *        secret;
757         
758         DEBUG_ENSURE(keytype <= USHRT_MAX);
759         DEBUG_ENSURE(secretsize < 4 * 1024);
760         /*
761          * See if we already have the key.  If so just stick in the
762          * new value.
763          */
764         sk = auth_findkey(keyno);
765         if (sk != NULL && keyno == sk->keyid) {
766                         /* TALOS-CAN-0054: make sure we have a new buffer! */
767                 if (NULL != sk->secret) {
768                         memset(sk->secret, 0, sk->secretsize);
769                         free(sk->secret);
770                 }
771                 sk->secret = emalloc(secretsize + 1);
772                 sk->type = (u_short)keytype;
773                 sk->secretsize = secretsize;
774                 /* make sure access lists don't leak here! */
775                 if (ka != sk->keyacclist) {
776                         keyacc_all_free(sk->keyacclist);
777                         sk->keyacclist = ka;
778                 }
779 #ifndef DISABLE_BUG1243_FIX
780                 memcpy(sk->secret, key, secretsize);
781 #else
782                 /* >MUST< use 'strncpy()' here! See above! */
783                 strncpy((char *)sk->secret, (const char *)key,
784                         secretsize);
785 #endif
786                 authcache_flush_id(keyno);
787                 return;
788         }
789
790         /*
791          * Need to allocate new structure.  Do it.
792          */
793         secret = emalloc(secretsize + 1);
794 #ifndef DISABLE_BUG1243_FIX
795         memcpy(secret, key, secretsize);
796 #else
797         /* >MUST< use 'strncpy()' here! See above! */
798         strncpy((char *)secret, (const char *)key, secretsize);
799 #endif
800         allocsymkey(keyno, 0, (u_short)keytype, 0,
801                     secretsize, secret, ka);
802 #ifdef DEBUG
803         if (debug >= 4) {
804                 size_t  j;
805
806                 printf("auth_setkey: key %d type %d len %d ", (int)keyno,
807                     keytype, (int)secretsize);
808                 for (j = 0; j < secretsize; j++) {
809                         printf("%02x", secret[j]);
810                 }
811                 printf("\n");
812         }       
813 #endif
814 }
815
816
817 /*
818  * auth_delkeys - delete non-autokey untrusted keys, and clear all info
819  *                except the trusted bit of non-autokey trusted keys, in
820  *                preparation for rereading the keys file.
821  */
822 void
823 auth_delkeys(void)
824 {
825         symkey *        sk;
826
827         ITER_DLIST_BEGIN(key_listhead, sk, llink, symkey)
828                 if (sk->keyid > NTP_MAXKEY) {   /* autokey */
829                         continue;
830                 }
831
832                 /*
833                  * Don't lose info as to which keys are trusted. Make
834                  * sure there are no dangling pointers!
835                  */
836                 if (KEY_TRUSTED & sk->flags) {
837                         if (sk->secret != NULL) {
838                                 memset(sk->secret, 0, sk->secretsize);
839                                 free(sk->secret);
840                                 sk->secret = NULL; /* TALOS-CAN-0054 */
841                         }
842                         sk->keyacclist = keyacc_all_free(sk->keyacclist);
843                         sk->secretsize = 0;
844                         sk->lifetime = 0;
845                 } else {
846                         freesymkey(sk);
847                 }
848         ITER_DLIST_END()
849 }
850
851
852 /*
853  * auth_agekeys - delete keys whose lifetimes have expired
854  */
855 void
856 auth_agekeys(void)
857 {
858         symkey *        sk;
859
860         ITER_DLIST_BEGIN(key_listhead, sk, llink, symkey)
861                 if (sk->lifetime > 0 && current_time > sk->lifetime) {
862                         freesymkey(sk);
863                         authkeyexpired++;
864                 }
865         ITER_DLIST_END()
866         DPRINTF(1, ("auth_agekeys: at %lu keys %lu expired %lu\n",
867                     current_time, authnumkeys, authkeyexpired));
868 }
869
870
871 /*
872  * authencrypt - generate message authenticator
873  *
874  * Returns length of authenticator field, zero if key not found.
875  */
876 size_t
877 authencrypt(
878         keyid_t         keyno,
879         u_int32 *       pkt,
880         size_t          length
881         )
882 {
883         /*
884          * A zero key identifier means the sender has not verified
885          * the last message was correctly authenticated. The MAC
886          * consists of a single word with value zero.
887          */
888         authencryptions++;
889         pkt[length / 4] = htonl(keyno);
890         if (0 == keyno) {
891                 return 4;
892         }
893         if (!authhavekey(keyno)) {
894                 return 0;
895         }
896
897         return MD5authencrypt(cache_type,
898                               cache_secret, cache_secretsize,
899                               pkt, length);
900 }
901
902
903 /*
904  * authdecrypt - verify message authenticator
905  *
906  * Returns TRUE if authenticator valid, FALSE if invalid or not found.
907  */
908 int
909 authdecrypt(
910         keyid_t         keyno,
911         u_int32 *       pkt,
912         size_t          length,
913         size_t          size
914         )
915 {
916         /*
917          * A zero key identifier means the sender has not verified
918          * the last message was correctly authenticated.  For our
919          * purpose this is an invalid authenticator.
920          */
921         authdecryptions++;
922         if (0 == keyno || !authhavekey(keyno) || size < 4) {
923                 return FALSE;
924         }
925
926         return MD5authdecrypt(cache_type,
927                               cache_secret, cache_secretsize,
928                               pkt, length, size);
929 }