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