From e51e8900b83ac6975479b6f081f782447638bf9e Mon Sep 17 00:00:00 2001 From: Christian Hopps Date: Sat, 24 Feb 2024 05:48:40 -0500 Subject: [PATCH] lib: add keychain northbound support Signed-off-by: Christian Hopps --- eigrpd/eigrp_main.c | 2 + lib/keychain.c | 1011 +--------------------------------- lib/keychain.h | 38 ++ lib/keychain_cli.c | 1033 +++++++++++++++++++++++++++++++++++ lib/keychain_nb.c | 1150 +++++++++++++++++---------------------- lib/subdir.am | 5 + lib/yang_wrappers.c | 26 + lib/yang_wrappers.h | 5 + mgmtd/mgmt_be_adapter.c | 2 + mgmtd/mgmt_main.c | 23 +- mgmtd/mgmt_vty.c | 2 + ospf6d/ospf6_main.c | 20 +- ospfd/ospf_main.c | 2 + python/xref2vtysh.py | 2 +- ripd/rip_main.c | 4 +- vtysh/vtysh.h | 2 +- 16 files changed, 1658 insertions(+), 1669 deletions(-) create mode 100644 lib/keychain_cli.c diff --git a/eigrpd/eigrp_main.c b/eigrpd/eigrp_main.c index 552ba7cd96a7..1491c569ec59 100644 --- a/eigrpd/eigrp_main.c +++ b/eigrpd/eigrp_main.c @@ -132,6 +132,8 @@ static const struct frr_yang_module_info *const eigrpd_yang_modules[] = { &frr_interface_info, &frr_route_map_info, &frr_vrf_info, + &ietf_key_chain_info, + &ietf_key_chain_deviation_info, }; /* clang-format off */ diff --git a/lib/keychain.c b/lib/keychain.c index 5ff0d1e43e9d..1982220bc7e3 100644 --- a/lib/keychain.c +++ b/lib/keychain.c @@ -6,19 +6,19 @@ #include "config.h" #include -#include "command.h" -#include "memory.h" -#include "linklist.h" #include "keychain.h" +#include "linklist.h" +#include "memory.h" -DEFINE_MTYPE_STATIC(LIB, KEY, "Key"); -DEFINE_MTYPE_STATIC(LIB, KEYCHAIN, "Key chain"); +DEFINE_MTYPE(LIB, KEY, "Key"); +DEFINE_MTYPE(LIB, KEYCHAIN, "Key chain"); +DEFINE_MTYPE(LIB, KEYCHAIN_DESC, "Key chain description"); DEFINE_QOBJ_TYPE(keychain); DEFINE_QOBJ_TYPE(key); /* Master list of key chain. */ -static struct list *keychain_list; +struct list *keychain_list; static struct keychain *keychain_new(void) { @@ -82,7 +82,7 @@ static void key_delete_func(struct key *key) key_free(key); } -static struct keychain *keychain_get(const char *name) +struct keychain *keychain_get(const char *name) { struct keychain *keychain; @@ -101,7 +101,7 @@ static struct keychain *keychain_get(const char *name) return keychain; } -static void keychain_delete(struct keychain *keychain) +void keychain_delete(struct keychain *keychain) { XFREE(MTYPE_KEYCHAIN, keychain->name); @@ -110,7 +110,7 @@ static void keychain_delete(struct keychain *keychain) keychain_free(keychain); } -static struct key *key_lookup(const struct keychain *keychain, uint32_t index) +struct key *key_lookup(const struct keychain *keychain, uint32_t index) { struct listnode *node; struct key *key; @@ -183,7 +183,7 @@ struct key *key_lookup_for_send(const struct keychain *keychain) return NULL; } -static struct key *key_get(const struct keychain *keychain, uint32_t index) +struct key *key_get(const struct keychain *keychain, uint32_t index) { struct key *key; @@ -200,7 +200,7 @@ static struct key *key_get(const struct keychain *keychain, uint32_t index) return key; } -static void key_delete(struct keychain *keychain, struct key *key) +void key_delete(struct keychain *keychain, struct key *key) { listnode_delete(keychain->key, key); @@ -208,122 +208,6 @@ static void key_delete(struct keychain *keychain, struct key *key) key_free(key); } -DEFUN_NOSH (key_chain, - key_chain_cmd, - "key chain WORD", - "Authentication key management\n" - "Key-chain management\n" - "Key-chain name\n") -{ - int idx_word = 2; - struct keychain *keychain; - - keychain = keychain_get(argv[idx_word]->arg); - VTY_PUSH_CONTEXT(KEYCHAIN_NODE, keychain); - - return CMD_SUCCESS; -} - -DEFUN (no_key_chain, - no_key_chain_cmd, - "no key chain WORD", - NO_STR - "Authentication key management\n" - "Key-chain management\n" - "Key-chain name\n") -{ - int idx_word = 3; - struct keychain *keychain; - - keychain = keychain_lookup(argv[idx_word]->arg); - - if (!keychain) { - vty_out(vty, "Can't find keychain %s\n", argv[idx_word]->arg); - return CMD_WARNING_CONFIG_FAILED; - } - - keychain_delete(keychain); - - return CMD_SUCCESS; -} - -DEFUN_NOSH (key, - key_cmd, - "key (0-2147483647)", - "Configure a key\n" - "Key identifier number\n") -{ - int idx_number = 1; - VTY_DECLVAR_CONTEXT(keychain, keychain); - struct key *key; - uint32_t index; - - index = strtoul(argv[idx_number]->arg, NULL, 10); - key = key_get(keychain, index); - VTY_PUSH_CONTEXT_SUB(KEYCHAIN_KEY_NODE, key); - - return CMD_SUCCESS; -} - -DEFUN (no_key, - no_key_cmd, - "no key (0-2147483647)", - NO_STR - "Delete a key\n" - "Key identifier number\n") -{ - int idx_number = 2; - VTY_DECLVAR_CONTEXT(keychain, keychain); - struct key *key; - uint32_t index; - - index = strtoul(argv[idx_number]->arg, NULL, 10); - key = key_lookup(keychain, index); - if (!key) { - vty_out(vty, "Can't find key %d\n", index); - return CMD_WARNING_CONFIG_FAILED; - } - - key_delete(keychain, key); - - vty->node = KEYCHAIN_NODE; - - return CMD_SUCCESS; -} - -DEFUN (key_string, - key_string_cmd, - "key-string LINE", - "Set key string\n" - "The key\n") -{ - int idx_line = 1; - VTY_DECLVAR_CONTEXT_SUB(key, key); - - if (key->string) - XFREE(MTYPE_KEY, key->string); - key->string = XSTRDUP(MTYPE_KEY, argv[idx_line]->arg); - - return CMD_SUCCESS; -} - -DEFUN (no_key_string, - no_key_string_cmd, - "no key-string [LINE]", - NO_STR - "Unset key string\n" - "The key\n") -{ - VTY_DECLVAR_CONTEXT_SUB(key, key); - - if (key->string) { - XFREE(MTYPE_KEY, key->string); - key->string = NULL; - } - - return CMD_SUCCESS; -} - const struct keychain_algo_info algo_info[] = { {KEYCHAIN_ALGO_NULL, "null", 0, 0, "NULL"}, {KEYCHAIN_ALGO_MD5, "md5", KEYCHAIN_MD5_HASH_SIZE, @@ -394,800 +278,6 @@ const char *keychain_get_algo_name_by_id(enum keychain_hash_algo key) return algo_info[key].name; } -DEFUN(cryptographic_algorithm, cryptographic_algorithm_cmd, - "cryptographic-algorithm " - "", - "Cryptographic-algorithm\n" - "Use MD5 algorithm\n" - "Use HMAC-SHA-1 algorithm\n" - "Use HMAC-SHA-256 algorithm\n" - "Use HMAC-SHA-384 algorithm\n" - "Use HMAC-SHA-512 algorithm\n") -{ - int algo_idx = 1; - uint8_t hash_algo = KEYCHAIN_ALGO_NULL; - - VTY_DECLVAR_CONTEXT_SUB(key, key); - hash_algo = keychain_get_algo_id_by_name(argv[algo_idx]->arg); -#ifndef CRYPTO_OPENSSL - if (hash_algo == KEYCHAIN_ALGO_NULL) { - vty_out(vty, - "Hash algorithm not supported, compile with --with-crypto=openssl\n"); - return CMD_WARNING_CONFIG_FAILED; - } -#endif /* CRYPTO_OPENSSL */ - key->hash_algo = hash_algo; - return CMD_SUCCESS; -} - -DEFUN(no_cryptographic_algorithm, no_cryptographic_algorithm_cmd, - "no cryptographic-algorithm " - "[]", - NO_STR - "Cryptographic-algorithm\n" - "Use MD5 algorithm\n" - "Use HMAC-SHA-1 algorithm\n" - "Use HMAC-SHA-256 algorithm\n" - "Use HMAC-SHA-384 algorithm\n" - "Use HMAC-SHA-512 algorithm\n") -{ - int algo_idx = 2; - uint8_t hash_algo = KEYCHAIN_ALGO_NULL; - - VTY_DECLVAR_CONTEXT_SUB(key, key); - if (argc > algo_idx) { - hash_algo = keychain_get_algo_id_by_name(argv[algo_idx]->arg); - if (hash_algo == KEYCHAIN_ALGO_NULL) { - vty_out(vty, - "Hash algorithm not supported, try compiling with --with-crypto=openssl\n"); - return CMD_WARNING_CONFIG_FAILED; - } - } - - if ((hash_algo != KEYCHAIN_ALGO_NULL) && (hash_algo != key->hash_algo)) - return CMD_SUCCESS; - - key->hash_algo = KEYCHAIN_ALGO_NULL; - return CMD_SUCCESS; -} - -/* Convert HH:MM:SS MON DAY YEAR to time_t value. -1 is returned when - given string is malformed. */ -static time_t key_str2time(const char *time_str, const char *day_str, - const char *month_str, const char *year_str) -{ - int i = 0; - char *colon; - struct tm tm; - time_t time; - unsigned int sec, min, hour; - unsigned int day, month, year; - - const char *month_name[] = { - "January", "February", "March", "April", "May", - "June", "July", "August", "September", "October", - "November", "December", NULL}; - -#define _GET_LONG_RANGE(V, STR, MMCOND) \ - { \ - unsigned long tmpl; \ - char *endptr = NULL; \ - tmpl = strtoul((STR), &endptr, 10); \ - if (*endptr != '\0' || tmpl == ULONG_MAX) \ - return -1; \ - if (MMCOND) \ - return -1; \ - (V) = tmpl; \ - } -#define GET_LONG_RANGE(V, STR, MIN, MAX) \ - _GET_LONG_RANGE(V, STR, tmpl<(MIN) || tmpl>(MAX)) -#define GET_LONG_RANGE0(V, STR, MAX) _GET_LONG_RANGE(V, STR, tmpl > (MAX)) - - /* Check hour field of time_str. */ - colon = strchr(time_str, ':'); - if (colon == NULL) - return -1; - *colon = '\0'; - - /* Hour must be between 0 and 23. */ - GET_LONG_RANGE0(hour, time_str, 23); - - /* Check min field of time_str. */ - time_str = colon + 1; - colon = strchr(time_str, ':'); - if (*time_str == '\0' || colon == NULL) - return -1; - *colon = '\0'; - - /* Min must be between 0 and 59. */ - GET_LONG_RANGE0(min, time_str, 59); - - /* Check sec field of time_str. */ - time_str = colon + 1; - if (*time_str == '\0') - return -1; - - /* Sec must be between 0 and 59. */ - GET_LONG_RANGE0(sec, time_str, 59); - - /* Check day_str. Day must be <1-31>. */ - GET_LONG_RANGE(day, day_str, 1, 31); - - /* Check month_str. Month must match month_name. */ - month = 0; - if (strlen(month_str) >= 3) - for (i = 0; month_name[i]; i++) - if (strncmp(month_str, month_name[i], strlen(month_str)) - == 0) { - month = i; - break; - } - if (!month_name[i]) - return -1; - - /* Check year_str. Year must be <1993-2035>. */ - GET_LONG_RANGE(year, year_str, 1993, 2035); - - memset(&tm, 0, sizeof(tm)); - tm.tm_sec = sec; - tm.tm_min = min; - tm.tm_hour = hour; - tm.tm_mon = month; - tm.tm_mday = day; - tm.tm_year = year - 1900; - - time = mktime(&tm); - - return time; -#undef GET_LONG_RANGE -} - -static int key_lifetime_set(struct vty *vty, struct key_range *krange, - const char *stime_str, const char *sday_str, - const char *smonth_str, const char *syear_str, - const char *etime_str, const char *eday_str, - const char *emonth_str, const char *eyear_str) -{ - time_t time_start; - time_t time_end; - - time_start = key_str2time(stime_str, sday_str, smonth_str, syear_str); - if (time_start < 0) { - vty_out(vty, "Malformed time value\n"); - return CMD_WARNING_CONFIG_FAILED; - } - time_end = key_str2time(etime_str, eday_str, emonth_str, eyear_str); - - if (time_end < 0) { - vty_out(vty, "Malformed time value\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (time_end <= time_start) { - vty_out(vty, "Expire time is not later than start time\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - krange->start = time_start; - krange->end = time_end; - - return CMD_SUCCESS; -} - -static int key_lifetime_duration_set(struct vty *vty, struct key_range *krange, - const char *stime_str, - const char *sday_str, - const char *smonth_str, - const char *syear_str, - const char *duration_str) -{ - time_t time_start; - uint32_t duration; - - time_start = key_str2time(stime_str, sday_str, smonth_str, syear_str); - if (time_start < 0) { - vty_out(vty, "Malformed time value\n"); - return CMD_WARNING_CONFIG_FAILED; - } - krange->start = time_start; - - duration = strtoul(duration_str, NULL, 10); - krange->duration = 1; - krange->end = time_start + duration; - - return CMD_SUCCESS; -} - -static int key_lifetime_infinite_set(struct vty *vty, struct key_range *krange, - const char *stime_str, - const char *sday_str, - const char *smonth_str, - const char *syear_str) -{ - time_t time_start; - - time_start = key_str2time(stime_str, sday_str, smonth_str, syear_str); - if (time_start < 0) { - vty_out(vty, "Malformed time value\n"); - return CMD_WARNING_CONFIG_FAILED; - } - krange->start = time_start; - - krange->end = -1; - - return CMD_SUCCESS; -} - -DEFUN (accept_lifetime_day_month_day_month, - accept_lifetime_day_month_day_month_cmd, - "accept-lifetime HH:MM:SS (1-31) MONTH (1993-2035) HH:MM:SS (1-31) MONTH (1993-2035)", - "Set accept lifetime of the key\n" - "Time to start\n" - "Day of th month to start\n" - "Month of the year to start\n" - "Year to start\n" - "Time to expire\n" - "Day of th month to expire\n" - "Month of the year to expire\n" - "Year to expire\n") -{ - int idx_hhmmss = 1; - int idx_number = 2; - int idx_month = 3; - int idx_number_2 = 4; - int idx_hhmmss_2 = 5; - int idx_number_3 = 6; - int idx_month_2 = 7; - int idx_number_4 = 8; - VTY_DECLVAR_CONTEXT_SUB(key, key); - - return key_lifetime_set( - vty, &key->accept, argv[idx_hhmmss]->arg, argv[idx_number]->arg, - argv[idx_month]->arg, argv[idx_number_2]->arg, - argv[idx_hhmmss_2]->arg, argv[idx_number_3]->arg, - argv[idx_month_2]->arg, argv[idx_number_4]->arg); -} - -DEFUN (accept_lifetime_day_month_month_day, - accept_lifetime_day_month_month_day_cmd, - "accept-lifetime HH:MM:SS (1-31) MONTH (1993-2035) HH:MM:SS MONTH (1-31) (1993-2035)", - "Set accept lifetime of the key\n" - "Time to start\n" - "Day of th month to start\n" - "Month of the year to start\n" - "Year to start\n" - "Time to expire\n" - "Month of the year to expire\n" - "Day of th month to expire\n" - "Year to expire\n") -{ - int idx_hhmmss = 1; - int idx_number = 2; - int idx_month = 3; - int idx_number_2 = 4; - int idx_hhmmss_2 = 5; - int idx_month_2 = 6; - int idx_number_3 = 7; - int idx_number_4 = 8; - VTY_DECLVAR_CONTEXT_SUB(key, key); - - return key_lifetime_set( - vty, &key->accept, argv[idx_hhmmss]->arg, argv[idx_number]->arg, - argv[idx_month]->arg, argv[idx_number_2]->arg, - argv[idx_hhmmss_2]->arg, argv[idx_number_3]->arg, - argv[idx_month_2]->arg, argv[idx_number_4]->arg); -} - -DEFUN (accept_lifetime_month_day_day_month, - accept_lifetime_month_day_day_month_cmd, - "accept-lifetime HH:MM:SS MONTH (1-31) (1993-2035) HH:MM:SS (1-31) MONTH (1993-2035)", - "Set accept lifetime of the key\n" - "Time to start\n" - "Month of the year to start\n" - "Day of th month to start\n" - "Year to start\n" - "Time to expire\n" - "Day of th month to expire\n" - "Month of the year to expire\n" - "Year to expire\n") -{ - int idx_hhmmss = 1; - int idx_month = 2; - int idx_number = 3; - int idx_number_2 = 4; - int idx_hhmmss_2 = 5; - int idx_number_3 = 6; - int idx_month_2 = 7; - int idx_number_4 = 8; - VTY_DECLVAR_CONTEXT_SUB(key, key); - - return key_lifetime_set( - vty, &key->accept, argv[idx_hhmmss]->arg, argv[idx_number]->arg, - argv[idx_month]->arg, argv[idx_number_2]->arg, - argv[idx_hhmmss_2]->arg, argv[idx_number_3]->arg, - argv[idx_month_2]->arg, argv[idx_number_4]->arg); -} - -DEFUN (accept_lifetime_month_day_month_day, - accept_lifetime_month_day_month_day_cmd, - "accept-lifetime HH:MM:SS MONTH (1-31) (1993-2035) HH:MM:SS MONTH (1-31) (1993-2035)", - "Set accept lifetime of the key\n" - "Time to start\n" - "Month of the year to start\n" - "Day of th month to start\n" - "Year to start\n" - "Time to expire\n" - "Month of the year to expire\n" - "Day of th month to expire\n" - "Year to expire\n") -{ - int idx_hhmmss = 1; - int idx_month = 2; - int idx_number = 3; - int idx_number_2 = 4; - int idx_hhmmss_2 = 5; - int idx_month_2 = 6; - int idx_number_3 = 7; - int idx_number_4 = 8; - VTY_DECLVAR_CONTEXT_SUB(key, key); - - return key_lifetime_set( - vty, &key->accept, argv[idx_hhmmss]->arg, argv[idx_number]->arg, - argv[idx_month]->arg, argv[idx_number_2]->arg, - argv[idx_hhmmss_2]->arg, argv[idx_number_3]->arg, - argv[idx_month_2]->arg, argv[idx_number_4]->arg); -} - -DEFUN (accept_lifetime_infinite_day_month, - accept_lifetime_infinite_day_month_cmd, - "accept-lifetime HH:MM:SS (1-31) MONTH (1993-2035) infinite", - "Set accept lifetime of the key\n" - "Time to start\n" - "Day of th month to start\n" - "Month of the year to start\n" - "Year to start\n" - "Never expires\n") -{ - int idx_hhmmss = 1; - int idx_number = 2; - int idx_month = 3; - int idx_number_2 = 4; - VTY_DECLVAR_CONTEXT_SUB(key, key); - - return key_lifetime_infinite_set( - vty, &key->accept, argv[idx_hhmmss]->arg, argv[idx_number]->arg, - argv[idx_month]->arg, argv[idx_number_2]->arg); -} - -DEFUN (accept_lifetime_infinite_month_day, - accept_lifetime_infinite_month_day_cmd, - "accept-lifetime HH:MM:SS MONTH (1-31) (1993-2035) infinite", - "Set accept lifetime of the key\n" - "Time to start\n" - "Month of the year to start\n" - "Day of th month to start\n" - "Year to start\n" - "Never expires\n") -{ - int idx_hhmmss = 1; - int idx_month = 2; - int idx_number = 3; - int idx_number_2 = 4; - VTY_DECLVAR_CONTEXT_SUB(key, key); - - return key_lifetime_infinite_set( - vty, &key->accept, argv[idx_hhmmss]->arg, argv[idx_number]->arg, - argv[idx_month]->arg, argv[idx_number_2]->arg); -} - -DEFUN (accept_lifetime_duration_day_month, - accept_lifetime_duration_day_month_cmd, - "accept-lifetime HH:MM:SS (1-31) MONTH (1993-2035) duration (1-2147483646)", - "Set accept lifetime of the key\n" - "Time to start\n" - "Day of th month to start\n" - "Month of the year to start\n" - "Year to start\n" - "Duration of the key\n" - "Duration seconds\n") -{ - int idx_hhmmss = 1; - int idx_number = 2; - int idx_month = 3; - int idx_number_2 = 4; - int idx_number_3 = 6; - VTY_DECLVAR_CONTEXT_SUB(key, key); - - return key_lifetime_duration_set( - vty, &key->accept, argv[idx_hhmmss]->arg, argv[idx_number]->arg, - argv[idx_month]->arg, argv[idx_number_2]->arg, - argv[idx_number_3]->arg); -} - -DEFUN (accept_lifetime_duration_month_day, - accept_lifetime_duration_month_day_cmd, - "accept-lifetime HH:MM:SS MONTH (1-31) (1993-2035) duration (1-2147483646)", - "Set accept lifetime of the key\n" - "Time to start\n" - "Month of the year to start\n" - "Day of th month to start\n" - "Year to start\n" - "Duration of the key\n" - "Duration seconds\n") -{ - int idx_hhmmss = 1; - int idx_month = 2; - int idx_number = 3; - int idx_number_2 = 4; - int idx_number_3 = 6; - VTY_DECLVAR_CONTEXT_SUB(key, key); - - return key_lifetime_duration_set( - vty, &key->accept, argv[idx_hhmmss]->arg, argv[idx_number]->arg, - argv[idx_month]->arg, argv[idx_number_2]->arg, - argv[idx_number_3]->arg); -} - -DEFUN (no_accept_lifetime, - no_accept_lifetime_cmd, - "no accept-lifetime", - NO_STR - "Unset accept-lifetime\n") -{ - VTY_DECLVAR_CONTEXT_SUB(key, key); - - if (key->accept.start) - key->accept.start = 0; - if (key->accept.end) - key->accept.end = 0; - if (key->accept.duration) - key->accept.duration = 0; - - return CMD_SUCCESS; -} - -DEFUN (send_lifetime_day_month_day_month, - send_lifetime_day_month_day_month_cmd, - "send-lifetime HH:MM:SS (1-31) MONTH (1993-2035) HH:MM:SS (1-31) MONTH (1993-2035)", - "Set send lifetime of the key\n" - "Time to start\n" - "Day of th month to start\n" - "Month of the year to start\n" - "Year to start\n" - "Time to expire\n" - "Day of th month to expire\n" - "Month of the year to expire\n" - "Year to expire\n") -{ - int idx_hhmmss = 1; - int idx_number = 2; - int idx_month = 3; - int idx_number_2 = 4; - int idx_hhmmss_2 = 5; - int idx_number_3 = 6; - int idx_month_2 = 7; - int idx_number_4 = 8; - VTY_DECLVAR_CONTEXT_SUB(key, key); - - return key_lifetime_set( - vty, &key->send, argv[idx_hhmmss]->arg, argv[idx_number]->arg, - argv[idx_month]->arg, argv[idx_number_2]->arg, - argv[idx_hhmmss_2]->arg, argv[idx_number_3]->arg, - argv[idx_month_2]->arg, argv[idx_number_4]->arg); -} - -DEFUN (send_lifetime_day_month_month_day, - send_lifetime_day_month_month_day_cmd, - "send-lifetime HH:MM:SS (1-31) MONTH (1993-2035) HH:MM:SS MONTH (1-31) (1993-2035)", - "Set send lifetime of the key\n" - "Time to start\n" - "Day of th month to start\n" - "Month of the year to start\n" - "Year to start\n" - "Time to expire\n" - "Month of the year to expire\n" - "Day of th month to expire\n" - "Year to expire\n") -{ - int idx_hhmmss = 1; - int idx_number = 2; - int idx_month = 3; - int idx_number_2 = 4; - int idx_hhmmss_2 = 5; - int idx_month_2 = 6; - int idx_number_3 = 7; - int idx_number_4 = 8; - VTY_DECLVAR_CONTEXT_SUB(key, key); - - return key_lifetime_set( - vty, &key->send, argv[idx_hhmmss]->arg, argv[idx_number]->arg, - argv[idx_month]->arg, argv[idx_number_2]->arg, - argv[idx_hhmmss_2]->arg, argv[idx_number_3]->arg, - argv[idx_month_2]->arg, argv[idx_number_4]->arg); -} - -DEFUN (send_lifetime_month_day_day_month, - send_lifetime_month_day_day_month_cmd, - "send-lifetime HH:MM:SS MONTH (1-31) (1993-2035) HH:MM:SS (1-31) MONTH (1993-2035)", - "Set send lifetime of the key\n" - "Time to start\n" - "Month of the year to start\n" - "Day of th month to start\n" - "Year to start\n" - "Time to expire\n" - "Day of th month to expire\n" - "Month of the year to expire\n" - "Year to expire\n") -{ - int idx_hhmmss = 1; - int idx_month = 2; - int idx_number = 3; - int idx_number_2 = 4; - int idx_hhmmss_2 = 5; - int idx_number_3 = 6; - int idx_month_2 = 7; - int idx_number_4 = 8; - VTY_DECLVAR_CONTEXT_SUB(key, key); - - return key_lifetime_set( - vty, &key->send, argv[idx_hhmmss]->arg, argv[idx_number]->arg, - argv[idx_month]->arg, argv[idx_number_2]->arg, - argv[idx_hhmmss_2]->arg, argv[idx_number_3]->arg, - argv[idx_month_2]->arg, argv[idx_number_4]->arg); -} - -DEFUN (send_lifetime_month_day_month_day, - send_lifetime_month_day_month_day_cmd, - "send-lifetime HH:MM:SS MONTH (1-31) (1993-2035) HH:MM:SS MONTH (1-31) (1993-2035)", - "Set send lifetime of the key\n" - "Time to start\n" - "Month of the year to start\n" - "Day of th month to start\n" - "Year to start\n" - "Time to expire\n" - "Month of the year to expire\n" - "Day of th month to expire\n" - "Year to expire\n") -{ - int idx_hhmmss = 1; - int idx_month = 2; - int idx_number = 3; - int idx_number_2 = 4; - int idx_hhmmss_2 = 5; - int idx_month_2 = 6; - int idx_number_3 = 7; - int idx_number_4 = 8; - VTY_DECLVAR_CONTEXT_SUB(key, key); - - return key_lifetime_set( - vty, &key->send, argv[idx_hhmmss]->arg, argv[idx_number]->arg, - argv[idx_month]->arg, argv[idx_number_2]->arg, - argv[idx_hhmmss_2]->arg, argv[idx_number_3]->arg, - argv[idx_month_2]->arg, argv[idx_number_4]->arg); -} - -DEFUN (send_lifetime_infinite_day_month, - send_lifetime_infinite_day_month_cmd, - "send-lifetime HH:MM:SS (1-31) MONTH (1993-2035) infinite", - "Set send lifetime of the key\n" - "Time to start\n" - "Day of th month to start\n" - "Month of the year to start\n" - "Year to start\n" - "Never expires\n") -{ - int idx_hhmmss = 1; - int idx_number = 2; - int idx_month = 3; - int idx_number_2 = 4; - VTY_DECLVAR_CONTEXT_SUB(key, key); - - return key_lifetime_infinite_set( - vty, &key->send, argv[idx_hhmmss]->arg, argv[idx_number]->arg, - argv[idx_month]->arg, argv[idx_number_2]->arg); -} - -DEFUN (send_lifetime_infinite_month_day, - send_lifetime_infinite_month_day_cmd, - "send-lifetime HH:MM:SS MONTH (1-31) (1993-2035) infinite", - "Set send lifetime of the key\n" - "Time to start\n" - "Month of the year to start\n" - "Day of th month to start\n" - "Year to start\n" - "Never expires\n") -{ - int idx_hhmmss = 1; - int idx_month = 2; - int idx_number = 3; - int idx_number_2 = 4; - VTY_DECLVAR_CONTEXT_SUB(key, key); - - return key_lifetime_infinite_set( - vty, &key->send, argv[idx_hhmmss]->arg, argv[idx_number]->arg, - argv[idx_month]->arg, argv[idx_number_2]->arg); -} - -DEFUN (send_lifetime_duration_day_month, - send_lifetime_duration_day_month_cmd, - "send-lifetime HH:MM:SS (1-31) MONTH (1993-2035) duration (1-2147483646)", - "Set send lifetime of the key\n" - "Time to start\n" - "Day of th month to start\n" - "Month of the year to start\n" - "Year to start\n" - "Duration of the key\n" - "Duration seconds\n") -{ - int idx_hhmmss = 1; - int idx_number = 2; - int idx_month = 3; - int idx_number_2 = 4; - int idx_number_3 = 6; - VTY_DECLVAR_CONTEXT_SUB(key, key); - - return key_lifetime_duration_set( - vty, &key->send, argv[idx_hhmmss]->arg, argv[idx_number]->arg, - argv[idx_month]->arg, argv[idx_number_2]->arg, - argv[idx_number_3]->arg); -} - -DEFUN (send_lifetime_duration_month_day, - send_lifetime_duration_month_day_cmd, - "send-lifetime HH:MM:SS MONTH (1-31) (1993-2035) duration (1-2147483646)", - "Set send lifetime of the key\n" - "Time to start\n" - "Month of the year to start\n" - "Day of th month to start\n" - "Year to start\n" - "Duration of the key\n" - "Duration seconds\n") -{ - int idx_hhmmss = 1; - int idx_month = 2; - int idx_number = 3; - int idx_number_2 = 4; - int idx_number_3 = 6; - VTY_DECLVAR_CONTEXT_SUB(key, key); - - return key_lifetime_duration_set( - vty, &key->send, argv[idx_hhmmss]->arg, argv[idx_number]->arg, - argv[idx_month]->arg, argv[idx_number_2]->arg, - argv[idx_number_3]->arg); -} - -DEFUN (no_send_lifetime, - no_send_lifetime_cmd, - "no send-lifetime", - NO_STR - "Unset send-lifetime\n") -{ - VTY_DECLVAR_CONTEXT_SUB(key, key); - - if (key->send.start) - key->send.start = 0; - if (key->send.end) - key->send.end = 0; - if (key->send.duration) - key->send.duration = 0; - - return CMD_SUCCESS; -} - -static int keychain_config_write(struct vty *vty); -static struct cmd_node keychain_node = { - .name = "keychain", - .node = KEYCHAIN_NODE, - .parent_node = CONFIG_NODE, - .prompt = "%s(config-keychain)# ", - .config_write = keychain_config_write, -}; - -static struct cmd_node keychain_key_node = { - .name = "keychain key", - .node = KEYCHAIN_KEY_NODE, - .parent_node = KEYCHAIN_NODE, - .prompt = "%s(config-keychain-key)# ", -}; - -static int keychain_strftime(char *buf, int bufsiz, time_t *time) -{ - struct tm tm; - size_t len; - - localtime_r(time, &tm); - - len = strftime(buf, bufsiz, "%T %b %d %Y", &tm); - - return len; -} - -static int keychain_config_write(struct vty *vty) -{ - struct keychain *keychain; - struct key *key; - struct listnode *node; - struct listnode *knode; - char buf[BUFSIZ]; - - for (ALL_LIST_ELEMENTS_RO(keychain_list, node, keychain)) { - vty_out(vty, "key chain %s\n", keychain->name); - - for (ALL_LIST_ELEMENTS_RO(keychain->key, knode, key)) { - vty_out(vty, " key %d\n", key->index); - - if (key->string) - vty_out(vty, " key-string %s\n", key->string); - - if (key->hash_algo != KEYCHAIN_ALGO_NULL) - vty_out(vty, " cryptographic-algorithm %s\n", - keychain_get_algo_name_by_id( - key->hash_algo)); - - if (key->accept.start) { - keychain_strftime(buf, BUFSIZ, - &key->accept.start); - vty_out(vty, " accept-lifetime %s", buf); - - if (key->accept.end == -1) - vty_out(vty, " infinite"); - else if (key->accept.duration) - vty_out(vty, " duration %ld", - (long)(key->accept.end - - key->accept.start)); - else { - keychain_strftime(buf, BUFSIZ, - &key->accept.end); - vty_out(vty, " %s", buf); - } - vty_out(vty, "\n"); - } - - if (key->send.start) { - keychain_strftime(buf, BUFSIZ, - &key->send.start); - vty_out(vty, " send-lifetime %s", buf); - - if (key->send.end == -1) - vty_out(vty, " infinite"); - else if (key->send.duration) - vty_out(vty, " duration %ld", - (long)(key->send.end - - key->send.start)); - else { - keychain_strftime(buf, BUFSIZ, - &key->send.end); - vty_out(vty, " %s", buf); - } - vty_out(vty, "\n"); - } - - vty_out(vty, " exit\n"); - } - vty_out(vty, "exit\n"); - vty_out(vty, "!\n"); - } - - return 0; -} - - -static void keychain_active_config(vector comps, struct cmd_token *token) -{ - struct keychain *keychain; - struct listnode *node; - - for (ALL_LIST_ELEMENTS_RO(keychain_list, node, keychain)) - vector_set(comps, XSTRDUP(MTYPE_COMPLETION, keychain->name)); -} - -static const struct cmd_variable_handler keychain_var_handlers[] = { - {.varname = "key_chain", .completions = keychain_active_config}, - {.tokenname = "KEYCHAIN_NAME", .completions = keychain_active_config}, - {.tokenname = "KCHAIN_NAME", .completions = keychain_active_config}, - {.completions = NULL} -}; - void keychain_terminate(void) { struct keychain *keychain; @@ -1202,70 +292,25 @@ void keychain_terminate(void) list_delete(&keychain_list); } -void keychain_init(void) +void keychain_init_new(bool in_backend) { keychain_list = list_new(); - /* Register handler for keychain auto config support */ - cmd_variable_handler_register(keychain_var_handlers); - install_node(&keychain_node); - install_node(&keychain_key_node); - - install_default(KEYCHAIN_NODE); - install_default(KEYCHAIN_KEY_NODE); - - install_element(CONFIG_NODE, &key_chain_cmd); - install_element(CONFIG_NODE, &no_key_chain_cmd); - install_element(KEYCHAIN_NODE, &key_cmd); - install_element(KEYCHAIN_NODE, &no_key_cmd); - - install_element(KEYCHAIN_NODE, &key_chain_cmd); - install_element(KEYCHAIN_NODE, &no_key_chain_cmd); - - install_element(KEYCHAIN_KEY_NODE, &key_string_cmd); - install_element(KEYCHAIN_KEY_NODE, &no_key_string_cmd); - - install_element(KEYCHAIN_KEY_NODE, &key_chain_cmd); - install_element(KEYCHAIN_KEY_NODE, &no_key_chain_cmd); - - install_element(KEYCHAIN_KEY_NODE, &key_cmd); - install_element(KEYCHAIN_KEY_NODE, &no_key_cmd); - - install_element(KEYCHAIN_KEY_NODE, - &accept_lifetime_day_month_day_month_cmd); - install_element(KEYCHAIN_KEY_NODE, - &accept_lifetime_day_month_month_day_cmd); - install_element(KEYCHAIN_KEY_NODE, - &accept_lifetime_month_day_day_month_cmd); - install_element(KEYCHAIN_KEY_NODE, - &accept_lifetime_month_day_month_day_cmd); - install_element(KEYCHAIN_KEY_NODE, - &accept_lifetime_infinite_day_month_cmd); - install_element(KEYCHAIN_KEY_NODE, - &accept_lifetime_infinite_month_day_cmd); - install_element(KEYCHAIN_KEY_NODE, - &accept_lifetime_duration_day_month_cmd); - install_element(KEYCHAIN_KEY_NODE, - &accept_lifetime_duration_month_day_cmd); - install_element(KEYCHAIN_KEY_NODE, &no_accept_lifetime_cmd); + if (!in_backend) + keychain_cli_init(); +} - install_element(KEYCHAIN_KEY_NODE, - &send_lifetime_day_month_day_month_cmd); - install_element(KEYCHAIN_KEY_NODE, - &send_lifetime_day_month_month_day_cmd); - install_element(KEYCHAIN_KEY_NODE, - &send_lifetime_month_day_day_month_cmd); - install_element(KEYCHAIN_KEY_NODE, - &send_lifetime_month_day_month_day_cmd); - install_element(KEYCHAIN_KEY_NODE, - &send_lifetime_infinite_day_month_cmd); - install_element(KEYCHAIN_KEY_NODE, - &send_lifetime_infinite_month_day_cmd); - install_element(KEYCHAIN_KEY_NODE, - &send_lifetime_duration_day_month_cmd); - install_element(KEYCHAIN_KEY_NODE, - &send_lifetime_duration_month_day_cmd); - install_element(KEYCHAIN_KEY_NODE, &no_send_lifetime_cmd); - install_element(KEYCHAIN_KEY_NODE, &cryptographic_algorithm_cmd); - install_element(KEYCHAIN_KEY_NODE, &no_cryptographic_algorithm_cmd); +void keychain_init(void) +{ + keychain_init_new(false); } + +const struct frr_yang_module_info ietf_key_chain_deviation_info = { + .name = "frr-deviations-ietf-key-chain", + .ignore_cfg_cbs = true, + .nodes = { + { + .xpath = NULL, + }, + }, +}; diff --git a/lib/keychain.h b/lib/keychain.h index c96b74ecce19..dc35c2ea392e 100644 --- a/lib/keychain.h +++ b/lib/keychain.h @@ -6,6 +6,8 @@ #ifndef _ZEBRA_KEYCHAIN_H #define _ZEBRA_KEYCHAIN_H +#include "memory.h" +#include "northbound.h" #include "qobj.h" #ifdef __cplusplus @@ -44,6 +46,10 @@ struct keychain_algo_info { const char *desc; }; +extern const struct frr_yang_module_info ietf_key_chain_info; +extern const struct frr_yang_module_info ietf_key_chain_cli_info; +extern const struct frr_yang_module_info ietf_key_chain_deviation_info; + extern const struct keychain_algo_info algo_info[]; uint16_t keychain_get_block_size(enum keychain_hash_algo key); uint16_t keychain_get_hash_len(enum keychain_hash_algo key); @@ -55,6 +61,8 @@ const char *keychain_get_algo_name_by_id(enum keychain_hash_algo key); struct keychain { char *name; + char *desc; + time_t last_touch; struct list *key; @@ -81,13 +89,43 @@ struct key { }; DECLARE_QOBJ_TYPE(key); +DECLARE_MTYPE(KEY); +DECLARE_MTYPE(KEYCHAIN); +DECLARE_MTYPE(KEYCHAIN_DESC); + +/* keychain implementation */ +extern struct list *keychain_list; +struct keychain *keychain_lookup(const char *name); +struct keychain *keychain_get(const char *name); +void keychain_delete(struct keychain *keychain); +struct key *key_lookup(const struct keychain *keychain, uint32_t index); +struct key *key_get(const struct keychain *keychain, uint32_t index); +void key_delete(struct keychain *keychain, struct key *key); + +void keychain_cli_init(void); +extern void key_chains_key_chain_cli_write(struct vty *vty, const struct lyd_node *dnode, bool show_defaults); +extern void key_chains_key_chain_cli_write_end(struct vty *vty, const struct lyd_node *dnode); +extern void key_chains_key_chain_description_cli_write(struct vty *vty, const struct lyd_node *dnode, bool show_defaults); +void key_chains_key_chain_key_cli_write(struct vty *vty, const struct lyd_node *dnode, bool show_defaults); +extern void key_chains_key_chain_key_cli_write_end(struct vty *vty, const struct lyd_node *dnode); +extern void key_chains_key_chain_key_lifetime_send_accept_lifetime_start_date_time_cli_write(struct vty *vty, const struct lyd_node *dnode, bool show_defaults); +extern void key_chains_key_chain_key_lifetime_send_lifetime_start_date_time_cli_write(struct vty *vty, const struct lyd_node *dnode, bool show_defaults); +extern void key_chains_key_chain_key_lifetime_accept_lifetime_start_date_time_cli_write(struct vty *vty, const struct lyd_node *dnode, bool show_defaults); +extern void key_chains_key_chain_key_crypto_algorithm_cli_write(struct vty *vty, const struct lyd_node *dnode, bool show_defaults); +extern void key_chains_key_chain_key_key_string_keystring_cli_write(struct vty *vty, const struct lyd_node *dnode, bool show_defaults); + +/* keychain users */ extern void keychain_init(void); +extern void keychain_init_new(bool in_backend); extern void keychain_terminate(void); extern struct keychain *keychain_lookup(const char *); extern struct key *key_lookup_for_accept(const struct keychain *, uint32_t); extern struct key *key_match_for_accept(const struct keychain *, const char *); extern struct key *key_lookup_for_send(const struct keychain *); const char *keychain_algo_str(enum keychain_hash_algo hash_algo); + + + #ifdef __cplusplus } #endif diff --git a/lib/keychain_cli.c b/lib/keychain_cli.c new file mode 100644 index 000000000000..3ab6e715632e --- /dev/null +++ b/lib/keychain_cli.c @@ -0,0 +1,1033 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * February 22 2024, Christian Hopps + * + * Copyright (C) 2024 LabN Consulting, L.L.C. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +#include "command.h" +#include "keychain.h" +#include "northbound.h" +#include "northbound_cli.h" +#include "vty.h" + +#include "lib/keychain_cli_clippy.c" + +DEFPY_YANG_NOSH( + key_chain, + key_chain_cmd, + "key chain WORD", + "Authentication key management\n" + "Key-chain management\n" + "Key-chain name\n") +{ + char *xpath; + int ret; + + xpath = asprintfrr(MTYPE_TMP, + "/ietf-key-chain:key-chains/key-chain[name='%s']", + chain); + nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); + ret = nb_cli_apply_changes(vty, NULL); + if (ret == CMD_SUCCESS) + VTY_PUSH_XPATH(KEYCHAIN_NODE, xpath); + XFREE(MTYPE_TMP, xpath); + return ret; +} + +DEFPY_YANG( + no_key_chain, + no_key_chain_cmd, + "no key chain WORD", + NO_STR + "Authentication key management\n" + "Key-chain management\n" + "Key-chain name\n") +{ + char *xpath; + + xpath = asprintfrr(MTYPE_TMP, + "/ietf-key-chain:key-chains/key-chain[name='%s']", + chain); + nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL); + XFREE(MTYPE_TMP, xpath); + return nb_cli_apply_changes_clear_pending(vty, NULL); +} + +DEFPY_YANG_NOSH( + key, + key_cmd, + "key (0-2147483647)", + "Configure a key\n" + "Key identifier number\n") +{ + char *xpath; + int ret; + + xpath = asprintfrr(MTYPE_TMP, "%s/key[key-id='%s']", VTY_CURR_XPATH, + key_str); + nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); + ret = nb_cli_apply_changes(vty, NULL); + if (ret == CMD_SUCCESS) + VTY_PUSH_XPATH(KEYCHAIN_KEY_NODE, xpath); + XFREE(MTYPE_TMP, xpath); + return ret; +} + +DEFPY_YANG( + no_key, + no_key_cmd, + "no key (0-2147483647)", + NO_STR + "Delete a key\n" + "Key identifier number\n") +{ + char *xpath; + + xpath = asprintfrr(MTYPE_TMP, "%s/key[key-id='%s']", VTY_CURR_XPATH, + key_str); + nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL); + XFREE(MTYPE_TMP, xpath); + return nb_cli_apply_changes_clear_pending(vty, NULL); +} + +DEFPY_YANG( + key_string, + key_string_cmd, + "key-string LINE", + "Set key string\n" + "The key\n") +{ + nb_cli_enqueue_change(vty, "./key-string/keystring", NB_OP_CREATE, line); + return nb_cli_apply_changes(vty, NULL); +} + +DEFPY_YANG( + no_key_string, + no_key_string_cmd, + "no key-string [LINE]", + NO_STR + "Unset key string\n" + "The key\n") +{ + nb_cli_enqueue_change(vty, "./key-string/keystring", NB_OP_DESTROY, line); + return nb_cli_apply_changes(vty, NULL); +} + +DEFPY_YANG( + cryptographic_algorithm, + cryptographic_algorithm_cmd, + "cryptographic-algorithm " + "$algo", + "Cryptographic-algorithm\n" + "Use MD5 algorithm\n" + "Use HMAC-SHA-1 algorithm\n" + "Use HMAC-SHA-256 algorithm\n" + "Use HMAC-SHA-384 algorithm\n" + "Use HMAC-SHA-512 algorithm\n") +{ + nb_cli_enqueue_change(vty, "./crypto-algorithm", NB_OP_CREATE, algo); + return nb_cli_apply_changes(vty, NULL); +} + +DEFPY_YANG( + no_cryptographic_algorithm, + no_cryptographic_algorithm_cmd, + "no cryptographic-algorithm " + "[$algo]", + NO_STR + "Cryptographic-algorithm\n" + "Use MD5 algorithm\n" + "Use HMAC-SHA-1 algorithm\n" + "Use HMAC-SHA-256 algorithm\n" + "Use HMAC-SHA-384 algorithm\n" + "Use HMAC-SHA-512 algorithm\n") +{ + nb_cli_enqueue_change(vty, "./crypto-algorithm", NB_OP_DESTROY, algo); + return nb_cli_apply_changes(vty, NULL); +} + +const char *month_name[] = { + "january", "february", "march", "april", "may", "june", "july", + "august", "september", "october", "november", "december", NULL +}; + +static int __get_month(const char *month_str) +{ + int i, len; + + len = strlen(month_str); + if (len < 3) + return -1; + for (i = 1; month_name[i-1]; i++) + if (strncasecmp(month_str, month_name[i-1], len) == 0) + return i; + return -1; +} + + +static long __timezone_offset(void) +{ + time_t now; + struct tm *tm_now; + + time(&now); + tm_now = localtime(&now); + return tm_now->tm_gmtoff; +} + +static int __lifetime_set(struct vty *vty, char timebuf[32], + const char *time_node, const char *leaf_node, + const char *time_str, const char *day_str, + const char *month_str, const char *year_str) +{ + char xpath[128]; + int month = __get_month(month_str); + int hoff, moff; + long offset; + + if (month < 1) { + vty_out(vty, "Bad month value: %s\n", month_str); + return -1; + } + + offset = __timezone_offset(); + hoff = offset / 3600; + if (offset < 0) + offset = -offset; + moff = (offset % 3600) / 60; + + snprintf(timebuf, 32, "%s-%02d-%02dT%s%+03d:%02d", year_str, month, + atoi(day_str), time_str, hoff, moff); + snprintf(xpath, sizeof(xpath), "./lifetime/%s/%s", time_node, leaf_node); + nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, timebuf); + return 0; +} + + +static int key_lifetime_set(struct vty *vty, const char *time_node, + const char *stime_str, const char *sday_str, + const char *smonth_str, const char *syear_str, + const char *etime_str, const char *eday_str, + const char *emonth_str, const char *eyear_str) +{ + char time1[32]; + char time2[32]; + + if (__lifetime_set(vty, time1, time_node, "start-date-time", stime_str, + sday_str, smonth_str, syear_str)) + return CMD_WARNING_CONFIG_FAILED; + + if (__lifetime_set(vty, time2, time_node, "end-date-time", stime_str, + sday_str, smonth_str, syear_str)) + return CMD_WARNING_CONFIG_FAILED; + + return nb_cli_apply_changes(vty, NULL); +} + +static int key_lifetime_duration_set(struct vty *vty, const char *time_node, + const char *stime_str, const char *sday_str, + const char *smonth_str, + const char *syear_str, + const char *duration_str) +{ + char xpath[128]; + char time[32]; + + if (__lifetime_set(vty, time, time_node, "start-date-time", stime_str, + sday_str, smonth_str, syear_str)) + return CMD_WARNING_CONFIG_FAILED; + + /* End time. */ + snprintf(xpath, sizeof(xpath), "./lifetime/%s/duration", time_node); + nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, duration_str); + + return nb_cli_apply_changes(vty, NULL); +} + +static int key_lifetime_infinite_set(struct vty *vty, const char *time_node, + const char *stime_str, const char *sday_str, + const char *smonth_str, + const char *syear_str) +{ + char xpath[128]; + char time[32]; + + if (__lifetime_set(vty, time, time_node, "start-date-time", stime_str, + sday_str, smonth_str, syear_str)) + return CMD_WARNING_CONFIG_FAILED; + + /* End time. */ + snprintf(xpath, sizeof(xpath), "./lifetime/%s/no-end-time", time_node); + nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, NULL); + + return nb_cli_apply_changes(vty, NULL); +} + +DEFPY_YANG( + accept_lifetime_day_month_day_month, + accept_lifetime_day_month_day_month_cmd, + "accept-lifetime HH:MM:SS (1-31) MONTH (1993-2035) HH:MM:SS (1-31) MONTH (1993-2035)", + "Set accept lifetime of the key\n" + "Time to start\n" + "Day of th month to start\n" + "Month of the year to start\n" + "Year to start\n" + "Time to expire\n" + "Day of th month to expire\n" + "Month of the year to expire\n" + "Year to expire\n") +{ + int idx_hhmmss = 1; + int idx_number = 2; + int idx_month = 3; + int idx_number_2 = 4; + int idx_hhmmss_2 = 5; + int idx_number_3 = 6; + int idx_month_2 = 7; + int idx_number_4 = 8; + + return key_lifetime_set(vty, "accept-lifetime", argv[idx_hhmmss]->arg, + argv[idx_number]->arg, argv[idx_month]->arg, + argv[idx_number_2]->arg, argv[idx_hhmmss_2]->arg, + argv[idx_number_3]->arg, argv[idx_month_2]->arg, + argv[idx_number_4]->arg); +} + +DEFPY_YANG(accept_lifetime_day_month_month_day, + accept_lifetime_day_month_month_day_cmd, + "accept-lifetime HH:MM:SS (1-31) MONTH (1993-2035) HH:MM:SS MONTH (1-31) (1993-2035)", + "Set accept lifetime of the key\n" + "Time to start\n" + "Day of th month to start\n" + "Month of the year to start\n" + "Year to start\n" + "Time to expire\n" + "Month of the year to expire\n" + "Day of th month to expire\n" + "Year to expire\n") +{ + int idx_hhmmss = 1; + int idx_number = 2; + int idx_month = 3; + int idx_number_2 = 4; + int idx_hhmmss_2 = 5; + int idx_month_2 = 6; + int idx_number_3 = 7; + int idx_number_4 = 8; + + return key_lifetime_set(vty, "accept-lifetime", argv[idx_hhmmss]->arg, + argv[idx_number]->arg, argv[idx_month]->arg, + argv[idx_number_2]->arg, argv[idx_hhmmss_2]->arg, + argv[idx_number_3]->arg, argv[idx_month_2]->arg, + argv[idx_number_4]->arg); +} + +DEFPY_YANG(accept_lifetime_month_day_day_month, + accept_lifetime_month_day_day_month_cmd, + "accept-lifetime HH:MM:SS MONTH (1-31) (1993-2035) HH:MM:SS (1-31) MONTH (1993-2035)", + "Set accept lifetime of the key\n" + "Time to start\n" + "Month of the year to start\n" + "Day of th month to start\n" + "Year to start\n" + "Time to expire\n" + "Day of th month to expire\n" + "Month of the year to expire\n" + "Year to expire\n") +{ + int idx_hhmmss = 1; + int idx_month = 2; + int idx_number = 3; + int idx_number_2 = 4; + int idx_hhmmss_2 = 5; + int idx_number_3 = 6; + int idx_month_2 = 7; + int idx_number_4 = 8; + + return key_lifetime_set(vty, "accept-lifetime", argv[idx_hhmmss]->arg, + argv[idx_number]->arg, argv[idx_month]->arg, + argv[idx_number_2]->arg, argv[idx_hhmmss_2]->arg, + argv[idx_number_3]->arg, argv[idx_month_2]->arg, + argv[idx_number_4]->arg); +} + +DEFPY_YANG(accept_lifetime_month_day_month_day, + accept_lifetime_month_day_month_day_cmd, + "accept-lifetime HH:MM:SS MONTH (1-31) (1993-2035) HH:MM:SS MONTH (1-31) (1993-2035)", + "Set accept lifetime of the key\n" + "Time to start\n" + "Month of the year to start\n" + "Day of th month to start\n" + "Year to start\n" + "Time to expire\n" + "Month of the year to expire\n" + "Day of th month to expire\n" + "Year to expire\n") +{ + int idx_hhmmss = 1; + int idx_month = 2; + int idx_number = 3; + int idx_number_2 = 4; + int idx_hhmmss_2 = 5; + int idx_month_2 = 6; + int idx_number_3 = 7; + int idx_number_4 = 8; + + return key_lifetime_set(vty, "accept-lifetime", argv[idx_hhmmss]->arg, + argv[idx_number]->arg, argv[idx_month]->arg, + argv[idx_number_2]->arg, argv[idx_hhmmss_2]->arg, + argv[idx_number_3]->arg, argv[idx_month_2]->arg, + argv[idx_number_4]->arg); +} + +DEFPY_YANG(accept_lifetime_infinite_day_month, + accept_lifetime_infinite_day_month_cmd, + "accept-lifetime HH:MM:SS (1-31) MONTH (1993-2035) infinite", + "Set accept lifetime of the key\n" + "Time to start\n" + "Day of th month to start\n" + "Month of the year to start\n" + "Year to start\n" + "Never expires\n") +{ + int idx_hhmmss = 1; + int idx_number = 2; + int idx_month = 3; + int idx_number_2 = 4; + + return key_lifetime_infinite_set(vty, "accept-lifetime", + argv[idx_hhmmss]->arg, + argv[idx_number]->arg, + argv[idx_month]->arg, + argv[idx_number_2]->arg); +} + +DEFPY_YANG(accept_lifetime_infinite_month_day, + accept_lifetime_infinite_month_day_cmd, + "accept-lifetime HH:MM:SS MONTH (1-31) (1993-2035) infinite", + "Set accept lifetime of the key\n" + "Time to start\n" + "Month of the year to start\n" + "Day of th month to start\n" + "Year to start\n" + "Never expires\n") +{ + int idx_hhmmss = 1; + int idx_month = 2; + int idx_number = 3; + int idx_number_2 = 4; + + return key_lifetime_infinite_set(vty, "accept-lifetime", + argv[idx_hhmmss]->arg, + argv[idx_number]->arg, + argv[idx_month]->arg, + argv[idx_number_2]->arg); +} + +DEFPY_YANG(accept_lifetime_duration_day_month, + accept_lifetime_duration_day_month_cmd, + "accept-lifetime HH:MM:SS (1-31) MONTH (1993-2035) duration (1-2147483646)", + "Set accept lifetime of the key\n" + "Time to start\n" + "Day of th month to start\n" + "Month of the year to start\n" + "Year to start\n" + "Duration of the key\n" + "Duration seconds\n") +{ + int idx_hhmmss = 1; + int idx_number = 2; + int idx_month = 3; + int idx_number_2 = 4; + int idx_number_3 = 6; + + return key_lifetime_duration_set(vty, "accept-lifetime", + argv[idx_hhmmss]->arg, + argv[idx_number]->arg, + argv[idx_month]->arg, + argv[idx_number_2]->arg, + argv[idx_number_3]->arg); +} + +DEFPY_YANG(accept_lifetime_duration_month_day, + accept_lifetime_duration_month_day_cmd, + "accept-lifetime HH:MM:SS MONTH (1-31) (1993-2035) duration (1-2147483646)", + "Set accept lifetime of the key\n" + "Time to start\n" + "Month of the year to start\n" + "Day of th month to start\n" + "Year to start\n" + "Duration of the key\n" + "Duration seconds\n") +{ + int idx_hhmmss = 1; + int idx_month = 2; + int idx_number = 3; + int idx_number_2 = 4; + int idx_number_3 = 6; + + return key_lifetime_duration_set(vty, "accept-lifetime", + argv[idx_hhmmss]->arg, + argv[idx_number]->arg, + argv[idx_month]->arg, + argv[idx_number_2]->arg, + argv[idx_number_3]->arg); +} + +DEFPY_YANG(no_accept_lifetime, + no_accept_lifetime_cmd, + "no accept-lifetime", + NO_STR + "Unset accept-lifetime\n") +{ + nb_cli_enqueue_change(vty, "accept-lifetime", NB_OP_DESTROY, NULL); + return nb_cli_apply_changes(vty, NULL); +} + +DEFPY_YANG( + send_lifetime_day_month_day_month, send_lifetime_day_month_day_month_cmd, + "send-lifetime HH:MM:SS (1-31) MONTH (1993-2035) HH:MM:SS (1-31) MONTH (1993-2035)", + "Set send lifetime of the key\n" + "Time to start\n" + "Day of th month to start\n" + "Month of the year to start\n" + "Year to start\n" + "Time to expire\n" + "Day of th month to expire\n" + "Month of the year to expire\n" + "Year to expire\n") +{ + int idx_hhmmss = 1; + int idx_number = 2; + int idx_month = 3; + int idx_number_2 = 4; + int idx_hhmmss_2 = 5; + int idx_number_3 = 6; + int idx_month_2 = 7; + int idx_number_4 = 8; + + return key_lifetime_set(vty, "send-lifetime", argv[idx_hhmmss]->arg, + argv[idx_number]->arg, argv[idx_month]->arg, + argv[idx_number_2]->arg, argv[idx_hhmmss_2]->arg, + argv[idx_number_3]->arg, argv[idx_month_2]->arg, + argv[idx_number_4]->arg); +} + +DEFPY_YANG(send_lifetime_day_month_month_day, + send_lifetime_day_month_month_day_cmd, + "send-lifetime HH:MM:SS (1-31) MONTH (1993-2035) HH:MM:SS MONTH (1-31) (1993-2035)", + "Set send lifetime of the key\n" + "Time to start\n" + "Day of th month to start\n" + "Month of the year to start\n" + "Year to start\n" + "Time to expire\n" + "Month of the year to expire\n" + "Day of th month to expire\n" + "Year to expire\n") +{ + int idx_hhmmss = 1; + int idx_number = 2; + int idx_month = 3; + int idx_number_2 = 4; + int idx_hhmmss_2 = 5; + int idx_month_2 = 6; + int idx_number_3 = 7; + int idx_number_4 = 8; + + return key_lifetime_set(vty, "send-lifetime", argv[idx_hhmmss]->arg, + argv[idx_number]->arg, argv[idx_month]->arg, + argv[idx_number_2]->arg, argv[idx_hhmmss_2]->arg, + argv[idx_number_3]->arg, argv[idx_month_2]->arg, + argv[idx_number_4]->arg); +} + +DEFPY_YANG(send_lifetime_month_day_day_month, + send_lifetime_month_day_day_month_cmd, + "send-lifetime HH:MM:SS MONTH (1-31) (1993-2035) HH:MM:SS (1-31) MONTH (1993-2035)", + "Set send lifetime of the key\n" + "Time to start\n" + "Month of the year to start\n" + "Day of th month to start\n" + "Year to start\n" + "Time to expire\n" + "Day of th month to expire\n" + "Month of the year to expire\n" + "Year to expire\n") +{ + int idx_hhmmss = 1; + int idx_month = 2; + int idx_number = 3; + int idx_number_2 = 4; + int idx_hhmmss_2 = 5; + int idx_number_3 = 6; + int idx_month_2 = 7; + int idx_number_4 = 8; + + return key_lifetime_set(vty, "send-lifetime", argv[idx_hhmmss]->arg, + argv[idx_number]->arg, argv[idx_month]->arg, + argv[idx_number_2]->arg, argv[idx_hhmmss_2]->arg, + argv[idx_number_3]->arg, argv[idx_month_2]->arg, + argv[idx_number_4]->arg); +} + +DEFPY_YANG(send_lifetime_month_day_month_day, + send_lifetime_month_day_month_day_cmd, + "send-lifetime HH:MM:SS MONTH (1-31) (1993-2035) HH:MM:SS MONTH (1-31) (1993-2035)", + "Set send lifetime of the key\n" + "Time to start\n" + "Month of the year to start\n" + "Day of th month to start\n" + "Year to start\n" + "Time to expire\n" + "Month of the year to expire\n" + "Day of th month to expire\n" + "Year to expire\n") +{ + int idx_hhmmss = 1; + int idx_month = 2; + int idx_number = 3; + int idx_number_2 = 4; + int idx_hhmmss_2 = 5; + int idx_month_2 = 6; + int idx_number_3 = 7; + int idx_number_4 = 8; + + return key_lifetime_set(vty, "send-lifetime", argv[idx_hhmmss]->arg, + argv[idx_number]->arg, argv[idx_month]->arg, + argv[idx_number_2]->arg, argv[idx_hhmmss_2]->arg, + argv[idx_number_3]->arg, argv[idx_month_2]->arg, + argv[idx_number_4]->arg); +} + +DEFPY_YANG(send_lifetime_infinite_day_month, + send_lifetime_infinite_day_month_cmd, + "send-lifetime HH:MM:SS (1-31) MONTH (1993-2035) infinite", + "Set send lifetime of the key\n" + "Time to start\n" + "Day of th month to start\n" + "Month of the year to start\n" + "Year to start\n" + "Never expires\n") +{ + int idx_hhmmss = 1; + int idx_number = 2; + int idx_month = 3; + int idx_number_2 = 4; + + return key_lifetime_infinite_set(vty, "send-lifetime", + argv[idx_hhmmss]->arg, + argv[idx_number]->arg, + argv[idx_month]->arg, + argv[idx_number_2]->arg); +} + +DEFPY_YANG(send_lifetime_infinite_month_day, + send_lifetime_infinite_month_day_cmd, + "send-lifetime HH:MM:SS MONTH (1-31) (1993-2035) infinite", + "Set send lifetime of the key\n" + "Time to start\n" + "Month of the year to start\n" + "Day of th month to start\n" + "Year to start\n" + "Never expires\n") +{ + int idx_hhmmss = 1; + int idx_month = 2; + int idx_number = 3; + int idx_number_2 = 4; + + return key_lifetime_infinite_set(vty, "send-lifetime", + argv[idx_hhmmss]->arg, + argv[idx_number]->arg, + argv[idx_month]->arg, + argv[idx_number_2]->arg); +} + +DEFPY_YANG(send_lifetime_duration_day_month, + send_lifetime_duration_day_month_cmd, + "send-lifetime HH:MM:SS (1-31) MONTH (1993-2035) duration (1-2147483646)", + "Set send lifetime of the key\n" + "Time to start\n" + "Day of th month to start\n" + "Month of the year to start\n" + "Year to start\n" + "Duration of the key\n" + "Duration seconds\n") +{ + int idx_hhmmss = 1; + int idx_number = 2; + int idx_month = 3; + int idx_number_2 = 4; + int idx_number_3 = 6; + + return key_lifetime_duration_set(vty, "send-lifetime", + argv[idx_hhmmss]->arg, + argv[idx_number]->arg, + argv[idx_month]->arg, + argv[idx_number_2]->arg, + argv[idx_number_3]->arg); +} + +DEFPY_YANG(send_lifetime_duration_month_day, + send_lifetime_duration_month_day_cmd, + "send-lifetime HH:MM:SS MONTH (1-31) (1993-2035) duration (1-2147483646)", + "Set send lifetime of the key\n" + "Time to start\n" + "Month of the year to start\n" + "Day of th month to start\n" + "Year to start\n" + "Duration of the key\n" + "Duration seconds\n") +{ + int idx_hhmmss = 1; + int idx_month = 2; + int idx_number = 3; + int idx_number_2 = 4; + int idx_number_3 = 6; + + return key_lifetime_duration_set(vty, "send-lifetime", + argv[idx_hhmmss]->arg, + argv[idx_number]->arg, + argv[idx_month]->arg, + argv[idx_number_2]->arg, + argv[idx_number_3]->arg); +} + +DEFUN (no_send_lifetime, + no_send_lifetime_cmd, + "no send-lifetime", + NO_STR + "Unset send-lifetime\n") +{ + nb_cli_enqueue_change(vty, "send-lifetime", NB_OP_DESTROY, NULL); + return nb_cli_apply_changes(vty, NULL); +} + +/* + * XPath: /ietf-key-chain:key-chains/key-chain + */ +void key_chains_key_chain_cli_write(struct vty *vty, + const struct lyd_node *dnode, + bool show_defaults) +{ + vty_out(vty, "key chain %s\n", yang_dnode_get_string(dnode, "name")); +} + +void key_chains_key_chain_cli_write_end(struct vty *vty, + const struct lyd_node *dnode) +{ + vty_out(vty, "exit\n"); + vty_out(vty, "!\n"); +} + +/* + * XPath: /ietf-key-chain:key-chains/key-chain/description + */ +void key_chains_key_chain_description_cli_write(struct vty *vty, + const struct lyd_node *dnode, + bool show_defaults) +{ + /* Implement CLI */ + /* vty_out(vty, " description %s\n", yang_dnode_get_string(dnode)); */ +} + +/* + * XPath: /ietf-key-chain:key-chains/key-chain/key + */ +void key_chains_key_chain_key_cli_write(struct vty *vty, + const struct lyd_node *dnode, + bool show_defaults) +{ + vty_out(vty, " key %s\n", yang_dnode_get_string(dnode, "key-id")); +} + +void key_chains_key_chain_key_cli_write_end(struct vty *vty, + const struct lyd_node *dnode) +{ + vty_out(vty, " exit\n"); +} + +static const char *__dnode_to_key_strftime(char *buf, size_t bufsize, + const struct lyd_node *lt_start_dnode) +{ + const char *timestr; + struct lyd_node *end_node; + struct tm tm; + uint32_t duration; + time_t time; + int len, sz; + char *s; + + s = buf; + sz = bufsize; + + timestr = yang_dnode_get_string(lt_start_dnode, NULL); + (void)ly_time_str2time(timestr, &time, NULL); + localtime_r(&time, &tm); + len = strftime(s, sz, "%T %b %e %Y", &tm); + s += len; + sz -= len; + + if (yang_dnode_exists(lt_start_dnode, "../no-end-time")) { + strlcat(s, " infinite", sz); + return buf; + } + + end_node = yang_dnode_get(lt_start_dnode, "../duration"); + if (end_node) { + duration = yang_dnode_get_uint32(end_node, NULL); + snprintf(s, sz, " duration %u", (uint)duration); + return buf; + } + + timestr = yang_dnode_get_string(lt_start_dnode, "../end-date-time"); + (void)ly_time_str2time(timestr, &time, NULL); + localtime_r(&time, &tm); + strftime(s, sz, " %T %b %e %Y", &tm); + return buf; +} + +/* + * XPath: /ietf-key-chain:key-chains/key-chain/key/lifetime/send-accept-lifetime/start-date-time + */ +void key_chains_key_chain_key_lifetime_send_accept_lifetime_start_date_time_cli_write( + struct vty *vty, const struct lyd_node *dnode, bool show_defaults) +{ + char s[256]; + + vty_out(vty, " send-lifetime %s\n", + __dnode_to_key_strftime(s, sizeof(s), dnode)); + vty_out(vty, " accept-lifetime %s\n", s); +} + +/* + * XPath: /ietf-key-chain:key-chains/key-chain/key/lifetime/send-lifetime/start-date-time + */ +void key_chains_key_chain_key_lifetime_send_lifetime_start_date_time_cli_write( + struct vty *vty, const struct lyd_node *dnode, bool show_defaults) +{ + char s[256]; + + vty_out(vty, " send-lifetime %s\n", + __dnode_to_key_strftime(s, sizeof(s), dnode)); +} + +/* + * XPath: /ietf-key-chain:key-chains/key-chain/key/lifetime/accept-lifetime/start-date-time + */ +void key_chains_key_chain_key_lifetime_accept_lifetime_start_date_time_cli_write( + struct vty *vty, const struct lyd_node *dnode, bool show_defaults) +{ + char s[256]; + + vty_out(vty, " accept-lifetime %s\n", + __dnode_to_key_strftime(s, sizeof(s), dnode)); +} + +/* + * XPath: /ietf-key-chain:key-chains/key-chain/key/crypto-algorithm + */ +void key_chains_key_chain_key_crypto_algorithm_cli_write( + struct vty *vty, const struct lyd_node *dnode, bool show_defaults) +{ + static const char prefix[] = "ietf-key-chain:"; + static const int prefix_len = sizeof(prefix) - 1; + const char *name = yang_dnode_get_string(dnode, NULL); + + if (!strncmp(name, prefix, prefix_len)) + name += prefix_len; + vty_out(vty, " cryptographic-algorithm %s\n", name); +} + +/* + * XPath: /ietf-key-chain:key-chains/key-chain/key/key-string/keystring + */ +void key_chains_key_chain_key_key_string_keystring_cli_write( + struct vty *vty, const struct lyd_node *dnode, bool show_defaults) +{ + vty_out(vty, " key-string %s\n", yang_dnode_get_string(dnode, NULL)); +} + +static const char * const keychain_features[] = { + "independent-send-accept-lifetime", + NULL, +}; + +/* clang-format off */ +const struct frr_yang_module_info ietf_key_chain_cli_info = { + .name = "ietf-key-chain", + .features = (const char **)keychain_features, + .ignore_cfg_cbs = true, + .nodes = { + { + .xpath = "/ietf-key-chain:key-chains/key-chain", + .cbs = { + .cli_show = key_chains_key_chain_cli_write, + .cli_show_end = key_chains_key_chain_cli_write_end, + } + }, + { + .xpath = "/ietf-key-chain:key-chains/key-chain/description", + .cbs = { + .cli_show = key_chains_key_chain_description_cli_write, + } + }, + { + .xpath = "/ietf-key-chain:key-chains/key-chain/key", + .cbs = { + .cli_show = key_chains_key_chain_key_cli_write, + .cli_show_end = key_chains_key_chain_key_cli_write_end, + } + }, + { + .xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/send-accept-lifetime/start-date-time", + .cbs = { + .cli_show = key_chains_key_chain_key_lifetime_send_accept_lifetime_start_date_time_cli_write, + } + }, + { + .xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/send-lifetime/start-date-time", + .cbs = { + .cli_show = key_chains_key_chain_key_lifetime_send_lifetime_start_date_time_cli_write, + } + }, + { + .xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/accept-lifetime/start-date-time", + .cbs = { + .cli_show = key_chains_key_chain_key_lifetime_accept_lifetime_start_date_time_cli_write, + } + }, + { + .xpath = "/ietf-key-chain:key-chains/key-chain/key/crypto-algorithm", + .cbs = { + .cli_show = key_chains_key_chain_key_crypto_algorithm_cli_write, + } + }, + { + .xpath = "/ietf-key-chain:key-chains/key-chain/key/key-string/keystring", + .cbs = { + .cli_show = key_chains_key_chain_key_key_string_keystring_cli_write, + } + }, + { + .xpath = NULL, + }, + } +}; + +static int keychain_config_write(struct vty *vty) +{ + const struct lyd_node *dnode; + int written = 0; + + dnode = yang_dnode_get(running_config->dnode, + "/ietf-key-chain:key-chains"); + if (dnode) { + nb_cli_show_dnode_cmds(vty, dnode, false); + written = 1; + } + return written; +} + +static struct cmd_node keychain_node = { + .name = "keychain", + .node = KEYCHAIN_NODE, + .parent_node = CONFIG_NODE, + .prompt = "%s(config-keychain)# ", + .config_write = keychain_config_write, +}; + +static struct cmd_node keychain_key_node = { + .name = "keychain key", + .node = KEYCHAIN_KEY_NODE, + .parent_node = KEYCHAIN_NODE, + .prompt = "%s(config-keychain-key)# ", +}; + +static const struct cmd_variable_handler keychain_var_handlers[] = { + {.varname = "key_chain", .xpath = "/ietf-key-chain:key-chains/key-chain/name" }, + {.tokenname = "KEYCHAIN_NAME", .xpath = "/ietf-key-chain:key-chains/key-chain/name" }, + {.completions = NULL} +}; + +void keychain_cli_init(void) +{ + /* Register handler for keychain auto config support */ + cmd_variable_handler_register(keychain_var_handlers); + install_node(&keychain_node); + install_node(&keychain_key_node); + + install_default(KEYCHAIN_NODE); + install_default(KEYCHAIN_KEY_NODE); + + install_element(CONFIG_NODE, &key_chain_cmd); + install_element(CONFIG_NODE, &no_key_chain_cmd); + install_element(KEYCHAIN_NODE, &key_cmd); + install_element(KEYCHAIN_NODE, &no_key_cmd); + + install_element(KEYCHAIN_NODE, &key_chain_cmd); + install_element(KEYCHAIN_NODE, &no_key_chain_cmd); + + install_element(KEYCHAIN_KEY_NODE, &key_string_cmd); + install_element(KEYCHAIN_KEY_NODE, &no_key_string_cmd); + + install_element(KEYCHAIN_KEY_NODE, &key_chain_cmd); + install_element(KEYCHAIN_KEY_NODE, &no_key_chain_cmd); + + install_element(KEYCHAIN_KEY_NODE, &key_cmd); + install_element(KEYCHAIN_KEY_NODE, &no_key_cmd); + + install_element(KEYCHAIN_KEY_NODE, + &accept_lifetime_day_month_day_month_cmd); + install_element(KEYCHAIN_KEY_NODE, + &accept_lifetime_day_month_month_day_cmd); + install_element(KEYCHAIN_KEY_NODE, + &accept_lifetime_month_day_day_month_cmd); + install_element(KEYCHAIN_KEY_NODE, + &accept_lifetime_month_day_month_day_cmd); + install_element(KEYCHAIN_KEY_NODE, + &accept_lifetime_infinite_day_month_cmd); + install_element(KEYCHAIN_KEY_NODE, + &accept_lifetime_infinite_month_day_cmd); + install_element(KEYCHAIN_KEY_NODE, + &accept_lifetime_duration_day_month_cmd); + install_element(KEYCHAIN_KEY_NODE, + &accept_lifetime_duration_month_day_cmd); + install_element(KEYCHAIN_KEY_NODE, &no_accept_lifetime_cmd); + + install_element(KEYCHAIN_KEY_NODE, + &send_lifetime_day_month_day_month_cmd); + install_element(KEYCHAIN_KEY_NODE, + &send_lifetime_day_month_month_day_cmd); + install_element(KEYCHAIN_KEY_NODE, + &send_lifetime_month_day_day_month_cmd); + install_element(KEYCHAIN_KEY_NODE, + &send_lifetime_month_day_month_day_cmd); + install_element(KEYCHAIN_KEY_NODE, + &send_lifetime_infinite_day_month_cmd); + install_element(KEYCHAIN_KEY_NODE, + &send_lifetime_infinite_month_day_cmd); + install_element(KEYCHAIN_KEY_NODE, + &send_lifetime_duration_day_month_cmd); + install_element(KEYCHAIN_KEY_NODE, + &send_lifetime_duration_month_day_cmd); + install_element(KEYCHAIN_KEY_NODE, &no_send_lifetime_cmd); + install_element(KEYCHAIN_KEY_NODE, &cryptographic_algorithm_cmd); + install_element(KEYCHAIN_KEY_NODE, &no_cryptographic_algorithm_cmd); +} diff --git a/lib/keychain_nb.c b/lib/keychain_nb.c index 1a2853a9052d..6a726ef83b26 100644 --- a/lib/keychain_nb.c +++ b/lib/keychain_nb.c @@ -1,92 +1,165 @@ // SPDX-License-Identifier: GPL-2.0-or-later +/* + * February 22 2024, Christian Hopps + * + * Copyright (C) 2024 LabN Consulting, L.L.C. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +#include "lib_errors.h" +#include "northbound.h" +#include "keychain.h" + +static void keychain_touch(struct keychain *keychain) +{ + keychain->last_touch = time(NULL); +} /* * XPath: /ietf-key-chain:key-chains/key-chain */ static int key_chains_key_chain_create(struct nb_cb_create_args *args) { - switch (args->event) { - case NB_EV_VALIDATE: - case NB_EV_PREPARE: - case NB_EV_ABORT: - case NB_EV_APPLY: - /* TODO: implement me. */ - break; - } + const char *name; + struct keychain *keychain; - return NB_OK; -} + if (args->event != NB_EV_APPLY) + return NB_OK; -static void key_chains_key_chain_cli_write(struct vty *vty, const struct lyd_node *dnode, bool show_defaults) -{ - /* TODO: this cli callback is optional; the cli output may not need to be done at each node. */ + name = yang_dnode_get_string(args->dnode, "name"); + keychain = keychain_get(name); + keychain_touch(keychain); + return NB_OK; } static int key_chains_key_chain_destroy(struct nb_cb_destroy_args *args) { - switch (args->event) { - case NB_EV_VALIDATE: - case NB_EV_PREPARE: - case NB_EV_ABORT: - case NB_EV_APPLY: - /* TODO: implement me. */ - break; - } + const char *name; + + if (args->event != NB_EV_APPLY) + return NB_OK; + name = yang_dnode_get_string(args->dnode, "name"); + keychain_delete(keychain_lookup(name)); return NB_OK; } static const void *key_chains_key_chain_get_next(struct nb_cb_get_next_args *args) { - /* TODO: implement me. */ - return NULL; + const struct listnode *prev = args->list_entry; + + return prev ? prev->next : keychain_list->head; } static int key_chains_key_chain_get_keys(struct nb_cb_get_keys_args *args) { - /* TODO: implement me. */ + const struct listnode *node = args->list_entry; + const struct keychain *keychain = node->data; + + args->keys->num = 1; + strlcpy(args->keys->key[0], keychain->name, sizeof(args->keys->key[0])); return NB_OK; } static const void *key_chains_key_chain_lookup_entry(struct nb_cb_lookup_entry_args *args) { - /* TODO: implement me. */ + const char *name = args->keys->key[0]; + struct keychain *keychain; + struct listnode *node; + + for (ALL_LIST_ELEMENTS_RO(keychain_list, node, keychain)) { + if (strcmp(keychain->name, name) == 0) + return node; + } return NULL; } + +static int __destroy_nop(struct nb_cb_destroy_args *args) +{ + /* modified by sibling or cleaned up by container destroy */ + return NB_OK; +} + +static struct key *__dnode_get_key2(const struct lyd_node *dnode, bool touch) +{ + struct keychain *keychain; + const char *name; + struct key *key; + uint32_t index; + + name = yang_dnode_get_string(dnode, "../../../name"); + keychain = keychain_lookup(name); + index = (uint32_t)yang_dnode_get_uint64(dnode, "../../key-id"); + key = key_lookup(keychain, index); + if (touch) + keychain_touch(keychain); + return key; +} + +static struct key *__dnode_get_key3(const struct lyd_node *dnode, bool touch) +{ + struct keychain *keychain; + const char *name; + struct key *key; + uint32_t index; + + name = yang_dnode_get_string(dnode, "../../../../name"); + keychain = keychain_lookup(name); + index = (uint32_t)yang_dnode_get_uint64(dnode, "../../../key-id"); + key = key_lookup(keychain, index); + if (touch) + keychain_touch(keychain); + return key; +} + /* * XPath: /ietf-key-chain:key-chains/key-chain/description */ static int key_chains_key_chain_description_modify(struct nb_cb_modify_args *args) { - switch (args->event) { - case NB_EV_VALIDATE: - case NB_EV_PREPARE: - case NB_EV_ABORT: - case NB_EV_APPLY: - /* TODO: implement me. */ - break; - } + struct keychain *keychain; + const char *name; - return NB_OK; -} + if (args->event != NB_EV_APPLY) + return NB_OK; -static void key_chains_key_chain_description_cli_write(struct vty *vty, const struct lyd_node *dnode, bool show_defaults) -{ - /* TODO: this cli callback is optional; the cli output may not need to be done at each node. */ + name = yang_dnode_get_string(args->dnode, "../name"); + keychain = keychain_lookup(name); + XFREE(MTYPE_KEYCHAIN_DESC, keychain->desc); + keychain->desc = XSTRDUP(MTYPE_KEYCHAIN_DESC, + yang_dnode_get_string(args->dnode, NULL)); + + keychain_touch(keychain); + return NB_OK; } static int key_chains_key_chain_description_destroy(struct nb_cb_destroy_args *args) { - switch (args->event) { - case NB_EV_VALIDATE: - case NB_EV_PREPARE: - case NB_EV_ABORT: - case NB_EV_APPLY: - /* TODO: implement me. */ - break; - } + struct keychain *keychain; + const char *name; + + if (args->event != NB_EV_APPLY) + return NB_OK; + name = yang_dnode_get_string(args->dnode, "../name"); + keychain = keychain_lookup(name); + XFREE(MTYPE_KEYCHAIN_DESC, keychain->desc); + + keychain_touch(keychain); return NB_OK; } @@ -95,8 +168,9 @@ static int key_chains_key_chain_description_destroy(struct nb_cb_destroy_args *a */ static struct yang_data *key_chains_key_chain_last_modified_timestamp_get_elem(struct nb_cb_get_elem_args *args) { - /* TODO: implement me. */ - return NULL; + const struct keychain *keychain = args->list_entry; + + return yang_data_new_date_and_time(args->xpath, keychain->last_touch); } /* @@ -104,269 +178,270 @@ static struct yang_data *key_chains_key_chain_last_modified_timestamp_get_elem(s */ static int key_chains_key_chain_key_create(struct nb_cb_create_args *args) { - switch (args->event) { - case NB_EV_VALIDATE: - case NB_EV_PREPARE: - case NB_EV_ABORT: - case NB_EV_APPLY: - /* TODO: implement me. */ - break; + struct keychain *keychain; + struct key *key; + const char *name; + uint64_t keyid; + + if (args->event != NB_EV_VALIDATE && args->event != NB_EV_APPLY) + return NB_OK; + + keyid = yang_dnode_get_uint64(args->dnode, "key-id"); + if (args->event == NB_EV_VALIDATE) { + if (keyid > UINT32_MAX) { + /* Warn most protocols can't use this value */ + flog_err(EC_LIB_NB_CB_CONFIG_VALIDATE, + "Protocols do not accept > 32-bit key-id values"); + return NB_EV_VALIDATE; + } + return NB_OK; } + if (args->event != NB_EV_APPLY) + return NB_OK; - return NB_OK; -} + name = yang_dnode_get_string(args->dnode, "../name"); + keychain = keychain_lookup(name); + assert(keyid <= UINT32_MAX); + key = key_get(keychain, (uint32_t)keyid); + assert(key); -static void key_chains_key_chain_key_cli_write(struct vty *vty, const struct lyd_node *dnode, bool show_defaults) -{ - /* TODO: this cli callback is optional; the cli output may not need to be done at each node. */ + keychain_touch(keychain); + return NB_OK; } static int key_chains_key_chain_key_destroy(struct nb_cb_destroy_args *args) { - switch (args->event) { - case NB_EV_VALIDATE: - case NB_EV_PREPARE: - case NB_EV_ABORT: - case NB_EV_APPLY: - /* TODO: implement me. */ - break; - } + struct keychain *keychain; + struct key *key; + const char *name; + uint64_t keyid; + + if (args->event != NB_EV_APPLY) + return NB_OK; + + keyid = yang_dnode_get_uint64(args->dnode, "key-id"); + if (keyid > UINT32_MAX) + return NB_ERR_NOT_FOUND; + name = yang_dnode_get_string(args->dnode, "../name"); + keychain = keychain_lookup(name); + key = key_lookup(keychain, (uint32_t)keyid); + key_delete(keychain, key); + keychain_touch(keychain); return NB_OK; } static const void *key_chains_key_chain_key_get_next(struct nb_cb_get_next_args *args) { - /* TODO: implement me. */ - return NULL; + const struct listnode *kcnode = args->parent_list_entry; + const struct keychain *keychain = kcnode->data; + const struct listnode *prev = args->list_entry; + + return prev ? prev->next : keychain->key->head; } static int key_chains_key_chain_key_get_keys(struct nb_cb_get_keys_args *args) { - /* TODO: implement me. */ + const struct listnode *node = args->list_entry; + const struct key *key = node->data; + + snprintf(args->keys->key[0], sizeof(args->keys->key[0]), "%" PRIu32, + key->index); + return NB_OK; } static const void *key_chains_key_chain_key_lookup_entry(struct nb_cb_lookup_entry_args *args) { - /* TODO: implement me. */ + const struct listnode *kcnode = args->parent_list_entry; + const struct keychain *keychain = kcnode->data; + struct listnode *node; + struct key *key; + uint32_t index; + + index = strtoul(args->keys->key[0], NULL, 0); + for (ALL_LIST_ELEMENTS_RO(keychain->key, node, key)) + if (key->index == index) + return node; return NULL; } -/* - * XPath: /ietf-key-chain:key-chains/key-chain/key/lifetime/send-accept-lifetime/always - */ -static int key_chains_key_chain_key_lifetime_send_accept_lifetime_always_create(struct nb_cb_create_args *args) +static int __lifetime_create(struct nb_cb_create_args *args, bool send, + bool accept, bool always) { - switch (args->event) { - case NB_EV_VALIDATE: - case NB_EV_PREPARE: - case NB_EV_ABORT: - case NB_EV_APPLY: - /* TODO: implement me. */ - break; - } + struct key *key; + + if (args->event != NB_EV_APPLY) + return NB_OK; + if (always) + key = __dnode_get_key3(args->dnode, true); + else + key = __dnode_get_key2(args->dnode, true); + if (send) { + key->send.start = 0; + key->send.end = -1; + key->send.duration = 0; + } + if (accept) { + key->accept.start = 0; + key->accept.end = -1; + key->accept.duration = 0; + } return NB_OK; } -static void key_chains_key_chain_key_lifetime_send_accept_lifetime_always_cli_write(struct vty *vty, const struct lyd_node *dnode, bool show_defaults) +static int __lifetime_start_date_time_modify(struct nb_cb_modify_args *args, + bool send, bool accept) { - /* TODO: this cli callback is optional; the cli output may not need to be done at each node. */ -} + struct key *key; + time_t time; -static int key_chains_key_chain_key_lifetime_send_accept_lifetime_always_destroy(struct nb_cb_destroy_args *args) -{ - switch (args->event) { - case NB_EV_VALIDATE: - case NB_EV_PREPARE: - case NB_EV_ABORT: - case NB_EV_APPLY: - /* TODO: implement me. */ - break; - } + if (args->event != NB_EV_APPLY) + return NB_OK; - return NB_OK; -} + key = __dnode_get_key3(args->dnode, true); + time = yang_dnode_get_date_and_time(args->dnode, NULL); -/* - * XPath: /ietf-key-chain:key-chains/key-chain/key/lifetime/send-accept-lifetime/start-date-time - */ -static int key_chains_key_chain_key_lifetime_send_accept_lifetime_start_date_time_modify(struct nb_cb_modify_args *args) -{ - switch (args->event) { - case NB_EV_VALIDATE: - case NB_EV_PREPARE: - case NB_EV_ABORT: - case NB_EV_APPLY: - /* TODO: implement me. */ - break; - } + if (send) + key->send.start = time; + if (accept) + key->accept.start = time; return NB_OK; } -static void key_chains_key_chain_key_lifetime_send_accept_lifetime_start_date_time_cli_write(struct vty *vty, const struct lyd_node *dnode, bool show_defaults) +static int __lifetime_no_end_time_create(struct nb_cb_create_args *args, + bool send, bool accept) { - /* TODO: this cli callback is optional; the cli output may not need to be done at each node. */ -} + struct key *key; -static int key_chains_key_chain_key_lifetime_send_accept_lifetime_start_date_time_destroy(struct nb_cb_destroy_args *args) -{ - switch (args->event) { - case NB_EV_VALIDATE: - case NB_EV_PREPARE: - case NB_EV_ABORT: - case NB_EV_APPLY: - /* TODO: implement me. */ - break; - } + if (args->event != NB_EV_APPLY) + return NB_OK; + key = __dnode_get_key3(args->dnode, true); + if (send) + key->send.end = -1; + if (accept) + key->accept.end = -1; return NB_OK; } -/* - * XPath: /ietf-key-chain:key-chains/key-chain/key/lifetime/send-accept-lifetime/no-end-time - */ -static int key_chains_key_chain_key_lifetime_send_accept_lifetime_no_end_time_create(struct nb_cb_create_args *args) +static int __lifetime_duration_modify(struct nb_cb_modify_args *args, bool send, + bool accept) { - switch (args->event) { - case NB_EV_VALIDATE: - case NB_EV_PREPARE: - case NB_EV_ABORT: - case NB_EV_APPLY: - /* TODO: implement me. */ - break; - } + struct key *key; + uint32_t duration; + time_t time; + + if (args->event != NB_EV_APPLY) + return NB_OK; + + key = __dnode_get_key3(args->dnode, true); + time = yang_dnode_get_date_and_time(args->dnode, "../start-date-time"); + duration = yang_dnode_get_uint32(args->dnode, NULL); + if (send) + key->send.end = time + duration; + if (accept) + key->accept.end = time + duration; return NB_OK; } -static void key_chains_key_chain_key_lifetime_send_accept_lifetime_no_end_time_cli_write(struct vty *vty, const struct lyd_node *dnode, bool show_defaults) +static int __lifetime_end_date_time_modify(struct nb_cb_modify_args *args, + bool send, bool accept) { - /* TODO: this cli callback is optional; the cli output may not need to be done at each node. */ -} + struct key *key; + time_t time; -static int key_chains_key_chain_key_lifetime_send_accept_lifetime_no_end_time_destroy(struct nb_cb_destroy_args *args) -{ - switch (args->event) { - case NB_EV_VALIDATE: - case NB_EV_PREPARE: - case NB_EV_ABORT: - case NB_EV_APPLY: - /* TODO: implement me. */ - break; - } + if (args->event != NB_EV_APPLY) + return NB_OK; + key = __dnode_get_key3(args->dnode, true); + time = yang_dnode_get_date_and_time(args->dnode, NULL); + + if (send) + key->send.end = time; + if (accept) + key->accept.end = time; return NB_OK; } /* - * XPath: /ietf-key-chain:key-chains/key-chain/key/lifetime/send-accept-lifetime/duration + * XPath: /ietf-key-chain:key-chains/key-chain/key/lifetime/send-accept-lifetime */ -static int key_chains_key_chain_key_lifetime_send_accept_lifetime_duration_modify(struct nb_cb_modify_args *args) +static int key_chains_key_chain_key_lifetime_send_accept_lifetime_create( + struct nb_cb_create_args *args) { - switch (args->event) { - case NB_EV_VALIDATE: - case NB_EV_PREPARE: - case NB_EV_ABORT: - case NB_EV_APPLY: - /* TODO: implement me. */ - break; - } - return NB_OK; + return __lifetime_create(args, true, true, false); } -static void key_chains_key_chain_key_lifetime_send_accept_lifetime_duration_cli_write(struct vty *vty, const struct lyd_node *dnode, bool show_defaults) +/* + * XPath: /ietf-key-chain:key-chains/key-chain/key/lifetime/send-accept-lifetime/always + */ +static int key_chains_key_chain_key_lifetime_send_accept_lifetime_always_create( + struct nb_cb_create_args *args) { - /* TODO: this cli callback is optional; the cli output may not need to be done at each node. */ + return __lifetime_create(args, true, true, true); } -static int key_chains_key_chain_key_lifetime_send_accept_lifetime_duration_destroy(struct nb_cb_destroy_args *args) +/* + * XPath: /ietf-key-chain:key-chains/key-chain/key/lifetime/send-accept-lifetime/start-date-time + */ +static int +key_chains_key_chain_key_lifetime_send_accept_lifetime_start_date_time_modify( + struct nb_cb_modify_args *args) { - switch (args->event) { - case NB_EV_VALIDATE: - case NB_EV_PREPARE: - case NB_EV_ABORT: - case NB_EV_APPLY: - /* TODO: implement me. */ - break; - } - - return NB_OK; + return __lifetime_start_date_time_modify(args, true, true); } /* - * XPath: /ietf-key-chain:key-chains/key-chain/key/lifetime/send-accept-lifetime/end-date-time + * XPath: /ietf-key-chain:key-chains/key-chain/key/lifetime/send-accept-lifetime/no-end-time */ -static int key_chains_key_chain_key_lifetime_send_accept_lifetime_end_date_time_modify(struct nb_cb_modify_args *args) +static int +key_chains_key_chain_key_lifetime_send_accept_lifetime_no_end_time_create( + struct nb_cb_create_args *args) { - switch (args->event) { - case NB_EV_VALIDATE: - case NB_EV_PREPARE: - case NB_EV_ABORT: - case NB_EV_APPLY: - /* TODO: implement me. */ - break; - } - - return NB_OK; + return __lifetime_no_end_time_create(args, true, true); } -static void key_chains_key_chain_key_lifetime_send_accept_lifetime_end_date_time_cli_write(struct vty *vty, const struct lyd_node *dnode, bool show_defaults) +/* + * XPath: /ietf-key-chain:key-chains/key-chain/key/lifetime/send-accept-lifetime/duration + */ +static int key_chains_key_chain_key_lifetime_send_accept_lifetime_duration_modify( + struct nb_cb_modify_args *args) { - /* TODO: this cli callback is optional; the cli output may not need to be done at each node. */ + return __lifetime_duration_modify(args, true, true); } -static int key_chains_key_chain_key_lifetime_send_accept_lifetime_end_date_time_destroy(struct nb_cb_destroy_args *args) +/* + * XPath: /ietf-key-chain:key-chains/key-chain/key/lifetime/send-accept-lifetime/end-date-time + */ +static int +key_chains_key_chain_key_lifetime_send_accept_lifetime_end_date_time_modify( + struct nb_cb_modify_args *args) { - switch (args->event) { - case NB_EV_VALIDATE: - case NB_EV_PREPARE: - case NB_EV_ABORT: - case NB_EV_APPLY: - /* TODO: implement me. */ - break; - } - - return NB_OK; + return __lifetime_end_date_time_modify(args, true, true); } /* - * XPath: /ietf-key-chain:key-chains/key-chain/key/lifetime/send-lifetime/always + * XPath: /ietf-key-chain:key-chains/key-chain/key/lifetime/send-lifetime */ -static int key_chains_key_chain_key_lifetime_send_lifetime_always_create(struct nb_cb_create_args *args) +static int key_chains_key_chain_key_lifetime_send_lifetime_create( + struct nb_cb_create_args *args) { - switch (args->event) { - case NB_EV_VALIDATE: - case NB_EV_PREPARE: - case NB_EV_ABORT: - case NB_EV_APPLY: - /* TODO: implement me. */ - break; - } - - return NB_OK; -} -static void key_chains_key_chain_key_lifetime_send_lifetime_always_cli_write(struct vty *vty, const struct lyd_node *dnode, bool show_defaults) -{ - /* TODO: this cli callback is optional; the cli output may not need to be done at each node. */ + return __lifetime_create(args, true, false, false); } -static int key_chains_key_chain_key_lifetime_send_lifetime_always_destroy(struct nb_cb_destroy_args *args) +/* + * XPath: /ietf-key-chain:key-chains/key-chain/key/lifetime/send-lifetime/always + */ +static int key_chains_key_chain_key_lifetime_send_lifetime_always_create( + struct nb_cb_create_args *args) { - switch (args->event) { - case NB_EV_VALIDATE: - case NB_EV_PREPARE: - case NB_EV_ABORT: - case NB_EV_APPLY: - /* TODO: implement me. */ - break; - } - - return NB_OK; + return __lifetime_create(args, true, false, true); } /* @@ -374,35 +449,7 @@ static int key_chains_key_chain_key_lifetime_send_lifetime_always_destroy(struct */ static int key_chains_key_chain_key_lifetime_send_lifetime_start_date_time_modify(struct nb_cb_modify_args *args) { - switch (args->event) { - case NB_EV_VALIDATE: - case NB_EV_PREPARE: - case NB_EV_ABORT: - case NB_EV_APPLY: - /* TODO: implement me. */ - break; - } - - return NB_OK; -} - -static void key_chains_key_chain_key_lifetime_send_lifetime_start_date_time_cli_write(struct vty *vty, const struct lyd_node *dnode, bool show_defaults) -{ - /* TODO: this cli callback is optional; the cli output may not need to be done at each node. */ -} - -static int key_chains_key_chain_key_lifetime_send_lifetime_start_date_time_destroy(struct nb_cb_destroy_args *args) -{ - switch (args->event) { - case NB_EV_VALIDATE: - case NB_EV_PREPARE: - case NB_EV_ABORT: - case NB_EV_APPLY: - /* TODO: implement me. */ - break; - } - - return NB_OK; + return __lifetime_start_date_time_modify(args, true, false); } /* @@ -410,35 +457,7 @@ static int key_chains_key_chain_key_lifetime_send_lifetime_start_date_time_destr */ static int key_chains_key_chain_key_lifetime_send_lifetime_no_end_time_create(struct nb_cb_create_args *args) { - switch (args->event) { - case NB_EV_VALIDATE: - case NB_EV_PREPARE: - case NB_EV_ABORT: - case NB_EV_APPLY: - /* TODO: implement me. */ - break; - } - - return NB_OK; -} - -static void key_chains_key_chain_key_lifetime_send_lifetime_no_end_time_cli_write(struct vty *vty, const struct lyd_node *dnode, bool show_defaults) -{ - /* TODO: this cli callback is optional; the cli output may not need to be done at each node. */ -} - -static int key_chains_key_chain_key_lifetime_send_lifetime_no_end_time_destroy(struct nb_cb_destroy_args *args) -{ - switch (args->event) { - case NB_EV_VALIDATE: - case NB_EV_PREPARE: - case NB_EV_ABORT: - case NB_EV_APPLY: - /* TODO: implement me. */ - break; - } - - return NB_OK; + return __lifetime_no_end_time_create(args, true, false); } /* @@ -446,35 +465,7 @@ static int key_chains_key_chain_key_lifetime_send_lifetime_no_end_time_destroy(s */ static int key_chains_key_chain_key_lifetime_send_lifetime_duration_modify(struct nb_cb_modify_args *args) { - switch (args->event) { - case NB_EV_VALIDATE: - case NB_EV_PREPARE: - case NB_EV_ABORT: - case NB_EV_APPLY: - /* TODO: implement me. */ - break; - } - - return NB_OK; -} - -static void key_chains_key_chain_key_lifetime_send_lifetime_duration_cli_write(struct vty *vty, const struct lyd_node *dnode, bool show_defaults) -{ - /* TODO: this cli callback is optional; the cli output may not need to be done at each node. */ -} - -static int key_chains_key_chain_key_lifetime_send_lifetime_duration_destroy(struct nb_cb_destroy_args *args) -{ - switch (args->event) { - case NB_EV_VALIDATE: - case NB_EV_PREPARE: - case NB_EV_ABORT: - case NB_EV_APPLY: - /* TODO: implement me. */ - break; - } - - return NB_OK; + return __lifetime_duration_modify(args, true, false); } /* @@ -482,35 +473,17 @@ static int key_chains_key_chain_key_lifetime_send_lifetime_duration_destroy(stru */ static int key_chains_key_chain_key_lifetime_send_lifetime_end_date_time_modify(struct nb_cb_modify_args *args) { - switch (args->event) { - case NB_EV_VALIDATE: - case NB_EV_PREPARE: - case NB_EV_ABORT: - case NB_EV_APPLY: - /* TODO: implement me. */ - break; - } - - return NB_OK; + return __lifetime_end_date_time_modify(args, true, false); } -static void key_chains_key_chain_key_lifetime_send_lifetime_end_date_time_cli_write(struct vty *vty, const struct lyd_node *dnode, bool show_defaults) -{ - /* TODO: this cli callback is optional; the cli output may not need to be done at each node. */ -} - -static int key_chains_key_chain_key_lifetime_send_lifetime_end_date_time_destroy(struct nb_cb_destroy_args *args) +/* + * XPath: /ietf-key-chain:key-chains/key-chain/key/lifetime/accept-lifetime + */ +static int key_chains_key_chain_key_lifetime_accept_lifetime_create( + struct nb_cb_create_args *args) { - switch (args->event) { - case NB_EV_VALIDATE: - case NB_EV_PREPARE: - case NB_EV_ABORT: - case NB_EV_APPLY: - /* TODO: implement me. */ - break; - } - return NB_OK; + return __lifetime_create(args, false, true, false); } /* @@ -518,35 +491,7 @@ static int key_chains_key_chain_key_lifetime_send_lifetime_end_date_time_destroy */ static int key_chains_key_chain_key_lifetime_accept_lifetime_always_create(struct nb_cb_create_args *args) { - switch (args->event) { - case NB_EV_VALIDATE: - case NB_EV_PREPARE: - case NB_EV_ABORT: - case NB_EV_APPLY: - /* TODO: implement me. */ - break; - } - - return NB_OK; -} - -static void key_chains_key_chain_key_lifetime_accept_lifetime_always_cli_write(struct vty *vty, const struct lyd_node *dnode, bool show_defaults) -{ - /* TODO: this cli callback is optional; the cli output may not need to be done at each node. */ -} - -static int key_chains_key_chain_key_lifetime_accept_lifetime_always_destroy(struct nb_cb_destroy_args *args) -{ - switch (args->event) { - case NB_EV_VALIDATE: - case NB_EV_PREPARE: - case NB_EV_ABORT: - case NB_EV_APPLY: - /* TODO: implement me. */ - break; - } - - return NB_OK; + return __lifetime_create(args, false, true, true); } /* @@ -554,35 +499,7 @@ static int key_chains_key_chain_key_lifetime_accept_lifetime_always_destroy(stru */ static int key_chains_key_chain_key_lifetime_accept_lifetime_start_date_time_modify(struct nb_cb_modify_args *args) { - switch (args->event) { - case NB_EV_VALIDATE: - case NB_EV_PREPARE: - case NB_EV_ABORT: - case NB_EV_APPLY: - /* TODO: implement me. */ - break; - } - - return NB_OK; -} - -static void key_chains_key_chain_key_lifetime_accept_lifetime_start_date_time_cli_write(struct vty *vty, const struct lyd_node *dnode, bool show_defaults) -{ - /* TODO: this cli callback is optional; the cli output may not need to be done at each node. */ -} - -static int key_chains_key_chain_key_lifetime_accept_lifetime_start_date_time_destroy(struct nb_cb_destroy_args *args) -{ - switch (args->event) { - case NB_EV_VALIDATE: - case NB_EV_PREPARE: - case NB_EV_ABORT: - case NB_EV_APPLY: - /* TODO: implement me. */ - break; - } - - return NB_OK; + return __lifetime_start_date_time_modify(args, false, true); } /* @@ -590,35 +507,7 @@ static int key_chains_key_chain_key_lifetime_accept_lifetime_start_date_time_des */ static int key_chains_key_chain_key_lifetime_accept_lifetime_no_end_time_create(struct nb_cb_create_args *args) { - switch (args->event) { - case NB_EV_VALIDATE: - case NB_EV_PREPARE: - case NB_EV_ABORT: - case NB_EV_APPLY: - /* TODO: implement me. */ - break; - } - - return NB_OK; -} - -static void key_chains_key_chain_key_lifetime_accept_lifetime_no_end_time_cli_write(struct vty *vty, const struct lyd_node *dnode, bool show_defaults) -{ - /* TODO: this cli callback is optional; the cli output may not need to be done at each node. */ -} - -static int key_chains_key_chain_key_lifetime_accept_lifetime_no_end_time_destroy(struct nb_cb_destroy_args *args) -{ - switch (args->event) { - case NB_EV_VALIDATE: - case NB_EV_PREPARE: - case NB_EV_ABORT: - case NB_EV_APPLY: - /* TODO: implement me. */ - break; - } - - return NB_OK; + return __lifetime_no_end_time_create(args, false, true); } /* @@ -626,35 +515,7 @@ static int key_chains_key_chain_key_lifetime_accept_lifetime_no_end_time_destroy */ static int key_chains_key_chain_key_lifetime_accept_lifetime_duration_modify(struct nb_cb_modify_args *args) { - switch (args->event) { - case NB_EV_VALIDATE: - case NB_EV_PREPARE: - case NB_EV_ABORT: - case NB_EV_APPLY: - /* TODO: implement me. */ - break; - } - - return NB_OK; -} - -static void key_chains_key_chain_key_lifetime_accept_lifetime_duration_cli_write(struct vty *vty, const struct lyd_node *dnode, bool show_defaults) -{ - /* TODO: this cli callback is optional; the cli output may not need to be done at each node. */ -} - -static int key_chains_key_chain_key_lifetime_accept_lifetime_duration_destroy(struct nb_cb_destroy_args *args) -{ - switch (args->event) { - case NB_EV_VALIDATE: - case NB_EV_PREPARE: - case NB_EV_ABORT: - case NB_EV_APPLY: - /* TODO: implement me. */ - break; - } - - return NB_OK; + return __lifetime_duration_modify(args, false, true); } /* @@ -662,35 +523,7 @@ static int key_chains_key_chain_key_lifetime_accept_lifetime_duration_destroy(st */ static int key_chains_key_chain_key_lifetime_accept_lifetime_end_date_time_modify(struct nb_cb_modify_args *args) { - switch (args->event) { - case NB_EV_VALIDATE: - case NB_EV_PREPARE: - case NB_EV_ABORT: - case NB_EV_APPLY: - /* TODO: implement me. */ - break; - } - - return NB_OK; -} - -static void key_chains_key_chain_key_lifetime_accept_lifetime_end_date_time_cli_write(struct vty *vty, const struct lyd_node *dnode, bool show_defaults) -{ - /* TODO: this cli callback is optional; the cli output may not need to be done at each node. */ -} - -static int key_chains_key_chain_key_lifetime_accept_lifetime_end_date_time_destroy(struct nb_cb_destroy_args *args) -{ - switch (args->event) { - case NB_EV_VALIDATE: - case NB_EV_PREPARE: - case NB_EV_ABORT: - case NB_EV_APPLY: - /* TODO: implement me. */ - break; - } - - return NB_OK; + return __lifetime_end_date_time_modify(args, false, true); } /* @@ -698,21 +531,67 @@ static int key_chains_key_chain_key_lifetime_accept_lifetime_end_date_time_destr */ static int key_chains_key_chain_key_crypto_algorithm_modify(struct nb_cb_modify_args *args) { - switch (args->event) { - case NB_EV_VALIDATE: - case NB_EV_PREPARE: - case NB_EV_ABORT: - case NB_EV_APPLY: - /* TODO: implement me. */ - break; + static const char prefix[] = "ietf-key-chain:"; + static const int prefix_len = sizeof(prefix) - 1; + struct keychain *keychain; + const char *name; + struct key *key; + uint32_t index; + uint8_t hash_algo; + + if (args->event != NB_EV_VALIDATE && args->event != NB_EV_APPLY) + return NB_OK; + + name = yang_dnode_get_string(args->dnode, "../../name"); + keychain = keychain_lookup(name); + index = (uint32_t)yang_dnode_get_uint64(args->dnode, "../key-id"); + key = key_lookup(keychain, index); + name = yang_dnode_get_string(args->dnode, NULL); + if (!strncmp(name, prefix, prefix_len)) + name += prefix_len; + hash_algo = keychain_get_algo_id_by_name(name); + + if (args->event == NB_EV_VALIDATE) { + if (!hash_algo) { + zlog_err("\"%s\" hash algo not supported", name); + return NB_ERR_VALIDATION; + } +#ifndef CRYPTO_OPENSSL + if (hash_algo == KEYCHAIN_ALGO_NULL) { + zlog_err("\"%s\" algo not supported, compile with --with-crypto=openssl", + name); + return NB_ERR_VALIDATION; + } +#endif /* CRYPTO_OPENSSL */ + return NB_OK; } + assert(args->event == NB_EV_APPLY); + key->hash_algo = hash_algo; + + keychain_touch(keychain); return NB_OK; } -static void key_chains_key_chain_key_crypto_algorithm_cli_write(struct vty *vty, const struct lyd_node *dnode, bool show_defaults) +static int key_chains_key_chain_key_crypto_algorithm_destroy( + struct nb_cb_destroy_args *args) { - /* TODO: this cli callback is optional; the cli output may not need to be done at each node. */ + struct keychain *keychain; + const char *name; + struct key *key; + uint32_t index; + + if (args->event != NB_EV_APPLY) + return NB_OK; + + name = yang_dnode_get_string(args->dnode, "../../../name"); + keychain = keychain_lookup(name); + index = (uint32_t)yang_dnode_get_uint64(args->dnode, "../../key-id"); + key = key_lookup(keychain, index); + key->hash_algo = KEYCHAIN_ALGO_NULL; + keychain_touch(keychain); + + return NB_OK; } /* @@ -720,33 +599,48 @@ static void key_chains_key_chain_key_crypto_algorithm_cli_write(struct vty *vty, */ static int key_chains_key_chain_key_key_string_keystring_modify(struct nb_cb_modify_args *args) { - switch (args->event) { - case NB_EV_VALIDATE: - case NB_EV_PREPARE: - case NB_EV_ABORT: - case NB_EV_APPLY: - /* TODO: implement me. */ - break; - } + struct keychain *keychain; + const char *name; + struct key *key; + uint32_t index; - return NB_OK; -} + if (args->event != NB_EV_APPLY) + return NB_OK; -static void key_chains_key_chain_key_key_string_keystring_cli_write(struct vty *vty, const struct lyd_node *dnode, bool show_defaults) -{ - /* TODO: this cli callback is optional; the cli output may not need to be done at each node. */ + name = yang_dnode_get_string(args->dnode, "../../../name"); + keychain = keychain_lookup(name); + index = (uint32_t)yang_dnode_get_uint64(args->dnode, "../../key-id"); + key = key_lookup(keychain, index); + assert(key); + + + if (key->string) + XFREE(MTYPE_KEY, key->string); + key->string = XSTRDUP(MTYPE_KEY, + yang_dnode_get_string(args->dnode, NULL)); + + keychain_touch(keychain); + return NB_OK; } static int key_chains_key_chain_key_key_string_keystring_destroy(struct nb_cb_destroy_args *args) { - switch (args->event) { - case NB_EV_VALIDATE: - case NB_EV_PREPARE: - case NB_EV_ABORT: - case NB_EV_APPLY: - /* TODO: implement me. */ - break; - } + struct keychain *keychain; + const char *name; + struct key *key; + uint32_t index; + + if (args->event != NB_EV_APPLY) + return NB_OK; + + name = yang_dnode_get_string(args->dnode, "../../../name"); + keychain = keychain_lookup(name); + index = (uint32_t)yang_dnode_get_uint64(args->dnode, "../../key-id"); + key = key_lookup(keychain, index); + assert(key); + + XFREE(MTYPE_KEY, key->string); + keychain_touch(keychain); return NB_OK; } @@ -756,8 +650,18 @@ static int key_chains_key_chain_key_key_string_keystring_destroy(struct nb_cb_de */ static struct yang_data *key_chains_key_chain_key_send_lifetime_active_get_elem(struct nb_cb_get_elem_args *args) { - /* TODO: implement me. */ - return NULL; + const struct listnode *node = args->list_entry; + const struct key *key = node->data; + time_t now = time(NULL); + bool active = false; + + if (key->send.start == 0) + active = true; + else if (key->send.start <= now) + if (key->send.end >= now || key->send.end == -1) + active = true; + + return yang_data_new_bool(args->xpath, active); } /* @@ -765,13 +669,29 @@ static struct yang_data *key_chains_key_chain_key_send_lifetime_active_get_elem( */ static struct yang_data *key_chains_key_chain_key_accept_lifetime_active_get_elem(struct nb_cb_get_elem_args *args) { - /* TODO: implement me. */ - return NULL; + const struct listnode *node = args->list_entry; + const struct key *key = node->data; + time_t now = time(NULL); + bool active = false; + + if (key->accept.start == 0) + active = true; + else if (key->accept.start <= now) + if (key->accept.end >= now || key->accept.end == -1) + active = true; + + return yang_data_new_bool(args->xpath, active); } +static const char * const keychain_features[] = { + "independent-send-accept-lifetime", + NULL, +}; + /* clang-format off */ -const struct frr_yang_module_info ietf_key_chain_nb_info = { +const struct frr_yang_module_info ietf_key_chain_info = { .name = "ietf-key-chain", + .features = (const char **)keychain_features, .nodes = { { .xpath = "/ietf-key-chain:key-chains/key-chain", @@ -781,6 +701,8 @@ const struct frr_yang_module_info ietf_key_chain_nb_info = { .get_next = key_chains_key_chain_get_next, .get_keys = key_chains_key_chain_get_keys, .lookup_entry = key_chains_key_chain_lookup_entry, + .cli_show = key_chains_key_chain_cli_write, + .cli_show_end = key_chains_key_chain_cli_write_end, } }, { @@ -788,6 +710,7 @@ const struct frr_yang_module_info ietf_key_chain_nb_info = { .cbs = { .modify = key_chains_key_chain_description_modify, .destroy = key_chains_key_chain_description_destroy, + .cli_show = key_chains_key_chain_description_cli_write, } }, { @@ -804,117 +727,145 @@ const struct frr_yang_module_info ietf_key_chain_nb_info = { .get_next = key_chains_key_chain_key_get_next, .get_keys = key_chains_key_chain_key_get_keys, .lookup_entry = key_chains_key_chain_key_lookup_entry, + .cli_show = key_chains_key_chain_key_cli_write, + .cli_show_end = key_chains_key_chain_key_cli_write_end, + } + }, + { + .xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/send-accept-lifetime", + .cbs = { + .create = key_chains_key_chain_key_lifetime_send_accept_lifetime_create, + .destroy = __destroy_nop, } }, { .xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/send-accept-lifetime/always", .cbs = { .create = key_chains_key_chain_key_lifetime_send_accept_lifetime_always_create, - .destroy = key_chains_key_chain_key_lifetime_send_accept_lifetime_always_destroy, + .destroy = __destroy_nop, } }, { .xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/send-accept-lifetime/start-date-time", .cbs = { .modify = key_chains_key_chain_key_lifetime_send_accept_lifetime_start_date_time_modify, - .destroy = key_chains_key_chain_key_lifetime_send_accept_lifetime_start_date_time_destroy, + .destroy = __destroy_nop, + .cli_show = key_chains_key_chain_key_lifetime_send_accept_lifetime_start_date_time_cli_write, } }, { .xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/send-accept-lifetime/no-end-time", .cbs = { .create = key_chains_key_chain_key_lifetime_send_accept_lifetime_no_end_time_create, - .destroy = key_chains_key_chain_key_lifetime_send_accept_lifetime_no_end_time_destroy, + .destroy = __destroy_nop, } }, { .xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/send-accept-lifetime/duration", .cbs = { .modify = key_chains_key_chain_key_lifetime_send_accept_lifetime_duration_modify, - .destroy = key_chains_key_chain_key_lifetime_send_accept_lifetime_duration_destroy, + .destroy = __destroy_nop, } }, { .xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/send-accept-lifetime/end-date-time", .cbs = { .modify = key_chains_key_chain_key_lifetime_send_accept_lifetime_end_date_time_modify, - .destroy = key_chains_key_chain_key_lifetime_send_accept_lifetime_end_date_time_destroy, + .destroy = __destroy_nop, + } + }, + { + .xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/send-lifetime", + .cbs = { + .create = key_chains_key_chain_key_lifetime_send_lifetime_create, + .destroy = __destroy_nop, } }, { .xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/send-lifetime/always", .cbs = { .create = key_chains_key_chain_key_lifetime_send_lifetime_always_create, - .destroy = key_chains_key_chain_key_lifetime_send_lifetime_always_destroy, + .destroy = __destroy_nop, } }, { .xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/send-lifetime/start-date-time", .cbs = { .modify = key_chains_key_chain_key_lifetime_send_lifetime_start_date_time_modify, - .destroy = key_chains_key_chain_key_lifetime_send_lifetime_start_date_time_destroy, + .destroy = __destroy_nop, + .cli_show = key_chains_key_chain_key_lifetime_send_lifetime_start_date_time_cli_write, } }, { .xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/send-lifetime/no-end-time", .cbs = { .create = key_chains_key_chain_key_lifetime_send_lifetime_no_end_time_create, - .destroy = key_chains_key_chain_key_lifetime_send_lifetime_no_end_time_destroy, + .destroy = __destroy_nop, } }, { .xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/send-lifetime/duration", .cbs = { .modify = key_chains_key_chain_key_lifetime_send_lifetime_duration_modify, - .destroy = key_chains_key_chain_key_lifetime_send_lifetime_duration_destroy, + .destroy = __destroy_nop, } }, { .xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/send-lifetime/end-date-time", .cbs = { .modify = key_chains_key_chain_key_lifetime_send_lifetime_end_date_time_modify, - .destroy = key_chains_key_chain_key_lifetime_send_lifetime_end_date_time_destroy, + .destroy = __destroy_nop, + } + }, + { + .xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/accept-lifetime", + .cbs = { + .create = key_chains_key_chain_key_lifetime_accept_lifetime_create, + .destroy = __destroy_nop, } }, { .xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/accept-lifetime/always", .cbs = { .create = key_chains_key_chain_key_lifetime_accept_lifetime_always_create, - .destroy = key_chains_key_chain_key_lifetime_accept_lifetime_always_destroy, + .destroy = __destroy_nop, } }, { .xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/accept-lifetime/start-date-time", .cbs = { .modify = key_chains_key_chain_key_lifetime_accept_lifetime_start_date_time_modify, - .destroy = key_chains_key_chain_key_lifetime_accept_lifetime_start_date_time_destroy, + .destroy = __destroy_nop, + .cli_show = key_chains_key_chain_key_lifetime_accept_lifetime_start_date_time_cli_write, } }, { .xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/accept-lifetime/no-end-time", .cbs = { .create = key_chains_key_chain_key_lifetime_accept_lifetime_no_end_time_create, - .destroy = key_chains_key_chain_key_lifetime_accept_lifetime_no_end_time_destroy, + .destroy = __destroy_nop, } }, { .xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/accept-lifetime/duration", .cbs = { .modify = key_chains_key_chain_key_lifetime_accept_lifetime_duration_modify, - .destroy = key_chains_key_chain_key_lifetime_accept_lifetime_duration_destroy, + .destroy = __destroy_nop, } }, { .xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/accept-lifetime/end-date-time", .cbs = { .modify = key_chains_key_chain_key_lifetime_accept_lifetime_end_date_time_modify, - .destroy = key_chains_key_chain_key_lifetime_accept_lifetime_end_date_time_destroy, + .destroy = __destroy_nop, } }, { .xpath = "/ietf-key-chain:key-chains/key-chain/key/crypto-algorithm", .cbs = { .modify = key_chains_key_chain_key_crypto_algorithm_modify, + .destroy = key_chains_key_chain_key_crypto_algorithm_destroy, + .cli_show = key_chains_key_chain_key_crypto_algorithm_cli_write, } }, { @@ -922,6 +873,7 @@ const struct frr_yang_module_info ietf_key_chain_nb_info = { .cbs = { .modify = key_chains_key_chain_key_key_string_keystring_modify, .destroy = key_chains_key_chain_key_key_string_keystring_destroy, + .cli_show = key_chains_key_chain_key_key_string_keystring_cli_write, } }, { @@ -939,135 +891,5 @@ const struct frr_yang_module_info ietf_key_chain_nb_info = { { .xpath = NULL, }, - } -}; - -/* clang-format off */ -const struct frr_yang_module_info ietf_key_chain_cli_info = { - .name = "ietf-key-chain", - .nodes = { - { - .xpath = "/ietf-key-chain:key-chains/key-chain", - .cbs = { - .cli_show = key_chains_key_chain_cli_write, - } - }, - { - .xpath = "/ietf-key-chain:key-chains/key-chain/description", - .cbs = { - .cli_show = key_chains_key_chain_description_cli_write, - } - }, - { - .xpath = "/ietf-key-chain:key-chains/key-chain/key", - .cbs = { - .cli_show = key_chains_key_chain_key_cli_write, - } - }, - { - .xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/send-accept-lifetime/always", - .cbs = { - .cli_show = key_chains_key_chain_key_lifetime_send_accept_lifetime_always_cli_write, - } - }, - { - .xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/send-accept-lifetime/start-date-time", - .cbs = { - .cli_show = key_chains_key_chain_key_lifetime_send_accept_lifetime_start_date_time_cli_write, - } - }, - { - .xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/send-accept-lifetime/no-end-time", - .cbs = { - .cli_show = key_chains_key_chain_key_lifetime_send_accept_lifetime_no_end_time_cli_write, - } - }, - { - .xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/send-accept-lifetime/duration", - .cbs = { - .cli_show = key_chains_key_chain_key_lifetime_send_accept_lifetime_duration_cli_write, - } - }, - { - .xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/send-accept-lifetime/end-date-time", - .cbs = { - .cli_show = key_chains_key_chain_key_lifetime_send_accept_lifetime_end_date_time_cli_write, - } - }, - { - .xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/send-lifetime/always", - .cbs = { - .cli_show = key_chains_key_chain_key_lifetime_send_lifetime_always_cli_write, - } - }, - { - .xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/send-lifetime/start-date-time", - .cbs = { - .cli_show = key_chains_key_chain_key_lifetime_send_lifetime_start_date_time_cli_write, - } - }, - { - .xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/send-lifetime/no-end-time", - .cbs = { - .cli_show = key_chains_key_chain_key_lifetime_send_lifetime_no_end_time_cli_write, - } - }, - { - .xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/send-lifetime/duration", - .cbs = { - .cli_show = key_chains_key_chain_key_lifetime_send_lifetime_duration_cli_write, - } - }, - { - .xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/send-lifetime/end-date-time", - .cbs = { - .cli_show = key_chains_key_chain_key_lifetime_send_lifetime_end_date_time_cli_write, - } - }, - { - .xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/accept-lifetime/always", - .cbs = { - .cli_show = key_chains_key_chain_key_lifetime_accept_lifetime_always_cli_write, - } - }, - { - .xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/accept-lifetime/start-date-time", - .cbs = { - .cli_show = key_chains_key_chain_key_lifetime_accept_lifetime_start_date_time_cli_write, - } - }, - { - .xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/accept-lifetime/no-end-time", - .cbs = { - .cli_show = key_chains_key_chain_key_lifetime_accept_lifetime_no_end_time_cli_write, - } - }, - { - .xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/accept-lifetime/duration", - .cbs = { - .cli_show = key_chains_key_chain_key_lifetime_accept_lifetime_duration_cli_write, - } - }, - { - .xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/accept-lifetime/end-date-time", - .cbs = { - .cli_show = key_chains_key_chain_key_lifetime_accept_lifetime_end_date_time_cli_write, - } - }, - { - .xpath = "/ietf-key-chain:key-chains/key-chain/key/crypto-algorithm", - .cbs = { - .cli_show = key_chains_key_chain_key_crypto_algorithm_cli_write, - } - }, - { - .xpath = "/ietf-key-chain:key-chains/key-chain/key/key-string/keystring", - .cbs = { - .cli_show = key_chains_key_chain_key_key_string_keystring_cli_write, - } - }, - { - .xpath = NULL, - }, - } + }, }; diff --git a/lib/subdir.am b/lib/subdir.am index 6893049c7e56..db11def74197 100644 --- a/lib/subdir.am +++ b/lib/subdir.am @@ -53,6 +53,8 @@ lib_libfrr_la_SOURCES = \ lib/jhash.c \ lib/json.c \ lib/keychain.c \ + lib/keychain_cli.c \ + lib/keychain_nb.c \ lib/ldp_sync.c \ lib/lib_errors.c \ lib/lib_vty.c \ @@ -148,7 +150,9 @@ nodist_lib_libfrr_la_SOURCES = \ yang/frr-vrf.yang.c \ yang/frr-routing.yang.c \ yang/frr-nexthop.yang.c \ + yang/ietf/frr-deviations-ietf-key-chain.yang.c \ yang/ietf/ietf-routing-types.yang.c \ + yang/ietf/ietf-key-chain.yang.c \ yang/ietf/ietf-interfaces.yang.c \ yang/ietf/ietf-bgp-types.yang.c \ yang/frr-module-translator.yang.c \ @@ -181,6 +185,7 @@ clippy_scan += \ lib/if.c \ lib/filter_cli.c \ lib/if_rmap.c \ + lib/keychain_cli.c \ lib/log_vty.c \ lib/mgmt_be_client.c \ lib/mgmt_fe_client.c \ diff --git a/lib/yang_wrappers.c b/lib/yang_wrappers.c index a0133954c328..38df18998b06 100644 --- a/lib/yang_wrappers.c +++ b/lib/yang_wrappers.c @@ -1052,6 +1052,32 @@ struct yang_data *yang_data_new_date_and_time(const char *xpath, time_t time) return yang_data_new(xpath, timebuf); } +struct timespec yang_dnode_get_date_and_timespec(const struct lyd_node *dnode, + const char *xpath_fmt, ...) +{ + const char *canon = YANG_DNODE_XPATH_GET_CANON(dnode, xpath_fmt); + struct timespec ts; + LY_ERR err; + + err = ly_time_str2ts(canon, &ts); + assert(!err); + + return ts; +} + +time_t yang_dnode_get_date_and_time(const struct lyd_node *dnode, + const char *xpath_fmt, ...) +{ + const char *canon = YANG_DNODE_XPATH_GET_CANON(dnode, xpath_fmt); + time_t time; + LY_ERR err; + + err = ly_time_str2time(canon, &time, NULL); + assert(!err); + + return time; +} + float yang_dnode_get_bandwidth_ieee_float32(const struct lyd_node *dnode, const char *xpath_fmt, ...) { diff --git a/lib/yang_wrappers.h b/lib/yang_wrappers.h index 59b5b13acdd9..d8a3dde28b44 100644 --- a/lib/yang_wrappers.h +++ b/lib/yang_wrappers.h @@ -7,6 +7,7 @@ #ifndef _FRR_NORTHBOUND_WRAPPERS_H_ #define _FRR_NORTHBOUND_WRAPPERS_H_ +#include #include "prefix.h" #ifdef __cplusplus @@ -201,6 +202,10 @@ extern void yang_dnode_get_mac(struct ethaddr *mac, const struct lyd_node *dnode /*data-and-time */ extern struct yang_data *yang_data_new_date_and_time(const char *xpath, time_t time); +struct timespec yang_dnode_get_date_and_timespec(const struct lyd_node *dnode, + const char *xpath_fmt, ...); +time_t yang_dnode_get_date_and_time(const struct lyd_node *dnode, + const char *xpath_fmt, ...); /* rt-types:bandwidth-ieee-float32 */ extern float yang_dnode_get_bandwidth_ieee_float32(const struct lyd_node *dnode, diff --git a/mgmtd/mgmt_be_adapter.c b/mgmtd/mgmt_be_adapter.c index b311bf469878..fc08a759ec9f 100644 --- a/mgmtd/mgmt_be_adapter.c +++ b/mgmtd/mgmt_be_adapter.c @@ -90,10 +90,12 @@ static const char *const ripd_config_xpaths[] = { "/frr-ripd:ripd", "/frr-route-map:lib", "/frr-vrf:lib", + "/ietf-key-map:key-chains", NULL, }; static const char *const ripd_oper_xpaths[] = { "/frr-ripd:ripd", + "/ietf-key-map:key-chains", NULL, }; #endif diff --git a/mgmtd/mgmt_main.c b/mgmtd/mgmt_main.c index cce16f51f604..e181d0da5ef0 100644 --- a/mgmtd/mgmt_main.c +++ b/mgmtd/mgmt_main.c @@ -10,6 +10,7 @@ #include "lib/version.h" #include "routemap.h" #include "filter.h" +#include "keychain.h" #include "libfrr.h" #include "frr_pthread.h" #include "mgmtd/mgmt.h" @@ -185,6 +186,8 @@ static const struct frr_yang_module_info *const mgmt_yang_modules[] = { &frr_zebra_cli_info, &zebra_route_map_info, + &ietf_key_chain_cli_info, + &ietf_key_chain_deviation_info, #ifdef HAVE_RIPD &frr_ripd_cli_info, @@ -199,20 +202,20 @@ static const struct frr_yang_module_info *const mgmt_yang_modules[] = { /* clang-format off */ FRR_DAEMON_INFO(mgmtd, MGMTD, - .vty_port = MGMTD_VTY_PORT, - .proghelp = "FRR Management Daemon.", + .vty_port = MGMTD_VTY_PORT, + .proghelp = "FRR Management Daemon.", - .signals = mgmt_signals, - .n_signals = array_size(mgmt_signals), + .signals = mgmt_signals, + .n_signals = array_size(mgmt_signals), - .privs = &mgmt_privs, + .privs = &mgmt_privs, - .yang_modules = mgmt_yang_modules, - .n_yang_modules = array_size(mgmt_yang_modules), + .yang_modules = mgmt_yang_modules, + .n_yang_modules = array_size(mgmt_yang_modules), - /* avoid libfrr trying to read our config file for us */ - .flags = FRR_MANUAL_VTY_START | FRR_NO_SPLIT_CONFIG, -); + /* avoid libfrr trying to read our config file for us */ + .flags = FRR_MANUAL_VTY_START | FRR_NO_SPLIT_CONFIG, + ); /* clang-format on */ #define DEPRECATED_OPTIONS "" diff --git a/mgmtd/mgmt_vty.c b/mgmtd/mgmt_vty.c index 12ea62eceff5..0e5c06bf8345 100644 --- a/mgmtd/mgmt_vty.c +++ b/mgmtd/mgmt_vty.c @@ -12,6 +12,7 @@ #include "command.h" #include "filter.h" #include "json.h" +#include "keychain.h" #include "network.h" #include "northbound_cli.h" #include "routemap.h" @@ -600,6 +601,7 @@ void mgmt_vty_init(void) filter_cli_init(); route_map_cli_init(); affinity_map_init(); + keychain_cli_init(); /* * Initialize command handling from VTYSH connection. diff --git a/ospf6d/ospf6_main.c b/ospf6d/ospf6_main.c index 17966e741e37..0e8504c5298f 100644 --- a/ospf6d/ospf6_main.c +++ b/ospf6d/ospf6_main.c @@ -169,6 +169,8 @@ static const struct frr_yang_module_info *const ospf6d_yang_modules[] = { &frr_vrf_info, &frr_ospf_route_map_info, &frr_ospf6_route_map_info, + &ietf_key_chain_info, + &ietf_key_chain_deviation_info, }; /* actual paths filled in main() */ @@ -182,19 +184,19 @@ static char *state_paths[] = { /* clang-format off */ FRR_DAEMON_INFO(ospf6d, OSPF6, - .vty_port = OSPF6_VTY_PORT, - .proghelp = "Implementation of the OSPFv3 routing protocol.", + .vty_port = OSPF6_VTY_PORT, + .proghelp = "Implementation of the OSPFv3 routing protocol.", - .signals = ospf6_signals, - .n_signals = array_size(ospf6_signals), + .signals = ospf6_signals, + .n_signals = array_size(ospf6_signals), - .privs = &ospf6d_privs, + .privs = &ospf6d_privs, - .yang_modules = ospf6d_yang_modules, - .n_yang_modules = array_size(ospf6d_yang_modules), + .yang_modules = ospf6d_yang_modules, + .n_yang_modules = array_size(ospf6d_yang_modules), - .state_paths = state_paths, -); + .state_paths = state_paths, + ); /* clang-format on */ /* Max wait time for config to load before accepting hellos */ diff --git a/ospfd/ospf_main.c b/ospfd/ospf_main.c index 6a4a9a148177..abad6c5b902f 100644 --- a/ospfd/ospf_main.c +++ b/ospfd/ospf_main.c @@ -134,6 +134,8 @@ static const struct frr_yang_module_info *const ospfd_yang_modules[] = { &frr_route_map_info, &frr_vrf_info, &frr_ospf_route_map_info, + &ietf_key_chain_info, + &ietf_key_chain_deviation_info, }; /* actual paths filled in main() */ diff --git a/python/xref2vtysh.py b/python/xref2vtysh.py index 91ccba64f0d0..177de757b04d 100644 --- a/python/xref2vtysh.py +++ b/python/xref2vtysh.py @@ -36,7 +36,7 @@ "lib/filter.c": "VTYSH_ACL_SHOW", "lib/filter_cli.c": "VTYSH_ACL_CONFIG", "lib/if.c": "VTYSH_INTERFACE", - "lib/keychain.c": "VTYSH_KEYS", + "lib/keychain_cli.c": "VTYSH_KEYS", "lib/mgmt_be_client.c": "VTYSH_MGMT_BACKEND", "lib/mgmt_fe_client.c": "VTYSH_MGMT_FRONTEND", "lib/lib_vty.c": "VTYSH_ALL", diff --git a/ripd/rip_main.c b/ripd/rip_main.c index 845c5078a574..734e7ac4d926 100644 --- a/ripd/rip_main.c +++ b/ripd/rip_main.c @@ -131,6 +131,8 @@ static const struct frr_yang_module_info *const ripd_yang_modules[] = { &frr_ripd_info, &frr_route_map_info, &frr_vrf_info, + &ietf_key_chain_info, + &ietf_key_chain_deviation_info, }; /* clang-format off */ @@ -189,7 +191,7 @@ int main(int argc, char **argv) /* Library initialization. */ rip_error_init(); - keychain_init(); + keychain_init_new(true); rip_vrf_init(); /* RIP related initialization. */ diff --git a/vtysh/vtysh.h b/vtysh/vtysh.h index 7758ceaea502..b35d56672a3c 100644 --- a/vtysh/vtysh.h +++ b/vtysh/vtysh.h @@ -75,7 +75,7 @@ extern struct event_loop *master; VTYSH_VRRPD | VTYSH_MGMTD #define VTYSH_INTERFACE VTYSH_INTERFACE_SUBSET | VTYSH_BGPD #define VTYSH_VRF VTYSH_INTERFACE_SUBSET | VTYSH_BGPD -#define VTYSH_KEYS VTYSH_RIPD | VTYSH_EIGRPD | VTYSH_OSPF6D | VTYSH_OSPFD +#define VTYSH_KEYS VTYSH_MGMTD | VTYSH_EIGRPD | VTYSH_OSPF6D | VTYSH_OSPFD /* Daemons who can process nexthop-group configs */ #define VTYSH_NH_GROUP VTYSH_PBRD|VTYSH_SHARPD #define VTYSH_SR VTYSH_ZEBRA|VTYSH_PATHD