From 822855b1281f8d7528c8b23c8f687f90fb15d8f4 Mon Sep 17 00:00:00 2001 From: eeff <33566201+eeff@users.noreply.github.com> Date: Sun, 6 Nov 2022 23:17:19 +0800 Subject: [PATCH 1/2] fix(restful): ensure all license key fields present --- plugins/restful/license.c | 22 ++++++++++++++++++---- plugins/restful/license.h | 3 +++ 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/plugins/restful/license.c b/plugins/restful/license.c index 8f152a56..ca48afa4 100644 --- a/plugins/restful/license.c +++ b/plugins/restful/license.c @@ -273,6 +273,7 @@ static int extract_license(const char *license_fname, const char *pub_key, goto final; } + unsigned mark = 0; for (i = 0; i < sk_X509_EXTENSION_num(ext_list); i++) { ext = sk_X509_EXTENSION_value(ext_list, i); obj = X509_EXTENSION_get_object(ext); @@ -286,25 +287,36 @@ static int extract_license(const char *license_fname, const char *pub_key, if (0 == strcmp(buf, LICENSE_KEY_TYPE)) { license->type_ = scan_licese_type(val); if (LICENSE_TYPE_MAX == license->type_) { - zlog_error(neuron, "invalid license type:`%s`", val); + nlog_error("invalid license type:`%s`", val); rv = NEU_ERR_LICENSE_INVALID; } + mark |= 0x01; } else if (0 == strcmp(buf, LICENSE_KEY_MAX_NODES)) { license->max_nodes_ = strtoul(val, NULL, 0); + mark |= 0x02; } else if (0 == strcmp(buf, LICENSE_KEY_MAX_NODE_TAGS)) { license->max_node_tags_ = strtoul(val, NULL, 0); + mark |= 0x04; } else if (0 == strcmp(buf, LICENSE_KEY_PLUGIN_FLAG)) { if (0 != scan_bitvec(license->plugin_flag_, sizeof(license->plugin_flag_), val)) { - zlog_error(neuron, "fail to scan license plugin flag:`%s`", - val); + nlog_error("fail to scan license plugin flag:`%s`", val); rv = NEU_ERR_LICENSE_INVALID; } + mark |= 0x08; + } else if (0 == strcmp(buf, LICENSE_KEY_TOKEN)) { + license->token_ = strdup(val); + mark |= 0x10; } } - nlog_info("certification verification success"); + if (0x0F == (mark & 0x0F)) { + nlog_info("certification verification success"); + } else { + rv = NEU_ERR_LICENSE_INVALID; + nlog_error("missing license key fields, mark:%u", mark); + } final: if (pkey) @@ -364,6 +376,7 @@ void license_init(license_t *license) void license_fini(license_t *license) { free(license->fname_); + free(license->token_); } license_t *license_new() @@ -411,6 +424,7 @@ int license_read(license_t *license, const char *fname) license_print(&lic); free(license->fname_); + free(license->token_); *license = lic; return rv; diff --git a/plugins/restful/license.h b/plugins/restful/license.h index a3be2eeb..97894775 100644 --- a/plugins/restful/license.h +++ b/plugins/restful/license.h @@ -50,6 +50,8 @@ // #define LICENSE_KEY_PLUGIN_FLAG "1.3.6.1.4.1.52509.13" +#define LICENSE_KEY_TOKEN "1.3.6.1.4.1.52509.14" + #ifdef __cplusplus extern "C" { #endif @@ -95,6 +97,7 @@ typedef struct { uint32_t max_nodes_; // max number of nodes uint32_t max_node_tags_; // max number of tags per node uint8_t plugin_flag_[200 / 8]; // plugin enable/disable bits + char * token_; // hardware token } license_t; // Initialize to be expired with no file. From 89bb08dc0bb13a5aaa92e4beff50d3fde96f274c Mon Sep 17 00:00:00 2001 From: eeff <33566201+eeff@users.noreply.github.com> Date: Sun, 6 Nov 2022 23:06:17 +0800 Subject: [PATCH 2/2] fix(restful): license api timestamp overflow in 32 bit platform --- plugins/restful/license.c | 37 +++++++++++++++++--------------- plugins/restful/license.h | 2 ++ plugins/restful/license_handle.c | 37 +++++++------------------------- 3 files changed, 30 insertions(+), 46 deletions(-) diff --git a/plugins/restful/license.c b/plugins/restful/license.c index ca48afa4..7173fa30 100644 --- a/plugins/restful/license.c +++ b/plugins/restful/license.c @@ -36,6 +36,7 @@ #include #include "errcodes.h" +#include "utils/asprintf.h" #include "utils/log.h" #include "license.h" @@ -81,7 +82,7 @@ static uint64_t mktimestamp(struct tm dt) return (ret); } -static uint64_t get_asn1_ts(ASN1_TIME *time) +static uint64_t get_asn1_ts(ASN1_TIME *time, char **ts_str) { struct tm t; const char *str = (const char *) time->data; @@ -97,7 +98,11 @@ static uint64_t get_asn1_ts(ASN1_TIME *time) &t.tm_hour, &t.tm_min, &t.tm_sec); } + neu_asprintf(ts_str, "%4d-%02d-%02d %02d:%02d:%02d", t.tm_year, t.tm_mon, + t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec); + t.tm_mon -= 1; + /* Note: we did not adjust the time based on time zone information */ return mktimestamp(t); } @@ -245,9 +250,14 @@ static int extract_license(const char *license_fname, const char *pub_key, not_before = X509_get_notBefore(cert); not_after = X509_get_notAfter(cert); - license->since_ = get_asn1_ts(not_before); - license->until_ = get_asn1_ts(not_after); + license->since_ = get_asn1_ts(not_before, &license->since_str_); + license->until_ = get_asn1_ts(not_after, &license->until_str_); nlog_info("certificate expire date: %s", not_after->data); + if (NULL == license->since_str_ || NULL == license->until_str_) { + nlog_warn("cannot strdup"); + rv = NEU_ERR_EINTERNAL; + goto final; + } subj = X509_get_subject_name(cert); for (i = 0; i < X509_NAME_entry_count(subj); i++) { @@ -342,26 +352,15 @@ const char *plugin_bit_str(plugin_bit_e b) void license_print(license_t *license) { - struct tm tm = {}; - char start[16] = {}; - char end[16] = {}; - time_t since = license->since_; - time_t until = license->until_; - const char *fmt = "%Y%m%dT%H%M%S"; - - gmtime_r(&since, &tm); - strftime(start, sizeof(start), fmt, &tm); - gmtime_r(&until, &tm); - strftime(end, sizeof(end), fmt, &tm); - char flag[sizeof(license->plugin_flag_) * 2 + 1] = {}; print_bitvec(flag, sizeof(flag), license->plugin_flag_, sizeof(license->plugin_flag_)); nlog_info("license `%s` for %s, from %s to %s, max_nodes:%" PRIu32 ", max_node_tags:%" PRIu32 ", flag:0x%s", - license->fname_, license_type_str(license->type_), start, end, - license->max_nodes_, license->max_node_tags_, flag); + license->fname_, license_type_str(license->type_), + license->since_str_, license->until_str_, license->max_nodes_, + license->max_node_tags_, flag); } void license_init(license_t *license) @@ -375,6 +374,8 @@ void license_init(license_t *license) void license_fini(license_t *license) { + free(license->since_str_); + free(license->until_str_); free(license->fname_); free(license->token_); } @@ -423,6 +424,8 @@ int license_read(license_t *license, const char *fname) license_print(&lic); + free(license->since_str_); + free(license->until_str_); free(license->fname_); free(license->token_); *license = lic; diff --git a/plugins/restful/license.h b/plugins/restful/license.h index 97894775..71946551 100644 --- a/plugins/restful/license.h +++ b/plugins/restful/license.h @@ -93,7 +93,9 @@ typedef struct { license_type_e type_; // license type char * fname_; // license file name uint64_t since_; // not before + char * since_str_; // uint64_t until_; // not after + char * until_str_; // uint32_t max_nodes_; // max number of nodes uint32_t max_node_tags_; // max number of tags per node uint8_t plugin_flag_[200 / 8]; // plugin enable/disable bits diff --git a/plugins/restful/license_handle.c b/plugins/restful/license_handle.c index cbed979e..d44b5790 100644 --- a/plugins/restful/license_handle.c +++ b/plugins/restful/license_handle.c @@ -135,17 +135,12 @@ int copy_license_file_if_necessary() void handle_get_license(nng_aio *aio) { - int rv = 0; - char * license_path = NULL; - license_t lic = {}; - neu_json_get_license_resp_t resp = {}; - time_t since = 0; - time_t until = 0; - char valid_since[20] = {}; - char valid_until[20] = {}; - struct tm tm = {}; - UT_array * plugin_names = NULL; - char * result = NULL; + int rv = 0; + char * license_path = NULL; + license_t lic = {}; + neu_json_get_license_resp_t resp = {}; + UT_array * plugin_names = NULL; + char * result = NULL; VALIDATE_JWT(aio); @@ -163,26 +158,10 @@ void handle_get_license(nng_aio *aio) goto final; } - since = license_not_before(&lic); - gmtime_r(&since, &tm); - if (0 == - strftime(valid_since, sizeof(valid_since), "%Y-%m-%d %H:%M:%S", &tm)) { - rv = NEU_ERR_EINTERNAL; - goto final; - } - - until = license_not_after(&lic); - gmtime_r(&until, &tm); - if (0 == - strftime(valid_until, sizeof(valid_until), "%Y-%m-%d %H:%M:%S", &tm)) { - rv = NEU_ERR_EINTERNAL; - goto final; - } - resp.license_type = (char *) license_type_str(license_get_type(&lic)); resp.valid = !license_is_expired(&lic); - resp.valid_since = valid_since; - resp.valid_until = valid_until; + resp.valid_since = lic.since_str_; + resp.valid_until = lic.until_str_; resp.max_nodes = license_get_max_nodes(&lic); resp.max_node_tags = license_get_max_node_tags(&lic);