From e528d2a70a248d14bd9526a4b54463b4e23e5dcd Mon Sep 17 00:00:00 2001 From: eeff <33566201+eeff@users.noreply.github.com> Date: Fri, 28 Oct 2022 14:20:23 +0800 Subject: [PATCH] feat(restful): remove license api --- CMakeLists.txt | 3 +- plugins/restful/handle.c | 21 +- plugins/restful/license.c | 417 ------------------------------- plugins/restful/license.h | 160 ------------ plugins/restful/license_handle.c | 356 -------------------------- plugins/restful/license_handle.h | 29 --- plugins/restful/rest.c | 7 - src/parser/neu_json_license.c | 133 ---------- src/parser/neu_json_license.h | 62 ----- 9 files changed, 6 insertions(+), 1182 deletions(-) delete mode 100644 plugins/restful/license.c delete mode 100644 plugins/restful/license.h delete mode 100644 plugins/restful/license_handle.c delete mode 100644 plugins/restful/license_handle.h delete mode 100644 src/parser/neu_json_license.c delete mode 100644 src/parser/neu_json_license.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 13e94f22..6873ac80 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -107,8 +107,6 @@ set(NEURON_SOURCES src/adapter/driver/cache.c src/adapter/driver/driver.c plugins/restful/handle.c - plugins/restful/license.c - plugins/restful/license_handle.c plugins/restful/log_handle.c plugins/restful/normal_handle.c plugins/restful/rw_handle.c @@ -131,6 +129,7 @@ add_executable(neuron) target_sources(neuron PRIVATE ${NEURON_SOURCES}) target_include_directories(neuron PRIVATE include/neuron src plugins) target_link_libraries(neuron dl neuron-base sqlite3 -lm) +target_link_options(neuron PRIVATE "LINKER:--export-dynamic") #copy file for run file(COPY ${CMAKE_SOURCE_DIR}/zlog.conf DESTINATION ${CMAKE_BINARY_DIR}/config) diff --git a/plugins/restful/handle.c b/plugins/restful/handle.c index f19f7b2d..d6989886 100644 --- a/plugins/restful/handle.c +++ b/plugins/restful/handle.c @@ -28,7 +28,6 @@ #include "datatag_handle.h" #include "group_config_handle.h" #include "http.h" -#include "license_handle.h" #include "log_handle.h" #include "normal_handle.h" #include "plugin_handle.h" @@ -95,9 +94,6 @@ struct neu_rest_handler cors_handler[] = { { .url = "/api/v2/node/state", }, - { - .url = "/api/v2/license", - }, { .url = "/api/v2/version", }, @@ -114,6 +110,11 @@ struct neu_rest_handler api_handlers[] = { .url = "/api/v2/hwtoken", .value.dst_url = "http://127.0.0.1:7003/api/v2/hwtoken", }, + { + .type = NEU_REST_HANDLER_PROXY, + .url = "/api/v2/license", + .value.dst_url = "http://127.0.0.1:7003/api/v2/license", + }, { .method = NEU_REST_METHOD_POST, .type = NEU_REST_HANDLER_FUNCTION, @@ -290,18 +291,6 @@ struct neu_rest_handler api_handlers[] = { .url = "/api/v2/level", .value.handler = handle_log_level, }, - { - .method = NEU_REST_METHOD_POST, - .type = NEU_REST_HANDLER_FUNCTION, - .url = "/api/v2/license", - .value.handler = handle_set_license, - }, - { - .method = NEU_REST_METHOD_GET, - .type = NEU_REST_HANDLER_FUNCTION, - .url = "/api/v2/license", - .value.handler = handle_get_license, - }, { .method = NEU_REST_METHOD_GET, .type = NEU_REST_HANDLER_FUNCTION, diff --git a/plugins/restful/license.c b/plugins/restful/license.c deleted file mode 100644 index 8f152a56..00000000 --- a/plugins/restful/license.c +++ /dev/null @@ -1,417 +0,0 @@ -/** - * NEURON IIoT System for Industry 4.0 - * Copyright (C) 2020-2022 EMQ Technologies Co., Ltd All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - **/ - -#define NEURON_LOG_LABEL "license" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "errcodes.h" -#include "utils/log.h" - -#include "license.h" - -const char root_cert_pub_key[] = "-----BEGIN PUBLIC KEY-----\n\ -MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyJgH+BvEJIStYvyw1keQ\n\ -/ixVPJ4GGjlP7lTKnZL3mqZyPXQUEaLnRmcQ3/ra8xYQPcfMReynqmrYmT45/eD2\n\ -tK7rdXTzYfOWoU0cXNQMaQS7be1bLF4QrAEbJhEsgkjX9rP30mrzZCjRRnkQtWmi\n\ -4DNBU4qOl6Ee9aAS5aY+L7DW646J47Tyc7gAA4sdZw04KGBXnSyXzyBvPaf+QByO\n\ -rOXUxBcxehHN/Ox41/duYFXSR40U6lyp49NYJ6yEUVWSp4oxsrkcgqyegNKXdW1D\n\ -8oqJXzxalbh/RB8YYlX+Ae377gEBlLefPFdSEYDRN/ajs3UIeqde6i20lVyDPIjE\n\ -cQIDAQAB\n\ ------END PUBLIC KEY-----"; - -static const uint32_t mon_yday[2][12] = { - { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }, - { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 }, -}; - -static int isleap(int year) -{ - return (year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0); -} - -static uint64_t mktimestamp(struct tm dt) -{ - uint64_t ret; - int i = 0; - - ret = ((uint64_t) dt.tm_year - 1970) * 365 * 24 * 3600; - ret += - (mon_yday[isleap(dt.tm_year)][dt.tm_mon] + dt.tm_mday - 1) * 24 * 3600; - ret += dt.tm_hour * 3600 + dt.tm_min * 60 + dt.tm_sec; - - for (i = 1970; i < dt.tm_year; i++) { - if (isleap(i)) { - ret += 24 * 3600; - } - } - if (ret > 4107715199) { // 2100-02-29 23:59:59 - ret += 24 * 3600; - } - return (ret); -} - -static uint64_t get_asn1_ts(ASN1_TIME *time) -{ - struct tm t; - const char *str = (const char *) time->data; - - memset(&t, 0, sizeof(t)); - - if (time->type == V_ASN1_UTCTIME) { /* two digit year */ - sscanf(str, "%2d%2d%2d%2d%2d%2dZ", &t.tm_year, &t.tm_mon, &t.tm_mday, - &t.tm_hour, &t.tm_min, &t.tm_sec); - t.tm_year += 2000; - } else if (time->type == V_ASN1_GENERALIZEDTIME) { /* four digit year */ - sscanf(str, "%4d%2d%2d%2d%2d%2dZ", &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); -} - -static int scan_bitvec(uint8_t vec[], size_t size, const char *hex) -{ - if ('0' == *hex && 'x' == tolower(*(hex + 1))) { - hex += 2; - } - - size_t i = 0; - size_t len = strlen(hex); - - while (i < len && i / 2 < size) { - char c = hex[len - 1 - i]; - uint8_t v = 0; - if ('0' <= c && c <= '9') { - v = c - '0'; - } else if ('a' <= c && c <= 'f') { - v = 10 + c - 'a'; - } else if ('A' <= c && c <= 'F') { - v = 10 + c - 'A'; - } else { - break; - } - - vec[i / 2] += v << ((i & 0x01) * 4); - ++i; - } - - return (i == len) ? 0 : -1; -} - -void print_bitvec(char *s, size_t size, uint8_t vec[], size_t n) -{ - size_t i = 0; - for (size_t j = n; j-- > 0 && i < size;) { - if (0 != j && 0 == vec[j]) { - continue; - } - uint8_t h = (vec[j] & 0xF0) >> 4; - uint8_t l = vec[j] & 0x0F; - s[i++] = (h < 10) ? ('0' + h) : ('A' + h - 10); - if (i < size) { - s[i++] = (l < 10) ? ('0' + l) : ('A' + l - 10); - } - } - - if (i < size) { - s[i] = '\0'; - } else if (size > 0) { - s[size - 1] = '\0'; - } -} - -static const char *const g_license_type_str_map_[] = { - [LICENSE_TYPE_TRIAL] = "trial", - [LICENSE_TYPE_RETAIL] = "retail", - [LICENSE_TYPE_SME] = "small-enterprise", -}; - -static const char *const g_plugin_bit_str_map[] = { - [PLUGIN_BIT_MODBUS_PLUS_TCP] = "modbus-plus-tcp", - [PLUGIN_BIT_MODBUS_RTU] = "modbus-rtu", - [PLUGIN_BIT_OPCUA] = "opcua", - [PLUGIN_BIT_S7COMM] = "s7comm", - [PLUGIN_BIT_FINS] = "fins", - [PLUGIN_BIT_QNA3E] = "QnA3E", - [PLUGIN_BIT_IEC60870_5_104] = "IEC60870-5-104", - [PLUGIN_BIT_KNX] = "KNXnet/IP", - [PLUGIN_BIT_NONA11] = "NONA11", - [PLUGIN_BIT_DLT645_2007] = "DLT645-2007", - [PLUGIN_BIT_BACNET] = "BACnet/IP", - [PLUGIN_BIT_MAX] = NULL, -}; - -static license_type_e scan_licese_type(const char *s) -{ - license_type_e t = LICENSE_TYPE_MAX; - for (int i = 0; i < LICENSE_TYPE_MAX; ++i) { - if (0 == strcmp(s, g_license_type_str_map_[i])) { - t = (license_type_e) i; - break; - } - } - - return t; -} - -static int extract_license(const char *license_fname, const char *pub_key, - license_t *license) -{ - BIO * certbio = NULL; - BIO * keybio = NULL; - X509 * cert = NULL; - X509_NAME * subj = NULL; - X509_NAME * issuer = NULL; - X509_NAME_ENTRY *entry = NULL; - EVP_PKEY * pkey = NULL; - const STACK_OF(X509_EXTENSION) * ext_list; - ASN1_OBJECT * obj; - ASN1_STRING * str; - ASN1_TIME * not_before, *not_after; - X509_EXTENSION * ext; - char buf[100]; - const unsigned char *value; - int i; - int rv = 0; - - OpenSSL_add_all_algorithms(); - - struct stat statbuf; - if (-1 == stat(license_fname, &statbuf)) { - rv = NEU_ERR_LICENSE_NOT_FOUND; - goto final; - } - - /* load emqx certificate */ - certbio = BIO_new(BIO_s_file()); - if (0 == BIO_read_filename(certbio, license_fname)) { - rv = NEU_ERR_LICENSE_INVALID; - goto final; - } - if (!(cert = PEM_read_bio_X509(certbio, NULL, NULL, NULL))) { - nlog_warn("loading certificate into memory"); - rv = NEU_ERR_LICENSE_INVALID; - goto final; - } - - /* load public key */ - keybio = BIO_new(BIO_s_mem()); - BIO_puts(keybio, pub_key); - if (!(pkey = PEM_read_bio_PUBKEY(keybio, NULL, NULL, NULL))) { - nlog_warn("loading pubkey into memory"); - rv = NEU_ERR_EINTERNAL; - goto final; - } - - /* Verify the certificates */ - if (X509_verify(cert, pkey) == 0) { - nlog_warn("certification verification failure"); - rv = NEU_ERR_LICENSE_INVALID; - goto final; - } - - 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); - nlog_info("certificate expire date: %s", not_after->data); - - subj = X509_get_subject_name(cert); - for (i = 0; i < X509_NAME_entry_count(subj); i++) { - entry = X509_NAME_get_entry(subj, i); - str = X509_NAME_ENTRY_get_data(entry); - value = ASN1_STRING_get0_data(str); - nlog_info("certificate subject: %s", value); - } - - issuer = X509_get_issuer_name(cert); - for (i = 0; i < X509_NAME_entry_count(issuer); i++) { - entry = X509_NAME_get_entry(issuer, i); - str = X509_NAME_ENTRY_get_data(entry); - value = ASN1_STRING_get0_data(str); - nlog_info("certificate issuer: %s", value); - } - - /* extract the certificate's extensions */ - - ext_list = X509_get0_extensions(cert); - if (sk_X509_EXTENSION_num(ext_list) <= 0) { - rv = NEU_ERR_LICENSE_INVALID; - goto final; - } - - 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); - str = X509_EXTENSION_get_data(ext); - OBJ_obj2txt(buf, sizeof buf, obj, 1); - value = ASN1_STRING_get0_data(str); - nlog_info("certificate OID: %s => %s", buf, &value[2]); - - const char *val = (char *) &value[2]; - - 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); - rv = NEU_ERR_LICENSE_INVALID; - } - } else if (0 == strcmp(buf, LICENSE_KEY_MAX_NODES)) { - license->max_nodes_ = strtoul(val, NULL, 0); - } else if (0 == strcmp(buf, LICENSE_KEY_MAX_NODE_TAGS)) { - license->max_node_tags_ = strtoul(val, NULL, 0); - } 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); - rv = NEU_ERR_LICENSE_INVALID; - } - } - } - - nlog_info("certification verification success"); - -final: - if (pkey) - EVP_PKEY_free(pkey); - if (cert) - X509_free(cert); - if (certbio) - BIO_free_all(certbio); - if (keybio) - BIO_free_all(keybio); - return rv; -} - -const char *license_type_str(license_type_e t) -{ - return g_license_type_str_map_[t]; -} - -const char *plugin_bit_str(plugin_bit_e b) -{ - return g_plugin_bit_str_map[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); -} - -void license_init(license_t *license) -{ - // no associate license file - // no plugins enabled - // expired license period - memset(license, 0, sizeof(*license)); - license->since_ = 1; -} - -void license_fini(license_t *license) -{ - free(license->fname_); -} - -license_t *license_new() -{ - license_t *license = malloc(sizeof(*license)); - if (NULL == license) { - return NULL; - } - - license_init(license); - - return license; -} - -void license_free(license_t *license) -{ - if (NULL == license) { - return; - } - - license_fini(license); - free(license); -} - -int license_read(license_t *license, const char *fname) -{ - if (NULL == license || NULL == fname) { - return -1; - } - - license_t lic; - license_init(&lic); - - lic.fname_ = strdup(fname); - if (NULL == lic.fname_) { - return -1; - } - - int rv = extract_license(fname, root_cert_pub_key, &lic); - if (0 != rv) { - license_fini(&lic); - return rv; - } - - license_print(&lic); - - free(license->fname_); - *license = lic; - - return rv; -} diff --git a/plugins/restful/license.h b/plugins/restful/license.h deleted file mode 100644 index a3be2eeb..00000000 --- a/plugins/restful/license.h +++ /dev/null @@ -1,160 +0,0 @@ -/** - * NEURON IIoT System for Industry 4.0 - * Copyright (C) 2020-2022 EMQ Technologies Co., Ltd All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - **/ - -#ifndef LICENSE_H -#define LICENSE_H - -#define LICENSE_FNAME "neuron.lic" - -// License type -// Type: string -// - "trial" -// - "retail" -// - "small-enterprise" -#define LICENSE_KEY_TYPE "1.3.6.1.4.1.52509.10" - -// Max number of nodes. -// Type: integer, non-negative -#define LICENSE_KEY_MAX_NODES "1.3.6.1.4.1.52509.11" - -// Max number of tags per node. -// Type: integer, non-negative -#define LICENSE_KEY_MAX_NODE_TAGS "1.3.6.1.4.1.52509.12" - -// Bit flag indicating which plugins are enabled. -// Type: integer -// -// MSB LSB -// ..., 63, 62, ... 3, 2, 1, 0 -// ^----many others--------------^ ^ ^ ^ -// | | | -// opcua----------------------------+ | | -// modbus_rtu--------------------------+ | -// modbus_plus_tcp------------------------+ -// -#define LICENSE_KEY_PLUGIN_FLAG "1.3.6.1.4.1.52509.13" - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include - -#include "errcodes.h" - -typedef enum { - LICENSE_TYPE_TRIAL = 0, // trial - LICENSE_TYPE_RETAIL = 1, // retail - LICENSE_TYPE_SME = 2, // small enterprise - LICENSE_TYPE_MAX, -} license_type_e; - -const char *license_type_str(license_type_e t); - -typedef enum { - PLUGIN_BIT_MODBUS_PLUS_TCP = 0, - PLUGIN_BIT_MODBUS_RTU = 1, - PLUGIN_BIT_OPCUA = 2, - PLUGIN_BIT_S7COMM = 3, - PLUGIN_BIT_FINS = 4, - PLUGIN_BIT_QNA3E = 5, - PLUGIN_BIT_IEC60870_5_104 = 6, - PLUGIN_BIT_KNX = 7, - PLUGIN_BIT_NONA11 = 8, - PLUGIN_BIT_DLT645_2007 = 9, - PLUGIN_BIT_BACNET = 10, - PLUGIN_BIT_MAX, -} plugin_bit_e; - -const char *plugin_bit_str(plugin_bit_e); - -// Representing a single license. -typedef struct { - license_type_e type_; // license type - char * fname_; // license file name - uint64_t since_; // not before - uint64_t until_; // not after - 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 -} license_t; - -// Initialize to be expired with no file. -void license_init(license_t *license); -void license_fini(license_t *license); - -// Create new expired license associated with no file. -license_t *license_new(); -void license_free(license_t *license); -// Read from license file. -int license_read(license_t *license, const char *license_fname); - -// Get associated license file name. -static inline const char *license_get_file_name(const license_t *license) -{ - return license->fname_; -} - -static inline license_type_e license_get_type(const license_t *license) -{ - return license->type_; -} - -// Get license expiry date. -static inline uint64_t license_not_before(const license_t *license) -{ - return license->since_; -} - -// Get license expiry date. -static inline uint64_t license_not_after(const license_t *license) -{ - return license->until_; -} - -// Check if the license is expired according to the current time. -static inline bool license_is_expired(const license_t *license) -{ - uint64_t now = time(NULL); - return now < license->since_ || license->until_ < now; -} - -static inline uint64_t license_get_max_nodes(const license_t *license) -{ - return license->max_nodes_; -} - -static inline uint64_t license_get_max_node_tags(const license_t *license) -{ - return license->max_node_tags_; -} - -static inline bool license_is_plugin_enabled(const license_t *license, - plugin_bit_e bit) -{ - return license->plugin_flag_[bit >> 3] & (1 << (bit & 0x07)); -} - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/plugins/restful/license_handle.c b/plugins/restful/license_handle.c deleted file mode 100644 index cbed979e..00000000 --- a/plugins/restful/license_handle.c +++ /dev/null @@ -1,356 +0,0 @@ -/** - * NEURON IIoT System for Industry 4.0 - * Copyright (C) 2020-2022 EMQ Technologies Co., Ltd All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - **/ - -#define _POSIX_C_SOURCE 200809L -#include -#include -#include -#include - -#include "argparse.h" -#include "errcodes.h" -#include "parser/neu_json_license.h" -#include "plugin.h" -#include "utils/asprintf.h" -#include "utils/log.h" -#include "json/neu_json_error.h" -#include "json/neu_json_fn.h" - -#include "handle.h" -#include "http.h" -#include "license.h" -#include "license_handle.h" - -static int set_license(const char *lic_str); -int backup_license_file(const char *lic_fname); -int get_plugin_names(const license_t *lic, UT_array *plugin_names); - -static inline char *get_license_path() -{ - char *s = NULL; - neu_asprintf(&s, "persistence/%s", LICENSE_FNAME); - return s; -} - -static int copy_file(const char *from, const char *to) -{ - int rv = 0; - char * buf = NULL; - FILE * fp = NULL; - struct stat statbuf = {}; - - if (0 != stat(from, &statbuf)) { - return NEU_ERR_EINTERNAL; - } - - buf = malloc(statbuf.st_size); - if (NULL == buf) { - return NEU_ERR_EINTERNAL; - } - - fp = fopen(from, "rb"); - if (NULL == fp) { - rv = NEU_ERR_EINTERNAL; - goto end; - } - - if ((size_t) statbuf.st_size != fread(buf, 1, statbuf.st_size, fp)) { - rv = NEU_ERR_EINTERNAL; - goto end; - } - - fclose(fp); - fp = fopen(to, "w"); - if (NULL == fp) { - rv = NEU_ERR_EINTERNAL; - goto end; - } - - if ((size_t) statbuf.st_size != fwrite(buf, 1, statbuf.st_size, fp)) { - rv = NEU_ERR_EINTERNAL; - goto end; - } - -end: - if (fp) { - fclose(fp); - } - free(buf); - return rv; -} - -int copy_license_file_if_necessary() -{ - struct stat statbuf = {}; - char * license_path = get_license_path(); - - if (NULL == license_path) { - return NEU_ERR_EINTERNAL; - } - - if (0 == stat(license_path, &statbuf)) { - free(license_path); - return 0; - } - - nlog_warn("license `%s` not found", license_path); - - char *fallback_path = NULL; - neu_asprintf(&fallback_path, "%s/%s", g_config_dir, LICENSE_FNAME); - if (NULL == fallback_path) { - free(license_path); - return NEU_ERR_EINTERNAL; - } - - if (0 != stat(fallback_path, &statbuf)) { - // no fallback license file - free(license_path); - free(fallback_path); - return 0; - } - - nlog_warn("fallback to `%s`", fallback_path); - int rv = copy_file(fallback_path, license_path); - - free(license_path); - free(fallback_path); - return rv; -} - -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; - - VALIDATE_JWT(aio); - - utarray_new(plugin_names, &ut_ptr_icd); - - license_path = get_license_path(); - if (NULL == license_path) { - rv = NEU_ERR_EINTERNAL; - goto final; - } - - license_init(&lic); - rv = license_read(&lic, license_path); - if (0 != rv) { - 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.max_nodes = license_get_max_nodes(&lic); - resp.max_node_tags = license_get_max_node_tags(&lic); - - rv = get_plugin_names(&lic, plugin_names); - if (0 != rv) { - goto final; - } - resp.n_enabled_plugin = utarray_len(plugin_names); - resp.enabled_plugins = - calloc(resp.n_enabled_plugin, - sizeof(neu_json_get_license_resp_enabled_plugin_t)); - utarray_foreach(plugin_names, char **, p_name) - { - int index = utarray_eltidx(plugin_names, p_name); - resp.enabled_plugins[index] = *p_name; - } - -final: - if (0 == rv) { - neu_json_encode_by_fn(&resp, neu_json_encode_get_license_resp, &result); - } else { - neu_json_error_resp_t error_code = { .error = rv }; - neu_json_encode_by_fn(&error_code, neu_json_encode_error_resp, &result); - } - http_response(aio, rv, result); - free(result); - license_fini(&lic); - utarray_free(plugin_names); - free(resp.enabled_plugins); - free(license_path); -} - -void handle_set_license(nng_aio *aio) -{ - REST_PROCESS_HTTP_REQUEST_VALIDATE_JWT( - aio, neu_json_set_license_req_t, neu_json_decode_set_license_req, { - NEU_JSON_RESPONSE_ERROR(set_license(req->license), { - http_response(aio, error_code.error, result_error); - }); - }); -} -static inline bool file_exists(const char *const path) -{ - struct stat buf = { 0 }; - return -1 != stat(path, &buf); -} - -static int set_license(const char *lic_str) -{ - int rv = 0; - size_t len = 0; - char * license_path = NULL; - char * fname_tmp = NULL; - FILE * fp = NULL; - license_t new_lic = {}; - - license_path = get_license_path(); - if (NULL == license_path) { - return NEU_ERR_EINTERNAL; - } - - if (0 > neu_asprintf(&fname_tmp, "%s.tmp", license_path)) { - rv = NEU_ERR_EINTERNAL; - goto final; - } - - len = strlen(lic_str); - if (len > 15000) { - // the license file won't exceed 15KB - rv = NEU_ERR_LICENSE_INVALID; - goto final; - } - - fp = fopen(fname_tmp, "w"); - if (NULL == fp) { - nlog_error("unable to create license tmp file `%s`", fname_tmp); - rv = NEU_ERR_EINTERNAL; - goto final; - } - - rv = fputs(lic_str, fp); - - if (rv < 0) { - nlog_error("unable to write license to file `%s`", fname_tmp); - rv = NEU_ERR_EINTERNAL; - goto final; - } - - fflush(fp); - - license_init(&new_lic); - rv = license_read(&new_lic, fname_tmp); - license_fini(&new_lic); - if (0 != rv) { - nlog_error("bad license string"); - goto final; - } - - if (license_is_expired(&new_lic)) { - nlog_error("expired license string"); - rv = NEU_ERR_LICENSE_EXPIRED; - goto final; - } - - if (file_exists(license_path) && 0 > backup_license_file(license_path)) { - nlog_error("unable to backup license file `%s`", license_path); - rv = NEU_ERR_EINTERNAL; - goto final; - } - - if (0 > rename(fname_tmp, license_path)) { - rv = NEU_ERR_EINTERNAL; - goto final; - } - - neu_plugin_t * plugin = neu_rest_get_plugin(); - neu_reqresp_head_t head = { .type = NEU_REQ_UPDATE_LICENSE }; - rv = neu_plugin_op(plugin, head, NULL); - if (0 != rv) { - rv = NEU_ERR_EINTERNAL; - } - -final: - if (fp) { - fclose(fp); - } - remove(fname_tmp); - free(license_path); - free(fname_tmp); - return rv; -} - -int backup_license_file(const char *lic_fname) -{ - struct tm tm = { .tm_isdst = -1 }; - time_t now = time(NULL); - const char *suffix = ".bak"; - size_t len = - strlen(lic_fname) + strlen(suffix) + 15 + 1; // 15 for timestamp - char *fname_bak = malloc(len); - - if (NULL == fname_bak) { - return NEU_ERR_EINTERNAL; - } - - size_t n = snprintf(fname_bak, len, "%s%s", lic_fname, suffix); - - gmtime_r(&now, &tm); - if (0 == strftime(fname_bak + n, len - n, ".%Y%m%d%H%M%S", &tm)) { - free(fname_bak); - return -1; - } - - int rv = link(lic_fname, fname_bak); - free(fname_bak); - return rv; -} - -int get_plugin_names(const license_t *lic, UT_array *plugin_names) -{ - for (plugin_bit_e b = PLUGIN_BIT_MODBUS_PLUS_TCP; b < PLUGIN_BIT_MAX; ++b) { - if (license_is_plugin_enabled(lic, b)) { - const char *s = plugin_bit_str(b); - if (NULL == s) { - return NEU_ERR_EINTERNAL; - } - utarray_push_back(plugin_names, &s); - } - } - return 0; -} diff --git a/plugins/restful/license_handle.h b/plugins/restful/license_handle.h deleted file mode 100644 index 4361d28d..00000000 --- a/plugins/restful/license_handle.h +++ /dev/null @@ -1,29 +0,0 @@ -/** - * NEURON IIoT System for Industry 4.0 - * Copyright (C) 2020-2022 EMQ Technologies Co., Ltd All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - **/ - -#ifndef _NEU_LICENSE_HANDLE_H_ -#define _NEU_LICENSE_HANDLE_H_ - -#include - -int copy_license_file_if_necessary(); -void handle_get_license(nng_aio *aio); -void handle_set_license(nng_aio *aio); - -#endif diff --git a/plugins/restful/rest.c b/plugins/restful/rest.c index adeced67..9dc83203 100644 --- a/plugins/restful/rest.c +++ b/plugins/restful/rest.c @@ -31,7 +31,6 @@ #include "group_config_handle.h" #include "handle.h" #include "http.h" -#include "license_handle.h" #include "plugin_handle.h" #include "proxy.h" #include "rest.h" @@ -146,12 +145,6 @@ static neu_plugin_t *dashb_plugin_open(void) const struct neu_rest_handler *rest_handlers = NULL; const struct neu_rest_handler *cors = NULL; - // copy license file for backward compatibility - if (0 != copy_license_file_if_necessary()) { - free(plugin); - return NULL; - } - neu_plugin_common_init(&plugin->common); plugin->handle_ctx = neu_rest_init_ctx(plugin); diff --git a/src/parser/neu_json_license.c b/src/parser/neu_json_license.c deleted file mode 100644 index 693df53a..00000000 --- a/src/parser/neu_json_license.c +++ /dev/null @@ -1,133 +0,0 @@ -/** - * NEURON IIoT System for Industry 4.0 - * Copyright (C) 2020-2022 EMQ Technologies Co., Ltd All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - **/ - -/* - * DO NOT EDIT THIS FILE MANUALLY! - * It was automatically generated by `json-autotype`. - */ - -#include -#include - -#include "json/json.h" - -#include "neu_json_license.h" - -int neu_json_encode_get_license_resp(void *json_object, void *param) -{ - int ret = 0; - neu_json_get_license_resp_t *resp = (neu_json_get_license_resp_t *) param; - - void *enabled_plugin_array = neu_json_array(); - neu_json_get_license_resp_enabled_plugin_t *p_enabled_plugin = - resp->enabled_plugins; - for (int i = 0; i < resp->n_enabled_plugin; i++) { - neu_json_elem_t enabled_plugin_elems[] = { { - .name = NULL, - .t = NEU_JSON_STR, - .v.val_str = *p_enabled_plugin, - } }; - enabled_plugin_array = neu_json_encode_array_value( - enabled_plugin_array, enabled_plugin_elems, - NEU_JSON_ELEM_SIZE(enabled_plugin_elems)); - p_enabled_plugin++; - } - - neu_json_elem_t resp_elems[] = { { - .name = "valid_until", - .t = NEU_JSON_STR, - .v.val_str = resp->valid_until, - }, - { - .name = "valid_since", - .t = NEU_JSON_STR, - .v.val_str = resp->valid_since, - }, - { - .name = "valid", - .t = NEU_JSON_BOOL, - .v.val_bool = resp->valid, - }, - { - .name = "max_nodes", - .t = NEU_JSON_INT, - .v.val_int = resp->max_nodes, - }, - { - .name = "max_node_tags", - .t = NEU_JSON_INT, - .v.val_int = resp->max_node_tags, - }, - { - .name = "license_type", - .t = NEU_JSON_STR, - .v.val_str = resp->license_type, - }, - { - .name = "error", - .t = NEU_JSON_INT, - .v.val_int = resp->error, - }, - { - .name = "enabled_plugins", - .t = NEU_JSON_OBJECT, - .v.val_object = enabled_plugin_array, - } }; - ret = neu_json_encode_field(json_object, resp_elems, - NEU_JSON_ELEM_SIZE(resp_elems)); - - return ret; -} - -int neu_json_decode_set_license_req(char * buf, - neu_json_set_license_req_t **result) -{ - int ret = 0; - neu_json_set_license_req_t *req = - calloc(1, sizeof(neu_json_set_license_req_t)); - if (NULL == req) { - return -1; - } - - neu_json_elem_t req_elems[] = { { - .name = "license", - .t = NEU_JSON_STR, - } }; - ret = neu_json_decode(buf, NEU_JSON_ELEM_SIZE(req_elems), req_elems); - if (ret != 0) { - goto decode_fail; - } - - req->license = req_elems[0].v.val_str; - - *result = req; - return ret; - -decode_fail: - free(req); - return -1; -} - -void neu_json_decode_set_license_req_free(neu_json_set_license_req_t *req) -{ - - free(req->license); - - free(req); -} diff --git a/src/parser/neu_json_license.h b/src/parser/neu_json_license.h deleted file mode 100644 index 4ceec089..00000000 --- a/src/parser/neu_json_license.h +++ /dev/null @@ -1,62 +0,0 @@ -/** - * NEURON IIoT System for Industry 4.0 - * Copyright (C) 2020-2022 EMQ Technologies Co., Ltd All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - **/ - -/* - * DO NOT EDIT THIS FILE MANUALLY! - * It was automatically generated by `json-autotype`. - */ - -#ifndef _NEU_JSON_API_NEU_JSON_LICENSE_H_ -#define _NEU_JSON_API_NEU_JSON_LICENSE_H_ - -#include "json/json.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef char *neu_json_get_license_resp_enabled_plugin_t; - -typedef struct { - bool valid; - int n_enabled_plugin; - neu_json_get_license_resp_enabled_plugin_t *enabled_plugins; - int64_t max_node_tags; - char * license_type; - int64_t error; - char * valid_until; - char * valid_since; - int64_t max_nodes; -} neu_json_get_license_resp_t; - -int neu_json_encode_get_license_resp(void *json_object, void *param); - -typedef struct { - char *license; -} neu_json_set_license_req_t; - -int neu_json_decode_set_license_req(char * buf, - neu_json_set_license_req_t **result); -void neu_json_decode_set_license_req_free(neu_json_set_license_req_t *req); - -#ifdef __cplusplus -} -#endif - -#endif