Import Upstream version 1.2.2
[quagga-debian.git] / lib / keychain.c
1 /* key-chain for authentication.
2    Copyright (C) 2000 Kunihiro Ishiguro
3
4 This file is part of GNU Zebra.
5
6 GNU Zebra is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published
8 by the Free Software Foundation; either version 2, or (at your
9 option) any later version.
10
11 GNU Zebra is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Zebra; see the file COPYING.  If not, write to the
18 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA.  */
20
21 #include <zebra.h>
22
23 #include "command.h"
24 #include "memory.h"
25 #include "linklist.h"
26 #include "keychain.h"
27
28 /* Master list of key chain. */
29 struct list *keychain_list;
30
31 static struct keychain *
32 keychain_new (void)
33 {
34   return XCALLOC (MTYPE_KEYCHAIN, sizeof (struct keychain));
35 }
36
37 static void
38 keychain_free (struct keychain *keychain)
39 {
40   XFREE (MTYPE_KEYCHAIN, keychain);
41 }
42
43 static struct key *
44 key_new (void)
45 {
46   return XCALLOC (MTYPE_KEY, sizeof (struct key));
47 }
48
49 static void
50 key_free (struct key *key)
51 {
52   XFREE (MTYPE_KEY, key);
53 }
54
55 struct keychain *
56 keychain_lookup (const char *name)
57 {
58   struct listnode *node;
59   struct keychain *keychain;
60
61   if (name == NULL)
62     return NULL;
63
64   for (ALL_LIST_ELEMENTS_RO (keychain_list, node, keychain))
65     {
66       if (strcmp (keychain->name, name) == 0)
67         return keychain;
68     }
69   return NULL;
70 }
71
72 static int
73 key_cmp_func (void *arg1, void *arg2)
74 {
75   const struct key *k1 = arg1;
76   const struct key *k2 = arg2;
77   
78   if (k1->index > k2->index)
79     return 1;
80   if (k1->index < k2->index)
81     return -1;
82   return 0;
83 }
84
85 static void
86 key_delete_func (struct key *key)
87 {
88   if (key->string)
89     free (key->string);
90   key_free (key);
91 }
92
93 static struct keychain *
94 keychain_get (const char *name)
95 {
96   struct keychain *keychain;
97
98   keychain = keychain_lookup (name);
99
100   if (keychain)
101     return keychain;
102
103   keychain = keychain_new ();
104   keychain->name = strdup (name);
105   keychain->key = list_new ();
106   keychain->key->cmp = (int (*)(void *, void *)) key_cmp_func;
107   keychain->key->del = (void (*)(void *)) key_delete_func;
108   listnode_add (keychain_list, keychain);
109
110   return keychain;
111 }
112
113 static void
114 keychain_delete (struct keychain *keychain)
115 {
116   if (keychain->name)
117     free (keychain->name);
118
119   list_delete (keychain->key);
120   listnode_delete (keychain_list, keychain);
121   keychain_free (keychain);
122 }
123
124 static struct key *
125 key_lookup (const struct keychain *keychain, u_int32_t index)
126 {
127   struct listnode *node;
128   struct key *key;
129
130   for (ALL_LIST_ELEMENTS_RO (keychain->key, node, key))
131     {
132       if (key->index == index)
133         return key;
134     }
135   return NULL;
136 }
137
138 struct key *
139 key_lookup_for_accept (const struct keychain *keychain, u_int32_t index)
140 {
141   struct listnode *node;
142   struct key *key;
143   time_t now;
144
145   now = time (NULL);
146
147   for (ALL_LIST_ELEMENTS_RO (keychain->key, node, key))
148     {
149       if (key->index >= index)
150         {
151           if (key->accept.start == 0)
152             return key;
153
154           if (key->accept.start <= now)
155             if (key->accept.end >= now || key->accept.end == -1)
156               return key;
157         }
158     }
159   return NULL;
160 }
161
162 struct key *
163 key_match_for_accept (const struct keychain *keychain, const char *auth_str)
164 {
165   struct listnode *node;
166   struct key *key;
167   time_t now;
168
169   now = time (NULL);
170
171   for (ALL_LIST_ELEMENTS_RO (keychain->key, node, key))
172     {
173       if (key->accept.start == 0 ||
174           (key->accept.start <= now &&
175            (key->accept.end >= now || key->accept.end == -1)))
176         if (strncmp (key->string, auth_str, 16) == 0)
177           return key;
178     }
179   return NULL;
180 }
181
182 struct key *
183 key_lookup_for_send (const struct keychain *keychain)
184 {
185   struct listnode *node;
186   struct key *key;
187   time_t now;
188
189   now = time (NULL);
190
191   for (ALL_LIST_ELEMENTS_RO (keychain->key, node, key))
192     {
193       if (key->send.start == 0)
194         return key;
195
196       if (key->send.start <= now)
197         if (key->send.end >= now || key->send.end == -1)
198           return key;
199     }
200   return NULL;
201 }
202
203 static struct key *
204 key_get (const struct keychain *keychain, u_int32_t index)
205 {
206   struct key *key;
207
208   key = key_lookup (keychain, index);
209
210   if (key)
211     return key;
212
213   key = key_new ();
214   key->index = index;
215   listnode_add_sort (keychain->key, key);
216
217   return key;
218 }
219
220 static void
221 key_delete (struct keychain *keychain, struct key *key)
222 {
223   listnode_delete (keychain->key, key);
224
225   if (key->string)
226     free (key->string);
227   key_free (key);
228 }
229
230 DEFUN (key_chain,
231        key_chain_cmd,
232        "key chain WORD",
233        "Authentication key management\n"
234        "Key-chain management\n"
235        "Key-chain name\n")
236 {
237   struct keychain *keychain;
238
239   keychain = keychain_get (argv[0]);
240   vty->index = keychain;
241   vty->node = KEYCHAIN_NODE;
242
243   return CMD_SUCCESS;
244 }
245
246 DEFUN (no_key_chain,
247        no_key_chain_cmd,
248        "no key chain WORD",
249        NO_STR
250        "Authentication key management\n"
251        "Key-chain management\n"
252        "Key-chain name\n")
253 {
254   struct keychain *keychain;
255
256   keychain = keychain_lookup (argv[0]);
257
258   if (! keychain)
259     {
260       vty_out (vty, "Can't find keychain %s%s", argv[0], VTY_NEWLINE);
261       return CMD_WARNING;
262     }
263
264   keychain_delete (keychain);
265
266   return CMD_SUCCESS;
267 }
268
269 DEFUN (key,
270        key_cmd,
271        "key <0-2147483647>",
272        "Configure a key\n"
273        "Key identifier number\n")
274 {
275   struct keychain *keychain;
276   struct key *key;
277   u_int32_t index;
278
279   keychain = vty->index;
280
281   VTY_GET_INTEGER ("key identifier", index, argv[0]);
282   key = key_get (keychain, index);
283   vty->index_sub = key;
284   vty->node = KEYCHAIN_KEY_NODE;
285   
286   return CMD_SUCCESS;
287 }
288
289 DEFUN (no_key,
290        no_key_cmd,
291        "no key <0-2147483647>",
292        NO_STR
293        "Delete a key\n"
294        "Key identifier number\n")
295 {
296   struct keychain *keychain;
297   struct key *key;
298   u_int32_t index;
299   
300   keychain = vty->index;
301
302   VTY_GET_INTEGER ("key identifier", index, argv[0]);
303   key = key_lookup (keychain, index);
304   if (! key)
305     {
306       vty_out (vty, "Can't find key %d%s", index, VTY_NEWLINE);
307       return CMD_WARNING;
308     }
309
310   key_delete (keychain, key);
311
312   vty->node = KEYCHAIN_NODE;
313
314   return CMD_SUCCESS;
315 }
316
317 DEFUN (key_string,
318        key_string_cmd,
319        "key-string LINE",
320        "Set key string\n"
321        "The key\n")
322 {
323   struct key *key;
324
325   key = vty->index_sub;
326
327   if (key->string)
328     free (key->string);
329   key->string = strdup (argv[0]);
330
331   return CMD_SUCCESS;
332 }
333
334 DEFUN (no_key_string,
335        no_key_string_cmd,
336        "no key-string [LINE]",
337        NO_STR
338        "Unset key string\n"
339        "The key\n")
340 {
341   struct key *key;
342
343   key = vty->index_sub;
344
345   if (key->string)
346     {
347       free (key->string);
348       key->string = NULL;
349     }
350
351   return CMD_SUCCESS;
352 }
353
354 /* Convert HH:MM:SS MON DAY YEAR to time_t value.  -1 is returned when
355    given string is malformed. */
356 static time_t 
357 key_str2time (const char *time_str, const char *day_str, const char *month_str,
358               const char *year_str)
359 {
360   int i = 0;
361   char *colon;
362   struct tm tm;
363   time_t time;
364   unsigned int sec, min, hour;
365   unsigned int day, month, year;
366
367   const char *month_name[] = 
368   {
369     "January",
370     "February",
371     "March",
372     "April",
373     "May",
374     "June",
375     "July",
376     "August",
377     "September",
378     "October",
379     "November",
380     "December",
381     NULL
382   };
383
384 #define _GET_LONG_RANGE(V,STR,MMCOND) \
385 { \
386   unsigned long tmpl; \
387   char *endptr = NULL; \
388   tmpl = strtoul ((STR), &endptr, 10); \
389   if (*endptr != '\0' || tmpl == ULONG_MAX) \
390     return -1; \
391   if (MMCOND) \
392     return -1; \
393   (V) = tmpl; \
394 }
395 #define GET_LONG_RANGE(V,STR,MIN,MAX) \
396         _GET_LONG_RANGE(V,STR,tmpl < (MIN) || tmpl > (MAX))
397 #define GET_LONG_RANGE0(V,STR,MAX) \
398         _GET_LONG_RANGE(V,STR,tmpl > (MAX))
399
400   /* Check hour field of time_str. */
401   colon = strchr (time_str, ':');
402   if (colon == NULL)
403     return -1;
404   *colon = '\0';
405
406   /* Hour must be between 0 and 23. */
407   GET_LONG_RANGE0 (hour, time_str, 23);
408
409   /* Check min field of time_str. */
410   time_str = colon + 1;
411   colon = strchr (time_str, ':');
412   if (*time_str == '\0' || colon == NULL)
413     return -1;
414   *colon = '\0';
415
416   /* Min must be between 0 and 59. */
417   GET_LONG_RANGE0 (min, time_str, 59);
418
419   /* Check sec field of time_str. */
420   time_str = colon + 1;
421   if (*time_str == '\0')
422     return -1;
423   
424   /* Sec must be between 0 and 59. */
425   GET_LONG_RANGE0 (sec, time_str, 59);
426   
427   /* Check day_str.  Day must be <1-31>. */
428   GET_LONG_RANGE (day, day_str, 1, 31);
429
430   /* Check month_str.  Month must match month_name. */
431   month = 0;
432   if (strlen (month_str) >= 3)
433     for (i = 0; month_name[i]; i++)
434       if (strncmp (month_str, month_name[i], strlen (month_str)) == 0)
435         {
436           month = i;
437           break;
438         }
439   if (! month_name[i])
440     return -1;
441
442   /* Check year_str.  Year must be <1993-2035>. */
443   GET_LONG_RANGE (year, year_str, 1993, 2035);
444   
445   memset (&tm, 0, sizeof (struct tm));
446   tm.tm_sec = sec;
447   tm.tm_min = min;
448   tm.tm_hour = hour;
449   tm.tm_mon = month;
450   tm.tm_mday = day;
451   tm.tm_year = year - 1900;
452     
453   time = mktime (&tm);
454   
455   return time;
456 #undef GET_LONG_RANGE
457 }
458
459 static int
460 key_lifetime_set (struct vty *vty, struct key_range *krange,
461                   const char *stime_str, const char *sday_str,
462                   const char *smonth_str, const char *syear_str,
463                   const char *etime_str, const char *eday_str,
464                   const char *emonth_str, const char *eyear_str)
465 {
466   time_t time_start;
467   time_t time_end;
468   
469   time_start = key_str2time (stime_str, sday_str, smonth_str, syear_str);
470   if (time_start < 0)
471     {
472       vty_out (vty, "Malformed time value%s", VTY_NEWLINE);
473       return CMD_WARNING;
474     }
475   time_end = key_str2time (etime_str, eday_str, emonth_str, eyear_str);
476
477   if (time_end < 0)
478     {
479       vty_out (vty, "Malformed time value%s", VTY_NEWLINE);
480       return CMD_WARNING;
481     }
482
483   if (time_end <= time_start)
484     {
485       vty_out (vty, "Expire time is not later than start time%s", VTY_NEWLINE);
486       return CMD_WARNING;
487     }
488
489   krange->start = time_start;
490   krange->end = time_end;
491
492   return CMD_SUCCESS;
493 }
494
495 static int
496 key_lifetime_duration_set (struct vty *vty, struct key_range *krange,
497                            const char *stime_str, const char *sday_str,
498                            const char *smonth_str, const char *syear_str,
499                            const char *duration_str)
500 {
501   time_t time_start;
502   u_int32_t duration;
503     
504   time_start = key_str2time (stime_str, sday_str, smonth_str, syear_str);
505   if (time_start < 0)
506     {
507       vty_out (vty, "Malformed time value%s", VTY_NEWLINE);
508       return CMD_WARNING;
509     }
510   krange->start = time_start;
511
512   VTY_GET_INTEGER ("duration", duration, duration_str);
513   krange->duration = 1;
514   krange->end = time_start + duration;
515
516   return CMD_SUCCESS;
517 }
518
519 static int
520 key_lifetime_infinite_set (struct vty *vty, struct key_range *krange,
521                            const char *stime_str, const char *sday_str,
522                            const char *smonth_str, const char *syear_str)
523 {
524   time_t time_start;
525     
526   time_start = key_str2time (stime_str, sday_str, smonth_str, syear_str);
527   if (time_start < 0)
528     {
529       vty_out (vty, "Malformed time value%s", VTY_NEWLINE);
530       return CMD_WARNING;
531     }
532   krange->start = time_start;
533
534   krange->end = -1;
535
536   return CMD_SUCCESS;
537 }
538
539 DEFUN (accept_lifetime_day_month_day_month,
540        accept_lifetime_day_month_day_month_cmd,
541        "accept-lifetime HH:MM:SS <1-31> MONTH <1993-2035> HH:MM:SS <1-31> MONTH <1993-2035>",
542        "Set accept lifetime of the key\n"
543        "Time to start\n"
544        "Day of th month to start\n"
545        "Month of the year to start\n"
546        "Year to start\n"
547        "Time to expire\n"
548        "Day of th month to expire\n"
549        "Month of the year to expire\n"
550        "Year to expire\n")
551 {
552   struct key *key;
553
554   key = vty->index_sub;
555
556   return key_lifetime_set (vty, &key->accept, argv[0], argv[1], argv[2],
557                            argv[3], argv[4], argv[5], argv[6], argv[7]);
558 }
559
560 DEFUN (accept_lifetime_day_month_month_day,
561        accept_lifetime_day_month_month_day_cmd,
562        "accept-lifetime HH:MM:SS <1-31> MONTH <1993-2035> HH:MM:SS MONTH <1-31> <1993-2035>",
563        "Set accept lifetime of the key\n"
564        "Time to start\n"
565        "Day of th month to start\n"
566        "Month of the year to start\n"
567        "Year to start\n"
568        "Time to expire\n"
569        "Month of the year to expire\n"
570        "Day of th month to expire\n"
571        "Year to expire\n")
572 {
573   struct key *key;
574
575   key = vty->index_sub;
576
577   return key_lifetime_set (vty, &key->accept, argv[0], argv[1], argv[2],
578                            argv[3], argv[4], argv[6], argv[5], argv[7]);
579 }
580
581 DEFUN (accept_lifetime_month_day_day_month,
582        accept_lifetime_month_day_day_month_cmd,
583        "accept-lifetime HH:MM:SS MONTH <1-31> <1993-2035> HH:MM:SS <1-31> MONTH <1993-2035>",
584        "Set accept lifetime of the key\n"
585        "Time to start\n"
586        "Month of the year to start\n"
587        "Day of th month to start\n"
588        "Year to start\n"
589        "Time to expire\n"
590        "Day of th month to expire\n"
591        "Month of the year to expire\n"
592        "Year to expire\n")
593 {
594   struct key *key;
595
596   key = vty->index_sub;
597
598   return key_lifetime_set (vty, &key->accept, argv[0], argv[2], argv[1],
599                            argv[3], argv[4], argv[5], argv[6], argv[7]);
600 }
601
602 DEFUN (accept_lifetime_month_day_month_day,
603        accept_lifetime_month_day_month_day_cmd,
604        "accept-lifetime HH:MM:SS MONTH <1-31> <1993-2035> HH:MM:SS MONTH <1-31> <1993-2035>",
605        "Set accept lifetime of the key\n"
606        "Time to start\n"
607        "Month of the year to start\n"
608        "Day of th month to start\n"
609        "Year to start\n"
610        "Time to expire\n"
611        "Month of the year to expire\n"
612        "Day of th month to expire\n"
613        "Year to expire\n")
614 {
615   struct key *key;
616
617   key = vty->index_sub;
618
619   return key_lifetime_set (vty, &key->accept, argv[0], argv[2], argv[1],
620                            argv[3], argv[4], argv[6], argv[5], argv[7]);
621 }
622
623 DEFUN (accept_lifetime_infinite_day_month,
624        accept_lifetime_infinite_day_month_cmd,
625        "accept-lifetime HH:MM:SS <1-31> MONTH <1993-2035> infinite",
626        "Set accept lifetime of the key\n"
627        "Time to start\n"
628        "Day of th month to start\n"
629        "Month of the year to start\n"
630        "Year to start\n"
631        "Never expires")
632 {
633   struct key *key;
634
635   key = vty->index_sub;
636
637   return key_lifetime_infinite_set (vty, &key->accept, argv[0], argv[1],
638                                     argv[2], argv[3]);
639 }
640
641 DEFUN (accept_lifetime_infinite_month_day,
642        accept_lifetime_infinite_month_day_cmd,
643        "accept-lifetime HH:MM:SS MONTH <1-31> <1993-2035> infinite",
644        "Set accept lifetime of the key\n"
645        "Time to start\n"
646        "Month of the year to start\n"
647        "Day of th month to start\n"
648        "Year to start\n"
649        "Never expires")
650 {
651   struct key *key;
652
653   key = vty->index_sub;
654
655   return key_lifetime_infinite_set (vty, &key->accept, argv[0], argv[2],
656                                     argv[1], argv[3]);
657 }
658
659 DEFUN (accept_lifetime_duration_day_month,
660        accept_lifetime_duration_day_month_cmd,
661        "accept-lifetime HH:MM:SS <1-31> MONTH <1993-2035> duration <1-2147483646>",
662        "Set accept lifetime of the key\n"
663        "Time to start\n"
664        "Day of th month to start\n"
665        "Month of the year to start\n"
666        "Year to start\n"
667        "Duration of the key\n"
668        "Duration seconds\n")
669 {
670   struct key *key;
671
672   key = vty->index_sub;
673
674   return key_lifetime_duration_set (vty, &key->accept, argv[0], argv[1],
675                                     argv[2], argv[3], argv[4]);
676 }
677
678 DEFUN (accept_lifetime_duration_month_day,
679        accept_lifetime_duration_month_day_cmd,
680        "accept-lifetime HH:MM:SS MONTH <1-31> <1993-2035> duration <1-2147483646>",
681        "Set accept lifetime of the key\n"
682        "Time to start\n"
683        "Month of the year to start\n"
684        "Day of th month to start\n"
685        "Year to start\n"
686        "Duration of the key\n"
687        "Duration seconds\n")
688 {
689   struct key *key;
690
691   key = vty->index_sub;
692
693   return key_lifetime_duration_set (vty, &key->accept, argv[0], argv[2],
694                                     argv[1], argv[3], argv[4]);
695 }
696
697 DEFUN (send_lifetime_day_month_day_month,
698        send_lifetime_day_month_day_month_cmd,
699        "send-lifetime HH:MM:SS <1-31> MONTH <1993-2035> HH:MM:SS <1-31> MONTH <1993-2035>",
700        "Set send lifetime of the key\n"
701        "Time to start\n"
702        "Day of th month to start\n"
703        "Month of the year to start\n"
704        "Year to start\n"
705        "Time to expire\n"
706        "Day of th month to expire\n"
707        "Month of the year to expire\n"
708        "Year to expire\n")
709 {
710   struct key *key;
711
712   key = vty->index_sub;
713
714   return key_lifetime_set (vty, &key->send, argv[0], argv[1], argv[2], argv[3],
715                            argv[4], argv[5], argv[6], argv[7]);
716 }
717
718 DEFUN (send_lifetime_day_month_month_day,
719        send_lifetime_day_month_month_day_cmd,
720        "send-lifetime HH:MM:SS <1-31> MONTH <1993-2035> HH:MM:SS MONTH <1-31> <1993-2035>",
721        "Set send lifetime of the key\n"
722        "Time to start\n"
723        "Day of th month to start\n"
724        "Month of the year to start\n"
725        "Year to start\n"
726        "Time to expire\n"
727        "Month of the year to expire\n"
728        "Day of th month to expire\n"
729        "Year to expire\n")
730 {
731   struct key *key;
732
733   key = vty->index_sub;
734
735   return key_lifetime_set (vty, &key->send, argv[0], argv[1], argv[2], argv[3],
736                            argv[4], argv[6], argv[5], argv[7]);
737 }
738
739 DEFUN (send_lifetime_month_day_day_month,
740        send_lifetime_month_day_day_month_cmd,
741        "send-lifetime HH:MM:SS MONTH <1-31> <1993-2035> HH:MM:SS <1-31> MONTH <1993-2035>",
742        "Set send lifetime of the key\n"
743        "Time to start\n"
744        "Month of the year to start\n"
745        "Day of th month to start\n"
746        "Year to start\n"
747        "Time to expire\n"
748        "Day of th month to expire\n"
749        "Month of the year to expire\n"
750        "Year to expire\n")
751 {
752   struct key *key;
753
754   key = vty->index_sub;
755
756   return key_lifetime_set (vty, &key->send, argv[0], argv[2], argv[1], argv[3],
757                            argv[4], argv[5], argv[6], argv[7]);
758 }
759
760 DEFUN (send_lifetime_month_day_month_day,
761        send_lifetime_month_day_month_day_cmd,
762        "send-lifetime HH:MM:SS MONTH <1-31> <1993-2035> HH:MM:SS MONTH <1-31> <1993-2035>",
763        "Set send lifetime of the key\n"
764        "Time to start\n"
765        "Month of the year to start\n"
766        "Day of th month to start\n"
767        "Year to start\n"
768        "Time to expire\n"
769        "Month of the year to expire\n"
770        "Day of th month to expire\n"
771        "Year to expire\n")
772 {
773   struct key *key;
774
775   key = vty->index_sub;
776
777   return key_lifetime_set (vty, &key->send, argv[0], argv[2], argv[1], argv[3],
778                            argv[4], argv[6], argv[5], argv[7]);
779 }
780
781 DEFUN (send_lifetime_infinite_day_month,
782        send_lifetime_infinite_day_month_cmd,
783        "send-lifetime HH:MM:SS <1-31> MONTH <1993-2035> infinite",
784        "Set send lifetime of the key\n"
785        "Time to start\n"
786        "Day of th month to start\n"
787        "Month of the year to start\n"
788        "Year to start\n"
789        "Never expires")
790 {
791   struct key *key;
792
793   key = vty->index_sub;
794
795   return key_lifetime_infinite_set (vty, &key->send, argv[0], argv[1], argv[2],
796                                     argv[3]);
797 }
798
799 DEFUN (send_lifetime_infinite_month_day,
800        send_lifetime_infinite_month_day_cmd,
801        "send-lifetime HH:MM:SS MONTH <1-31> <1993-2035> infinite",
802        "Set send lifetime of the key\n"
803        "Time to start\n"
804        "Month of the year to start\n"
805        "Day of th month to start\n"
806        "Year to start\n"
807        "Never expires")
808 {
809   struct key *key;
810
811   key = vty->index_sub;
812
813   return key_lifetime_infinite_set (vty, &key->send, argv[0], argv[2], argv[1],
814                                     argv[3]);
815 }
816
817 DEFUN (send_lifetime_duration_day_month,
818        send_lifetime_duration_day_month_cmd,
819        "send-lifetime HH:MM:SS <1-31> MONTH <1993-2035> duration <1-2147483646>",
820        "Set send lifetime of the key\n"
821        "Time to start\n"
822        "Day of th month to start\n"
823        "Month of the year to start\n"
824        "Year to start\n"
825        "Duration of the key\n"
826        "Duration seconds\n")
827 {
828   struct key *key;
829
830   key = vty->index_sub;
831
832   return key_lifetime_duration_set (vty, &key->send, argv[0], argv[1], argv[2],
833                                     argv[3], argv[4]);
834 }
835
836 DEFUN (send_lifetime_duration_month_day,
837        send_lifetime_duration_month_day_cmd,
838        "send-lifetime HH:MM:SS MONTH <1-31> <1993-2035> duration <1-2147483646>",
839        "Set send lifetime of the key\n"
840        "Time to start\n"
841        "Month of the year to start\n"
842        "Day of th month to start\n"
843        "Year to start\n"
844        "Duration of the key\n"
845        "Duration seconds\n")
846 {
847   struct key *key;
848
849   key = vty->index_sub;
850
851   return key_lifetime_duration_set (vty, &key->send, argv[0], argv[2], argv[1],
852                                     argv[3], argv[4]);
853 }
854
855 static struct cmd_node keychain_node =
856 {
857   KEYCHAIN_NODE,
858   "%s(config-keychain)# ",
859   1
860 };
861
862 static struct cmd_node keychain_key_node =
863 {
864   KEYCHAIN_KEY_NODE,
865   "%s(config-keychain-key)# ",
866   1
867 };
868
869 static int
870 keychain_strftime (char *buf, int bufsiz, time_t *time)
871 {
872   struct tm *tm;
873   size_t len;
874
875   tm = localtime (time);
876
877   len = strftime (buf, bufsiz, "%T %b %d %Y", tm);
878
879   return len;
880 }
881
882 static int
883 keychain_config_write (struct vty *vty)
884 {
885   struct keychain *keychain;
886   struct key *key;
887   struct listnode *node;
888   struct listnode *knode;
889   char buf[BUFSIZ];
890
891   for (ALL_LIST_ELEMENTS_RO (keychain_list, node, keychain))
892     {
893       vty_out (vty, "key chain %s%s", keychain->name, VTY_NEWLINE);
894       
895       for (ALL_LIST_ELEMENTS_RO (keychain->key, knode, key))
896         {
897           vty_out (vty, " key %d%s", key->index, VTY_NEWLINE);
898
899           if (key->string)
900             vty_out (vty, "  key-string %s%s", key->string, VTY_NEWLINE);
901
902           if (key->accept.start)
903             {
904               keychain_strftime (buf, BUFSIZ, &key->accept.start);
905               vty_out (vty, "  accept-lifetime %s", buf);
906
907               if (key->accept.end == -1)
908                 vty_out (vty, " infinite");
909               else if (key->accept.duration)
910                 vty_out (vty, " duration %ld",
911                          (long)(key->accept.end - key->accept.start));
912               else
913                 {
914                   keychain_strftime (buf, BUFSIZ, &key->accept.end);
915                   vty_out (vty, " %s", buf);
916                 }
917               vty_out (vty, "%s", VTY_NEWLINE);
918             }
919
920           if (key->send.start)
921             {
922               keychain_strftime (buf, BUFSIZ, &key->send.start);
923               vty_out (vty, "  send-lifetime %s", buf);
924
925               if (key->send.end == -1)
926                 vty_out (vty, " infinite");
927               else if (key->send.duration)
928                 vty_out (vty, " duration %ld", (long)(key->send.end - key->send.start));
929               else
930                 {
931                   keychain_strftime (buf, BUFSIZ, &key->send.end);
932                   vty_out (vty, " %s", buf);
933                 }
934               vty_out (vty, "%s", VTY_NEWLINE);
935             }
936         }
937       vty_out (vty, "!%s", VTY_NEWLINE);
938     }
939
940   return 0;
941 }
942
943 void
944 keychain_init ()
945 {
946   keychain_list = list_new ();
947
948   install_node (&keychain_node, keychain_config_write);
949   install_node (&keychain_key_node, NULL);
950
951   install_default (KEYCHAIN_NODE);
952   install_default (KEYCHAIN_KEY_NODE);
953
954   install_element (CONFIG_NODE, &key_chain_cmd);
955   install_element (CONFIG_NODE, &no_key_chain_cmd);
956   install_element (KEYCHAIN_NODE, &key_cmd);
957   install_element (KEYCHAIN_NODE, &no_key_cmd);
958
959   install_element (KEYCHAIN_NODE, &key_chain_cmd);
960   install_element (KEYCHAIN_NODE, &no_key_chain_cmd);
961
962   install_element (KEYCHAIN_KEY_NODE, &key_string_cmd);
963   install_element (KEYCHAIN_KEY_NODE, &no_key_string_cmd);
964
965   install_element (KEYCHAIN_KEY_NODE, &key_chain_cmd);
966   install_element (KEYCHAIN_KEY_NODE, &no_key_chain_cmd);
967
968   install_element (KEYCHAIN_KEY_NODE, &key_cmd);
969   install_element (KEYCHAIN_KEY_NODE, &no_key_cmd);
970
971   install_element (KEYCHAIN_KEY_NODE, &accept_lifetime_day_month_day_month_cmd);
972   install_element (KEYCHAIN_KEY_NODE, &accept_lifetime_day_month_month_day_cmd);
973   install_element (KEYCHAIN_KEY_NODE, &accept_lifetime_month_day_day_month_cmd);
974   install_element (KEYCHAIN_KEY_NODE, &accept_lifetime_month_day_month_day_cmd);
975   install_element (KEYCHAIN_KEY_NODE, &accept_lifetime_infinite_day_month_cmd);
976   install_element (KEYCHAIN_KEY_NODE, &accept_lifetime_infinite_month_day_cmd);
977   install_element (KEYCHAIN_KEY_NODE, &accept_lifetime_duration_day_month_cmd);
978   install_element (KEYCHAIN_KEY_NODE, &accept_lifetime_duration_month_day_cmd);
979
980   install_element (KEYCHAIN_KEY_NODE, &send_lifetime_day_month_day_month_cmd);
981   install_element (KEYCHAIN_KEY_NODE, &send_lifetime_day_month_month_day_cmd);
982   install_element (KEYCHAIN_KEY_NODE, &send_lifetime_month_day_day_month_cmd);
983   install_element (KEYCHAIN_KEY_NODE, &send_lifetime_month_day_month_day_cmd);
984   install_element (KEYCHAIN_KEY_NODE, &send_lifetime_infinite_day_month_cmd);
985   install_element (KEYCHAIN_KEY_NODE, &send_lifetime_infinite_month_day_cmd);
986   install_element (KEYCHAIN_KEY_NODE, &send_lifetime_duration_day_month_cmd);
987   install_element (KEYCHAIN_KEY_NODE, &send_lifetime_duration_month_day_cmd);
988 }