diff --git a/CHANGELOG.md b/CHANGELOG.md index 684baef22..9eb4b3a3d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ### Added - Add a new modification_time column to reports [#1513](https://github.com/greenbone/gvmd/pull/1513), [#1519](https://github.com/greenbone/gvmd/pull/1519), [#1590](https://github.com/greenbone/gvmd/pull/1590) - Add basic Sentry integration and logging [#1550](https://github.com/greenbone/gvmd/pull/1550) +- Add GMP get_license and modify_license [#1642](https://github.com/greenbone/gvmd/pull/1642) ### Changed - Use pg-gvm extension for C PostgreSQL functions [#1400](https://github.com/greenbone/gvmd/pull/1400), [#1453](https://github.com/greenbone/gvmd/pull/1453) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 63a5b6f8e..c1a86b224 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -103,6 +103,7 @@ add_executable (manage-utils-test gvmd.c gmpd.c manage.c sql.c manage_acl.c manage_configs.c manage_get.c + manage_license.c manage_port_lists.c manage_preferences.c manage_report_formats.c manage_authentication.c @@ -115,6 +116,7 @@ add_executable (manage-utils-test sql_pg.c manage_pg.c lsc_user.c lsc_crypt.c utils.c gmp.c gmp_base.c gmp_configs.c gmp_delete.c gmp_get.c + gmp_license.c gmp_port_lists.c gmp_report_formats.c gmp_tickets.c gmp_tls_certificates.c) @@ -128,6 +130,7 @@ add_executable (manage-test gvmd.c gmpd.c manage_utils.c sql.c manage_acl.c manage_configs.c manage_get.c + manage_license.c manage_port_lists.c manage_preferences.c manage_report_formats.c manage_authentication.c @@ -140,6 +143,7 @@ add_executable (manage-test sql_pg.c manage_pg.c lsc_user.c lsc_crypt.c utils.c gmp.c gmp_base.c gmp_configs.c gmp_delete.c gmp_get.c + gmp_license.c gmp_port_lists.c gmp_report_formats.c gmp_tickets.c gmp_tls_certificates.c) @@ -153,6 +157,7 @@ add_executable (manage-sql-test gvmd.c gmpd.c manage_utils.c manage.c sql.c manage_acl.c manage_configs.c manage_get.c + manage_license.c manage_port_lists.c manage_preferences.c manage_report_formats.c manage_authentication.c @@ -165,6 +170,7 @@ add_executable (manage-sql-test sql_pg.c manage_pg.c lsc_user.c lsc_crypt.c utils.c gmp.c gmp_base.c gmp_configs.c gmp_delete.c gmp_get.c + gmp_license.c gmp_port_lists.c gmp_report_formats.c gmp_tickets.c gmp_tls_certificates.c) @@ -178,6 +184,7 @@ add_executable (gmp-tickets-test gvmd.c gmpd.c manage_utils.c manage.c sql.c manage_acl.c manage_configs.c manage_get.c + manage_license.c manage_port_lists.c manage_preferences.c manage_report_formats.c manage_authentication.c @@ -190,6 +197,7 @@ add_executable (gmp-tickets-test sql_pg.c manage_pg.c lsc_user.c lsc_crypt.c utils.c gmp.c gmp_base.c gmp_configs.c gmp_delete.c gmp_get.c + gmp_license.c gmp_port_lists.c gmp_report_formats.c gmp_tls_certificates.c) add_test (gmp-tickets-test gmp-tickets-test) @@ -202,6 +210,7 @@ add_executable (utils-test gvmd.c gmpd.c manage_utils.c manage.c sql.c manage_acl.c manage_configs.c manage_get.c + manage_license.c manage_port_lists.c manage_preferences.c manage_report_formats.c manage_authentication.c @@ -214,6 +223,7 @@ add_executable (utils-test sql_pg.c manage_pg.c lsc_user.c lsc_crypt.c gmp.c gmp_base.c gmp_configs.c gmp_delete.c gmp_get.c + gmp_license.c gmp_port_lists.c gmp_report_formats.c gmp_tickets.c gmp_tls_certificates.c) @@ -229,6 +239,7 @@ add_executable (gvmd gmpd.c manage_utils.c manage.c sql.c manage_acl.c manage_configs.c manage_get.c + manage_license.c manage_port_lists.c manage_preferences.c manage_report_formats.c manage_authentication.c @@ -241,6 +252,7 @@ add_executable (gvmd sql_pg.c manage_pg.c lsc_user.c lsc_crypt.c utils.c gmp.c gmp_base.c gmp_configs.c gmp_delete.c gmp_get.c + gmp_license.c gmp_port_lists.c gmp_report_formats.c gmp_tickets.c gmp_tls_certificates.c) diff --git a/src/gmp.c b/src/gmp.c index 4202f28ca..c1da7f7d8 100644 --- a/src/gmp.c +++ b/src/gmp.c @@ -88,6 +88,7 @@ #include "gmp_delete.h" #include "gmp_get.h" #include "gmp_configs.h" +#include "gmp_license.h" #include "gmp_port_lists.h" #include "gmp_report_formats.h" #include "gmp_tickets.h" @@ -4329,6 +4330,7 @@ typedef enum CLIENT_GET_FILTERS, CLIENT_GET_GROUPS, CLIENT_GET_INFO, + CLIENT_GET_LICENSE, CLIENT_GET_NOTES, CLIENT_GET_NVTS, CLIENT_GET_NVT_FAMILIES, @@ -4401,6 +4403,7 @@ typedef enum CLIENT_MODIFY_GROUP_COMMENT, CLIENT_MODIFY_GROUP_NAME, CLIENT_MODIFY_GROUP_USERS, + CLIENT_MODIFY_LICENSE, CLIENT_MODIFY_NOTE, CLIENT_MODIFY_NOTE_ACTIVE, CLIENT_MODIFY_NOTE_HOSTS, @@ -5282,6 +5285,13 @@ gmp_xml_handle_start_element (/* unused */ GMarkupParseContext* context, attribute_values); set_client_state (CLIENT_GET_GROUPS); } + else if (strcasecmp ("GET_LICENSE", element_name) == 0) + { + get_license_start (gmp_parser, + attribute_names, + attribute_values); + set_client_state (CLIENT_GET_LICENSE); + } else if (strcasecmp ("GET_NOTES", element_name) == 0) { const gchar* attribute; @@ -5777,6 +5787,13 @@ gmp_xml_handle_start_element (/* unused */ GMarkupParseContext* context, &modify_port_list_data->port_list_id); set_client_state (CLIENT_MODIFY_PORT_LIST); } + else if (strcasecmp ("MODIFY_LICENSE", element_name) == 0) + { + modify_license_start (gmp_parser, + attribute_names, + attribute_values); + set_client_state (CLIENT_MODIFY_LICENSE); + } else if (strcasecmp ("MODIFY_NOTE", element_name) == 0) { append_attribute (attribute_names, attribute_values, "note_id", @@ -7708,6 +7725,11 @@ gmp_xml_handle_start_element (/* unused */ GMarkupParseContext* context, set_read_over (gmp_parser); break; + case CLIENT_MODIFY_LICENSE: + modify_license_element_start (gmp_parser, element_name, + attribute_names, attribute_values); + break; + case CLIENT_MODIFY_NOTE: if (strcasecmp ("ACTIVE", element_name) == 0) set_client_state (CLIENT_MODIFY_NOTE_ACTIVE); @@ -18812,6 +18834,15 @@ gmp_xml_handle_end_element (/* unused */ GMarkupParseContext* context, handle_get_info (gmp_parser, error); break; + case CLIENT_GET_LICENSE: + { + if (get_license_element_end (gmp_parser, + error, + element_name)) + set_client_state (CLIENT_AUTHENTIC); + break; + } + case CLIENT_GET_NOTES: handle_get_notes (gmp_parser, error); break; @@ -23196,6 +23227,15 @@ gmp_xml_handle_end_element (/* unused */ GMarkupParseContext* context, CLOSE (CLIENT_MODIFY_GROUP, NAME); CLOSE (CLIENT_MODIFY_GROUP, USERS); + case CLIENT_MODIFY_LICENSE: + { + if (modify_license_element_end (gmp_parser, + error, + element_name)) + set_client_state (CLIENT_AUTHENTIC); + break; + } + case CLIENT_MODIFY_NOTE: { if (acl_user_may ("modify_note") == 0) @@ -26319,6 +26359,11 @@ gmp_xml_handle_text (/* unused */ GMarkupParseContext* context, } + case CLIENT_GET_LICENSE: + get_license_element_text (text, text_len); + break; + + APPEND (CLIENT_MODIFY_ALERT_NAME, &modify_alert_data->name); @@ -26392,6 +26437,11 @@ gmp_xml_handle_text (/* unused */ GMarkupParseContext* context, &modify_group_data->users); + case CLIENT_MODIFY_LICENSE: + modify_license_element_text (text, text_len); + break; + + APPEND (CLIENT_MODIFY_NOTE_ACTIVE, &modify_note_data->active); diff --git a/src/gmp_license.c b/src/gmp_license.c new file mode 100644 index 000000000..14c8fc199 --- /dev/null +++ b/src/gmp_license.c @@ -0,0 +1,487 @@ +/* Copyright (C) 2021 Greenbone Networks GmbH + * + * SPDX-License-Identifier: AGPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +/** + * @file gmp_license.c + * @brief GVM GMP layer: License information + * + * This includes function and variable definitions for GMP handling + * of license information. + */ + +#include "gmp_license.h" +#include "manage_license.h" +#include "utils.h" + +#undef G_LOG_DOMAIN +/** + * @brief GLib log domain. + */ +#define G_LOG_DOMAIN "md gmp" + +/* GET_LICENSE. */ + +/** + * @brief The get_license command. + */ +typedef struct +{ + context_data_t *context; ///< XML parser context. +} get_license_t; + +/** + * @brief Parser callback data. + * + * This is initially 0 because it's a global variable. + */ +static get_license_t get_license_data; + +/** + * @brief Reset command data. + */ +static void +get_license_reset () +{ + if (get_license_data.context->first) + { + free_entity (get_license_data.context->first->data); + g_slist_free_1 (get_license_data.context->first); + } + g_free (get_license_data.context); + memset (&get_license_data, 0, sizeof (get_license_t)); +} + +/** + * @brief Start a command. + * + * @param[in] gmp_parser GMP parser. + * @param[in] attribute_names All attribute names. + * @param[in] attribute_values All attribute values. + */ +void +get_license_start (gmp_parser_t *gmp_parser, + const gchar **attribute_names, + const gchar **attribute_values) +{ + memset (&get_license_data, 0, sizeof (get_license_t)); + get_license_data.context = g_malloc0 (sizeof (context_data_t)); + get_license_element_start (gmp_parser, "get_license", + attribute_names, attribute_values); +} + +/** + * @brief Start element. + * + * @param[in] gmp_parser GMP parser. + * @param[in] name Element name. + * @param[in] attribute_names All attribute names. + * @param[in] attribute_values All attribute values. + */ +void +get_license_element_start (gmp_parser_t *gmp_parser, + const gchar *name, + const gchar **attribute_names, + const gchar **attribute_values) +{ + xml_handle_start_element (get_license_data.context, name, + attribute_names, attribute_values); +} + +/** + * @brief Writes XML for a license access key to a GString buffer. + * + * This is meant to be used to traverse a GTree with g_tree_foreach. + * + * @param[in] key The key from the tree, i.e. the access key name. + * @param[in] value The value from the tree, i.e. the key content. + * @param[in] buffer The GString to buffer the XML element. + * + * @return Always FALSE to continue traversing the GTree. + */ +static gboolean +buffer_license_key_xml (gchar *key, gchar *value, GString *buffer) +{ + xml_string_append (buffer, + "%s", + key, value); + return FALSE; +} + +/** + * @brief Writes XML for a license signature info item to a GString buffer. + * + * This is meant to be used to traverse a GTree with g_tree_foreach. + * + * @param[in] key The key from the tree, i.e. the info item name. + * @param[in] value The value from the tree, i.e. the info item content. + * @param[in] buffer The GString to buffer the XML element. + * + * @return Always FALSE to continue traversing the GTree. + */ +static gboolean +buffer_license_signature_xml (gchar *key, gchar *value, GString *buffer) +{ + xml_string_append (buffer, + "%s", + key, value); + return FALSE; +} + + +/** + * @brief Writes license data to a GString as XML + * + * @param[in] response The GString buffer to write the license content to. + * @param[in] license_data The license data struct to get the data from. + */ +static void +buffer_license_content_xml (GString *response, license_data_t *license_data) +{ + xml_string_append (response, + "" + "" + "%s" + "%s" + "%s" + "%s" + "%s", + license_data->meta->id, + license_data->meta->version, + license_data->meta->title, + license_data->meta->type, + license_data->meta->customer_name); + + xml_string_append (response, + "%s", + iso_time (&license_data->meta->created)); + xml_string_append (response, + "%s", + iso_time (&license_data->meta->begins)); + xml_string_append (response, + "%s", + iso_time (&license_data->meta->expires)); + + xml_string_append (response, + "" + "" + "%s" + "%s" + "%d" + "" + "", + license_data->appliance->model, + license_data->appliance->model_type, + license_data->appliance->sensor); + + g_tree_foreach (license_data->keys, + (GTraverseFunc) buffer_license_key_xml, + response); + + xml_string_append (response, + "" + ""); + + g_tree_foreach (license_data->signatures, + (GTraverseFunc) buffer_license_signature_xml, + response); + + xml_string_append (response, + "" + ""); +} + + +/** + * @brief Execute command. + * + * @param[in] gmp_parser GMP parser. + * @param[in] error Error parameter. + */ +static void +get_license_run (gmp_parser_t *gmp_parser, + GError **error) +{ + int ret; + + gchar *license_status; + license_data_t *license_data; + + license_status = NULL; + license_data = NULL; + + ret = manage_get_license (&license_status, + &license_data); + + switch (ret) + { + case 0: + { + GString *response; + + response = g_string_new (""); + xml_string_append (response, + "" + "" + "%s", + STATUS_OK, + STATUS_OK_TEXT, + license_status); + + if (license_data) + { + buffer_license_content_xml (response, license_data); + } + + xml_string_append (response, + "" + ""); + + SEND_TO_CLIENT_OR_FAIL (response->str); + g_string_free (response, TRUE); + } + break; + case 1: + SENDF_TO_CLIENT_OR_FAIL + ("", + STATUS_SERVICE_DOWN); + break; + case 99: + SEND_TO_CLIENT_OR_FAIL (XML_ERROR_ACCESS ("get_license")); + break; + default: + SEND_TO_CLIENT_OR_FAIL (XML_INTERNAL_ERROR ("get_license")); + break; + } + + g_free (license_status); + license_data_free (license_data); + + get_license_reset (); +} + +/** + * @brief End element. + * + * @param[in] gmp_parser GMP parser. + * @param[in] error Error parameter. + * @param[in] name Element name. + * + * @return 0 success, 1 command finished. + */ +int +get_license_element_end (gmp_parser_t *gmp_parser, + GError **error, + const gchar *name) +{ + xml_handle_end_element (get_license_data.context, name); + if (get_license_data.context->done) + { + get_license_run (gmp_parser, error); + return 1; + } + return 0; +} + +/** + * @brief Add text to element. + * + * @param[in] text Text. + * @param[in] text_len Text length. + */ +void +get_license_element_text (const gchar *text, + gsize text_len) +{ + xml_handle_text (get_license_data.context, text, text_len); +} + + +/* MODIFY_LICENSE. */ + +/** + * @brief The modify_license command. + */ +typedef struct +{ + context_data_t *context; ///< XML parser context. +} modify_license_t; + +/** + * @brief Parser callback data. + * + * This is initially 0 because it's a global variable. + */ +static modify_license_t modify_license_data; + +/** + * @brief Reset command data. + */ +static void +modify_license_reset () +{ + if (modify_license_data.context->first) + { + free_entity (modify_license_data.context->first->data); + g_slist_free_1 (modify_license_data.context->first); + } + g_free (modify_license_data.context); + memset (&modify_license_data, 0, sizeof (modify_license_t)); +} + +/** + * @brief Start a command. + * + * @param[in] gmp_parser GMP parser. + * @param[in] attribute_names All attribute names. + * @param[in] attribute_values All attribute values. + */ +void +modify_license_start (gmp_parser_t *gmp_parser, + const gchar **attribute_names, + const gchar **attribute_values) +{ + memset (&modify_license_data, 0, sizeof (modify_license_t)); + modify_license_data.context = g_malloc0 (sizeof (context_data_t)); + modify_license_element_start (gmp_parser, "modify_license", + attribute_names, attribute_values); +} + +/** + * @brief Start element. + * + * @param[in] gmp_parser GMP parser. + * @param[in] name Element name. + * @param[in] attribute_names All attribute names. + * @param[in] attribute_values All attribute values. + */ +void +modify_license_element_start (gmp_parser_t *gmp_parser, + const gchar *name, + const gchar **attribute_names, + const gchar **attribute_values) +{ + xml_handle_start_element (modify_license_data.context, name, + attribute_names, attribute_values); +} + +/** + * @brief Handles modifying the license + * + * @param[in] file_content The content of the new license file. + * @param[in] allow_empty Whether to allow an empty file. + * + * @return 0 success, 1 service unavailable, 2 empty file not allowed, + * 99 permission denied. + */ +static int +modify_license (gchar *file_content, gboolean allow_empty) +{ + if (allow_empty == FALSE + && (file_content == NULL || strcmp (file_content, "") == 0)) + return 2; + + return 0; +} + +/** + * @brief Execute command. + * + * @param[in] gmp_parser GMP parser. + * @param[in] error Error parameter. + */ +static void +modify_license_run (gmp_parser_t *gmp_parser, + GError **error) +{ + entity_t entity, file_entity; + const char* allow_empty_str; + int allow_empty, ret; + + entity = (entity_t) modify_license_data.context->first->data; + + allow_empty_str = entity_attribute (entity, "allow_empty"); + allow_empty = allow_empty_str ? atoi(allow_empty_str) != 0 : 0; + + file_entity = entity_child (entity, "file"); + + ret = modify_license (file_entity ? file_entity->text : NULL, allow_empty); + switch (ret) + { + case 0: + SEND_TO_CLIENT_OR_FAIL (XML_OK ("modify_license")); + break; + case 1: + SENDF_TO_CLIENT_OR_FAIL + ("", + STATUS_SERVICE_DOWN); + break; + case 2: + SENDF_TO_CLIENT_OR_FAIL + (XML_ERROR_SYNTAX ("modify_license", + "A non-empty FILE or the allow_empty attribute" + " is required")); + break; + case 99: + SEND_TO_CLIENT_OR_FAIL (XML_ERROR_ACCESS ("modify_license")); + break; + default: + SEND_TO_CLIENT_OR_FAIL (XML_INTERNAL_ERROR ("modify_license")); + break; + } + + modify_license_reset (); +} + +/** + * @brief End element. + * + * @param[in] gmp_parser GMP parser. + * @param[in] error Error parameter. + * @param[in] name Element name. + * + * @return 0 success, 1 command finished. + */ +int +modify_license_element_end (gmp_parser_t *gmp_parser, + GError **error, + const gchar *name) +{ + xml_handle_end_element (modify_license_data.context, name); + if (modify_license_data.context->done) + { + modify_license_run (gmp_parser, error); + return 1; + } + return 0; +} + +/** + * @brief Add text to element. + * + * @param[in] text Text. + * @param[in] text_len Text length. + */ +void +modify_license_element_text (const gchar *text, + gsize text_len) +{ + xml_handle_text (modify_license_data.context, text, text_len); +} diff --git a/src/gmp_license.h b/src/gmp_license.h new file mode 100644 index 000000000..d6f8691a2 --- /dev/null +++ b/src/gmp_license.h @@ -0,0 +1,75 @@ +/* Copyright (C) 2021 Greenbone Networks GmbH + * + * SPDX-License-Identifier: AGPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#include "gmp_base.h" + +#include +#include + + +/** + * @file gmp_tls_certificates.h + * @brief GVM GMP layer: License information headers + * + * Headers for GMP handling of license information. + */ + +/* GET_LICENSE. */ + +void +get_license_start (gmp_parser_t *, + const gchar **, + const gchar **); + +void +get_license_element_start (gmp_parser_t *, + const gchar *, + const gchar **, + const gchar **); + +int +get_license_element_end (gmp_parser_t *, + GError **, + const gchar *); + +void +get_license_element_text (const gchar *, + gsize); + + +/* MODIFY_LICENSE. */ + +void +modify_license_start (gmp_parser_t *, + const gchar **, + const gchar **); + +void +modify_license_element_start (gmp_parser_t *, + const gchar *, + const gchar **, + const gchar **); + +int +modify_license_element_end (gmp_parser_t *, + GError **, + const gchar *); + +void +modify_license_element_text (const gchar *, + gsize); diff --git a/src/manage_license.c b/src/manage_license.c new file mode 100644 index 000000000..d45fa8d8b --- /dev/null +++ b/src/manage_license.c @@ -0,0 +1,201 @@ +/* Copyright (C) 2020-2021 Greenbone Networks GmbH + * + * SPDX-License-Identifier: AGPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +/** + * @file manage_license.c + * @brief GVM management layer: License information. + * + * Non-SQL license information code for the GVM management layer. + */ + +#include "manage_acl.h" +#include "manage_license.h" +#include "utils.h" + +/* Data types */ + +/** + * @brief Allocates a new license metadata struct + * + * @return Newly allocated license metadata. Free with license_meta_free. + */ +license_meta_t * +license_meta_new () +{ + return g_malloc0 (sizeof (license_meta_t)); +} + +/** + * @brief Frees a license metadata struct and its fields. + * + * @param[in] data The data struct to free. + */ +void +license_meta_free (license_meta_t *data) +{ + if (data == NULL) + return; + + free (data->id); + free (data->version); + free (data->title); + free (data->type); + free (data->customer_name); + + g_free (data); +} + +/** + * @brief Allocates a new license appliance data struct + * + * @return Newly allocated license appliance data. Free with license_meta_free. + */ +license_appliance_t * +license_appliance_new () +{ + return g_malloc0 (sizeof (license_appliance_t)); +} + +/** + * @brief Frees a license appliance data struct and its fields. + * + * @param[in] data The data struct to free. + */ +void +license_appliance_free (license_appliance_t *data) +{ + if (data == NULL) + return; + + free (data->model); + free (data->model_type); + + g_free (data); +} + +/** + * @brief Allocates a new license data struct + * + * @return Newly allocated license data. Free with license_meta_free. + */ +license_data_t * +license_data_new () +{ + license_data_t *data = g_malloc0 (sizeof (license_data_t)); + + data->meta = license_meta_new (); + data->appliance = license_appliance_new (); + + data->keys = g_tree_new_full ((GCompareDataFunc) g_ascii_strcasecmp, + NULL, g_free, g_free); + + data->signatures = g_tree_new_full ((GCompareDataFunc) g_ascii_strcasecmp, + NULL, g_free, g_free); + + return data; +} + +/** + * @brief Frees a license data struct and its fields. + * + * @param[in] data The data struct to free. + */ +void +license_data_free (license_data_t *data) +{ + if (data == NULL) + return; + + license_meta_free (data->meta); + license_appliance_free (data->appliance); + g_tree_destroy (data->keys); + g_tree_destroy (data->signatures); + + g_free (data); +} + +/* Actions */ + +/** + * @brief Update the license file by replacing it with the given one. + * + * @param[in] new_license The content of the new license. + * + * @return 0 success, 99 permission denied. + */ +int +manage_update_license_file (const char *new_license) +{ + if (! acl_user_may ("modify_license")) + return 99; + + g_message ("%s: Uploaded new license file (%lu bytes)", + __func__, strlen (new_license)); + + return 0; +} + +/** + * @brief Get the current license information. + * + * @param[out] status The validation status (e.g. "valid", "expired"). + * @param[out] license_data The content of the license organized in a struct. + * + * @return 0 success, 1 service unavailable, 99 permission denied. + */ +int +manage_get_license (gchar **status, + license_data_t **license_data) +{ + if (! acl_user_may ("get_license")) + return 99; + + if (status) + *status = g_strdup ("active"); + + if (license_data) + { + *license_data = license_data_new (); + license_meta_t *license_meta = (*license_data)->meta; + license_appliance_t *license_appliance = (*license_data)->appliance; + + // TODO : replace dummy data with data from license service + license_meta->id = g_strdup ("4711"); + license_meta->version = g_strdup_printf("1.0.0"); + license_meta->title = g_strdup ("Test License"); + license_meta->type = g_strdup ("trial"); + license_meta->customer_name = g_strdup ("Jane Doe"); + license_meta->created = time (NULL) - 3600; + license_meta->begins = time (NULL); + license_meta->expires = time (NULL) + 3600 * 24 * 8; + + license_appliance->model = g_strdup ("trial"); + license_appliance->model_type = g_strdup ("virtual"); + license_appliance->sensor = FALSE; + + g_tree_replace ((*license_data)->keys, + g_strdup ("feed"), + g_strdup ("*base64 GSF key*")); + + g_tree_replace ((*license_data)->signatures, + g_strdup ("license"), + g_strdup ("*base64 signature*")); + } + + return 0; +} diff --git a/src/manage_license.h b/src/manage_license.h new file mode 100644 index 000000000..ad3a0c9e7 --- /dev/null +++ b/src/manage_license.h @@ -0,0 +1,88 @@ +/* Copyright (C) 2020-2021 Greenbone Networks GmbH + * + * SPDX-License-Identifier: AGPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +/** + * @file manage_license.c + * @brief GVM management layer: License information headers. + * + * Headers for non-SQL license information code for the GVM management layer. + */ + +#include + +/* Data types */ + +/** + * @brief Defines the metadata of a license + */ +typedef struct { + char *id; ///< Unique Identifier of the license + char *version; ///< Version of the license file schema + char *title; ///< Short title summarizing the license + char *type; ///< Type of license, e.g. trial or commercial + char *customer_name; ///< Name of the customer + time_t created; ///< Time the license was created + time_t begins; ///< Time after which the license becomes valid + time_t expires; ///< Time the license expires +} license_meta_t; + +license_meta_t * +license_meta_new (); + +void +license_meta_free (license_meta_t *); + +/** + * @brief Defines the hardware and appliance information of a license + */ +typedef struct { + char *model; ///< Appliance model, e.g. "one", "ceno", "450", ... + char *model_type; ///< Appliance model type, e.g. "virtual" or "hardware" + gboolean sensor; ///< Whether the license is applied to a sensor or not +} license_appliance_t; + +license_appliance_t * +license_appliance_new (); + +void +license_appliance_free (license_appliance_t *); + +/** + * @brief Defines the information contained in a license + */ +typedef struct { + license_meta_t *meta; ///< License metadata + license_appliance_t *appliance; ///< Hardware and appliance information + GTree *keys; ///< Base64 encoded access keys, e.g. feed key + GTree *signatures; ///< Signature info of the license +} license_data_t; + +license_data_t * +license_data_new (); + +void +license_data_free (license_data_t *); + + +/* Actions */ + +int +manage_update_license_file (const char *); + +int +manage_get_license (char **, license_data_t **); diff --git a/src/schema_formats/XML/GMP.xml.in b/src/schema_formats/XML/GMP.xml.in index 8b28ec81c..4e97c3fb4 100644 --- a/src/schema_formats/XML/GMP.xml.in +++ b/src/schema_formats/XML/GMP.xml.in @@ -12605,6 +12605,207 @@ along with this program. If not, see . + + get_license + Get the current license + +

