diff --git a/plugins/restful/license_handle.c b/plugins/restful/license_handle.c index bc9ec0ec..c6bffd63 100644 --- a/plugins/restful/license_handle.c +++ b/plugins/restful/license_handle.c @@ -17,17 +17,111 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. **/ +#define _POSIX_C_SOURCE 200809L +#include +#include + +#include "neu_errcodes.h" +#include "neu_file.h" #include "neu_plugin.h" #include "json/neu_json_error.h" #include "json/neu_json_fn.h" -#include "json/neu_json_node.h" +#include "json/neu_json_license.h" #include "handle.h" #include "http.h" - +#include "license.h" #include "license_handle.h" +#define LICENSE_PATH LICENSE_DIR "/" LICENSE_FNAME + +static int set_license(const char *lic_str); +int backup_license_file(const char *lic_fname); + void handle_set_license(nng_aio *aio) { - VALIDATE_JWT(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 int set_license(const char *lic_str) +{ + int rv = 0; + license_t new_lic = {}; + const char *fname_tmp = LICENSE_PATH ".tmp"; + + int len = strlen(lic_str); + if (len > 15000) { + // the license file won't exceed 15KB + return NEU_ERR_LICENSE_INVALID; + } + + FILE *fp = fopen(fname_tmp, "w"); + if (NULL == fp) { + log_error("unable to create license tmp file `%s`", fname_tmp); + return NEU_ERR_EINTERNAL; + } + + rv = fputs(lic_str, fp); + + if (rv < 0) { + log_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) { + log_error("bad license string"); + goto final; + } + + if (license_is_expired(&new_lic)) { + log_error("expired license string"); + rv = NEU_ERR_LICENSE_EXPIRED; + goto final; + } + + if (file_exists(LICENSE_PATH) && 0 > backup_license_file(LICENSE_PATH)) { + log_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; + } + +final: + fclose(fp); + remove(fname_tmp); + return rv; +} + +int backup_license_file(const char *lic_fname) +{ + struct tm tm = { .tm_isdst = -1 }; + time_t now = time(NULL); + char fname_bak[128] = { 0 }; + + size_t n = snprintf(fname_bak, sizeof(fname_bak), "%s.bak", lic_fname); + if (sizeof(fname_bak) == n) { + return -1; + } + + gmtime_r(&now, &tm); + if (0 == + strftime(fname_bak + n, sizeof(fname_bak) - n, ".%Y%m%d%H%M%S", &tm)) { + return -1; + } + + return link(lic_fname, fname_bak); }