1 /*****************************************************************
3 ** @(#) dki.c (c) Jan 2005 Holger Zuleger hznet.de
5 ** A library for managing BIND dnssec key files.
7 ** Copyright (c) Jan 2005, Holger Zuleger HZnet. All rights reserved.
9 ** This software is open source.
11 ** Redistribution and use in source and binary forms, with or without
12 ** modification, are permitted provided that the following conditions
15 ** Redistributions of source code must retain the above copyright notice,
16 ** this list of conditions and the following disclaimer.
18 ** Redistributions in binary form must reproduce the above copyright notice,
19 ** this list of conditions and the following disclaimer in the documentation
20 ** and/or other materials provided with the distribution.
22 ** Neither the name of Holger Zuleger HZnet nor the names of its contributors may
23 ** be used to endorse or promote products derived from this software without
24 ** specific prior written permission.
26 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 ** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 ** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
30 ** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 ** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 ** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 ** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 ** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 ** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 ** POSSIBILITY OF SUCH DAMAGE.
39 *****************************************************************/
43 # include <ctype.h> /* tolower(), ... */
44 # include <unistd.h> /* link(), unlink(), ... */
46 # include <sys/types.h>
47 # include <sys/time.h>
48 # include <sys/stat.h>
54 # include "config_zkt.h"
56 # include "domaincmp.h"
63 /*****************************************************************
64 ** private (static) function declaration and definition
65 *****************************************************************/
66 static char dki_estr[255+1];
68 static dki_t *dki_alloc ()
71 dki_t *dkp = malloc (sizeof (dki_t));
73 if ( (dkp = malloc (sizeof (dki_t))) )
75 memset (dkp, 0, sizeof (dki_t));
79 snprintf (dki_estr, sizeof (dki_estr),
80 "dki_alloc: Out of memory");
84 static int dki_readfile (FILE *fp, dki_t *dkp)
86 int algo, flags, type;
91 char val[14+1]; /* e.g. "YYYYMMDDhhmmss" | "60d" */
96 while ( (c = getc (fp)) == ';' ) /* line start with comment ? */
98 tag[0] = val[0] = '\0';
99 if ( (c = getc (fp)) == '%' ) /* special comment? */
101 while ( (c = getc (fp)) == ' ' || c == '\t' )
104 /* then try to read in the creation, expire and lifetime */
105 if ( fscanf (fp, "%25[a-zA-Z]=%14s", tag, val) == 2 )
107 dbg_val2 ("dki_readfile: tag=%s val=%s \n", tag, val);
108 switch ( tolower (tag[0]) )
110 case 'g': dkp->gentime = timestr2time (val); break;
111 case 'e': dkp->exptime = timestr2time (val); break;
112 case 'l': dkp->lifetime = atoi (val) * DAYSEC; break;
118 while ( (c = getc (fp)) != EOF && c != '\n' ) /* eat up rest of the line */
121 ungetc (c, fp); /* push back last char */
123 if ( fscanf (fp, "%4095s", buf) != 1 ) /* read label */
126 if ( strcmp (buf, dkp->name) != 0 )
129 #if defined(TTL_IN_KEYFILE_ALLOWED) && TTL_IN_KEYFILE_ALLOWED
130 /* skip optional TTL value */
131 while ( (c = getc (fp)) != EOF && isspace (c) ) /* skip spaces */
133 if ( isdigit (c) ) /* skip ttl */
136 ungetc (c, fp); /* oops, no ttl */
139 if ( (c = fscanf (fp, " IN DNSKEY %d %d %d", &flags, &type, &algo)) != 3 &&
140 (c = fscanf (fp, "KEY %d %d %d", &flags, &type, &algo)) != 3 )
142 if ( type != 3 || algo != dkp->algo )
143 return -4; /* no DNSKEY or algorithm mismatch */
144 if ( ((flags >> 8) & 0xFF) != 01 )
145 return -5; /* no ZONE key */
148 if ( fgets (buf, sizeof buf, fp) == NULL || buf[0] == '\0' )
150 p = buf + strlen (buf);
151 *--p = '\0'; /* delete trailing \n */
152 /* delete leading ws */
153 for ( p = buf; *p && isspace (*p); p++ )
156 dkp->pubkey = strdup (p);
161 static int dki_writeinfo (const dki_t *dkp, const char *path)
165 assert (dkp != NULL);
166 assert (path != NULL && path[0] != '\0');
168 if ( (fp = fopen (path, "w")) == NULL )
170 dbg_val1 ("dki_writeinfo %s\n", path);
171 if ( dki_prt_dnskey_raw (dkp, fp) == 0 )
174 touch (path, dkp->time); /* restore time of key file */
179 static int dki_setstat (dki_t *dkp, int status, int preserve_time);
181 /*****************************************************************
182 ** public function definition
183 *****************************************************************/
185 /*****************************************************************
187 *****************************************************************/
188 void dki_free (dki_t *dkp)
190 assert (dkp != NULL);
197 /*****************************************************************
199 *****************************************************************/
200 void dki_freelist (dki_t **listp)
205 assert (listp != NULL);
218 #if defined(USE_TREE) && USE_TREE
219 /*****************************************************************
221 *****************************************************************/
222 void dki_tfree (dki_t **tree)
224 assert (tree != NULL);
225 // TODO: tdestroy is a GNU extension
226 // tdestroy (*tree, dki_free);
230 /*****************************************************************
232 ** create new keyfile
233 ** allocate memory for new dki key and init with keyfile
234 *****************************************************************/
235 dki_t *dki_new (const char *dir, const char *name, int ksk, int algo, int bitsize, const char *rfile, int lf_days)
239 char randfile[254+1];
250 if ( rfile && *rfile )
251 snprintf (randfile, sizeof (randfile), "-r %.250s ", rfile);
253 if ( algo == DK_ALGO_RSA || algo == DK_ALGO_RSASHA1 )
257 snprintf (cmdline, sizeof (cmdline), "cd %s ; %s %s%s-n ZONE -a %s -b %d %s %s",
258 dir, KEYGENCMD, randfile, expflag, dki_algo2str(algo), bitsize, flag, name);
260 snprintf (cmdline, sizeof (cmdline), "%s %s%s-n ZONE -a %s -b %d %s %s",
261 KEYGENCMD, randfile, expflag, dki_algo2str(algo), bitsize, flag, name);
265 if ( (fp = popen (cmdline, "r")) == NULL || fgets (fname, sizeof fname, fp) == NULL )
269 len = strlen (fname) - 1;
270 if ( len >= 0 && fname[len] == '\n' )
273 new = dki_read (dir, fname);
275 dki_setlifetime (new, lf_days); /* sets gentime + proposed lifetime */
280 /*****************************************************************
282 ** read key from file 'filename' (independed of the extension)
283 *****************************************************************/
284 dki_t *dki_read (const char *dirname, const char *filename)
291 char fname[MAX_FNAMESIZE+1];
292 char path[MAX_PATHSIZE+1];
295 if ( (dkp = dki_alloc ()) == NULL )
298 len = sizeof (fname) - 1;
300 strncpy (fname, filename, len);
302 len = strlen (fname); /* delete extension */
303 if ( len > 4 && strcmp (&fname[len - 4], DKI_KEY_FILEEXT) == 0 )
304 fname[len - 4] = '\0';
305 else if ( len > 10 && strcmp (&fname[len - 10], DKI_PUB_FILEEXT) == 0 )
306 fname[len - 10] = '\0';
307 else if ( len > 8 && strcmp (&fname[len - 8], DKI_ACT_FILEEXT) == 0 )
308 fname[len - 8] = '\0';
309 else if ( len > 12 && strcmp (&fname[len - 12], DKI_DEP_FILEEXT) == 0 )
310 fname[len - 12] = '\0';
313 assert (strlen (dirname)+1 < sizeof (dkp->dname));
314 strcpy (dkp->dname, dirname);
316 assert (strlen (fname)+1 < sizeof (dkp->fname));
317 strcpy (dkp->fname, fname);
319 if ( sscanf (fname, "K%254[^+]+%hd+%d", dkp->name, &dkp->algo, &dkp->tag) != 3 )
321 snprintf (dki_estr, sizeof (dki_estr),
322 "dki_read: Filename don't match expected format (%s)", fname);
326 pathname (path, sizeof (path), dkp->dname, dkp->fname, DKI_KEY_FILEEXT);
327 dbg_val ("dki_read: path \"%s\"\n", path);
328 if ( (fp = fopen (path, "r")) == NULL )
330 snprintf (dki_estr, sizeof (dki_estr),
331 "dki_read: Can\'t open file \"%s\" for reading", path);
336 if ( (err = dki_readfile (fp, dkp)) != 0 )
339 snprintf (dki_estr, sizeof (dki_estr),
340 "dki_read: Can\'t read key from file %s (errno %d)", path, err);
346 if ( fstat (fileno(fp), &st) )
348 snprintf (dki_estr, sizeof (dki_estr),
349 "dki_read: Can\'t stat file %s", fname);
352 dkp->time = st.st_mtime;
355 pathname (path, sizeof (path), dkp->dname, dkp->fname, DKI_ACT_FILEEXT);
356 if ( fileexist (path) )
358 if ( dki_isrevoked (dkp) )
359 dkp->status = DKI_REV;
361 dkp->status = DKI_ACT;
365 pathname (path, sizeof (path), dkp->dname, dkp->fname, DKI_PUB_FILEEXT);
366 if ( fileexist (path) )
367 dkp->status = DKI_PUB;
370 pathname (path, sizeof (path), dkp->dname, dkp->fname, DKI_DEP_FILEEXT);
371 if ( fileexist (path) )
372 dkp->status = DKI_DEP;
374 dkp->status = DKI_SEP;
385 /*****************************************************************
387 ** read key files from directory 'dir' and, if recursive is
388 ** true, from all directorys below that.
389 *****************************************************************/
390 int dki_readdir (const char *dir, dki_t **listp, int recursive)
394 struct dirent *dentp;
395 char path[MAX_PATHSIZE+1];
397 dbg_val ("directory: opendir(%s)\n", dir);
398 if ( (dirp = opendir (dir)) == NULL )
401 while ( (dentp = readdir (dirp)) != NULL )
403 if ( is_dotfile (dentp->d_name) )
406 dbg_val ("directory: check %s\n", dentp->d_name);
407 pathname (path, sizeof (path), dir, dentp->d_name, NULL);
408 if ( is_directory (path) && recursive )
410 dbg_val ("directory: recursive %s\n", path);
411 dki_readdir (path, listp, recursive);
413 else if ( is_keyfilename (dentp->d_name) )
414 if ( (dkp = dki_read (dir, dentp->d_name)) )
415 dki_add (listp, dkp);
421 /*****************************************************************
422 ** dki_setstatus_preservetime ()
423 ** set status of key and change extension to
424 ** ".published", ".private" or ".depreciated"
425 *****************************************************************/
426 int dki_setstatus_preservetime (dki_t *dkp, int status)
428 return dki_setstat (dkp, status, 1);
431 /*****************************************************************
433 ** set status of key and change extension to
434 ** ".published", ".private" or ".depreciated"
435 *****************************************************************/
436 int dki_setstatus (dki_t *dkp, int status)
438 return dki_setstat (dkp, status, 0);
441 /*****************************************************************
443 ** low level function of dki_setstatus and dki_setstatus_preservetime
444 *****************************************************************/
445 static int dki_setstat (dki_t *dkp, int status, int preserve_time)
447 char frompath[MAX_PATHSIZE+1];
448 char topath[MAX_PATHSIZE+1];
455 currtime = time (NULL);
456 status = tolower (status);
457 switch ( dkp->status ) /* look at old status */
466 pathname (frompath, sizeof (frompath), dkp->dname, dkp->fname, DKI_ACT_FILEEXT);
471 pathname (frompath, sizeof (frompath), dkp->dname, dkp->fname, DKI_DEP_FILEEXT);
473 case 'p': /* or 's' */
474 if ( status == 'p' || status == 's' )
476 pathname (frompath, sizeof (frompath), dkp->dname, dkp->fname, DKI_PUB_FILEEXT);
479 /* TODO: set error code */
483 dbg_val ("dki_setstat: \"%s\"\n", frompath);
484 dbg_val ("dki_setstat: to status \"%c\"\n", status);
486 /* a state change could result in different things: */
487 /* 1) write a new keyfile when the REVOKE bit is set or unset */
488 if ( status == 'r' || (status == 'a' && dki_isrevoked (dkp)) )
490 pathname (topath, sizeof (topath), dkp->dname, dkp->fname, DKI_KEY_FILEEXT);
493 dki_setflag (dkp, DK_FLAG_REVOKE); /* set REVOKE bit */
495 dki_unsetflag (dkp, DK_FLAG_REVOKE); /* clear REVOKE bit */
498 dki_writeinfo (dkp, topath); /* ..and write it to the key file */
500 if ( !preserve_time )
501 touch (topath, time (NULL));
507 /* 2) change the filename of the private key in all other cases */
510 totime = file_mtime (frompath); /* get original timestamp */
515 pathname (topath, sizeof (topath), dkp->dname, dkp->fname, DKI_ACT_FILEEXT);
518 pathname (topath, sizeof (topath), dkp->dname, dkp->fname, DKI_DEP_FILEEXT);
520 case 's': /* standby means a "published KSK" */
521 if ( !dki_isksk (dkp) )
526 pathname (topath, sizeof (topath), dkp->dname, dkp->fname, DKI_PUB_FILEEXT);
532 dbg_val ("dki_setstat: to \"%s\"\n", topath);
533 if ( link (frompath, topath) == 0 )
535 dkp->status = status;
537 totime = time (NULL); /* set .key file to current time */
538 pathname (topath, sizeof (topath), dkp->dname, dkp->fname, DKI_KEY_FILEEXT);
539 touch (topath, totime); /* store/restore time of status change */
545 /*****************************************************************
547 ** rename files associated with key, so that the keys are not
548 ** recognized by the zkt tools e.g.
549 ** Kdo.ma.in.+001+12345.key ==> kdo.ma.in.+001+12345.key
550 ** (second one starts with a lower case 'k')
551 *****************************************************************/
552 dki_t *dki_remove (dki_t *dkp)
554 char path[MAX_PATHSIZE+1];
555 char newpath[MAX_PATHSIZE+1];
556 char newfile[MAX_FNAMESIZE+1];
559 static const char *ext[] = {
560 DKI_KEY_FILEEXT, DKI_PUB_FILEEXT,
561 DKI_ACT_FILEEXT, DKI_DEP_FILEEXT,
568 strncpy (newfile, dkp->fname, sizeof (newfile));
569 *newfile = tolower (*newfile);
570 for ( pext = ext; *pext; pext++ )
572 pathname (path, sizeof (path), dkp->dname, dkp->fname, *pext);
573 if ( fileexist (path) )
575 pathname (newpath, sizeof (newpath), dkp->dname, newfile, *pext);
577 dbg_val2 ("dki_remove: %s ==> %s \n", path, newpath);
578 rename (path, newpath);
587 /*****************************************************************
589 ** delete files associated with key and free allocated memory
590 *****************************************************************/
591 dki_t *dki_destroy (dki_t *dkp)
593 char path[MAX_PATHSIZE+1];
596 static const char *ext[] = {
597 DKI_KEY_FILEEXT, DKI_PUB_FILEEXT,
598 DKI_ACT_FILEEXT, DKI_DEP_FILEEXT,
605 for ( pext = ext; *pext; pext++ )
607 pathname (path, sizeof (path), dkp->dname, dkp->fname, *pext);
608 if ( fileexist (path) )
610 dbg_val ("dki_remove: %s \n", path);
620 /*****************************************************************
622 ** return a string describing the key algorithm
623 *****************************************************************/
624 char *dki_algo2str (int algo)
628 case DK_ALGO_RSA: return ("RSAMD5");
629 case DK_ALGO_DH: return ("DH");
630 case DK_ALGO_DSA: return ("DSA");
631 case DK_ALGO_EC: return ("EC");
632 case DK_ALGO_RSASHA1: return ("RSASHA1");
633 case DK_ALGO_NSEC3DSA: return ("NSEC3DSA");
634 case DK_ALGO_NSEC3RSASHA1: return ("NSEC3RSASHA1");
639 /*****************************************************************
641 ** return a short string describing the key algorithm
642 *****************************************************************/
643 char *dki_algo2sstr (int algo)
647 case DK_ALGO_RSA: return ("RSAMD5");
648 case DK_ALGO_DH: return ("DH");
649 case DK_ALGO_DSA: return ("DSA");
650 case DK_ALGO_EC: return ("EC");
651 case DK_ALGO_RSASHA1: return ("RSASHA1");
652 case DK_ALGO_NSEC3DSA: return ("N3DSA");
653 case DK_ALGO_NSEC3RSASHA1: return ("N3RSA1");
658 /*****************************************************************
660 ** return error string
661 *****************************************************************/
662 const char *dki_geterrstr ()
667 /*****************************************************************
669 *****************************************************************/
670 int dki_prt_dnskey (const dki_t *dkp, FILE *fp)
672 return dki_prt_dnskeyttl (dkp, fp, 0);
675 /*****************************************************************
676 ** dki_prt_dnskeyttl ()
677 *****************************************************************/
678 int dki_prt_dnskeyttl (const dki_t *dkp, FILE *fp, int ttl)
686 fprintf (fp, "%s ", dkp->name);
688 fprintf (fp, "%d ", ttl);
689 fprintf (fp, "IN DNSKEY ");
690 fprintf (fp, "%d 3 %d (", dkp->flags, dkp->algo);
691 fprintf (fp, "\n\t\t\t");
692 for ( p = dkp->pubkey; *p ; p++ )
694 fprintf (fp, "\n\t\t\t");
697 fprintf (fp, "\n\t\t");
698 if ( dki_isrevoked (dkp) )
699 fprintf (fp, ") ; key id = %u (original key id = %u)", (dkp->tag + 128) % 65535, dkp->tag);
701 fprintf (fp, ") ; key id = %u", dkp->tag);
707 /*****************************************************************
708 ** dki_prt_dnskey_raw ()
709 *****************************************************************/
710 int dki_prt_dnskey_raw (const dki_t *dkp, FILE *fp)
719 fprintf (fp, ";%%\tgenerationtime=%s\n", time2isostr (dkp->gentime, 's'));
720 if ( (days = dki_lifetimedays (dkp)) )
721 fprintf (fp, ";%%\tlifetime=%dd\n", days);
723 fprintf (fp, ";%%\texpirationtime=%s\n", time2isostr (dkp->exptime, 's'));
725 fprintf (fp, "%s ", dkp->name);
728 fprintf (fp, "%d ", ttl);
730 fprintf (fp, "IN DNSKEY ");
731 fprintf (fp, "%d 3 %d ", dkp->flags, dkp->algo);
732 fprintf (fp, "%s\n", dkp->pubkey);
737 /*****************************************************************
738 ** dki_prt_comment ()
739 *****************************************************************/
740 int dki_prt_comment (const dki_t *dkp, FILE *fp)
747 len += fprintf (fp, "; %s ", dkp->name);
748 len += fprintf (fp, "tag=%u ", dkp->tag);
749 len += fprintf (fp, "algo=%s ", dki_algo2str(dkp->algo));
750 len += fprintf (fp, "generated %s\n", time2str (dkp->time, 's'));
755 /*****************************************************************
756 ** dki_prt_trustedkey ()
757 *****************************************************************/
758 int dki_prt_trustedkey (const dki_t *dkp, FILE *fp)
767 len += fprintf (fp, "\"%s\" ", dkp->name);
768 spaces = 22 - (strlen (dkp->name) + 3);
769 len += fprintf (fp, "%*s", spaces > 0 ? spaces : 0 , " ");
770 len += fprintf (fp, "%d 3 %d ", dkp->flags, dkp->algo);
772 len += fprintf (fp, "\n\t\t\t%7s", " ");
773 len += fprintf (fp, "\"");
774 for ( p = dkp->pubkey; *p ; p++ )
776 len += fprintf (fp, "\n\t\t\t\t");
778 putc (*p, fp), len += 1;
780 if ( dki_isrevoked (dkp) )
781 len += fprintf (fp, "\" ; # key id = %u (original key id = %u)\n\n", (dkp->tag + 128) % 65535, dkp->tag);
783 len += fprintf (fp, "\" ; # key id = %u\n\n", dkp->tag);
788 /*****************************************************************
789 ** dki_cmp () return <0 | 0 | >0
790 *****************************************************************/
791 int dki_cmp (const dki_t *a, const dki_t *b)
796 if ( a == NULL ) return -1;
797 if ( b == NULL ) return 1;
799 /* sort by domain name, */
800 if ( (res = domaincmp (a->name, b->name)) != 0 )
803 /* then by key type, */
804 if ( (res = dki_isksk (b) - dki_isksk (a)) != 0 )
807 /* and last by creation time, */
808 return (ulong)a->time - (ulong)b->time;
811 #if defined(USE_TREE) && USE_TREE
812 /*****************************************************************
813 ** dki_allcmp () return <0 | 0 | >0
814 *****************************************************************/
815 int dki_allcmp (const dki_t *a, const dki_t *b)
820 if ( a == NULL ) return -1;
821 if ( b == NULL ) return 1;
823 // fprintf (stderr, "dki_allcmp %s, %s)\n", a->name, b->name);
824 /* sort by domain name, */
825 if ( (res = domaincmp (a->name, b->name)) != 0 )
828 /* then by key type, */
829 if ( (res = dki_isksk (b) - dki_isksk (a)) != 0 )
833 if ( (res = (ulong)a->time - (ulong)b->time) != 0 )
836 /* and last by tag */
837 return a->tag - b->tag;
840 /*****************************************************************
841 ** dki_namecmp () return <0 | 0 | >0
842 *****************************************************************/
843 int dki_namecmp (const dki_t *a, const dki_t *b)
846 if ( a == NULL ) return -1;
847 if ( b == NULL ) return 1;
849 return domaincmp (a->name, b->name);
851 /*****************************************************************
852 ** dki_tagcmp () return <0 | 0 | >0
853 *****************************************************************/
854 int dki_tagcmp (const dki_t *a, const dki_t *b)
857 if ( a == NULL ) return -1;
858 if ( b == NULL ) return 1;
860 return a->tag - b->tag;
864 /*****************************************************************
866 *****************************************************************/
867 int dki_timecmp (const dki_t *a, const dki_t *b)
870 if ( a == NULL ) return -1;
871 if ( b == NULL ) return 1;
873 return ((ulong)a->time - (ulong)b->time);
876 /*****************************************************************
877 ** dki_time () return the timestamp of the key
878 *****************************************************************/
879 time_t dki_time (const dki_t *dkp)
882 assert (dkp != NULL);
886 /*****************************************************************
887 ** dki_exptime () return the expiration timestamp of the key
888 *****************************************************************/
889 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)
902 assert (dkp != NULL);
903 return (dkp->lifetime);
906 /*****************************************************************
907 ** dki_lifetimedays (dkp) return the lifetime of the key in days!
908 *****************************************************************/
909 ushort dki_lifetimedays (const dki_t *dkp)
912 assert (dkp != NULL);
913 return (dkp->lifetime / DAYSEC);
916 /*****************************************************************
917 ** dki_gentime (dkp) return the generation timestamp of the key
918 *****************************************************************/
919 time_t dki_gentime (const dki_t *dkp)
922 assert (dkp != NULL);
923 return (dkp->gentime > 0L ? dkp->gentime: dkp->time);
926 /*****************************************************************
927 ** dki_setlifetime (dkp, int days)
928 ** set the lifetime in days (and also the gentime if not set)
929 ** return the old lifetime of the key in days!
930 *****************************************************************/
931 ushort dki_setlifetime (dki_t *dkp, int days)
934 char path[MAX_PATHSIZE+1];
937 assert (dkp != NULL);
939 lifetsec = dkp->lifetime; /* old lifetime */
940 dkp->lifetime = days * DAYSEC; /* set new lifetime */
942 dbg_val1 ("dki_setlifetime (%d)\n", days);
943 if ( lifetsec == 0 ) /* initial setup (old lifetime was zero)? */
944 dkp->gentime = dkp->time;
946 pathname (path, sizeof (path), dkp->dname, dkp->fname, DKI_KEY_FILEEXT);
947 dki_writeinfo (dkp, path);
949 return (lifetsec / DAYSEC);
952 /*****************************************************************
953 ** dki_setexptime (dkp, time_t sec)
954 ** set the expiration time of the key in seconds since the epoch
955 ** return the old exptime
956 *****************************************************************/
957 time_t dki_setexptime (dki_t *dkp, time_t sec)
959 char path[MAX_PATHSIZE+1];
963 assert (dkp != NULL);
965 dbg_val1 ("dki_setexptime (%ld)\n", sec);
966 oldexptime = dkp->exptime;
969 pathname (path, sizeof (path), dkp->dname, dkp->fname, DKI_KEY_FILEEXT);
970 dki_writeinfo (dkp, path);
972 #if 0 /* not necessary ? */
973 touch (path, time (NULL));
978 /*****************************************************************
979 ** dki_age () return age of key in seconds since 'curr'
980 *****************************************************************/
981 int dki_age (const dki_t *dkp, time_t curr)
984 assert (dkp != NULL);
985 return ((ulong)curr - (ulong)dkp->time);
988 /*****************************************************************
989 ** dki_getflag () return the flags field of a key
990 *****************************************************************/
991 dk_flag_t dki_getflag (const dki_t *dkp, time_t curr)
997 /*****************************************************************
998 ** dki_setflag () set a flag of a key
999 *****************************************************************/
1000 dk_flag_t dki_setflag (dki_t *dkp, dk_flag_t flag)
1003 return dkp->flags |= (ushort)flag;
1006 /*****************************************************************
1007 ** dki_unsetflag () unset a flag of a key
1008 *****************************************************************/
1009 dk_flag_t dki_unsetflag (dki_t *dkp, dk_flag_t flag)
1012 return dkp->flags &= ~((ushort)flag);
1015 /*****************************************************************
1017 *****************************************************************/
1018 int dki_isksk (const dki_t *dkp)
1021 assert (dkp != NULL);
1022 return (dkp->flags & DK_FLAG_KSK) == DK_FLAG_KSK;
1025 /*****************************************************************
1027 *****************************************************************/
1028 int dki_isrevoked (const dki_t *dkp)
1031 assert (dkp != NULL);
1032 return (dkp->flags & DK_FLAG_REVOKE) == DK_FLAG_REVOKE;
1035 /*****************************************************************
1036 ** dki_isdepreciated ()
1037 *****************************************************************/
1038 int dki_isdepreciated (const dki_t *dkp)
1041 return dki_status (dkp) == DKI_DEPRECIATED;
1044 /*****************************************************************
1046 *****************************************************************/
1047 int dki_isactive (const dki_t *dkp)
1050 return dki_status (dkp) == DKI_ACTIVE;
1053 /*****************************************************************
1054 ** dki_ispublished ()
1055 *****************************************************************/
1056 int dki_ispublished (const dki_t *dkp)
1059 return dki_status (dkp) == DKI_PUBLISHED;
1063 /*****************************************************************
1064 ** dki_status () return key status
1065 *****************************************************************/
1066 dk_status_t dki_status (const dki_t *dkp)
1069 assert (dkp != NULL);
1070 return (dkp->status);
1073 /*****************************************************************
1074 ** dki_statusstr () return key status as string
1075 *****************************************************************/
1076 const char *dki_statusstr (const dki_t *dkp)
1079 assert (dkp != NULL);
1080 switch ( dkp->status )
1082 case DKI_ACT: return "active";
1083 case DKI_PUB: if ( dki_isksk (dkp) )
1087 case DKI_DEP: return "depreciated";
1088 case DKI_REV: return "revoked";
1089 case DKI_SEP: return "sep";
1094 /*****************************************************************
1095 ** dki_add () add a key to the given list
1096 *****************************************************************/
1097 dki_t *dki_add (dki_t **list, dki_t *new)
1108 last = curr = *list;
1109 while ( curr && dki_cmp (curr, new) < 0 )
1115 if ( curr == *list ) /* add node at start of list */
1117 else /* add node at end or between two nodes */
1124 /*****************************************************************
1125 ** dki_search () search a key with the given tag, or the first
1126 ** occurence of a key with the given name
1127 *****************************************************************/
1128 const dki_t *dki_search (const dki_t *list, int tag, const char *name)
1135 while ( curr && (tag != curr->tag ||
1136 (name && *name && strcmp (name, curr->name) != 0)) )
1138 else if ( name && *name )
1139 while ( curr && strcmp (name, curr->name) != 0 )
1147 #if defined(USE_TREE) && USE_TREE
1148 /*****************************************************************
1149 ** dki_tadd () add a key to the given tree
1150 *****************************************************************/
1151 dki_t *dki_tadd (dki_t **tree, dki_t *new)
1156 p = tsearch (new, tree, dki_namecmp);
1158 dbg_val ("dki_tadd: New entry %s added\n", new->name);
1161 dbg_val ("dki_tadd: New key added to %s\n", new->name);
1168 /*****************************************************************
1169 ** dki_tsearch () search a key with the given tag, or the first
1170 ** occurence of a key with the given name
1171 *****************************************************************/
1172 const dki_t *dki_tsearch (const dki_t *tree, int tag, const char *name)
1179 snprintf (search.name, sizeof (search.name), "%s", name);
1180 p = tfind (&search, &tree, dki_namecmp);
1184 return dki_search (*p, tag, name);
1188 /*****************************************************************
1189 ** dki_find () find the n'th ksk or zsk key with given status
1190 *****************************************************************/
1191 const dki_t *dki_find (const dki_t *list, int ksk, int status, int no)
1198 for ( dkp = list; no > 0 && dkp; dkp = dkp->next )
1199 if ( dki_isksk (dkp) == ksk && dki_status (dkp) == status )