+ The client uses the get_license command to get the current license. +

+
+ + + + + + status + status + 1 + + + status_text + text + 1 + + license + + + license + The license information + + status + content + + + status + Status of the license + text + + + content + The main content of the license file + + meta + appliance + keys + signatures + + + meta + License metadata + + version + id + title + type + customer_name + created + begins + expires + + + version + Version of the license file schema + text + + + id + Unique Identifier of the license + text + + + title + Short title summarizing the license + text + + + type + License type, e.g. "trial" or "commercial" + text + + + customer_name + Name of the customer the license is issued for + text + + + created + Time the license was created + iso_time + + + begins + Time after which the license is valid + iso_time + + + expires + Time the license expires + iso_time + + + + appliance + Hardware and appliance information + + model + model_type + + + model + Appliance model, e.g. "one" + text + + + model_type + Appliance model type, e.g. "virtual" or "hardware" + text + + + sensor + Whether the license is applied to a sensor or not + boolean + + + + keys + Base64 encoded access keys, e.g. feed keys + + key + + + key + A Base64 encoded access key + + + name + Name of the key + text + + text + + + + + signatures + Signatures of the license + + signature + + + signature + A signature info item + + + name + Name of the signature + text + + text + + + + + + + + Get the current license + + + + + + + + active + + + 4711 + 1.0.0 + Test License + trial + Jane Doe + 2021-08-27T06:05:21Z + 2021-08-27T07:05:21Z + 2021-09-04T07:05:21Z + + + trial + virtual + 0 + + + *base64 GSF key* + + + *base64 signature* + + + + + + +
get_nvts Get one or many NVTs @@ -23618,6 +23819,59 @@ along with this program. If not, see . + + modify_license + Modify the existing license + +

+ The client uses the modify_license command to change the current + license. +

+

+ The license has to be provided as a valid license TOML file. +

+
+ + + allow_empty + Whether to allow an empty file + boolean + 0 + + file + + + file + The license TOML file in plain-text form + text + + + + + status + status + 1 + + + status_text + text + 1 + + + + + Upload an new license file + + + [...] + + + + + + + +
modify_note Modify an existing note