etc/services - sync with NetBSD-8
[minix.git] / external / bsd / bind / dist / contrib / zkt-1.1.3 / dki.c
blobdd412b557eb165bcc8151686f9de6d28afa90d30
1 /* $NetBSD: dki.c,v 1.1.1.1 2015/07/08 15:37:48 christos Exp $ */
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 # define KEYGEN_COMPMODE "-C -q " /* this is the compability mode needed since BIND 9.7 */
233 /*****************************************************************
234 ** dki_new ()
235 ** create new keyfile
236 ** allocate memory for new dki key and init with keyfile
237 *****************************************************************/
238 dki_t *dki_new (const char *dir, const char *name, int ksk, int algo, int bitsize, const char *rfile, int lf_days)
240 char cmdline[511+1];
241 char fname[254+1];
242 char randfile[254+1];
243 FILE *fp;
244 int len;
245 char *flag = "";
246 char *expflag = "";
247 dki_t *new;
249 if ( ksk )
250 flag = "-f KSK";
252 randfile[0] = '\0';
253 if ( rfile && *rfile )
254 snprintf (randfile, sizeof (randfile), "-r %.250s ", rfile);
256 #if defined(BIND_VERSION) && BIND_VERSION < 90902
257 if ( algo == DK_ALGO_RSA || algo == DK_ALGO_RSASHA1 || algo == DK_ALGO_RSASHA256 || algo == DK_ALGO_RSASHA512 )
258 expflag = "-e ";
259 #endif
260 if ( dir && *dir )
261 snprintf (cmdline, sizeof (cmdline), "cd %s ; %s %s%s%s-n ZONE -a %s -b %d %s %s",
262 dir, KEYGENCMD, KEYGEN_COMPMODE, randfile, expflag, dki_algo2str(algo), bitsize, flag, name);
263 else
264 snprintf (cmdline, sizeof (cmdline), "%s %s%s%s-n ZONE -a %s -b %d %s %s",
265 KEYGENCMD, KEYGEN_COMPMODE, randfile, expflag, dki_algo2str(algo), bitsize, flag, name);
267 dbg_msg (cmdline);
269 if ( (fp = popen (cmdline, "r")) == NULL || fgets (fname, sizeof fname, fp) == NULL )
270 return NULL;
271 pclose (fp);
273 len = strlen (fname) - 1;
274 if ( len >= 0 && fname[len] == '\n' )
275 fname[len] = '\0';
277 new = dki_read (dir, fname);
278 if ( new )
279 dki_setlifetime (new, lf_days); /* sets gentime + proposed lifetime */
281 return new;
284 /*****************************************************************
285 ** dki_read ()
286 ** read key from file 'filename' (independed of the extension)
287 *****************************************************************/
288 dki_t *dki_read (const char *dirname, const char *filename)
290 dki_t *dkp;
291 FILE *fp;
292 struct stat st;
293 int len;
294 int err;
295 char fname[MAX_FNAMESIZE+1];
296 char path[MAX_PATHSIZE+1];
298 dki_estr[0] = '\0';
299 if ( (dkp = dki_alloc ()) == NULL )
300 return (NULL);
302 len = sizeof (fname) - 1;
303 fname[len] = '\0';
304 strncpy (fname, filename, len);
306 len = strlen (fname); /* delete extension */
307 if ( len > 4 && strcmp (&fname[len - 4], DKI_KEY_FILEEXT) == 0 )
308 fname[len - 4] = '\0';
309 else if ( len > 10 && strcmp (&fname[len - 10], DKI_PUB_FILEEXT) == 0 )
310 fname[len - 10] = '\0';
311 else if ( len > 8 && strcmp (&fname[len - 8], DKI_ACT_FILEEXT) == 0 )
312 fname[len - 8] = '\0';
313 else if ( len > 12 && strcmp (&fname[len - 12], DKI_DEP_FILEEXT) == 0 )
314 fname[len - 12] = '\0';
315 dbg_line ();
317 assert (strlen (dirname)+1 < sizeof (dkp->dname));
318 strcpy (dkp->dname, dirname);
320 assert (strlen (fname)+1 < sizeof (dkp->fname));
321 strcpy (dkp->fname, fname);
322 dbg_line ();
323 if ( sscanf (fname, "K%254[^+]+%hd+%d", dkp->name, &dkp->algo, &dkp->tag) != 3 )
325 snprintf (dki_estr, sizeof (dki_estr),
326 "dki_read: Filename don't match expected format (%s)", fname);
327 return (NULL);
330 pathname (path, sizeof (path), dkp->dname, dkp->fname, DKI_KEY_FILEEXT);
331 dbg_val ("dki_read: path \"%s\"\n", path);
332 if ( (fp = fopen (path, "r")) == NULL )
334 snprintf (dki_estr, sizeof (dki_estr),
335 "dki_read: Can\'t open file \"%s\" for reading", path);
336 return (NULL);
339 dbg_line ();
340 if ( (err = dki_readfile (fp, dkp)) != 0 )
342 dbg_line ();
343 snprintf (dki_estr, sizeof (dki_estr),
344 "dki_read: Can\'t read key from file %s (errno %d)", path, err);
345 fclose (fp);
346 return (NULL);
349 dbg_line ();
350 if ( fstat (fileno(fp), &st) )
352 snprintf (dki_estr, sizeof (dki_estr),
353 "dki_read: Can\'t stat file %s", fname);
354 return (NULL);
356 dkp->time = st.st_mtime;
358 dbg_line ();
359 pathname (path, sizeof (path), dkp->dname, dkp->fname, DKI_ACT_FILEEXT);
360 if ( fileexist (path) )
362 if ( dki_isrevoked (dkp) )
363 dkp->status = DKI_REV;
364 else
365 dkp->status = DKI_ACT;
367 else
369 pathname (path, sizeof (path), dkp->dname, dkp->fname, DKI_PUB_FILEEXT);
370 if ( fileexist (path) )
371 dkp->status = DKI_PUB;
372 else
374 pathname (path, sizeof (path), dkp->dname, dkp->fname, DKI_DEP_FILEEXT);
375 if ( fileexist (path) )
376 dkp->status = DKI_DEP;
377 else
378 dkp->status = DKI_SEP;
382 dbg_line ();
383 fclose (fp);
385 dbg_line ();
386 return dkp;
389 /*****************************************************************
390 ** dki_readdir ()
391 ** read key files from directory 'dir' and, if recursive is
392 ** true, from all directorys below that.
393 *****************************************************************/
394 int dki_readdir (const char *dir, dki_t **listp, int recursive)
396 dki_t *dkp;
397 DIR *dirp;
398 struct dirent *dentp;
399 char path[MAX_PATHSIZE+1];
401 dbg_val ("directory: opendir(%s)\n", dir);
402 if ( (dirp = opendir (dir)) == NULL )
403 return 0;
405 while ( (dentp = readdir (dirp)) != NULL )
407 if ( is_dotfilename (dentp->d_name) )
408 continue;
410 dbg_val ("directory: check %s\n", dentp->d_name);
411 pathname (path, sizeof (path), dir, dentp->d_name, NULL);
412 if ( is_directory (path) && recursive )
414 dbg_val ("directory: recursive %s\n", path);
415 dki_readdir (path, listp, recursive);
417 else if ( is_keyfilename (dentp->d_name) )
418 if ( (dkp = dki_read (dir, dentp->d_name)) )
419 dki_add (listp, dkp);
421 closedir (dirp);
422 return 1;
425 /*****************************************************************
426 ** dki_setstatus_preservetime ()
427 ** set status of key and change extension to
428 ** ".published", ".private" or ".depreciated"
429 *****************************************************************/
430 int dki_setstatus_preservetime (dki_t *dkp, int status)
432 return dki_setstat (dkp, status, 1);
435 /*****************************************************************
436 ** dki_setstatus ()
437 ** set status of key and change extension to
438 ** ".published", ".private" or ".depreciated"
439 *****************************************************************/
440 int dki_setstatus (dki_t *dkp, int status)
442 return dki_setstat (dkp, status, 0);
445 /*****************************************************************
446 ** dki_setstat ()
447 ** low level function of dki_setstatus and dki_setstatus_preservetime
448 *****************************************************************/
449 static int dki_setstat (dki_t *dkp, int status, int preserve_time)
451 char frompath[MAX_PATHSIZE+1];
452 char topath[MAX_PATHSIZE+1];
453 time_t totime;
455 if ( dkp == NULL )
456 return 0;
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");
637 case DK_ALGO_RSASHA256: return ("RSASHA256");
638 case DK_ALGO_RSASHA512: return ("RSASHA512");
640 return ("unknown");
643 /*****************************************************************
644 ** dki_algo2sstr ()
645 ** return a short string describing the key algorithm
646 *****************************************************************/
647 char *dki_algo2sstr (int algo)
649 switch ( algo )
651 case DK_ALGO_RSA: return ("RSAMD5");
652 case DK_ALGO_DH: return ("DH");
653 case DK_ALGO_DSA: return ("DSA");
654 case DK_ALGO_EC: return ("EC");
655 case DK_ALGO_RSASHA1: return ("RSASHA1");
656 case DK_ALGO_NSEC3DSA: return ("N3DSA");
657 case DK_ALGO_NSEC3RSASHA1: return ("N3RSA1");
658 case DK_ALGO_RSASHA256: return ("RSASHA2");
659 case DK_ALGO_RSASHA512: return ("RSASHA5");
661 return ("unknown");
664 /*****************************************************************
665 ** dki_geterrstr ()
666 ** return error string
667 *****************************************************************/
668 const char *dki_geterrstr ()
670 return dki_estr;
673 /*****************************************************************
674 ** dki_prt_dnskey ()
675 *****************************************************************/
676 int dki_prt_dnskey (const dki_t *dkp, FILE *fp)
678 return dki_prt_dnskeyttl (dkp, fp, 0);
681 /*****************************************************************
682 ** dki_prt_dnskeyttl ()
683 *****************************************************************/
684 int dki_prt_dnskeyttl (const dki_t *dkp, FILE *fp, int ttl)
686 char *p;
688 if ( dkp == NULL )
689 return 0;
691 fprintf (fp, "%s ", dkp->name);
692 if ( ttl > 0 )
693 fprintf (fp, "%d ", ttl);
694 fprintf (fp, "IN DNSKEY ");
695 fprintf (fp, "%d 3 %d (", dkp->flags, dkp->algo);
696 fprintf (fp, "\n\t\t\t");
697 for ( p = dkp->pubkey; *p ; p++ )
698 if ( *p == ' ' )
699 fprintf (fp, "\n\t\t\t");
700 else
701 putc (*p, fp);
702 fprintf (fp, "\n\t\t");
703 if ( dki_isrevoked (dkp) )
704 fprintf (fp, ") ; key id = %u (original key id = %u)", (dkp->tag + 128) % 65535, dkp->tag);
705 else
706 fprintf (fp, ") ; key id = %u", dkp->tag);
707 fprintf (fp, "\n");
709 return 1;
712 /*****************************************************************
713 ** dki_prt_dnskey_raw ()
714 *****************************************************************/
715 int dki_prt_dnskey_raw (const dki_t *dkp, FILE *fp)
717 int days;
719 if ( dkp == NULL )
720 return 0;
722 if ( dkp->gentime )
723 fprintf (fp, ";%%\tgenerationtime=%s\n", time2isostr (dkp->gentime, 's'));
724 if ( (days = dki_lifetimedays (dkp)) )
725 fprintf (fp, ";%%\tlifetime=%dd\n", days);
726 if ( dkp->exptime )
727 fprintf (fp, ";%%\texpirationtime=%s\n", time2isostr (dkp->exptime, 's'));
729 fprintf (fp, "%s ", dkp->name);
730 #if 0
731 if ( ttl > 0 )
732 fprintf (fp, "%d ", ttl);
733 #endif
734 fprintf (fp, "IN DNSKEY ");
735 fprintf (fp, "%d 3 %d ", dkp->flags, dkp->algo);
736 fprintf (fp, "%s\n", dkp->pubkey);
738 return 1;
741 /*****************************************************************
742 ** dki_prt_comment ()
743 *****************************************************************/
744 int dki_prt_comment (const dki_t *dkp, FILE *fp)
746 int len = 0;
748 if ( dkp == NULL )
749 return len;
750 len += fprintf (fp, "; %s ", dkp->name);
751 len += fprintf (fp, "tag=%u ", dkp->tag);
752 len += fprintf (fp, "algo=%s ", dki_algo2str(dkp->algo));
753 len += fprintf (fp, "generated %s\n", time2str (dkp->time, 's'));
755 return len;
758 /*****************************************************************
759 ** dki_prt_trustedkey ()
760 *****************************************************************/
761 int dki_prt_trustedkey (const dki_t *dkp, FILE *fp)
763 char *p;
764 int spaces;
765 int len = 0;
767 if ( dkp == NULL )
768 return len;
769 len += fprintf (fp, "\"%s\" ", dkp->name);
770 spaces = 22 - (strlen (dkp->name) + 3);
771 len += fprintf (fp, "%*s", spaces > 0 ? spaces : 0 , " ");
772 len += fprintf (fp, "%d 3 %d ", dkp->flags, dkp->algo);
773 if ( spaces < 0 )
774 len += fprintf (fp, "\n\t\t\t%7s", " ");
775 len += fprintf (fp, "\"");
776 for ( p = dkp->pubkey; *p ; p++ )
777 if ( *p == ' ' )
778 len += fprintf (fp, "\n\t\t\t\t");
779 else
780 putc (*p, fp), len += 1;
782 if ( dki_isrevoked (dkp) )
783 len += fprintf (fp, "\" ; # key id = %u (original key id = %u)\n\n", (dkp->tag + 128) % 65535, dkp->tag);
784 else
785 len += fprintf (fp, "\" ; # key id = %u\n\n", dkp->tag);
786 return len;
789 /*****************************************************************
790 ** dki_prt_managedkey ()
791 *****************************************************************/
792 int dki_prt_managedkey (const dki_t *dkp, FILE *fp)
794 char *p;
795 int spaces;
796 int len = 0;
798 if ( dkp == NULL )
799 return len;
800 len += fprintf (fp, "\"%s\" ", dkp->name);
801 spaces = 22 - (strlen (dkp->name) + 3);
802 len += fprintf (fp, "initial-key ");
803 spaces -= 13;
804 len += fprintf (fp, "%*s", spaces > 0 ? spaces : 0 , " ");
805 len += fprintf (fp, "%d 3 %d ", dkp->flags, dkp->algo);
806 if ( spaces < 0 )
807 len += fprintf (fp, "\n\t\t\t%7s", " ");
808 len += fprintf (fp, "\"");
809 for ( p = dkp->pubkey; *p ; p++ )
810 if ( *p == ' ' )
811 len += fprintf (fp, "\n\t\t\t\t");
812 else
813 putc (*p, fp), len += 1;
815 if ( dki_isrevoked (dkp) )
816 len += fprintf (fp, "\" ; # key id = %u (original key id = %u)\n\n", (dkp->tag + 128) % 65535, dkp->tag);
817 else
818 len += fprintf (fp, "\" ; # key id = %u\n\n", dkp->tag);
819 return len;
823 /*****************************************************************
824 ** dki_cmp () return <0 | 0 | >0
825 *****************************************************************/
826 int dki_cmp (const dki_t *a, const dki_t *b)
828 int res;
830 if ( a == NULL ) return -1;
831 if ( b == NULL ) return 1;
833 /* sort by domain name, */
834 if ( (res = domaincmp (a->name, b->name)) != 0 )
835 return res;
837 /* then by key type, */
838 if ( (res = dki_isksk (b) - dki_isksk (a)) != 0 )
839 return res;
841 /* and last by creation time, */
842 return (ulong)a->time - (ulong)b->time;
845 #if defined(USE_TREE) && USE_TREE
846 /*****************************************************************
847 ** dki_allcmp () return <0 | 0 | >0
848 *****************************************************************/
849 int dki_allcmp (const dki_t *a, const dki_t *b)
851 int res;
853 if ( a == NULL ) return -1;
854 if ( b == NULL ) return 1;
856 // fprintf (stderr, "dki_allcmp %s, %s)\n", a->name, b->name);
857 /* sort by domain name, */
858 if ( (res = domaincmp (a->name, b->name)) != 0 )
859 return res;
861 /* then by key type, */
862 if ( (res = dki_isksk (b) - dki_isksk (a)) != 0 )
863 return res;
865 /* creation time, */
866 if ( (res = (ulong)a->time - (ulong)b->time) != 0 )
867 return res;
869 /* and last by tag */
870 return a->tag - b->tag;
873 /*****************************************************************
874 ** dki_namecmp () return <0 | 0 | >0
875 *****************************************************************/
876 int dki_namecmp (const dki_t *a, const dki_t *b)
878 if ( a == NULL ) return -1;
879 if ( b == NULL ) return 1;
881 return domaincmp (a->name, b->name);
884 /*****************************************************************
885 ** dki_revnamecmp () return <0 | 0 | >0
886 *****************************************************************/
887 int dki_revnamecmp (const dki_t *a, const dki_t *b)
889 if ( a == NULL ) return -1;
890 if ( b == NULL ) return 1;
892 return domaincmp_dir (a->name, b->name, 0);
895 /*****************************************************************
896 ** dki_tagcmp () return <0 | 0 | >0
897 *****************************************************************/
898 int dki_tagcmp (const dki_t *a, const dki_t *b)
900 if ( a == NULL ) return -1;
901 if ( b == NULL ) return 1;
903 return a->tag - b->tag;
905 #endif
907 /*****************************************************************
908 ** dki_timecmp ()
909 *****************************************************************/
910 int dki_timecmp (const dki_t *a, const dki_t *b)
912 if ( a == NULL ) return -1;
913 if ( b == NULL ) return 1;
915 return ((ulong)a->time - (ulong)b->time);
918 /*****************************************************************
919 ** dki_algo () return the algorithm of the key
920 *****************************************************************/
921 time_t dki_algo (const dki_t *dkp)
923 assert (dkp != NULL);
924 return (dkp->algo);
927 /*****************************************************************
928 ** dki_time () return the timestamp of the key
929 *****************************************************************/
930 time_t dki_time (const dki_t *dkp)
932 assert (dkp != NULL);
933 return (dkp->time);
936 /*****************************************************************
937 ** dki_exptime () return the expiration timestamp of the key
938 *****************************************************************/
939 time_t dki_exptime (const dki_t *dkp)
941 assert (dkp != NULL);
942 return (dkp->exptime);
945 /*****************************************************************
946 ** dki_lifetime (dkp) return the lifetime of the key in sec!
947 *****************************************************************/
948 time_t dki_lifetime (const dki_t *dkp)
950 assert (dkp != NULL);
951 return (dkp->lifetime);
954 /*****************************************************************
955 ** dki_lifetimedays (dkp) return the lifetime of the key in days!
956 *****************************************************************/
957 ushort dki_lifetimedays (const dki_t *dkp)
959 assert (dkp != NULL);
960 return (dkp->lifetime / DAYSEC);
963 /*****************************************************************
964 ** dki_gentime (dkp) return the generation timestamp of the key
965 *****************************************************************/
966 time_t dki_gentime (const dki_t *dkp)
968 assert (dkp != NULL);
969 return (dkp->gentime > 0L ? dkp->gentime: dkp->time);
972 /*****************************************************************
973 ** dki_setlifetime (dkp, int days)
974 ** set the lifetime in days (and also the gentime if not set)
975 ** return the old lifetime of the key in days!
976 *****************************************************************/
977 ushort dki_setlifetime (dki_t *dkp, int days)
979 ulong lifetsec;
980 char path[MAX_PATHSIZE+1];
982 assert (dkp != NULL);
984 lifetsec = dkp->lifetime; /* old lifetime */
985 dkp->lifetime = days * DAYSEC; /* set new lifetime */
987 dbg_val1 ("dki_setlifetime (%d)\n", days);
988 if ( lifetsec == 0 ) /* initial setup (old lifetime was zero)? */
989 dkp->gentime = dkp->time;
991 pathname (path, sizeof (path), dkp->dname, dkp->fname, DKI_KEY_FILEEXT);
992 dki_writeinfo (dkp, path);
994 return (lifetsec / DAYSEC);
997 /*****************************************************************
998 ** dki_setexptime (dkp, time_t sec)
999 ** set the expiration time of the key in seconds since the epoch
1000 ** return the old exptime
1001 *****************************************************************/
1002 time_t dki_setexptime (dki_t *dkp, time_t sec)
1004 char path[MAX_PATHSIZE+1];
1005 time_t oldexptime;
1007 assert (dkp != NULL);
1009 dbg_val1 ("dki_setexptime (%ld)\n", sec);
1010 oldexptime = dkp->exptime;
1011 dkp->exptime = sec;
1013 pathname (path, sizeof (path), dkp->dname, dkp->fname, DKI_KEY_FILEEXT);
1014 dki_writeinfo (dkp, path);
1016 #if 0 /* not necessary ? */
1017 touch (path, time (NULL));
1018 #endif
1019 return (oldexptime);
1022 /*****************************************************************
1023 ** dki_age () return age of key in seconds since 'curr'
1024 *****************************************************************/
1025 int dki_age (const dki_t *dkp, time_t curr)
1027 assert (dkp != NULL);
1028 return ((ulong)curr - (ulong)dkp->time);
1031 /*****************************************************************
1032 ** dki_getflag () return the flags field of a key
1033 *****************************************************************/
1034 dk_flag_t dki_getflag (const dki_t *dkp, time_t curr)
1036 return dkp->flags;
1039 /*****************************************************************
1040 ** dki_setflag () set a flag of a key
1041 *****************************************************************/
1042 dk_flag_t dki_setflag (dki_t *dkp, dk_flag_t flag)
1044 return dkp->flags |= (ushort)flag;
1047 /*****************************************************************
1048 ** dki_unsetflag () unset a flag of a key
1049 *****************************************************************/
1050 dk_flag_t dki_unsetflag (dki_t *dkp, dk_flag_t flag)
1052 return dkp->flags &= ~((ushort)flag);
1055 /*****************************************************************
1056 ** dki_isksk ()
1057 *****************************************************************/
1058 int dki_isksk (const dki_t *dkp)
1060 assert (dkp != NULL);
1061 return (dkp->flags & DK_FLAG_KSK) == DK_FLAG_KSK;
1064 /*****************************************************************
1065 ** dki_isrevoked ()
1066 *****************************************************************/
1067 int dki_isrevoked (const dki_t *dkp)
1069 assert (dkp != NULL);
1070 return (dkp->flags & DK_FLAG_REVOKE) == DK_FLAG_REVOKE;
1073 /*****************************************************************
1074 ** dki_isdepreciated ()
1075 *****************************************************************/
1076 int dki_isdepreciated (const dki_t *dkp)
1078 return dki_status (dkp) == DKI_DEPRECIATED;
1081 /*****************************************************************
1082 ** dki_isactive ()
1083 *****************************************************************/
1084 int dki_isactive (const dki_t *dkp)
1086 return dki_status (dkp) == DKI_ACTIVE;
1089 /*****************************************************************
1090 ** dki_ispublished ()
1091 *****************************************************************/
1092 int dki_ispublished (const dki_t *dkp)
1094 return dki_status (dkp) == DKI_PUBLISHED;
1098 /*****************************************************************
1099 ** dki_status () return key status
1100 *****************************************************************/
1101 dk_status_t dki_status (const dki_t *dkp)
1103 assert (dkp != NULL);
1104 return (dkp->status);
1107 /*****************************************************************
1108 ** dki_statusstr () return key status as string
1109 *****************************************************************/
1110 const char *dki_statusstr (const dki_t *dkp)
1112 assert (dkp != NULL);
1113 switch ( dkp->status )
1115 case DKI_ACT: return "active";
1116 case DKI_PUB: if ( dki_isksk (dkp) )
1117 return "standby";
1118 else
1119 return "published";
1120 case DKI_DEP: return "depreciated";
1121 case DKI_REV: return "revoked";
1122 case DKI_SEP: return "sep";
1124 return "unknown";
1127 /*****************************************************************
1128 ** dki_add () add a key to the given list
1129 *****************************************************************/
1130 dki_t *dki_add (dki_t **list, dki_t *new)
1132 dki_t *curr;
1133 dki_t *last;
1135 if ( list == NULL )
1136 return NULL;
1137 if ( new == NULL )
1138 return *list;
1140 last = curr = *list;
1141 while ( curr && dki_cmp (curr, new) < 0 )
1143 last = curr;
1144 curr = curr->next;
1147 if ( curr == *list ) /* add node at start of list */
1148 *list = new;
1149 else /* add node at end or between two nodes */
1150 last->next = new;
1151 new->next = curr;
1153 return *list;
1156 /*****************************************************************
1157 ** dki_search () search a key with the given tag, or the first
1158 ** occurence of a key with the given name
1159 *****************************************************************/
1160 const dki_t *dki_search (const dki_t *list, int tag, const char *name)
1162 const dki_t *curr;
1164 curr = list;
1165 if ( tag )
1166 while ( curr && (tag != curr->tag ||
1167 (name && *name && strcmp (name, curr->name) != 0)) )
1168 curr = curr->next;
1169 else if ( name && *name )
1170 while ( curr && strcmp (name, curr->name) != 0 )
1171 curr = curr->next;
1172 else
1173 curr = NULL;
1175 return curr;
1178 #if defined(USE_TREE) && USE_TREE
1179 /*****************************************************************
1180 ** dki_tadd () add a key to the given tree
1181 *****************************************************************/
1182 dki_t *dki_tadd (dki_t **tree, dki_t *new, int sub_before)
1184 dki_t **p;
1186 if ( sub_before )
1187 p = tsearch (new, tree, dki_namecmp);
1188 else
1189 p = tsearch (new, tree, dki_revnamecmp);
1190 if ( *p == new )
1191 dbg_val ("dki_tadd: New entry %s added\n", new->name);
1192 else
1194 dbg_val ("dki_tadd: New key added to %s\n", new->name);
1195 dki_add (p, new);
1198 return *p;
1201 /*****************************************************************
1202 ** dki_tsearch () search a key with the given tag, or the first
1203 ** occurence of a key with the given name
1204 *****************************************************************/
1205 const dki_t *dki_tsearch (const dki_t *tree, int tag, const char *name)
1207 dki_t search;
1208 dki_t **p;
1210 search.tag = tag;
1211 snprintf (search.name, sizeof (search.name), "%s", name);
1212 p = tfind (&search, &tree, dki_namecmp);
1213 if ( p == NULL )
1214 return NULL;
1216 return dki_search (*p, tag, name);
1218 #endif
1220 /*****************************************************************
1221 ** dki_find () find the n'th ksk or zsk key with given status
1222 *****************************************************************/
1223 const dki_t *dki_find (const dki_t *list, int ksk, int status, int no)
1225 const dki_t *dkp;
1226 const dki_t *last;
1228 last = NULL;
1229 for ( dkp = list; no > 0 && dkp; dkp = dkp->next )
1230 if ( dki_isksk (dkp) == ksk && dki_status (dkp) == status )
1232 no--;
1233 last = dkp;
1236 return last;
1239 /*****************************************************************
1240 ** dki_findalgo () find the n'th ksk or zsk key with given
1241 ** algorithm and status
1242 *****************************************************************/
1243 const dki_t *dki_findalgo (const dki_t *list, int ksk, int alg, int status, int no)
1245 const dki_t *dkp;
1246 const dki_t *last;
1248 last = NULL;
1249 for ( dkp = list; no > 0 && dkp; dkp = dkp->next )
1250 if ( dki_isksk (dkp) == ksk && dki_algo (dkp) == alg &&
1251 dki_status (dkp) == status )
1253 no--;
1254 last = dkp;
1257 return last;