No empty .Rs/.Re
[netbsd-mini2440.git] / external / bsd / bind / dist / contrib / zkt / dki.c
blob76226998b01ad07dad425ccdfe752810366763c6
1 /* $NetBSD$ */
3 /*****************************************************************
4 **
5 ** @(#) dki.c (c) Jan 2005 Holger Zuleger hznet.de
6 **
7 ** A library for managing BIND dnssec key files.
8 **
9 ** Copyright (c) Jan 2005, Holger Zuleger HZnet. All rights reserved.
11 ** This software is open source.
13 ** Redistribution and use in source and binary forms, with or without
14 ** modification, are permitted provided that the following conditions
15 ** are met:
17 ** Redistributions of source code must retain the above copyright notice,
18 ** this list of conditions and the following disclaimer.
20 ** Redistributions in binary form must reproduce the above copyright notice,
21 ** this list of conditions and the following disclaimer in the documentation
22 ** and/or other materials provided with the distribution.
24 ** Neither the name of Holger Zuleger HZnet nor the names of its contributors may
25 ** be used to endorse or promote products derived from this software without
26 ** specific prior written permission.
28 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
30 ** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
31 ** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
32 ** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
33 ** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34 ** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35 ** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36 ** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37 ** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 ** POSSIBILITY OF SUCH DAMAGE.
41 *****************************************************************/
43 # include <stdio.h>
44 # include <string.h>
45 # include <ctype.h> /* tolower(), ... */
46 # include <unistd.h> /* link(), unlink(), ... */
47 # include <stdlib.h>
48 # include <sys/types.h>
49 # include <sys/time.h>
50 # include <sys/stat.h>
51 # include <dirent.h>
52 # include <assert.h>
53 #ifdef HAVE_CONFIG_H
54 # include <config.h>
55 #endif
56 # include "config_zkt.h"
57 # include "debug.h"
58 # include "domaincmp.h"
59 # include "misc.h"
60 # include "zconf.h"
61 #define extern
62 # include "dki.h"
63 #undef extern
65 /*****************************************************************
66 ** private (static) function declaration and definition
67 *****************************************************************/
68 static char dki_estr[255+1];
70 static dki_t *dki_alloc ()
72 dki_estr[0] = '\0';
73 dki_t *dkp = malloc (sizeof (dki_t));
75 if ( (dkp = malloc (sizeof (dki_t))) )
77 memset (dkp, 0, sizeof (dki_t));
78 return dkp;
81 snprintf (dki_estr, sizeof (dki_estr),
82 "dki_alloc: Out of memory");
83 return NULL;
86 static int dki_readfile (FILE *fp, dki_t *dkp)
88 int algo, flags, type;
89 int c;
90 char *p;
91 char buf[4095+1];
92 char tag[25+1];
93 char val[14+1]; /* e.g. "YYYYMMDDhhmmss" | "60d" */
95 assert (dkp != NULL);
96 assert (fp != NULL);
98 while ( (c = getc (fp)) == ';' ) /* line start with comment ? */
100 tag[0] = val[0] = '\0';
101 if ( (c = getc (fp)) == '%' ) /* special comment? */
103 while ( (c = getc (fp)) == ' ' || c == '\t' )
105 ungetc (c, fp);
106 /* then try to read in the creation, expire and lifetime */
107 if ( fscanf (fp, "%25[a-zA-Z]=%14s", tag, val) == 2 )
109 dbg_val2 ("dki_readfile: tag=%s val=%s \n", tag, val);
110 switch ( tolower (tag[0]) )
112 case 'g': dkp->gentime = timestr2time (val); break;
113 case 'e': dkp->exptime = timestr2time (val); break;
114 case 'l': dkp->lifetime = atoi (val) * DAYSEC; break;
118 else
119 ungetc (c, fp);
120 while ( (c = getc (fp)) != EOF && c != '\n' ) /* eat up rest of the line */
123 ungetc (c, fp); /* push back last char */
125 if ( fscanf (fp, "%4095s", buf) != 1 ) /* read label */
126 return -1;
128 if ( strcmp (buf, dkp->name) != 0 )
129 return -2;
131 #if defined(TTL_IN_KEYFILE_ALLOWED) && TTL_IN_KEYFILE_ALLOWED
132 /* skip optional TTL value */
133 while ( (c = getc (fp)) != EOF && isspace (c) ) /* skip spaces */
135 if ( isdigit (c) ) /* skip ttl */
136 fscanf (fp, "%*d");
137 else
138 ungetc (c, fp); /* oops, no ttl */
139 #endif
141 if ( (c = fscanf (fp, " IN DNSKEY %d %d %d", &flags, &type, &algo)) != 3 &&
142 (c = fscanf (fp, "KEY %d %d %d", &flags, &type, &algo)) != 3 )
143 return -3;
144 if ( type != 3 || algo != dkp->algo )
145 return -4; /* no DNSKEY or algorithm mismatch */
146 if ( ((flags >> 8) & 0xFF) != 01 )
147 return -5; /* no ZONE key */
148 dkp->flags = flags;
150 if ( fgets (buf, sizeof buf, fp) == NULL || buf[0] == '\0' )
151 return -6;
152 p = buf + strlen (buf);
153 *--p = '\0'; /* delete trailing \n */
154 /* delete leading ws */
155 for ( p = buf; *p && isspace (*p); p++ )
158 dkp->pubkey = strdup (p);
160 return 0;
163 static int dki_writeinfo (const dki_t *dkp, const char *path)
165 FILE *fp;
167 assert (dkp != NULL);
168 assert (path != NULL && path[0] != '\0');
170 if ( (fp = fopen (path, "w")) == NULL )
171 return 0;
172 dbg_val1 ("dki_writeinfo %s\n", path);
173 if ( dki_prt_dnskey_raw (dkp, fp) == 0 )
174 return 0;
175 fclose (fp);
176 touch (path, dkp->time); /* restore time of key file */
178 return 1;
181 static int dki_setstat (dki_t *dkp, int status, int preserve_time);
183 /*****************************************************************
184 ** public function definition
185 *****************************************************************/
187 /*****************************************************************
188 ** dki_free ()
189 *****************************************************************/
190 void dki_free (dki_t *dkp)
192 assert (dkp != NULL);
194 if ( dkp->pubkey )
195 free (dkp->pubkey);
196 free (dkp);
199 /*****************************************************************
200 ** dki_freelist ()
201 *****************************************************************/
202 void dki_freelist (dki_t **listp)
204 dki_t *curr;
205 dki_t *next;
207 assert (listp != NULL);
209 curr = *listp;
210 while ( curr )
212 next = curr->next;
213 dki_free (curr);
214 curr = next;
216 if ( *listp )
217 *listp = NULL;
220 #if defined(USE_TREE) && USE_TREE
221 /*****************************************************************
222 ** dki_tfree ()
223 *****************************************************************/
224 void dki_tfree (dki_t **tree)
226 assert (tree != NULL);
227 // TODO: tdestroy is a GNU extension
228 // tdestroy (*tree, dki_free);
230 #endif
232 /*****************************************************************
233 ** dki_new ()
234 ** create new keyfile
235 ** allocate memory for new dki key and init with keyfile
236 *****************************************************************/
237 dki_t *dki_new (const char *dir, const char *name, int ksk, int algo, int bitsize, const char *rfile, int lf_days)
239 char cmdline[511+1];
240 char fname[254+1];
241 char randfile[254+1];
242 FILE *fp;
243 int len;
244 char *flag = "";
245 char *expflag = "";
246 dki_t *new;
248 if ( ksk )
249 flag = "-f KSK";
251 randfile[0] = '\0';
252 if ( rfile && *rfile )
253 snprintf (randfile, sizeof (randfile), "-r %.250s ", rfile);
255 if ( algo == DK_ALGO_RSA || algo == DK_ALGO_RSASHA1 )
256 expflag = "-e ";
258 if ( dir && *dir )
259 snprintf (cmdline, sizeof (cmdline), "cd %s ; %s %s%s-n ZONE -a %s -b %d %s %s",
260 dir, KEYGENCMD, randfile, expflag, dki_algo2str(algo), bitsize, flag, name);
261 else
262 snprintf (cmdline, sizeof (cmdline), "%s %s%s-n ZONE -a %s -b %d %s %s",
263 KEYGENCMD, randfile, expflag, dki_algo2str(algo), bitsize, flag, name);
265 dbg_msg (cmdline);
267 if ( (fp = popen (cmdline, "r")) == NULL || fgets (fname, sizeof fname, fp) == NULL )
268 return NULL;
269 pclose (fp);
271 len = strlen (fname) - 1;
272 if ( len >= 0 && fname[len] == '\n' )
273 fname[len] = '\0';
275 new = dki_read (dir, fname);
276 if ( new )
277 dki_setlifetime (new, lf_days); /* sets gentime + proposed lifetime */
279 return new;
282 /*****************************************************************
283 ** dki_read ()
284 ** read key from file 'filename' (independed of the extension)
285 *****************************************************************/
286 dki_t *dki_read (const char *dirname, const char *filename)
288 dki_t *dkp;
289 FILE *fp;
290 struct stat st;
291 int len;
292 int err;
293 char fname[MAX_FNAMESIZE+1];
294 char path[MAX_PATHSIZE+1];
296 dki_estr[0] = '\0';
297 if ( (dkp = dki_alloc ()) == NULL )
298 return (NULL);
300 len = sizeof (fname) - 1;
301 fname[len] = '\0';
302 strncpy (fname, filename, len);
304 len = strlen (fname); /* delete extension */
305 if ( len > 4 && strcmp (&fname[len - 4], DKI_KEY_FILEEXT) == 0 )
306 fname[len - 4] = '\0';
307 else if ( len > 10 && strcmp (&fname[len - 10], DKI_PUB_FILEEXT) == 0 )
308 fname[len - 10] = '\0';
309 else if ( len > 8 && strcmp (&fname[len - 8], DKI_ACT_FILEEXT) == 0 )
310 fname[len - 8] = '\0';
311 else if ( len > 12 && strcmp (&fname[len - 12], DKI_DEP_FILEEXT) == 0 )
312 fname[len - 12] = '\0';
313 dbg_line ();
315 assert (strlen (dirname)+1 < sizeof (dkp->dname));
316 strcpy (dkp->dname, dirname);
318 assert (strlen (fname)+1 < sizeof (dkp->fname));
319 strcpy (dkp->fname, fname);
320 dbg_line ();
321 if ( sscanf (fname, "K%254[^+]+%hd+%d", dkp->name, &dkp->algo, &dkp->tag) != 3 )
323 snprintf (dki_estr, sizeof (dki_estr),
324 "dki_read: Filename don't match expected format (%s)", fname);
325 return (NULL);
328 pathname (path, sizeof (path), dkp->dname, dkp->fname, DKI_KEY_FILEEXT);
329 dbg_val ("dki_read: path \"%s\"\n", path);
330 if ( (fp = fopen (path, "r")) == NULL )
332 snprintf (dki_estr, sizeof (dki_estr),
333 "dki_read: Can\'t open file \"%s\" for reading", path);
334 return (NULL);
337 dbg_line ();
338 if ( (err = dki_readfile (fp, dkp)) != 0 )
340 dbg_line ();
341 snprintf (dki_estr, sizeof (dki_estr),
342 "dki_read: Can\'t read key from file %s (errno %d)", path, err);
343 fclose (fp);
344 return (NULL);
347 dbg_line ();
348 if ( fstat (fileno(fp), &st) )
350 snprintf (dki_estr, sizeof (dki_estr),
351 "dki_read: Can\'t stat file %s", fname);
352 return (NULL);
354 dkp->time = st.st_mtime;
356 dbg_line ();
357 pathname (path, sizeof (path), dkp->dname, dkp->fname, DKI_ACT_FILEEXT);
358 if ( fileexist (path) )
360 if ( dki_isrevoked (dkp) )
361 dkp->status = DKI_REV;
362 else
363 dkp->status = DKI_ACT;
365 else
367 pathname (path, sizeof (path), dkp->dname, dkp->fname, DKI_PUB_FILEEXT);
368 if ( fileexist (path) )
369 dkp->status = DKI_PUB;
370 else
372 pathname (path, sizeof (path), dkp->dname, dkp->fname, DKI_DEP_FILEEXT);
373 if ( fileexist (path) )
374 dkp->status = DKI_DEP;
375 else
376 dkp->status = DKI_SEP;
380 dbg_line ();
381 fclose (fp);
383 dbg_line ();
384 return dkp;
387 /*****************************************************************
388 ** dki_readdir ()
389 ** read key files from directory 'dir' and, if recursive is
390 ** true, from all directorys below that.
391 *****************************************************************/
392 int dki_readdir (const char *dir, dki_t **listp, int recursive)
394 dki_t *dkp;
395 DIR *dirp;
396 struct dirent *dentp;
397 char path[MAX_PATHSIZE+1];
399 dbg_val ("directory: opendir(%s)\n", dir);
400 if ( (dirp = opendir (dir)) == NULL )
401 return 0;
403 while ( (dentp = readdir (dirp)) != NULL )
405 if ( is_dotfilename (dentp->d_name) )
406 continue;
408 dbg_val ("directory: check %s\n", dentp->d_name);
409 pathname (path, sizeof (path), dir, dentp->d_name, NULL);
410 if ( is_directory (path) && recursive )
412 dbg_val ("directory: recursive %s\n", path);
413 dki_readdir (path, listp, recursive);
415 else if ( is_keyfilename (dentp->d_name) )
416 if ( (dkp = dki_read (dir, dentp->d_name)) )
417 dki_add (listp, dkp);
419 closedir (dirp);
420 return 1;
423 /*****************************************************************
424 ** dki_setstatus_preservetime ()
425 ** set status of key and change extension to
426 ** ".published", ".private" or ".depreciated"
427 *****************************************************************/
428 int dki_setstatus_preservetime (dki_t *dkp, int status)
430 return dki_setstat (dkp, status, 1);
433 /*****************************************************************
434 ** dki_setstatus ()
435 ** set status of key and change extension to
436 ** ".published", ".private" or ".depreciated"
437 *****************************************************************/
438 int dki_setstatus (dki_t *dkp, int status)
440 return dki_setstat (dkp, status, 0);
443 /*****************************************************************
444 ** dki_setstat ()
445 ** low level function of dki_setstatus and dki_setstatus_preservetime
446 *****************************************************************/
447 static int dki_setstat (dki_t *dkp, int status, int preserve_time)
449 char frompath[MAX_PATHSIZE+1];
450 char topath[MAX_PATHSIZE+1];
451 time_t totime;
452 time_t currtime;
454 if ( dkp == NULL )
455 return 0;
457 currtime = time (NULL);
458 status = tolower (status);
459 switch ( dkp->status ) /* look at old status */
461 case 'r':
462 if ( status == 'r' )
463 return 1;
464 break;
465 case 'a':
466 if ( status == 'a' )
467 return 1;
468 pathname (frompath, sizeof (frompath), dkp->dname, dkp->fname, DKI_ACT_FILEEXT);
469 break;
470 case 'd':
471 if ( status == 'd' )
472 return 1;
473 pathname (frompath, sizeof (frompath), dkp->dname, dkp->fname, DKI_DEP_FILEEXT);
474 break;
475 case 'p': /* or 's' */
476 if ( status == 'p' || status == 's' )
477 return 1;
478 pathname (frompath, sizeof (frompath), dkp->dname, dkp->fname, DKI_PUB_FILEEXT);
479 break;
480 default:
481 /* TODO: set error code */
482 return 0;
485 dbg_val ("dki_setstat: \"%s\"\n", frompath);
486 dbg_val ("dki_setstat: to status \"%c\"\n", status);
488 /* a state change could result in different things: */
489 /* 1) write a new keyfile when the REVOKE bit is set or unset */
490 if ( status == 'r' || (status == 'a' && dki_isrevoked (dkp)) )
492 pathname (topath, sizeof (topath), dkp->dname, dkp->fname, DKI_KEY_FILEEXT);
494 if ( status == 'r' )
495 dki_setflag (dkp, DK_FLAG_REVOKE); /* set REVOKE bit */
496 else
497 dki_unsetflag (dkp, DK_FLAG_REVOKE); /* clear REVOKE bit */
500 dki_writeinfo (dkp, topath); /* ..and write it to the key file */
502 if ( !preserve_time )
503 touch (topath, time (NULL));
505 return 0;
509 /* 2) change the filename of the private key in all other cases */
510 totime = 0L;
511 if ( preserve_time )
512 totime = file_mtime (frompath); /* get original timestamp */
513 topath[0] = '\0';
514 switch ( status )
516 case 'a':
517 pathname (topath, sizeof (topath), dkp->dname, dkp->fname, DKI_ACT_FILEEXT);
518 break;
519 case 'd':
520 pathname (topath, sizeof (topath), dkp->dname, dkp->fname, DKI_DEP_FILEEXT);
521 break;
522 case 's': /* standby means a "published KSK" */
523 if ( !dki_isksk (dkp) )
524 return 2;
525 status = 'p';
526 /* fall through */
527 case 'p':
528 pathname (topath, sizeof (topath), dkp->dname, dkp->fname, DKI_PUB_FILEEXT);
529 break;
532 if ( topath[0] )
534 dbg_val ("dki_setstat: to \"%s\"\n", topath);
535 if ( link (frompath, topath) == 0 )
536 unlink (frompath);
537 dkp->status = status;
538 if ( !totime )
539 totime = time (NULL); /* set .key file to current time */
540 pathname (topath, sizeof (topath), dkp->dname, dkp->fname, DKI_KEY_FILEEXT);
541 touch (topath, totime); /* store/restore time of status change */
544 return 0;
547 /*****************************************************************
548 ** dki_remove ()
549 ** rename files associated with key, so that the keys are not
550 ** recognized by the zkt tools e.g.
551 ** Kdo.ma.in.+001+12345.key ==> kdo.ma.in.+001+12345.key
552 ** (second one starts with a lower case 'k')
553 *****************************************************************/
554 dki_t *dki_remove (dki_t *dkp)
556 char path[MAX_PATHSIZE+1];
557 char newpath[MAX_PATHSIZE+1];
558 char newfile[MAX_FNAMESIZE+1];
559 dki_t *next;
560 const char **pext;
561 static const char *ext[] = {
562 DKI_KEY_FILEEXT, DKI_PUB_FILEEXT,
563 DKI_ACT_FILEEXT, DKI_DEP_FILEEXT,
564 NULL
567 if ( dkp == NULL )
568 return NULL;
570 strncpy (newfile, dkp->fname, sizeof (newfile));
571 *newfile = tolower (*newfile);
572 for ( pext = ext; *pext; pext++ )
574 pathname (path, sizeof (path), dkp->dname, dkp->fname, *pext);
575 if ( fileexist (path) )
577 pathname (newpath, sizeof (newpath), dkp->dname, newfile, *pext);
579 dbg_val2 ("dki_remove: %s ==> %s \n", path, newpath);
580 rename (path, newpath);
583 next = dkp->next;
584 dki_free (dkp);
586 return next;
589 /*****************************************************************
590 ** dki_destroy ()
591 ** delete files associated with key and free allocated memory
592 *****************************************************************/
593 dki_t *dki_destroy (dki_t *dkp)
595 char path[MAX_PATHSIZE+1];
596 dki_t *next;
597 const char **pext;
598 static const char *ext[] = {
599 DKI_KEY_FILEEXT, DKI_PUB_FILEEXT,
600 DKI_ACT_FILEEXT, DKI_DEP_FILEEXT,
601 NULL
604 if ( dkp == NULL )
605 return NULL;
607 for ( pext = ext; *pext; pext++ )
609 pathname (path, sizeof (path), dkp->dname, dkp->fname, *pext);
610 if ( fileexist (path) )
612 dbg_val ("dki_remove: %s \n", path);
613 unlink (path);
616 next = dkp->next;
617 dki_free (dkp);
619 return next;
622 /*****************************************************************
623 ** dki_algo2str ()
624 ** return a string describing the key algorithm
625 *****************************************************************/
626 char *dki_algo2str (int algo)
628 switch ( algo )
630 case DK_ALGO_RSA: return ("RSAMD5");
631 case DK_ALGO_DH: return ("DH");
632 case DK_ALGO_DSA: return ("DSA");
633 case DK_ALGO_EC: return ("EC");
634 case DK_ALGO_RSASHA1: return ("RSASHA1");
635 case DK_ALGO_NSEC3DSA: return ("NSEC3DSA");
636 case DK_ALGO_NSEC3RSASHA1: return ("NSEC3RSASHA1");
638 return ("unknown");
641 /*****************************************************************
642 ** dki_algo2sstr ()
643 ** return a short string describing the key algorithm
644 *****************************************************************/
645 char *dki_algo2sstr (int algo)
647 switch ( algo )
649 case DK_ALGO_RSA: return ("RSAMD5");
650 case DK_ALGO_DH: return ("DH");
651 case DK_ALGO_DSA: return ("DSA");
652 case DK_ALGO_EC: return ("EC");
653 case DK_ALGO_RSASHA1: return ("RSASHA1");
654 case DK_ALGO_NSEC3DSA: return ("N3DSA");
655 case DK_ALGO_NSEC3RSASHA1: return ("N3RSA1");
657 return ("unknown");
660 /*****************************************************************
661 ** dki_geterrstr ()
662 ** return error string
663 *****************************************************************/
664 const char *dki_geterrstr ()
666 return dki_estr;
669 /*****************************************************************
670 ** dki_prt_dnskey ()
671 *****************************************************************/
672 int dki_prt_dnskey (const dki_t *dkp, FILE *fp)
674 return dki_prt_dnskeyttl (dkp, fp, 0);
677 /*****************************************************************
678 ** dki_prt_dnskeyttl ()
679 *****************************************************************/
680 int dki_prt_dnskeyttl (const dki_t *dkp, FILE *fp, int ttl)
682 char *p;
684 if ( dkp == NULL )
685 return 0;
687 fprintf (fp, "%s ", dkp->name);
688 if ( ttl > 0 )
689 fprintf (fp, "%d ", ttl);
690 fprintf (fp, "IN DNSKEY ");
691 fprintf (fp, "%d 3 %d (", dkp->flags, dkp->algo);
692 fprintf (fp, "\n\t\t\t");
693 for ( p = dkp->pubkey; *p ; p++ )
694 if ( *p == ' ' )
695 fprintf (fp, "\n\t\t\t");
696 else
697 putc (*p, fp);
698 fprintf (fp, "\n\t\t");
699 if ( dki_isrevoked (dkp) )
700 fprintf (fp, ") ; key id = %u (original key id = %u)", (dkp->tag + 128) % 65535, dkp->tag);
701 else
702 fprintf (fp, ") ; key id = %u", dkp->tag);
703 fprintf (fp, "\n");
705 return 1;
708 /*****************************************************************
709 ** dki_prt_dnskey_raw ()
710 *****************************************************************/
711 int dki_prt_dnskey_raw (const dki_t *dkp, FILE *fp)
713 int days;
715 if ( dkp == NULL )
716 return 0;
718 if ( dkp->gentime )
719 fprintf (fp, ";%%\tgenerationtime=%s\n", time2isostr (dkp->gentime, 's'));
720 if ( (days = dki_lifetimedays (dkp)) )
721 fprintf (fp, ";%%\tlifetime=%dd\n", days);
722 if ( dkp->exptime )
723 fprintf (fp, ";%%\texpirationtime=%s\n", time2isostr (dkp->exptime, 's'));
725 fprintf (fp, "%s ", dkp->name);
726 #if 0
727 if ( ttl > 0 )
728 fprintf (fp, "%d ", ttl);
729 #endif
730 fprintf (fp, "IN DNSKEY ");
731 fprintf (fp, "%d 3 %d ", dkp->flags, dkp->algo);
732 fprintf (fp, "%s\n", dkp->pubkey);
734 return 1;
737 /*****************************************************************
738 ** dki_prt_comment ()
739 *****************************************************************/
740 int dki_prt_comment (const dki_t *dkp, FILE *fp)
742 int len = 0;
744 if ( dkp == NULL )
745 return len;
746 len += fprintf (fp, "; %s ", dkp->name);
747 len += fprintf (fp, "tag=%u ", dkp->tag);
748 len += fprintf (fp, "algo=%s ", dki_algo2str(dkp->algo));
749 len += fprintf (fp, "generated %s\n", time2str (dkp->time, 's'));
751 return len;
754 /*****************************************************************
755 ** dki_prt_trustedkey ()
756 *****************************************************************/
757 int dki_prt_trustedkey (const dki_t *dkp, FILE *fp)
759 char *p;
760 int spaces;
761 int len = 0;
763 if ( dkp == NULL )
764 return len;
765 len += fprintf (fp, "\"%s\" ", dkp->name);
766 spaces = 22 - (strlen (dkp->name) + 3);
767 len += fprintf (fp, "%*s", spaces > 0 ? spaces : 0 , " ");
768 len += fprintf (fp, "%d 3 %d ", dkp->flags, dkp->algo);
769 if ( spaces < 0 )
770 len += fprintf (fp, "\n\t\t\t%7s", " ");
771 len += fprintf (fp, "\"");
772 for ( p = dkp->pubkey; *p ; p++ )
773 if ( *p == ' ' )
774 len += fprintf (fp, "\n\t\t\t\t");
775 else
776 putc (*p, fp), len += 1;
778 if ( dki_isrevoked (dkp) )
779 len += fprintf (fp, "\" ; # key id = %u (original key id = %u)\n\n", (dkp->tag + 128) % 65535, dkp->tag);
780 else
781 len += fprintf (fp, "\" ; # key id = %u\n\n", dkp->tag);
782 return len;
786 /*****************************************************************
787 ** dki_cmp () return <0 | 0 | >0
788 *****************************************************************/
789 int dki_cmp (const dki_t *a, const dki_t *b)
791 int res;
793 if ( a == NULL ) return -1;
794 if ( b == NULL ) return 1;
796 /* sort by domain name, */
797 if ( (res = domaincmp (a->name, b->name)) != 0 )
798 return res;
800 /* then by key type, */
801 if ( (res = dki_isksk (b) - dki_isksk (a)) != 0 )
802 return res;
804 /* and last by creation time, */
805 return (ulong)a->time - (ulong)b->time;
808 #if defined(USE_TREE) && USE_TREE
809 /*****************************************************************
810 ** dki_allcmp () return <0 | 0 | >0
811 *****************************************************************/
812 int dki_allcmp (const dki_t *a, const dki_t *b)
814 int res;
816 if ( a == NULL ) return -1;
817 if ( b == NULL ) return 1;
819 // fprintf (stderr, "dki_allcmp %s, %s)\n", a->name, b->name);
820 /* sort by domain name, */
821 if ( (res = domaincmp (a->name, b->name)) != 0 )
822 return res;
824 /* then by key type, */
825 if ( (res = dki_isksk (b) - dki_isksk (a)) != 0 )
826 return res;
828 /* creation time, */
829 if ( (res = (ulong)a->time - (ulong)b->time) != 0 )
830 return res;
832 /* and last by tag */
833 return a->tag - b->tag;
836 /*****************************************************************
837 ** dki_namecmp () return <0 | 0 | >0
838 *****************************************************************/
839 int dki_namecmp (const dki_t *a, const dki_t *b)
841 if ( a == NULL ) return -1;
842 if ( b == NULL ) return 1;
844 return domaincmp (a->name, b->name);
846 /*****************************************************************
847 ** dki_tagcmp () return <0 | 0 | >0
848 *****************************************************************/
849 int dki_tagcmp (const dki_t *a, const dki_t *b)
851 if ( a == NULL ) return -1;
852 if ( b == NULL ) return 1;
854 return a->tag - b->tag;
856 #endif
858 /*****************************************************************
859 ** dki_timecmp ()
860 *****************************************************************/
861 int dki_timecmp (const dki_t *a, const dki_t *b)
863 if ( a == NULL ) return -1;
864 if ( b == NULL ) return 1;
866 return ((ulong)a->time - (ulong)b->time);
869 /*****************************************************************
870 ** dki_algo () return the algorithm of the key
871 *****************************************************************/
872 time_t dki_algo (const dki_t *dkp)
874 assert (dkp != NULL);
875 return (dkp->algo);
878 /*****************************************************************
879 ** dki_time () return the timestamp of the key
880 *****************************************************************/
881 time_t dki_time (const dki_t *dkp)
883 assert (dkp != NULL);
884 return (dkp->time);
887 /*****************************************************************
888 ** dki_exptime () return the expiration timestamp of the key
889 *****************************************************************/
890 time_t dki_exptime (const dki_t *dkp)
892 assert (dkp != NULL);
893 return (dkp->exptime);
896 /*****************************************************************
897 ** dki_lifetime (dkp) return the lifetime of the key in sec!
898 *****************************************************************/
899 time_t dki_lifetime (const dki_t *dkp)
901 assert (dkp != NULL);
902 return (dkp->lifetime);
905 /*****************************************************************
906 ** dki_lifetimedays (dkp) return the lifetime of the key in days!
907 *****************************************************************/
908 ushort dki_lifetimedays (const dki_t *dkp)
910 assert (dkp != NULL);
911 return (dkp->lifetime / DAYSEC);
914 /*****************************************************************
915 ** dki_gentime (dkp) return the generation timestamp of the key
916 *****************************************************************/
917 time_t dki_gentime (const dki_t *dkp)
919 assert (dkp != NULL);
920 return (dkp->gentime > 0L ? dkp->gentime: dkp->time);
923 /*****************************************************************
924 ** dki_setlifetime (dkp, int days)
925 ** set the lifetime in days (and also the gentime if not set)
926 ** return the old lifetime of the key in days!
927 *****************************************************************/
928 ushort dki_setlifetime (dki_t *dkp, int days)
930 ulong lifetsec;
931 char path[MAX_PATHSIZE+1];
933 assert (dkp != NULL);
935 lifetsec = dkp->lifetime; /* old lifetime */
936 dkp->lifetime = days * DAYSEC; /* set new lifetime */
938 dbg_val1 ("dki_setlifetime (%d)\n", days);
939 if ( lifetsec == 0 ) /* initial setup (old lifetime was zero)? */
940 dkp->gentime = dkp->time;
942 pathname (path, sizeof (path), dkp->dname, dkp->fname, DKI_KEY_FILEEXT);
943 dki_writeinfo (dkp, path);
945 return (lifetsec / DAYSEC);
948 /*****************************************************************
949 ** dki_setexptime (dkp, time_t sec)
950 ** set the expiration time of the key in seconds since the epoch
951 ** return the old exptime
952 *****************************************************************/
953 time_t dki_setexptime (dki_t *dkp, time_t sec)
955 char path[MAX_PATHSIZE+1];
956 time_t oldexptime;
958 assert (dkp != NULL);
960 dbg_val1 ("dki_setexptime (%ld)\n", sec);
961 oldexptime = dkp->exptime;
962 dkp->exptime = sec;
964 pathname (path, sizeof (path), dkp->dname, dkp->fname, DKI_KEY_FILEEXT);
965 dki_writeinfo (dkp, path);
967 #if 0 /* not necessary ? */
968 touch (path, time (NULL));
969 #endif
970 return (oldexptime);
973 /*****************************************************************
974 ** dki_age () return age of key in seconds since 'curr'
975 *****************************************************************/
976 int dki_age (const dki_t *dkp, time_t curr)
978 assert (dkp != NULL);
979 return ((ulong)curr - (ulong)dkp->time);
982 /*****************************************************************
983 ** dki_getflag () return the flags field of a key
984 *****************************************************************/
985 dk_flag_t dki_getflag (const dki_t *dkp, time_t curr)
987 return dkp->flags;
990 /*****************************************************************
991 ** dki_setflag () set a flag of a key
992 *****************************************************************/
993 dk_flag_t dki_setflag (dki_t *dkp, dk_flag_t flag)
995 return dkp->flags |= (ushort)flag;
998 /*****************************************************************
999 ** dki_unsetflag () unset a flag of a key
1000 *****************************************************************/
1001 dk_flag_t dki_unsetflag (dki_t *dkp, dk_flag_t flag)
1003 return dkp->flags &= ~((ushort)flag);
1006 /*****************************************************************
1007 ** dki_isksk ()
1008 *****************************************************************/
1009 int dki_isksk (const dki_t *dkp)
1011 assert (dkp != NULL);
1012 return (dkp->flags & DK_FLAG_KSK) == DK_FLAG_KSK;
1015 /*****************************************************************
1016 ** dki_isrevoked ()
1017 *****************************************************************/
1018 int dki_isrevoked (const dki_t *dkp)
1020 assert (dkp != NULL);
1021 return (dkp->flags & DK_FLAG_REVOKE) == DK_FLAG_REVOKE;
1024 /*****************************************************************
1025 ** dki_isdepreciated ()
1026 *****************************************************************/
1027 int dki_isdepreciated (const dki_t *dkp)
1029 return dki_status (dkp) == DKI_DEPRECIATED;
1032 /*****************************************************************
1033 ** dki_isactive ()
1034 *****************************************************************/
1035 int dki_isactive (const dki_t *dkp)
1037 return dki_status (dkp) == DKI_ACTIVE;
1040 /*****************************************************************
1041 ** dki_ispublished ()
1042 *****************************************************************/
1043 int dki_ispublished (const dki_t *dkp)
1045 return dki_status (dkp) == DKI_PUBLISHED;
1049 /*****************************************************************
1050 ** dki_status () return key status
1051 *****************************************************************/
1052 dk_status_t dki_status (const dki_t *dkp)
1054 assert (dkp != NULL);
1055 return (dkp->status);
1058 /*****************************************************************
1059 ** dki_statusstr () return key status as string
1060 *****************************************************************/
1061 const char *dki_statusstr (const dki_t *dkp)
1063 assert (dkp != NULL);
1064 switch ( dkp->status )
1066 case DKI_ACT: return "active";
1067 case DKI_PUB: if ( dki_isksk (dkp) )
1068 return "standby";
1069 else
1070 return "published";
1071 case DKI_DEP: return "depreciated";
1072 case DKI_REV: return "revoked";
1073 case DKI_SEP: return "sep";
1075 return "unknown";
1078 /*****************************************************************
1079 ** dki_add () add a key to the given list
1080 *****************************************************************/
1081 dki_t *dki_add (dki_t **list, dki_t *new)
1083 dki_t *curr;
1084 dki_t *last;
1086 if ( list == NULL )
1087 return NULL;
1088 if ( new == NULL )
1089 return *list;
1091 last = curr = *list;
1092 while ( curr && dki_cmp (curr, new) < 0 )
1094 last = curr;
1095 curr = curr->next;
1098 if ( curr == *list ) /* add node at start of list */
1099 *list = new;
1100 else /* add node at end or between two nodes */
1101 last->next = new;
1102 new->next = curr;
1104 return *list;
1107 /*****************************************************************
1108 ** dki_search () search a key with the given tag, or the first
1109 ** occurence of a key with the given name
1110 *****************************************************************/
1111 const dki_t *dki_search (const dki_t *list, int tag, const char *name)
1113 const dki_t *curr;
1115 curr = list;
1116 if ( tag )
1117 while ( curr && (tag != curr->tag ||
1118 (name && *name && strcmp (name, curr->name) != 0)) )
1119 curr = curr->next;
1120 else if ( name && *name )
1121 while ( curr && strcmp (name, curr->name) != 0 )
1122 curr = curr->next;
1123 else
1124 curr = NULL;
1126 return curr;
1129 #if defined(USE_TREE) && USE_TREE
1130 /*****************************************************************
1131 ** dki_tadd () add a key to the given tree
1132 *****************************************************************/
1133 dki_t *dki_tadd (dki_t **tree, dki_t *new)
1135 dki_t **p;
1137 p = tsearch (new, tree, dki_namecmp);
1138 if ( *p == new )
1139 dbg_val ("dki_tadd: New entry %s added\n", new->name);
1140 else
1142 dbg_val ("dki_tadd: New key added to %s\n", new->name);
1143 dki_add (p, new);
1146 return *p;
1149 /*****************************************************************
1150 ** dki_tsearch () search a key with the given tag, or the first
1151 ** occurence of a key with the given name
1152 *****************************************************************/
1153 const dki_t *dki_tsearch (const dki_t *tree, int tag, const char *name)
1155 dki_t search;
1156 dki_t **p;
1158 search.tag = tag;
1159 snprintf (search.name, sizeof (search.name), "%s", name);
1160 p = tfind (&search, &tree, dki_namecmp);
1161 if ( p == NULL )
1162 return NULL;
1164 return dki_search (*p, tag, name);
1166 #endif
1168 /*****************************************************************
1169 ** dki_find () find the n'th ksk or zsk key with given status
1170 *****************************************************************/
1171 const dki_t *dki_find (const dki_t *list, int ksk, int status, int no)
1173 const dki_t *dkp;
1174 const dki_t *last;
1176 last = NULL;
1177 for ( dkp = list; no > 0 && dkp; dkp = dkp->next )
1178 if ( dki_isksk (dkp) == ksk && dki_status (dkp) == status )
1180 no--;
1181 last = dkp;
1184 return last;
1187 /*****************************************************************
1188 ** dki_findalgo () find the n'th ksk or zsk key with given
1189 ** algorithm and status
1190 *****************************************************************/
1191 const dki_t *dki_findalgo (const dki_t *list, int ksk, int alg, int status, int no)
1193 const dki_t *dkp;
1194 const dki_t *last;
1196 last = NULL;
1197 for ( dkp = list; no > 0 && dkp; dkp = dkp->next )
1198 if ( dki_isksk (dkp) == ksk && dki_algo (dkp) == alg &&
1199 dki_status (dkp) == status )
1201 no--;
1202 last = dkp;
1205 return last;