3 /*****************************************************************
5 ** @(#) dki.c (c) Jan 2005 Holger Zuleger hznet.de
7 ** A library for managing BIND dnssec key files.
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
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 *****************************************************************/
45 # include <ctype.h> /* tolower(), ... */
46 # include <unistd.h> /* link(), unlink(), ... */
48 # include <sys/types.h>
49 # include <sys/time.h>
50 # include <sys/stat.h>
56 # include "config_zkt.h"
58 # include "domaincmp.h"
65 /*****************************************************************
66 ** private (static) function declaration and definition
67 *****************************************************************/
68 static char dki_estr
[255+1];
70 static dki_t
*dki_alloc ()
73 dki_t
*dkp
= malloc (sizeof (dki_t
));
75 if ( (dkp
= malloc (sizeof (dki_t
))) )
77 memset (dkp
, 0, sizeof (dki_t
));
81 snprintf (dki_estr
, sizeof (dki_estr
),
82 "dki_alloc: Out of memory");
86 static int dki_readfile (FILE *fp
, dki_t
*dkp
)
88 int algo
, flags
, type
;
93 char val
[14+1]; /* e.g. "YYYYMMDDhhmmss" | "60d" */
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' )
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;
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 */
128 if ( strcmp (buf
, dkp
->name
) != 0 )
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 */
138 ungetc (c
, fp
); /* oops, no ttl */
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 )
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 */
150 if ( fgets (buf
, sizeof buf
, fp
) == NULL
|| buf
[0] == '\0' )
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
);
163 static int dki_writeinfo (const dki_t
*dkp
, const char *path
)
167 assert (dkp
!= NULL
);
168 assert (path
!= NULL
&& path
[0] != '\0');
170 if ( (fp
= fopen (path
, "w")) == NULL
)
172 dbg_val1 ("dki_writeinfo %s\n", path
);
173 if ( dki_prt_dnskey_raw (dkp
, fp
) == 0 )
176 touch (path
, dkp
->time
); /* restore time of key file */
181 static int dki_setstat (dki_t
*dkp
, int status
, int preserve_time
);
183 /*****************************************************************
184 ** public function definition
185 *****************************************************************/
187 /*****************************************************************
189 *****************************************************************/
190 void dki_free (dki_t
*dkp
)
192 assert (dkp
!= NULL
);
199 /*****************************************************************
201 *****************************************************************/
202 void dki_freelist (dki_t
**listp
)
207 assert (listp
!= NULL
);
220 #if defined(USE_TREE) && USE_TREE
221 /*****************************************************************
223 *****************************************************************/
224 void dki_tfree (dki_t
**tree
)
226 assert (tree
!= NULL
);
227 // TODO: tdestroy is a GNU extension
228 // tdestroy (*tree, dki_free);
232 /*****************************************************************
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
)
241 char randfile
[254+1];
252 if ( rfile
&& *rfile
)
253 snprintf (randfile
, sizeof (randfile
), "-r %.250s ", rfile
);
255 if ( algo
== DK_ALGO_RSA
|| algo
== DK_ALGO_RSASHA1
)
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
);
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
);
267 if ( (fp
= popen (cmdline
, "r")) == NULL
|| fgets (fname
, sizeof fname
, fp
) == NULL
)
271 len
= strlen (fname
) - 1;
272 if ( len
>= 0 && fname
[len
] == '\n' )
275 new = dki_read (dir
, fname
);
277 dki_setlifetime (new, lf_days
); /* sets gentime + proposed lifetime */
282 /*****************************************************************
284 ** read key from file 'filename' (independed of the extension)
285 *****************************************************************/
286 dki_t
*dki_read (const char *dirname
, const char *filename
)
293 char fname
[MAX_FNAMESIZE
+1];
294 char path
[MAX_PATHSIZE
+1];
297 if ( (dkp
= dki_alloc ()) == NULL
)
300 len
= sizeof (fname
) - 1;
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';
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
);
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
);
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
);
338 if ( (err
= dki_readfile (fp
, dkp
)) != 0 )
341 snprintf (dki_estr
, sizeof (dki_estr
),
342 "dki_read: Can\'t read key from file %s (errno %d)", path
, err
);
348 if ( fstat (fileno(fp
), &st
) )
350 snprintf (dki_estr
, sizeof (dki_estr
),
351 "dki_read: Can\'t stat file %s", fname
);
354 dkp
->time
= st
.st_mtime
;
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
;
363 dkp
->status
= DKI_ACT
;
367 pathname (path
, sizeof (path
), dkp
->dname
, dkp
->fname
, DKI_PUB_FILEEXT
);
368 if ( fileexist (path
) )
369 dkp
->status
= DKI_PUB
;
372 pathname (path
, sizeof (path
), dkp
->dname
, dkp
->fname
, DKI_DEP_FILEEXT
);
373 if ( fileexist (path
) )
374 dkp
->status
= DKI_DEP
;
376 dkp
->status
= DKI_SEP
;
387 /*****************************************************************
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
)
396 struct dirent
*dentp
;
397 char path
[MAX_PATHSIZE
+1];
399 dbg_val ("directory: opendir(%s)\n", dir
);
400 if ( (dirp
= opendir (dir
)) == NULL
)
403 while ( (dentp
= readdir (dirp
)) != NULL
)
405 if ( is_dotfilename (dentp
->d_name
) )
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
);
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 /*****************************************************************
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 /*****************************************************************
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];
457 currtime
= time (NULL
);
458 status
= tolower (status
);
459 switch ( dkp
->status
) /* look at old status */
468 pathname (frompath
, sizeof (frompath
), dkp
->dname
, dkp
->fname
, DKI_ACT_FILEEXT
);
473 pathname (frompath
, sizeof (frompath
), dkp
->dname
, dkp
->fname
, DKI_DEP_FILEEXT
);
475 case 'p': /* or 's' */
476 if ( status
== 'p' || status
== 's' )
478 pathname (frompath
, sizeof (frompath
), dkp
->dname
, dkp
->fname
, DKI_PUB_FILEEXT
);
481 /* TODO: set error code */
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
);
495 dki_setflag (dkp
, DK_FLAG_REVOKE
); /* set REVOKE bit */
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
));
509 /* 2) change the filename of the private key in all other cases */
512 totime
= file_mtime (frompath
); /* get original timestamp */
517 pathname (topath
, sizeof (topath
), dkp
->dname
, dkp
->fname
, DKI_ACT_FILEEXT
);
520 pathname (topath
, sizeof (topath
), dkp
->dname
, dkp
->fname
, DKI_DEP_FILEEXT
);
522 case 's': /* standby means a "published KSK" */
523 if ( !dki_isksk (dkp
) )
528 pathname (topath
, sizeof (topath
), dkp
->dname
, dkp
->fname
, DKI_PUB_FILEEXT
);
534 dbg_val ("dki_setstat: to \"%s\"\n", topath
);
535 if ( link (frompath
, topath
) == 0 )
537 dkp
->status
= status
;
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 */
547 /*****************************************************************
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];
561 static const char *ext
[] = {
562 DKI_KEY_FILEEXT
, DKI_PUB_FILEEXT
,
563 DKI_ACT_FILEEXT
, DKI_DEP_FILEEXT
,
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
);
589 /*****************************************************************
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];
598 static const char *ext
[] = {
599 DKI_KEY_FILEEXT
, DKI_PUB_FILEEXT
,
600 DKI_ACT_FILEEXT
, DKI_DEP_FILEEXT
,
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
);
622 /*****************************************************************
624 ** return a string describing the key algorithm
625 *****************************************************************/
626 char *dki_algo2str (int 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");
641 /*****************************************************************
643 ** return a short string describing the key algorithm
644 *****************************************************************/
645 char *dki_algo2sstr (int 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");
660 /*****************************************************************
662 ** return error string
663 *****************************************************************/
664 const char *dki_geterrstr ()
669 /*****************************************************************
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
)
687 fprintf (fp
, "%s ", dkp
->name
);
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
++ )
695 fprintf (fp
, "\n\t\t\t");
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
);
702 fprintf (fp
, ") ; key id = %u", dkp
->tag
);
708 /*****************************************************************
709 ** dki_prt_dnskey_raw ()
710 *****************************************************************/
711 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
)
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'));
754 /*****************************************************************
755 ** dki_prt_trustedkey ()
756 *****************************************************************/
757 int dki_prt_trustedkey (const dki_t
*dkp
, FILE *fp
)
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
);
770 len
+= fprintf (fp
, "\n\t\t\t%7s", " ");
771 len
+= fprintf (fp
, "\"");
772 for ( p
= dkp
->pubkey
; *p
; p
++ )
774 len
+= fprintf (fp
, "\n\t\t\t\t");
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
);
781 len
+= fprintf (fp
, "\" ; # key id = %u\n\n", dkp
->tag
);
786 /*****************************************************************
787 ** dki_cmp () return <0 | 0 | >0
788 *****************************************************************/
789 int dki_cmp (const dki_t
*a
, const dki_t
*b
)
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 )
800 /* then by key type, */
801 if ( (res
= dki_isksk (b
) - dki_isksk (a
)) != 0 )
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
)
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 )
824 /* then by key type, */
825 if ( (res
= dki_isksk (b
) - dki_isksk (a
)) != 0 )
829 if ( (res
= (ulong
)a
->time
- (ulong
)b
->time
) != 0 )
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
;
858 /*****************************************************************
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
);
878 /*****************************************************************
879 ** dki_time () return the timestamp of the key
880 *****************************************************************/
881 time_t dki_time (const dki_t
*dkp
)
883 assert (dkp
!= NULL
);
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
)
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];
958 assert (dkp
!= NULL
);
960 dbg_val1 ("dki_setexptime (%ld)\n", sec
);
961 oldexptime
= dkp
->exptime
;
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
));
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
)
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 /*****************************************************************
1008 *****************************************************************/
1009 int dki_isksk (const dki_t
*dkp
)
1011 assert (dkp
!= NULL
);
1012 return (dkp
->flags
& DK_FLAG_KSK
) == DK_FLAG_KSK
;
1015 /*****************************************************************
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 /*****************************************************************
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
) )
1071 case DKI_DEP
: return "depreciated";
1072 case DKI_REV
: return "revoked";
1073 case DKI_SEP
: return "sep";
1078 /*****************************************************************
1079 ** dki_add () add a key to the given list
1080 *****************************************************************/
1081 dki_t
*dki_add (dki_t
**list
, dki_t
*new)
1091 last
= curr
= *list
;
1092 while ( curr
&& dki_cmp (curr
, new) < 0 )
1098 if ( curr
== *list
) /* add node at start of list */
1100 else /* add node at end or between two nodes */
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
)
1117 while ( curr
&& (tag
!= curr
->tag
||
1118 (name
&& *name
&& strcmp (name
, curr
->name
) != 0)) )
1120 else if ( name
&& *name
)
1121 while ( curr
&& strcmp (name
, curr
->name
) != 0 )
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)
1137 p
= tsearch (new, tree
, dki_namecmp
);
1139 dbg_val ("dki_tadd: New entry %s added\n", new->name
);
1142 dbg_val ("dki_tadd: New key added to %s\n", new->name
);
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
)
1159 snprintf (search
.name
, sizeof (search
.name
), "%s", name
);
1160 p
= tfind (&search
, &tree
, dki_namecmp
);
1164 return dki_search (*p
, tag
, name
);
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
)
1177 for ( dkp
= list
; no
> 0 && dkp
; dkp
= dkp
->next
)
1178 if ( dki_isksk (dkp
) == ksk
&& dki_status (dkp
) == status
)
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
)
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
)