From 3aa9b2d2484cfe2a7375e3813bb0e04f35415132 Mon Sep 17 00:00:00 2001 From: Timo Pollmeier Date: Thu, 7 Mar 2019 17:42:25 +0100 Subject: [PATCH 01/18] Add basic GET_TLS_CERTIFICATES command This adds the basic tables and GET_... GMP command to handle TLS certificates as separate assets outside the report host details. --- src/CMakeLists.txt | 7 +- src/gmp.c | 5 + src/gmp_tls_certificates.c | 207 +++++++++++++++++++++++++ src/gmp_tls_certificates.h | 39 +++++ src/manage.h | 1 + src/manage_pg.c | 26 ++++ src/manage_sql.c | 1 + src/manage_sql_tls_certificates.c | 241 ++++++++++++++++++++++++++++++ src/manage_sql_tls_certificates.h | 30 ++++ src/manage_sqlite3.c | 10 ++ src/manage_tls_certificates.h | 63 ++++++++ 11 files changed, 628 insertions(+), 2 deletions(-) create mode 100644 src/gmp_tls_certificates.c create mode 100644 src/gmp_tls_certificates.h create mode 100644 src/manage_sql_tls_certificates.c create mode 100644 src/manage_sql_tls_certificates.h create mode 100644 src/manage_tls_certificates.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 482e76ac0..6e73ff332 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -99,12 +99,13 @@ add_executable (${BINARY_NAME} manage_acl.c manage_config_discovery.c manage_config_host_discovery.c manage_config_system_discovery.c manage_sql.c manage_sql_nvts.c manage_sql_secinfo.c - manage_sql_tickets.c + manage_sql_tickets.c manage_sql_tls_certificates.c manage_migrators.c scanner.c ${BACKEND_FILES} lsc_user.c lsc_crypt.c utils.c comm.c otp.c - gmp.c gmp_base.c gmp_delete.c gmp_get.c gmp_tickets.c) + gmp.c gmp_base.c gmp_delete.c gmp_get.c gmp_tickets.c + gmp_tls_certificates.c) if (BACKEND STREQUAL SQLITE3) target_link_libraries (${BINARY_NAME} m @@ -277,6 +278,7 @@ set (C_FILES "${CMAKE_CURRENT_SOURCE_DIR}/gvmd.c" "${CMAKE_CURRENT_SOURCE_DIR}/gmp_delete.c" "${CMAKE_CURRENT_SOURCE_DIR}/gmp_get.c" "${CMAKE_CURRENT_SOURCE_DIR}/gmp_tickets.c" + "${CMAKE_CURRENT_SOURCE_DIR}/gmp_tls_certificates.c" "${CMAKE_CURRENT_SOURCE_DIR}/otp.c" "${CMAKE_CURRENT_SOURCE_DIR}/manage.c" "${CMAKE_CURRENT_SOURCE_DIR}/manage_utils.c" @@ -294,6 +296,7 @@ set (C_FILES "${CMAKE_CURRENT_SOURCE_DIR}/gvmd.c" "${CMAKE_CURRENT_SOURCE_DIR}/manage_sql_nvts.c" "${CMAKE_CURRENT_SOURCE_DIR}/manage_sql_secinfo.c" "${CMAKE_CURRENT_SOURCE_DIR}/manage_sql_tickets.c" + "${CMAKE_CURRENT_SOURCE_DIR}/manage_sql_tls_certificates.c" "${CMAKE_CURRENT_SOURCE_DIR}/manage_sqlite3.c" "${CMAKE_CURRENT_SOURCE_DIR}/manage_migrators.c" "${CMAKE_CURRENT_SOURCE_DIR}/comm.c" diff --git a/src/gmp.c b/src/gmp.c index e0f0d808c..ead905f2e 100644 --- a/src/gmp.c +++ b/src/gmp.c @@ -89,6 +89,7 @@ #include "gmp_delete.h" #include "gmp_get.h" #include "gmp_tickets.h" +#include "gmp_tls_certificates.h" #include "manage.h" #include "manage_acl.h" #include "utils.h" @@ -5245,6 +5246,7 @@ typedef enum CLIENT_GET_TARGETS, CLIENT_GET_TASKS, CLIENT_GET_TICKETS, + CLIENT_GET_TLS_CERTIFICATES, CLIENT_GET_USERS, CLIENT_GET_VERSION, CLIENT_GET_VERSION_AUTHENTIC, @@ -6681,6 +6683,7 @@ gmp_xml_handle_start_element (/* unused */ GMarkupParseContext* context, set_client_state (CLIENT_GET_TASKS); } ELSE_GET_START (tickets, TICKETS) + ELSE_GET_START (tls_certificates, TLS_CERTIFICATES) else if (strcasecmp ("GET_USERS", element_name) == 0) { get_data_parse_attributes (&get_users_data->get, "user", @@ -20873,6 +20876,8 @@ gmp_xml_handle_end_element (/* unused */ GMarkupParseContext* context, CASE_GET_END (TICKETS, tickets); + CASE_GET_END (TLS_CERTIFICATES, tls_certificates); + case CLIENT_GET_USERS: handle_get_users (gmp_parser, error); break; diff --git a/src/gmp_tls_certificates.c b/src/gmp_tls_certificates.c new file mode 100644 index 000000000..12cb3d328 --- /dev/null +++ b/src/gmp_tls_certificates.c @@ -0,0 +1,207 @@ +/* Copyright (C) 2019 Greenbone Networks GmbH + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + * 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; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/** + * @file gmp_tls_certificates.c + * @brief GVM GMP layer: TLS certificates + * + * This includes function and variable definitions for GMP handling + * of TLS certificates. + */ + +#include "gmp_tls_certificates.h" +#include "gmp_base.h" +#include "gmp_get.h" +#include "manage_tls_certificates.h" + +#include +#include +#include + +#include + +#undef G_LOG_DOMAIN +/** + * @brief GLib log domain. + */ +#define G_LOG_DOMAIN "md gmp" + + + +/* GET_TLS_CERTIFICATES. */ + +/** + * @brief The get_tls_certificates command. + */ +typedef struct +{ + get_data_t get; ///< Get args. +} get_tls_certificates_t; + +/** + * @brief Parser callback data. + * + * This is initially 0 because it's a global variable. + */ +static get_tls_certificates_t get_tls_certificates_data; + +/** + * @brief Reset command data. + */ +static void +get_tls_certificates_reset () +{ + get_data_reset (&get_tls_certificates_data.get); + memset (&get_tls_certificates_data, 0, sizeof (get_tls_certificates_t)); +} + +/** + * @brief Handle command start element. + * + * @param[in] attribute_names All attribute names. + * @param[in] attribute_values All attribute values. + */ +void +get_tls_certificates_start (const gchar **attribute_names, + const gchar **attribute_values) +{ + get_data_parse_attributes (&get_tls_certificates_data.get, "tls_certificate", + attribute_names, + attribute_values); +} + +/** + * @brief Handle end element. + * + * @param[in] gmp_parser GMP parser. + * @param[in] error Error parameter. + */ +void +get_tls_certificates_run (gmp_parser_t *gmp_parser, GError **error) +{ + iterator_t tls_certificates; + int count, filtered, ret, first; + + count = 0; + + ret = init_get ("get_tls_certificates", + &get_tls_certificates_data.get, + "TLS Certificates", + &first); + if (ret) + { + switch (ret) + { + case 99: + SEND_TO_CLIENT_OR_FAIL + (XML_ERROR_SYNTAX ("get_tls_certificates", + "Permission denied")); + break; + default: + internal_error_send_to_client (error); + get_tls_certificates_reset (); + return; + } + get_tls_certificates_reset (); + return; + } + + /* Setup the iterator. */ + + ret = init_tls_certificate_iterator (&tls_certificates, + &get_tls_certificates_data.get); + if (ret) + { + switch (ret) + { + case 1: + if (send_find_error_to_client ("get_tls_certificates", + "tls_certificate", + get_tls_certificates_data.get.id, + gmp_parser)) + { + error_send_to_client (error); + get_tls_certificates_reset (); + return; + } + break; + case 2: + if (send_find_error_to_client + ("get_tls_certificates", "filter", + get_tls_certificates_data.get.filt_id, gmp_parser)) + { + error_send_to_client (error); + get_tls_certificates_reset (); + return; + } + break; + case -1: + SEND_TO_CLIENT_OR_FAIL + (XML_INTERNAL_ERROR ("get_tls_certificates")); + break; + } + get_tls_certificates_reset (); + return; + } + + /* Loop through tls_certificates, sending XML. */ + + SEND_GET_START ("tls_certificate"); + while (1) + { + ret = get_next (&tls_certificates, &get_tls_certificates_data.get, + &first, &count, init_tls_certificate_iterator); + if (ret == 1) + break; + if (ret == -1) + { + internal_error_send_to_client (error); + get_tls_certificates_reset (); + return; + } + + /* Send generic GET command elements. */ + + SEND_GET_COMMON (tls_certificate, &get_tls_certificates_data.get, + &tls_certificates); + + /* Send tls_certificate info. */ + SENDF_TO_CLIENT_OR_FAIL + ("%s" + "%d" + "%s" + "%s" + "", + tls_certificate_iterator_certificate (&tls_certificates), + tls_certificate_iterator_trust (&tls_certificates), + tls_certificate_iterator_subject_dn (&tls_certificates), + tls_certificate_iterator_issuer_dn (&tls_certificates)); + count++; + } + cleanup_iterator (&tls_certificates); + filtered = get_tls_certificates_data.get.id + ? 1 + : tls_certificate_count (&get_tls_certificates_data.get); + SEND_GET_END ("tls_certificate", + &get_tls_certificates_data.get, + count, + filtered); + + get_tls_certificates_reset (); +} diff --git a/src/gmp_tls_certificates.h b/src/gmp_tls_certificates.h new file mode 100644 index 000000000..f7a298a6c --- /dev/null +++ b/src/gmp_tls_certificates.h @@ -0,0 +1,39 @@ +/* Copyright (C) 2019 Greenbone Networks GmbH + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + * 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; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/** + * @file gmp_tls_certificates.h + * @brief GVM GMP layer: TLS Certificates headers + * + * Headers for GMP handling of TLS Certificates. + */ + +#ifndef _GVMD_GMP_TLS_CERTIFICATES_H +#define _GVMD_GMP_TLS_CERTIFICATES_H + +#include "gmp_base.h" +#include "manage.h" + +void +get_tls_certificates_start (const gchar **, const gchar **); + +void +get_tls_certificates_run (gmp_parser_t *, GError **); + +#endif /* not _GVMD_GMP_TLS_CERTIFICATES_H */ diff --git a/src/manage.h b/src/manage.h index 8c4ddee00..ac9df2a37 100644 --- a/src/manage.h +++ b/src/manage.h @@ -331,6 +331,7 @@ typedef long long int tag_t; typedef long long int target_t; typedef long long int task_t; typedef long long int ticket_t; +typedef long long int tls_certificate_t; typedef long long int result_t; typedef long long int report_t; typedef long long int report_host_t; diff --git a/src/manage_pg.c b/src/manage_pg.c index 43cd1a696..18f17004c 100644 --- a/src/manage_pg.c +++ b/src/manage_pg.c @@ -2490,6 +2490,32 @@ create_tables () " result_uuid text," " report integer);"); // REFERENCES reports_trash (id) ON DELETE RESTRICT + sql ("CREATE TABLE IF NOT EXISTS tls_certificates" + " (id SERIAL PRIMARY KEY," + " uuid text UNIQUE NOT NULL," + " owner integer REFERENCES users (id) ON DELETE RESTRICT," + " name text," + " comment text," + " creation_time integer," + " modification_time integer," + " certificate text," + " subject_dn text," + " issuer_dn text," + " trust integer);"); + + sql ("CREATE TABLE IF NOT EXISTS tls_certificates_trash" + " (id SERIAL PRIMARY KEY," + " uuid text UNIQUE NOT NULL," + " owner integer REFERENCES users (id) ON DELETE RESTRICT," + " name text," + " comment text," + " creation_time integer," + " modification_time integer," + " certificate text," + " subject_dn text," + " issuer_dn text," + " trust integer);"); + sql ("CREATE TABLE IF NOT EXISTS scanners" " (id SERIAL PRIMARY KEY," " uuid text UNIQUE NOT NULL," diff --git a/src/manage_sql.c b/src/manage_sql.c index b38da657f..e51f4ca31 100644 --- a/src/manage_sql.c +++ b/src/manage_sql.c @@ -635,6 +635,7 @@ command_t gmp_commands[] {"GET_TARGETS", "Get all targets."}, {"GET_TASKS", "Get all tasks."}, {"GET_TICKETS", "Get all tickets."}, + {"GET_TLS_CERTIFICATES", "Get all TLS certificates."}, {"GET_USERS", "Get all users."}, {"GET_VERSION", "Get the Greenbone Management Protocol version."}, {"GET_VULNS", "Get all vulnerabilities."}, diff --git a/src/manage_sql_tls_certificates.c b/src/manage_sql_tls_certificates.c new file mode 100644 index 000000000..8d0817915 --- /dev/null +++ b/src/manage_sql_tls_certificates.c @@ -0,0 +1,241 @@ +/* Copyright (C) 2019 Greenbone Networks GmbH + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + * 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; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/** + * @file manage_sql_tls_certificates.c + * @brief GVM management layer: TLS Certificates SQL + * + * The TLS Certificates SQL for the GVM management layer. + */ + +#include "manage_tls_certificates.h" +#include "manage_acl.h" +#include "manage_sql_tls_certificates.h" +#include "manage_sql.h" +#include "sql.h" + +#include +#include + +/** + * @brief Filter columns for tls_certificate iterator. + */ +#define TLS_CERTIFICATE_ITERATOR_FILTER_COLUMNS \ + { GET_ITERATOR_FILTER_COLUMNS, "subject_dn", "issuer_dn", NULL } + +/** + * @brief TLS Certificate iterator columns. + */ +#define TLS_CERTIFICATE_ITERATOR_COLUMNS \ + { \ + GET_ITERATOR_COLUMNS (tls_certificates), \ + { \ + "certificate", \ + NULL, \ + KEYWORD_TYPE_STRING \ + }, \ + { \ + "subject_dn", \ + NULL, \ + KEYWORD_TYPE_STRING \ + }, \ + { \ + "issuer_dn", \ + NULL, \ + KEYWORD_TYPE_STRING \ + }, \ + { \ + "trust", \ + NULL, \ + KEYWORD_TYPE_INTEGER \ + }, \ + { NULL, NULL, KEYWORD_TYPE_UNKNOWN } \ + } + +/** + * @brief TLS Certificate iterator columns for trash case. + */ +#define TLS_CERTIFICATE_ITERATOR_TRASH_COLUMNS \ + { \ + GET_ITERATOR_COLUMNS (tls_certificates_trash), \ + { \ + "certificate", \ + NULL, \ + KEYWORD_TYPE_STRING \ + }, \ + { \ + "subject_dn", \ + NULL, \ + KEYWORD_TYPE_STRING \ + }, \ + { \ + "issuer_dn", \ + NULL, \ + KEYWORD_TYPE_STRING \ + }, \ + { \ + "trust", \ + NULL, \ + KEYWORD_TYPE_INTEGER \ + }, \ + { NULL, NULL, KEYWORD_TYPE_UNKNOWN } \ + } + +/** + * @brief Count number of tls_certificates. + * + * @param[in] get GET params. + * + * @return Total number of tls_certificates in filtered set. + */ +int +tls_certificate_count (const get_data_t *get) +{ + static const char *extra_columns[] = TLS_CERTIFICATE_ITERATOR_FILTER_COLUMNS; + static column_t columns[] = TLS_CERTIFICATE_ITERATOR_COLUMNS; + static column_t trash_columns[] = TLS_CERTIFICATE_ITERATOR_TRASH_COLUMNS; + + return count ("tls_certificate", get, columns, trash_columns, extra_columns, + 0, 0, 0, TRUE); +} + +/** + * @brief Initialise a tls_certificate iterator. + * + * @param[in] iterator Iterator. + * @param[in] get GET data. + * + * @return 0 success, 1 failed to find tls_certificate, + * 2 failed to find filter, -1 error. + */ +int +init_tls_certificate_iterator (iterator_t *iterator, const get_data_t *get) +{ + static const char *filter_columns[] = TLS_CERTIFICATE_ITERATOR_FILTER_COLUMNS; + static column_t columns[] = TLS_CERTIFICATE_ITERATOR_COLUMNS; + static column_t trash_columns[] = TLS_CERTIFICATE_ITERATOR_TRASH_COLUMNS; + + return init_get_iterator (iterator, + "tls_certificate", + get, + columns, + trash_columns, + filter_columns, + 0, + NULL, + NULL, + TRUE); +} + +/** + * @brief Get a column value from a tls_certificate iterator. + * + * @param[in] iterator Iterator. + * + * @return Value of the column or NULL if iteration is complete. + */ +DEF_ACCESS (tls_certificate_iterator_certificate, GET_ITERATOR_COLUMN_COUNT); + +/** + * @brief Get a column value from a tls_certificate iterator. + * + * @param[in] iterator Iterator. + * + * @return Value of the column or NULL if iteration is complete. + */ +DEF_ACCESS (tls_certificate_iterator_subject_dn, + GET_ITERATOR_COLUMN_COUNT + 1); + +/** + * @brief Get a column value from a tls_certificate iterator. + * + * @param[in] iterator Iterator. + * + * @return Value of the column or NULL if iteration is complete. + */ +DEF_ACCESS (tls_certificate_iterator_issuer_dn, + GET_ITERATOR_COLUMN_COUNT + 2); + +/** + * @brief Get a column value from a tls_certificate iterator. + * + * @param[in] iterator Iterator. + * + * @return Value of the column or NULL if iteration is complete. + */ +int +tls_certificate_iterator_trust (iterator_t *iterator) +{ + if (iterator->done) + return 0; + + return iterator_int (iterator, GET_ITERATOR_COLUMN_COUNT + 3); +} + +/** + * @brief Return whether a tls_certificate is in use. + * + * @param[in] tls_certificate TLS Certificate. + * + * @return 1 if in use, else 0. + */ +int +tls_certificate_in_use (tls_certificate_t tls_certificate) +{ + return 0; +} + +/** + * @brief Return whether a trashcan tls_certificate is in use. + * + * @param[in] tls_certificate TLS Certificate. + * + * @return 1 if in use, else 0. + */ +int +trash_tls_certificate_in_use (tls_certificate_t tls_certificate) +{ + return 0; +} + +/** + * @brief Return whether a tls_certificate is writable. + * + * @param[in] tls_certificate TLS Certificate. + * + * @return 1 if writable, else 0. + */ +int +tls_certificate_writable (tls_certificate_t tls_certificate) +{ + return 1; +} + +/** + * @brief Return whether a trashcan tls_certificate is writable. + * + * @param[in] tls_certificate TLS Certificate. + * + * @return 1 if writable, else 0. + */ +int +trash_tls_certificate_writable (tls_certificate_t tls_certificate) +{ + return trash_tls_certificate_in_use (tls_certificate) == 0; +} diff --git a/src/manage_sql_tls_certificates.h b/src/manage_sql_tls_certificates.h new file mode 100644 index 000000000..b4762aafb --- /dev/null +++ b/src/manage_sql_tls_certificates.h @@ -0,0 +1,30 @@ +/* Copyright (C) 2019 Greenbone Networks GmbH + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + * 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; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/** + * @file manage_sql_tls_certificates.h + * @brief GVM management layer: TLS Certificates SQL headers + * + * Headers for TLS Certificates SQL for the GVM management layer. + */ + +#ifndef _GVMD_MANAGE_SQL_TLS_CERTIFICATES_H +#define _GVMD_MANAGE_SQL_TLS_CERTIFICATES_H + +#endif /* not _GVMD_MANAGE_SQL_TLS_CERTIFICATES_H */ diff --git a/src/manage_sqlite3.c b/src/manage_sqlite3.c index 8bfd48a29..a7766af51 100644 --- a/src/manage_sqlite3.c +++ b/src/manage_sqlite3.c @@ -3817,6 +3817,16 @@ create_tables () sql ("CREATE TABLE IF NOT EXISTS ticket_results_trash" " (id INTEGER PRIMARY KEY, ticket, result, result_location," " result_uuid, report);"); + sql ("CREATE TABLE IF NOT EXISTS tls_certificates" + " (id INTEGER PRIMARY KEY, uuid text UNIQUE, owner integer," + " name text, comment text, creation_time integer," + " modification_time integer, certificate text, subject_dn text," + " issuer_dn text, trust integer);"); + sql ("CREATE TABLE IF NOT EXISTS tls_certificates_trash" + " (id INTEGER PRIMARY KEY, uuid text UNIQUE, owner integer," + " name text, comment text, creation_time integer," + " modification_time integer, certificate text, subject_dn text," + " issuer_dn text, trust integer);"); sql ("CREATE TABLE IF NOT EXISTS scanners" " (id INTEGER PRIMARY KEY, uuid, owner INTEGER, name, comment," " host, port, type, ca_pub, credential INTEGER," diff --git a/src/manage_tls_certificates.h b/src/manage_tls_certificates.h new file mode 100644 index 000000000..93caaa18d --- /dev/null +++ b/src/manage_tls_certificates.h @@ -0,0 +1,63 @@ +/* Copyright (C) 2019 Greenbone Networks GmbH + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + * 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; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/** + * @file manage_sql_tls_certificates.h + * @brief GVM management layer: TLS Certificates SQL headers + * + * Headers for TLS Certificates SQL for the GVM management layer. + */ + +#ifndef _GVMD_MANAGE_TLS_CERTIFICATES_H +#define _GVMD_MANAGE_TLS_CERTIFICATES_H + +#include "manage.h" +#include "iterator.h" + +int +tls_certificate_count (const get_data_t *); + +int +init_tls_certificate_iterator (iterator_t *, const get_data_t *); + +const char* +tls_certificate_iterator_certificate (iterator_t*); + +const char* +tls_certificate_iterator_subject_dn (iterator_t*); + +const char* +tls_certificate_iterator_issuer_dn (iterator_t*); + +int +tls_certificate_iterator_trust (iterator_t *); + +int +tls_certificate_in_use (tls_certificate_t); + +int +trash_tls_certificate_in_use (tls_certificate_t); + +int +tls_certificate_writable (tls_certificate_t); + +int +trash_tls_certificate_writable (tls_certificate_t); + +#endif /* not _GVMD_MANAGE_TLS_CERTIFICATES_H */ From bf422966110fa40bc2c769acb0380fadca4fe51c Mon Sep 17 00:00:00 2001 From: Timo Pollmeier Date: Mon, 11 Mar 2019 17:36:51 +0100 Subject: [PATCH 02/18] Add basic CREATE_TLS_CERTIFICATE command This allows adding a new TLS certificate from a certificate file. --- src/gmp.c | 23 ++++ src/gmp_tls_certificates.c | 220 ++++++++++++++++++++++++++++++ src/gmp_tls_certificates.h | 14 ++ src/manage_sql_tls_certificates.c | 104 ++++++++++++++ src/manage_tls_certificates.h | 10 ++ 5 files changed, 371 insertions(+) diff --git a/src/gmp.c b/src/gmp.c index ead905f2e..d9be973c6 100644 --- a/src/gmp.c +++ b/src/gmp.c @@ -5178,6 +5178,7 @@ typedef enum CLIENT_CREATE_TASK_SCHEDULE_PERIODS, CLIENT_CREATE_TASK_TARGET, CLIENT_CREATE_TICKET, + CLIENT_CREATE_TLS_CERTIFICATE, CLIENT_CREATE_USER, CLIENT_CREATE_USER_COMMENT, CLIENT_CREATE_USER_COPY, @@ -5789,6 +5790,12 @@ gmp_xml_handle_start_element (/* unused */ GMarkupParseContext* context, attribute_values); set_client_state (CLIENT_CREATE_TICKET); } + else if (strcasecmp ("CREATE_TLS_CERTIFICATE", element_name) == 0) + { + create_tls_certificate_start (gmp_parser, attribute_names, + attribute_values); + set_client_state (CLIENT_CREATE_TLS_CERTIFICATE); + } else if (strcasecmp ("CREATE_USER", element_name) == 0) { set_client_state (CLIENT_CREATE_USER); @@ -9224,6 +9231,12 @@ gmp_xml_handle_start_element (/* unused */ GMarkupParseContext* context, attribute_values); break; + case CLIENT_CREATE_TLS_CERTIFICATE: + create_tls_certificate_element_start (gmp_parser, element_name, + attribute_names, + attribute_values); + break; + case CLIENT_CREATE_USER: if (strcasecmp ("COMMENT", element_name) == 0) set_client_state (CLIENT_CREATE_USER_COMMENT); @@ -25048,6 +25061,12 @@ gmp_xml_handle_end_element (/* unused */ GMarkupParseContext* context, set_client_state (CLIENT_AUTHENTIC); break; + case CLIENT_CREATE_TLS_CERTIFICATE: + if (create_tls_certificate_element_end (gmp_parser, error, + element_name)) + set_client_state (CLIENT_AUTHENTIC); + break; + case CLIENT_CREATE_USER: { gchar *errdesc; @@ -29677,6 +29696,10 @@ gmp_xml_handle_text (/* unused */ GMarkupParseContext* context, create_ticket_element_text (text, text_len); break; + case CLIENT_CREATE_TLS_CERTIFICATE: + create_tls_certificate_element_text (text, text_len); + break; + APPEND (CLIENT_CREATE_USER_COMMENT, &create_user_data->comment); diff --git a/src/gmp_tls_certificates.c b/src/gmp_tls_certificates.c index 12cb3d328..bca30207f 100644 --- a/src/gmp_tls_certificates.c +++ b/src/gmp_tls_certificates.c @@ -205,3 +205,223 @@ get_tls_certificates_run (gmp_parser_t *gmp_parser, GError **error) get_tls_certificates_reset (); } + + +/* CREATE_TLS_CERTIFICATE. */ + +/** + * @brief The create_tls_certificate command. + */ +typedef struct +{ + context_data_t *context; ///< XML parser context. +} create_tls_certificate_t; + +/** + * @brief Parser callback data. + * + * This is initially 0 because it's a global variable. + */ +static create_tls_certificate_t create_tls_certificate_data; + +/** + * @brief Reset command data. + */ +static void +create_tls_certificate_reset () +{ + if (create_tls_certificate_data.context->first) + { + free_entity (create_tls_certificate_data.context->first->data); + g_slist_free_1 (create_tls_certificate_data.context->first); + } + g_free (create_tls_certificate_data.context); + memset (&create_tls_certificate_data, 0, sizeof (create_tls_certificate_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 +create_tls_certificate_start (gmp_parser_t *gmp_parser, + const gchar **attribute_names, + const gchar **attribute_values) +{ + memset (&create_tls_certificate_data, 0, sizeof (create_tls_certificate_t)); + create_tls_certificate_data.context = g_malloc0 (sizeof (context_data_t)); + create_tls_certificate_element_start (gmp_parser, "create_tls_certificate", + 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 +create_tls_certificate_element_start (gmp_parser_t *gmp_parser, const gchar *name, + const gchar **attribute_names, + const gchar **attribute_values) +{ + xml_handle_start_element (create_tls_certificate_data.context, name, attribute_names, + attribute_values); +} + +/** + * @brief Execute command. + * + * @param[in] gmp_parser GMP parser. + * @param[in] error Error parameter. + */ +void +create_tls_certificate_run (gmp_parser_t *gmp_parser, GError **error) +{ + entity_t entity, copy, comment, name, certificate; + tls_certificate_t new_tls_certificate; + + entity = (entity_t) create_tls_certificate_data.context->first->data; + + copy = entity_child (entity, "copy"); + + if (copy) + { + /* Copy from an existing tls_certificate and exit. */ + + name = entity_child (entity, "name"); + comment = entity_child (entity, "comment"); + switch (copy_tls_certificate (name ? entity_text (name) : NULL, + comment ? entity_text (comment) : NULL, + entity_text (copy), &new_tls_certificate)) + { + case 0: + { + char *uuid; + uuid = tls_certificate_uuid (new_tls_certificate); + SENDF_TO_CLIENT_OR_FAIL (XML_OK_CREATED_ID + ("create_tls_certificate"), + uuid); + log_event ("tls_certificate", "TLS Certificate", uuid, "created"); + free (uuid); + break; + } + case 1: + SEND_TO_CLIENT_OR_FAIL + (XML_ERROR_SYNTAX ("create_tls_certificate", + "TLS Certificate exists already")); + log_event_fail ("tls_certificate", "TLS Certificate", NULL, + "created"); + break; + case 2: + if (send_find_error_to_client ("create_tls_certificate", + "tls_certificate", + entity_text (copy), + gmp_parser)) + { + error_send_to_client (error); + return; + } + log_event_fail ("tls_certificate", + "TLS Certificate", + NULL, + "created"); + break; + case 99: + SEND_TO_CLIENT_OR_FAIL + (XML_ERROR_SYNTAX ("create_tls_certificate", + "Permission denied")); + log_event_fail ("tls_certificate", + "TLS Certificate", + NULL, + "created"); + break; + case -1: + default: + SEND_TO_CLIENT_OR_FAIL + (XML_INTERNAL_ERROR ("create_tls_certificate")); + log_event_fail ("tls_certificate", + "TLS Certificate", + NULL, + "created"); + break; + } + create_tls_certificate_reset (); + return; + } + + /* Check given info. */ + + name = entity_child (entity, "name"); + comment = entity_child (entity, "comment"); + certificate = entity_child (entity, "certificate"); + + switch (create_tls_certificate + (name ? entity_text (comment) : NULL, + comment ? entity_text (comment) : "", + certificate ? entity_text (certificate) : NULL, + &new_tls_certificate)) + { + case 0: + { + char *uuid = tls_certificate_uuid (new_tls_certificate); + SENDF_TO_CLIENT_OR_FAIL (XML_OK_CREATED_ID ("create_tls_certificate"), + uuid); + log_event ("tls_certificate", "TLS Certificate", uuid, "created"); + free (uuid); + break; + } + case 99: + SEND_TO_CLIENT_OR_FAIL + (XML_ERROR_SYNTAX ("create_tls_certificate", + "Permission denied")); + log_event_fail ("tls_certificate", "TLS Certificate", NULL, "created"); + break; + case -1: + default: + SEND_TO_CLIENT_OR_FAIL (XML_INTERNAL_ERROR ("create_tls_certificate")); + log_event_fail ("tls_certificate", "TLS Certificate", NULL, "created"); + break; + } + + create_tls_certificate_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 +create_tls_certificate_element_end (gmp_parser_t *gmp_parser, GError **error, + const gchar *name) +{ + xml_handle_end_element (create_tls_certificate_data.context, name); + if (create_tls_certificate_data.context->done) + { + create_tls_certificate_run (gmp_parser, error); + return 1; + } + return 0; +} + +/** + * @brief Add text to element. + * + * @param[in] text Text. + * @param[in] text_len Text length. + */ +void +create_tls_certificate_element_text (const gchar *text, gsize text_len) +{ + xml_handle_text (create_tls_certificate_data.context, text, text_len); +} diff --git a/src/gmp_tls_certificates.h b/src/gmp_tls_certificates.h index f7a298a6c..522c381ab 100644 --- a/src/gmp_tls_certificates.h +++ b/src/gmp_tls_certificates.h @@ -36,4 +36,18 @@ get_tls_certificates_start (const gchar **, const gchar **); void get_tls_certificates_run (gmp_parser_t *, GError **); +void +create_tls_certificate_start (gmp_parser_t *, const gchar **, const gchar **); + +void +create_tls_certificate_element_start (gmp_parser_t *, const gchar *, + const gchar **, const gchar **); + +int +create_tls_certificate_element_end (gmp_parser_t *, GError **error, + const gchar *); + +void +create_tls_certificate_element_text (const gchar *, gsize); + #endif /* not _GVMD_GMP_TLS_CERTIFICATES_H */ diff --git a/src/manage_sql_tls_certificates.c b/src/manage_sql_tls_certificates.c index 8d0817915..e414e09b7 100644 --- a/src/manage_sql_tls_certificates.c +++ b/src/manage_sql_tls_certificates.c @@ -33,6 +33,12 @@ #include #include +#undef G_LOG_DOMAIN +/** + * @brief GLib log domain. + */ +#define G_LOG_DOMAIN "md manage" + /** * @brief Filter columns for tls_certificate iterator. */ @@ -239,3 +245,101 @@ trash_tls_certificate_writable (tls_certificate_t tls_certificate) { return trash_tls_certificate_in_use (tls_certificate) == 0; } + +/** + * @brief Create a TLS certificate. + * + * @param[in] name Name of new TLS certificate. + * @param[in] comment Comment of TLS certificate. + * @param[in] base64_data Base64 encoded certificate file content. + * @param[out] ticket Created TLS certificate. + * + * @return 0 success, 1 invalid certificate, 99 permission denied, -1 error. + */ +int +create_tls_certificate (const char *name, + const char *comment, + const char *certificate, + tls_certificate_t *tls_certificate) +{ + int ret; + char *md5_fingerprint, *subject_dn, *issuer_dn; + time_t activation_time, expiration_time; + + subject_dn = NULL; // TODO add to get_certificate_info + + ret = get_certificate_info (certificate, + &activation_time, + &expiration_time, + &md5_fingerprint, + &issuer_dn); + + if (ret) + return 1; + + sql ("INSERT INTO tls_certificates" + " (uuid, owner, name, comment, creation_time, modification_time," + " certificate, subject_dn, issuer_dn, trust)" + " SELECT make_uuid(), (SELECT id FROM users WHERE users.uuid = '%s')," + " '%s', '%s', m_now(), m_now(), '%s', '%s', '%s', 0;", + current_credentials.uuid, + name ? name : md5_fingerprint, + comment ? comment : "", + certificate ? certificate : "", + subject_dn ? subject_dn : "", + issuer_dn ? issuer_dn : ""); + + if (tls_certificate) + *tls_certificate = sql_last_insert_id (); + + return 0; +} + +/** + * @brief Create a TLS certificate from an existing TLS certificate. + * + * @param[in] name Name. NULL to copy from existing TLS certificate. + * @param[in] comment Comment. NULL to copy from existing TLS certificate. + * @param[in] ticket_id UUID of existing TLS certificate. + * @param[out] new_ticket New TLS certificate. + * + * @return 0 success, + * 1 TLS certificate exists already, + * 2 failed to find existing TLS certificate, + * 99 permission denied, + * -1 error. + */ +int +copy_tls_certificate (const char *name, + const char *comment, + const char *tls_certificate_id, + tls_certificate_t *new_tls_certificate) +{ + int ret; + tls_certificate_t old_tls_certificate; + + assert (new_tls_certificate); + + ret = copy_resource ("tls_certificate", name, comment, tls_certificate_id, + "certificate, subject_dn, issuer_dn, trust", + 0, new_tls_certificate, &old_tls_certificate); + if (ret) + return ret; + + return 0; +} + + +/** + * @brief Return the UUID of a TLS certificate. + * + * @param[in] tls_certificate TLS certificate. + * + * @return Newly allocated UUID if available, else NULL. + */ +char* +tls_certificate_uuid (tls_certificate_t tls_certificate) +{ + return sql_string ("SELECT uuid FROM tls_certificates WHERE id = %llu;", + tls_certificate); +} diff --git a/src/manage_tls_certificates.h b/src/manage_tls_certificates.h index 93caaa18d..6d22322af 100644 --- a/src/manage_tls_certificates.h +++ b/src/manage_tls_certificates.h @@ -60,4 +60,14 @@ tls_certificate_writable (tls_certificate_t); int trash_tls_certificate_writable (tls_certificate_t); +int +create_tls_certificate (const char *, const char *, const char *, + tls_certificate_t *); + +int +copy_tls_certificate (const char* name, const char* comment, const char* tls_certificate_id, ticket_t* new_ticket); + +char* +tls_certificate_uuid (tls_certificate_t); + #endif /* not _GVMD_MANAGE_TLS_CERTIFICATES_H */ From 7bd13bd381186d838b3ef6c217983b5937e758a8 Mon Sep 17 00:00:00 2001 From: Timo Pollmeier Date: Tue, 12 Mar 2019 09:42:54 +0100 Subject: [PATCH 03/18] Add TLS certificate md5 and validity columns This adds the columns md5_fingerprint, activation_time and expiration_time to tls certificates. --- src/gmp_tls_certificates.c | 8 ++ src/manage_pg.c | 6 ++ src/manage_sql_tls_certificates.c | 127 ++++++++++++++++++++++++++++-- src/manage_sqlite3.c | 6 +- src/manage_tls_certificates.h | 12 +++ 5 files changed, 152 insertions(+), 7 deletions(-) diff --git a/src/gmp_tls_certificates.c b/src/gmp_tls_certificates.c index bca30207f..928f09b58 100644 --- a/src/gmp_tls_certificates.c +++ b/src/gmp_tls_certificates.c @@ -184,12 +184,20 @@ get_tls_certificates_run (gmp_parser_t *gmp_parser, GError **error) /* Send tls_certificate info. */ SENDF_TO_CLIENT_OR_FAIL ("%s" + "%s" "%d" + "%d" + "%s" + "%s" "%s" "%s" "", tls_certificate_iterator_certificate (&tls_certificates), + tls_certificate_iterator_md5_fingerprint (&tls_certificates), tls_certificate_iterator_trust (&tls_certificates), + tls_certificate_iterator_valid (&tls_certificates), + tls_certificate_iterator_activation_time (&tls_certificates), + tls_certificate_iterator_expiration_time (&tls_certificates), tls_certificate_iterator_subject_dn (&tls_certificates), tls_certificate_iterator_issuer_dn (&tls_certificates)); count++; diff --git a/src/manage_pg.c b/src/manage_pg.c index 18f17004c..c59d851bc 100644 --- a/src/manage_pg.c +++ b/src/manage_pg.c @@ -2501,6 +2501,9 @@ create_tables () " certificate text," " subject_dn text," " issuer_dn text," + " activation_time integer," + " expiration_time integer," + " md5_fingerprint text," " trust integer);"); sql ("CREATE TABLE IF NOT EXISTS tls_certificates_trash" @@ -2514,6 +2517,9 @@ create_tables () " certificate text," " subject_dn text," " issuer_dn text," + " activation_time integer," + " expiration_time integer," + " md5_fingerprint text," " trust integer);"); sql ("CREATE TABLE IF NOT EXISTS scanners" diff --git a/src/manage_sql_tls_certificates.c b/src/manage_sql_tls_certificates.c index e414e09b7..37b49496d 100644 --- a/src/manage_sql_tls_certificates.c +++ b/src/manage_sql_tls_certificates.c @@ -43,7 +43,8 @@ * @brief Filter columns for tls_certificate iterator. */ #define TLS_CERTIFICATE_ITERATOR_FILTER_COLUMNS \ - { GET_ITERATOR_FILTER_COLUMNS, "subject_dn", "issuer_dn", NULL } + { GET_ITERATOR_FILTER_COLUMNS, "subject_dn", "issuer_dn", "md5_fingerprint", \ + "activates", "expires", "valid", NULL } /** * @brief TLS Certificate iterator columns. @@ -71,6 +72,38 @@ NULL, \ KEYWORD_TYPE_INTEGER \ }, \ + { \ + "md5_fingerprint", \ + NULL, \ + KEYWORD_TYPE_STRING \ + }, \ + { \ + "iso_time (activation_time)", \ + "activation_time", \ + KEYWORD_TYPE_INTEGER \ + }, \ + { \ + "iso_time (expiration_time)", \ + "expiration_time", \ + KEYWORD_TYPE_INTEGER \ + }, \ + { \ + "(CASE WHEN (expiration_time >= m_now() OR expiration_time = -1)" \ + " AND (activation_time <= m_now() OR activation_time = -1)" \ + " THEN 1 ELSE 0 END)", \ + "valid", \ + KEYWORD_TYPE_INTEGER \ + }, \ + { \ + "activation_time", \ + "activates", \ + KEYWORD_TYPE_INTEGER \ + }, \ + { \ + "expiration_time", \ + "expires", \ + KEYWORD_TYPE_INTEGER \ + }, \ { NULL, NULL, KEYWORD_TYPE_UNKNOWN } \ } @@ -100,6 +133,38 @@ NULL, \ KEYWORD_TYPE_INTEGER \ }, \ + { \ + "md5_fingerprint", \ + NULL, \ + KEYWORD_TYPE_STRING \ + }, \ + { \ + "iso_time (activation_time)", \ + "activation_time", \ + KEYWORD_TYPE_INTEGER \ + }, \ + { \ + "iso_time (expiration_time)", \ + "expiration_time", \ + KEYWORD_TYPE_INTEGER \ + }, \ + { \ + "(CASE WHEN (expiration_time >= m_now() OR expiration_time = -1)" \ + " AND (activation_time <= m_now() OR activation_time = -1)" \ + " THEN 1 ELSE 0 END)", \ + "valid", \ + KEYWORD_TYPE_INTEGER \ + }, \ + { \ + "activation_time", \ + "activates", \ + KEYWORD_TYPE_INTEGER \ + }, \ + { \ + "expiration_time", \ + "expires", \ + KEYWORD_TYPE_INTEGER \ + }, \ { NULL, NULL, KEYWORD_TYPE_UNKNOWN } \ } @@ -194,6 +259,52 @@ tls_certificate_iterator_trust (iterator_t *iterator) return iterator_int (iterator, GET_ITERATOR_COLUMN_COUNT + 3); } +/** + * @brief Get a column value from a tls_certificate iterator. + * + * @param[in] iterator Iterator. + * + * @return Value of the column or NULL if iteration is complete. + */ +DEF_ACCESS (tls_certificate_iterator_md5_fingerprint, + GET_ITERATOR_COLUMN_COUNT + 4); + +/** + * @brief Get a column value from a tls_certificate iterator. + * + * @param[in] iterator Iterator. + * + * @return Value of the column or NULL if iteration is complete. + */ +DEF_ACCESS (tls_certificate_iterator_activation_time, + GET_ITERATOR_COLUMN_COUNT + 5); + +/** + * @brief Get a column value from a tls_certificate iterator. + * + * @param[in] iterator Iterator. + * + * @return Value of the column or NULL if iteration is complete. + */ +DEF_ACCESS (tls_certificate_iterator_expiration_time, + GET_ITERATOR_COLUMN_COUNT + 6); + +/** + * @brief Get a column value from a tls_certificate iterator. + * + * @param[in] iterator Iterator. + * + * @return Value of the column or NULL if iteration is complete. + */ +int +tls_certificate_iterator_valid (iterator_t *iterator) +{ + if (iterator->done) + return 0; + + return iterator_int (iterator, GET_ITERATOR_COLUMN_COUNT + 7); +} + /** * @brief Return whether a tls_certificate is in use. * @@ -279,15 +390,20 @@ create_tls_certificate (const char *name, sql ("INSERT INTO tls_certificates" " (uuid, owner, name, comment, creation_time, modification_time," - " certificate, subject_dn, issuer_dn, trust)" + " certificate, subject_dn, issuer_dn, trust," + " activation_time, expiration_time, md5_fingerprint)" " SELECT make_uuid(), (SELECT id FROM users WHERE users.uuid = '%s')," - " '%s', '%s', m_now(), m_now(), '%s', '%s', '%s', 0;", + " '%s', '%s', m_now(), m_now(), '%s', '%s', '%s', 0," + " %ld, %ld, '%s';", current_credentials.uuid, name ? name : md5_fingerprint, comment ? comment : "", certificate ? certificate : "", subject_dn ? subject_dn : "", - issuer_dn ? issuer_dn : ""); + issuer_dn ? issuer_dn : "", + activation_time, + expiration_time, + md5_fingerprint); if (tls_certificate) *tls_certificate = sql_last_insert_id (); @@ -321,7 +437,8 @@ copy_tls_certificate (const char *name, assert (new_tls_certificate); ret = copy_resource ("tls_certificate", name, comment, tls_certificate_id, - "certificate, subject_dn, issuer_dn, trust", + "certificate, subject_dn, issuer_dn, trust," + "activation_time, expiration_time, md5_fingerprint", 0, new_tls_certificate, &old_tls_certificate); if (ret) return ret; diff --git a/src/manage_sqlite3.c b/src/manage_sqlite3.c index a7766af51..73fa2ad9c 100644 --- a/src/manage_sqlite3.c +++ b/src/manage_sqlite3.c @@ -3821,12 +3821,14 @@ create_tables () " (id INTEGER PRIMARY KEY, uuid text UNIQUE, owner integer," " name text, comment text, creation_time integer," " modification_time integer, certificate text, subject_dn text," - " issuer_dn text, trust integer);"); + " issuer_dn text, activation_time integer, expiration_time integer," + " md5_fingerprint text, trust integer);"); sql ("CREATE TABLE IF NOT EXISTS tls_certificates_trash" " (id INTEGER PRIMARY KEY, uuid text UNIQUE, owner integer," " name text, comment text, creation_time integer," " modification_time integer, certificate text, subject_dn text," - " issuer_dn text, trust integer);"); + " issuer_dn text, activation_time integer, expiration_time integer," + " md5_fingerprint text, trust integer);"); sql ("CREATE TABLE IF NOT EXISTS scanners" " (id INTEGER PRIMARY KEY, uuid, owner INTEGER, name, comment," " host, port, type, ca_pub, credential INTEGER," diff --git a/src/manage_tls_certificates.h b/src/manage_tls_certificates.h index 6d22322af..8ebdf6b21 100644 --- a/src/manage_tls_certificates.h +++ b/src/manage_tls_certificates.h @@ -48,6 +48,18 @@ tls_certificate_iterator_issuer_dn (iterator_t*); int tls_certificate_iterator_trust (iterator_t *); +const char* +tls_certificate_iterator_md5_fingerprint (iterator_t*); + +const char* +tls_certificate_iterator_activation_time (iterator_t*); + +const char* +tls_certificate_iterator_expiration_time (iterator_t*); + +int +tls_certificate_iterator_valid (iterator_t *); + int tls_certificate_in_use (tls_certificate_t); From b0306a9293fddfa782ccb94a8aff629818b3c03c Mon Sep 17 00:00:00 2001 From: Timo Pollmeier Date: Tue, 12 Mar 2019 10:30:59 +0100 Subject: [PATCH 04/18] Get subject in create_tls_certificate. This adds an output parameter to the get_certificate_info function which is used by create_tls_certificate to get the subject DN. --- src/gmp.c | 10 +++++----- src/manage.c | 15 ++++++++++++++- src/manage.h | 7 ++++++- src/manage_sql_tls_certificates.c | 1 + 4 files changed, 26 insertions(+), 7 deletions(-) diff --git a/src/gmp.c b/src/gmp.c index d9be973c6..1d429366e 100644 --- a/src/gmp.c +++ b/src/gmp.c @@ -13654,7 +13654,7 @@ handle_get_credentials (gmp_parser_t *gmp_parser, GError **error) gchar *fingerprint, *issuer; get_certificate_info (cert, &activation_time, &expiration_time, - &fingerprint, &issuer); + &fingerprint, NULL, &issuer); activation_time_str = certificate_iso_time (activation_time); expiration_time_str = certificate_iso_time (expiration_time); SENDF_TO_CLIENT_OR_FAIL @@ -17015,7 +17015,7 @@ handle_get_scanners (gmp_parser_t *gmp_parser, GError **error) gchar *fingerprint, *issuer; get_certificate_info (scanner_iterator_ca_pub (&scanners), &activation_time, &expiration_time, - &fingerprint, &issuer); + &fingerprint, NULL, &issuer); activation_time_str = certificate_iso_time (activation_time); expiration_time_str = certificate_iso_time (expiration_time); SENDF_TO_CLIENT_OR_FAIL @@ -17060,7 +17060,7 @@ handle_get_scanners (gmp_parser_t *gmp_parser, GError **error) gchar *fingerprint, *issuer; get_certificate_info (scanner_iterator_key_pub (&scanners), &activation_time, &expiration_time, - &fingerprint, &issuer); + &fingerprint, NULL, &issuer); activation_time_str = certificate_iso_time (activation_time); expiration_time_str = certificate_iso_time (expiration_time); SENDF_TO_CLIENT_OR_FAIL @@ -17938,7 +17938,7 @@ handle_get_settings (gmp_parser_t *gmp_parser, GError **error) get_certificate_info (setting_iterator_value (&settings), &activation_time, &expiration_time, &fingerprint, - &issuer); + NULL, &issuer); activation_time_str = certificate_iso_time (activation_time); expiration_time_str = certificate_iso_time (expiration_time); SENDF_TO_CLIENT_OR_FAIL @@ -20710,7 +20710,7 @@ gmp_xml_handle_end_element (/* unused */ GMarkupParseContext* context, get_certificate_info (ldap_cacert, &activation_time, &expiration_time, &fingerprint, - &issuer); + NULL, &issuer); activation_time_str = certificate_iso_time (activation_time); expiration_time_str = certificate_iso_time (expiration_time); SENDF_TO_CLIENT_OR_FAIL diff --git a/src/manage.c b/src/manage.c index 8ff460f96..364db1b0a 100644 --- a/src/manage.c +++ b/src/manage.c @@ -309,7 +309,7 @@ truncate_private_key (const gchar* private_key) int get_certificate_info (const gchar* certificate, time_t* activation_time, time_t* expiration_time, - gchar** fingerprint, gchar** issuer) + gchar** fingerprint, gchar **subject, gchar** issuer) { gchar *cert_truncated; @@ -320,6 +320,8 @@ get_certificate_info (const gchar* certificate, *expiration_time = -1; if (fingerprint) *fingerprint = NULL; + if (subject) + *subject = NULL; if (issuer) *issuer = NULL; @@ -383,6 +385,17 @@ get_certificate_info (const gchar* certificate, g_string_free (string, FALSE); } + if (subject) + { + size_t buffer_size; + gchar *buffer; + gnutls_x509_crt_get_dn (gnutls_cert, NULL, &buffer_size); + buffer = g_malloc (buffer_size); + gnutls_x509_crt_get_dn (gnutls_cert, buffer, &buffer_size); + + *subject = buffer; + } + if (issuer) { size_t buffer_size; diff --git a/src/manage.h b/src/manage.h index ac9df2a37..e832a6f16 100644 --- a/src/manage.h +++ b/src/manage.h @@ -158,7 +158,12 @@ gchar* truncate_private_key (const gchar*); int -get_certificate_info (const gchar*, time_t*, time_t*, gchar**, gchar**); +get_certificate_info (const gchar *, + time_t *, + time_t *, + gchar **, + gchar **, + gchar **); gchar * certificate_iso_time (time_t); diff --git a/src/manage_sql_tls_certificates.c b/src/manage_sql_tls_certificates.c index 37b49496d..06260c549 100644 --- a/src/manage_sql_tls_certificates.c +++ b/src/manage_sql_tls_certificates.c @@ -383,6 +383,7 @@ create_tls_certificate (const char *name, &activation_time, &expiration_time, &md5_fingerprint, + &subject_dn, &issuer_dn); if (ret) From 5921f19d76c760ce691bf9bcfb5d657fc8b0c4b7 Mon Sep 17 00:00:00 2001 From: Timo Pollmeier Date: Wed, 12 Jun 2019 12:20:56 +0200 Subject: [PATCH 05/18] Fix TLS certificate function documentation This fixes a few mistakes in the function documentation of get_certificate_info, create_tls_certificate and copy_tls_certificate. --- src/manage.c | 1 + src/manage_sql_tls_certificates.c | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/manage.c b/src/manage.c index 0af123cf4..2ffb48a36 100644 --- a/src/manage.c +++ b/src/manage.c @@ -303,6 +303,7 @@ truncate_private_key (const gchar* private_key) * @param[out] activation_time Pointer to write activation time to. * @param[out] expiration_time Pointer to write expiration time to. * @param[out] fingerprint Pointer for newly allocated fingerprint. + * @param[out] subject Pointer for newly allocated subject DN. * @param[out] issuer Pointer for newly allocated issuer DN. * * @return 0 success, -1 error. diff --git a/src/manage_sql_tls_certificates.c b/src/manage_sql_tls_certificates.c index 06260c549..4a2175072 100644 --- a/src/manage_sql_tls_certificates.c +++ b/src/manage_sql_tls_certificates.c @@ -362,8 +362,8 @@ trash_tls_certificate_writable (tls_certificate_t tls_certificate) * * @param[in] name Name of new TLS certificate. * @param[in] comment Comment of TLS certificate. - * @param[in] base64_data Base64 encoded certificate file content. - * @param[out] ticket Created TLS certificate. + * @param[in] certificate Plain certificate file content. + * @param[out] tls_certificate Created TLS certificate. * * @return 0 success, 1 invalid certificate, 99 permission denied, -1 error. */ @@ -417,8 +417,8 @@ create_tls_certificate (const char *name, * * @param[in] name Name. NULL to copy from existing TLS certificate. * @param[in] comment Comment. NULL to copy from existing TLS certificate. - * @param[in] ticket_id UUID of existing TLS certificate. - * @param[out] new_ticket New TLS certificate. + * @param[in] tls_certificate_id UUID of existing TLS certificate. + * @param[out] new_tls_certificate New TLS certificate. * * @return 0 success, * 1 TLS certificate exists already, From 3b600f8ab8833aa259873cdb22209927e30935c9 Mon Sep 17 00:00:00 2001 From: Timo Pollmeier Date: Wed, 12 Jun 2019 17:26:57 +0200 Subject: [PATCH 06/18] Fix copy, add delete for tls_certificates This fixes some issues that prevented copy_tls_certificate from working, adds the delete_tls_certificate GMP command and other functions related to deleting for TLS certificates. --- src/gmp.c | 8 + src/manage.c | 3 + src/manage_sql.c | 12 ++ src/manage_sql_tls_certificates.c | 250 ++++++++++++++++++++++++++++++ src/manage_sql_tls_certificates.h | 15 ++ src/manage_tls_certificates.h | 3 +- src/manage_utils.c | 1 + 7 files changed, 291 insertions(+), 1 deletion(-) diff --git a/src/gmp.c b/src/gmp.c index fc82f5297..17e45c6f1 100644 --- a/src/gmp.c +++ b/src/gmp.c @@ -5234,6 +5234,7 @@ typedef enum CLIENT_DELETE_TARGET, CLIENT_DELETE_TASK, CLIENT_DELETE_TICKET, + CLIENT_DELETE_TLS_CERTIFICATE, CLIENT_DELETE_USER, CLIENT_DESCRIBE_AUTH, CLIENT_EMPTY_TRASHCAN, @@ -6062,6 +6063,12 @@ gmp_xml_handle_start_element (/* unused */ GMarkupParseContext* context, attribute_names, attribute_values); set_client_state (CLIENT_DELETE_TICKET); } + else if (strcasecmp ("DELETE_TLS_CERTIFICATE", element_name) == 0) + { + delete_start ("tls_certificate", "TLS Certificate", + attribute_names, attribute_values); + set_client_state (CLIENT_DELETE_TLS_CERTIFICATE); + } else if (strcasecmp ("DELETE_USER", element_name) == 0) { const gchar* attribute; @@ -20575,6 +20582,7 @@ gmp_xml_handle_end_element (/* unused */ GMarkupParseContext* context, break; case CLIENT_DELETE_TICKET: + case CLIENT_DELETE_TLS_CERTIFICATE: delete_run (gmp_parser, error); set_client_state (CLIENT_AUTHENTIC); break; diff --git a/src/manage.c b/src/manage.c index 2ffb48a36..c7d0de525 100644 --- a/src/manage.c +++ b/src/manage.c @@ -51,6 +51,7 @@ #include "manage_sql_secinfo.h" #include "manage_sql_nvts.h" #include "manage_sql_tickets.h" +#include "manage_sql_tls_certificates.h" #include "comm.h" #include "utils.h" @@ -9972,6 +9973,8 @@ delete_resource (const char *type, const char *resource_id, int ultimate) { if (strcasecmp (type, "ticket") == 0) return delete_ticket (resource_id, ultimate); + if (strcasecmp (type, "tls_certificate") == 0) + return delete_tls_certificate (resource_id, ultimate); assert (0); return -1; } diff --git a/src/manage_sql.c b/src/manage_sql.c index d181befa7..03e805678 100644 --- a/src/manage_sql.c +++ b/src/manage_sql.c @@ -35,6 +35,7 @@ #include "manage_sql_nvts.h" #include "manage_tickets.h" #include "manage_sql_tickets.h" +#include "manage_sql_tls_certificates.h" #include "manage_acl.h" #include "lsc_user.h" #include "sql.h" @@ -586,6 +587,7 @@ command_t gmp_commands[] {"CREATE_TARGET", "Create a target."}, {"CREATE_TASK", "Create a task."}, {"CREATE_TICKET", "Create a ticket."}, + {"CREATE_TLS_CERTIFICATE", "Create a TLS certificate."}, {"CREATE_USER", "Create a new user."}, {"DELETE_AGENT", "Delete an agent."}, {"DELETE_ALERT", "Delete an alert."}, @@ -608,6 +610,7 @@ command_t gmp_commands[] {"DELETE_TARGET", "Delete a target."}, {"DELETE_TASK", "Delete a task."}, {"DELETE_TICKET", "Delete a ticket."}, + {"DELETE_TLS_CERTIFICATE", "Delete a TLS certificate."}, {"DELETE_USER", "Delete an existing user."}, {"DESCRIBE_AUTH", "Get details about the used authentication methods."}, {"EMPTY_TRASHCAN", "Empty the trashcan."}, @@ -59951,10 +59954,16 @@ manage_restore (const char *id) return 99; } + /* Ticket. */ ret = restore_ticket (id); if (ret != 2) return ret; + /* TLS Certificate. */ + ret = restore_tls_certificate (id); + if (ret != 2) + return ret; + /* Agent. */ if (find_trash ("agent", id, &resource)) @@ -61156,6 +61165,7 @@ manage_empty_trashcan () current_credentials.uuid); sql ("DELETE FROM configs_trash" WHERE_OWNER); empty_trashcan_tickets (); + empty_trashcan_tls_certificates(); sql ("DELETE FROM permissions" " WHERE subject_type = 'group'" " AND subject IN (SELECT id from groups_trash" @@ -65750,6 +65760,7 @@ delete_user (const char *user_id_arg, const char *name_arg, int ultimate, inheritor, user); inherit_tickets (user, inheritor); + inherit_tls_certificates (user, inheritor); sql ("UPDATE groups SET owner = %llu WHERE owner = %llu;", inheritor, user); @@ -65817,6 +65828,7 @@ delete_user (const char *user_id_arg, const char *name_arg, int ultimate, user); sql ("DELETE FROM tags_trash WHERE owner = %llu;", user); delete_tickets_user (user); + delete_tls_certificates_user (user); /* Delete assets (not directly referenced). */ diff --git a/src/manage_sql_tls_certificates.c b/src/manage_sql_tls_certificates.c index 4a2175072..a8b71822e 100644 --- a/src/manage_sql_tls_certificates.c +++ b/src/manage_sql_tls_certificates.c @@ -447,6 +447,256 @@ copy_tls_certificate (const char *name, return 0; } +/** + * @brief Delete a tls_certificate. + * + * @param[in] tls_certificate_id UUID of tls_certificate. + * @param[in] ultimate Whether to remove entirely, or to trashcan. + * + * @return 0 success, 1 fail because tls_certificate is in use, + * 2 failed to find tls_certificate, + * 3 predefined tls_certificate, 99 permission denied, -1 error. + */ +int +delete_tls_certificate (const char *tls_certificate_id, int ultimate) +{ + tls_certificate_t tls_certificate = 0; + + sql_begin_immediate (); + + if (acl_user_may ("delete_tls_certificate") == 0) + { + sql_rollback (); + return 99; + } + + /* Search in the regular table. */ + + if (find_resource_with_permission ("tls_certificate", + tls_certificate_id, + &tls_certificate, + "delete_tls_certificate", + 0)) + { + sql_rollback (); + return -1; + } + + if (tls_certificate == 0) + { + /* No such tls_certificate, check the trashcan. */ + + if (find_trash ("tls_certificate", + tls_certificate_id, + &tls_certificate)) + { + sql_rollback (); + return -1; + } + if (tls_certificate == 0) + { + sql_rollback (); + return 2; + } + if (ultimate == 0) + { + /* It's already in the trashcan. */ + sql_commit (); + return 0; + } + + sql ("DELETE FROM permissions" + " WHERE resource_type = 'tls_certificate'" + " AND resource_location = %i" + " AND resource = %llu;", + LOCATION_TRASH, + tls_certificate); + + tags_remove_resource ("tls_certificate", + tls_certificate, + LOCATION_TRASH); + + sql ("DELETE FROM tls_certificates_trash WHERE id = %llu;", + tls_certificate); + + sql_commit (); + return 0; + } + + /* Ticket was found in regular table. */ + + if (ultimate == 0) + { + tls_certificate_t trash_tls_certificate; + + /* Move to trash. */ + + sql ("INSERT INTO tls_certificates_trash" + " (uuid, owner, name, comment, creation_time, modification_time," + " certificate, subject_dn, issuer_dn, trust," + " activation_time, expiration_time, md5_fingerprint)" + " SELECT" + " uuid, owner, name, comment, creation_time, modification_time," + " certificate, subject_dn, issuer_dn, trust," + " activation_time, expiration_time, md5_fingerprint" + " FROM tls_certificates WHERE id = %llu;", + tls_certificate); + + trash_tls_certificate = sql_last_insert_id (); + + permissions_set_locations ("tls_certificate", + tls_certificate, + trash_tls_certificate, + LOCATION_TRASH); + tags_set_locations ("tls_certificate", + tls_certificate, + trash_tls_certificate, + LOCATION_TRASH); + } + else + { + /* Delete entirely. */ + + sql ("DELETE FROM permissions" + " WHERE resource_type = 'tls_certificate'" + " AND resource_location = %i" + " AND resource = %llu;", + LOCATION_TABLE, + tls_certificate); + + tags_remove_resource ("tls_certificate", + tls_certificate, + LOCATION_TABLE); + } + + sql ("DELETE FROM tls_certificates WHERE id = %llu;", + tls_certificate); + + sql_commit (); + return 0; +} + +/** + * @brief Try restore a tls_certificate. + * + * If success, ends transaction for caller before exiting. + * + * @param[in] tls_certificate_id UUID of resource. + * + * @return 0 success, 1 fail because tls_certificate is in use, + * 2 failed to find tls_certificate, -1 error. + */ +int +restore_tls_certificate (const char *tls_certificate_id) +{ + tls_certificate_t trash_tls_certificate, tls_certificate; + + if (find_trash ("tls_certificate", + tls_certificate_id, + &trash_tls_certificate)) + { + sql_rollback (); + return -1; + } + + if (trash_tls_certificate == 0) + return 2; + + /* Move the tls_certificate back to the regular table. */ + + sql ("INSERT INTO tls_certificates" + " (uuid, owner, name, comment, creation_time, modification_time," + " certificate, subject_dn, issuer_dn, trust," + " activation_time, expiration_time, md5_fingerprint)" + " SELECT" + " uuid, owner, name, comment, creation_time, modification_time," + " certificate, subject_dn, issuer_dn, trust," + " activation_time, expiration_time, md5_fingerprint" + " FROM tls_certificates_trash WHERE id = %llu;", + trash_tls_certificate); + + tls_certificate = sql_last_insert_id (); + + /* Adjust references to the tls_certificate. */ + + permissions_set_locations ("tls_certificate", + trash_tls_certificate, + tls_certificate, + LOCATION_TABLE); + tags_set_locations ("tls_certificate", + trash_tls_certificate, + tls_certificate, + LOCATION_TABLE); + + /* Clear out the trashcan tls_certificate. */ + + sql ("DELETE FROM tls_certificates_trash WHERE id = %llu;", + trash_tls_certificate); + + sql_commit (); + return 0; +} + +/** + * @brief Empty TLS certificate trashcans. + */ +void +empty_trashcan_tls_certificates () +{ + sql ("DELETE FROM permissions" + " WHERE resource_type = 'tls_certificate'" + " AND resource_location = %i" + " AND resource IN (SELECT id FROM tls_certificates_trash" + " WHERE owner = (SELECT id FROM users" + " WHERE uuid = '%s'));", + LOCATION_TRASH, + current_credentials.uuid); + + sql ("DELETE FROM tickets_trash" + " WHERE owner = (SELECT id FROM users WHERE uuid = '%s');", + current_credentials.uuid); +} + +/** + * @brief Delete all TLS certificate owner by a user. + * + * Also delete trash TLS certificates. + * + * @param[in] user The user. + */ +void +delete_tls_certificates_user (user_t user) +{ + /* Regular tls_certificate. */ + + sql ("DELETE FROM tls_certificate WHERE owner = %llu;", user); + + /* Trash tls_certificate. */ + + sql ("DELETE FROM tls_certificate_trash WHERE owner = %llu;", user); +} + +/** + * @brief Change ownership of tls_certificate, for user deletion. + * + * Also assign tls_certificate that are assigned to the user to the inheritor. + * + * @param[in] user Current owner. + * @param[in] inheritor New owner. + */ +void +inherit_tls_certificates (user_t user, user_t inheritor) +{ + /* Regular tls_certificate. */ + + sql ("UPDATE tls_certificate SET owner = %llu WHERE owner = %llu;", + inheritor, user); + + /* Trash tickets. */ + + sql ("UPDATE tls_certificate_trash SET owner = %llu WHERE owner = %llu;", + inheritor, user); +} /** * @brief Return the UUID of a TLS certificate. diff --git a/src/manage_sql_tls_certificates.h b/src/manage_sql_tls_certificates.h index b4762aafb..b51be75ed 100644 --- a/src/manage_sql_tls_certificates.h +++ b/src/manage_sql_tls_certificates.h @@ -27,4 +27,19 @@ #ifndef _GVMD_MANAGE_SQL_TLS_CERTIFICATES_H #define _GVMD_MANAGE_SQL_TLS_CERTIFICATES_H +int +delete_tls_certificate (const char *, int); + +int +restore_tls_certificate (const char *); + +void +empty_trashcan_tls_certificates (); + +void +delete_tls_certificates_user (user_t); + +void +inherit_tls_certificates (user_t, user_t); + #endif /* not _GVMD_MANAGE_SQL_TLS_CERTIFICATES_H */ diff --git a/src/manage_tls_certificates.h b/src/manage_tls_certificates.h index 8ebdf6b21..1c6924669 100644 --- a/src/manage_tls_certificates.h +++ b/src/manage_tls_certificates.h @@ -77,7 +77,8 @@ create_tls_certificate (const char *, const char *, const char *, tls_certificate_t *); int -copy_tls_certificate (const char* name, const char* comment, const char* tls_certificate_id, ticket_t* new_ticket); +copy_tls_certificate (const char*, const char*, const char*, + tls_certificate_t*); char* tls_certificate_uuid (tls_certificate_t); diff --git a/src/manage_utils.c b/src/manage_utils.c index 374488e0c..7d8b61559 100644 --- a/src/manage_utils.c +++ b/src/manage_utils.c @@ -790,6 +790,7 @@ valid_db_resource_type (const char* type) || (strcasecmp (type, "target") == 0) || (strcasecmp (type, "task") == 0) || (strcasecmp (type, "ticket") == 0) + || (strcasecmp (type, "tls_certificate") == 0) || (strcasecmp (type, "user") == 0); } From b8a431d0e6dc332b3e745974fcc218fbfb8f22ad Mon Sep 17 00:00:00 2001 From: Timo Pollmeier Date: Thu, 13 Jun 2019 09:40:44 +0200 Subject: [PATCH 07/18] Add modify_tls_certificate GMP command --- src/gmp.c | 23 ++++ src/gmp_tls_certificates.c | 208 ++++++++++++++++++++++++++++++ src/gmp_tls_certificates.h | 14 ++ src/manage_sql.c | 1 + src/manage_sql_tls_certificates.c | 126 ++++++++++++++++++ src/manage_tls_certificates.h | 4 + 6 files changed, 376 insertions(+) diff --git a/src/gmp.c b/src/gmp.c index 17e45c6f1..e66befc29 100644 --- a/src/gmp.c +++ b/src/gmp.c @@ -5460,6 +5460,7 @@ typedef enum CLIENT_MODIFY_TASK_HOSTS_ORDERING, CLIENT_MODIFY_TASK_SCANNER, CLIENT_MODIFY_TICKET, + CLIENT_MODIFY_TLS_CERTIFICATE, CLIENT_MODIFY_USER, CLIENT_MODIFY_USER_COMMENT, CLIENT_MODIFY_USER_GROUPS, @@ -6911,6 +6912,12 @@ gmp_xml_handle_start_element (/* unused */ GMarkupParseContext* context, attribute_values); set_client_state (CLIENT_MODIFY_TICKET); } + else if (strcasecmp ("MODIFY_TLS_CERTIFICATE", element_name) == 0) + { + modify_tls_certificate_start (gmp_parser, attribute_names, + attribute_values); + set_client_state (CLIENT_MODIFY_TLS_CERTIFICATE); + } else if (strcasecmp ("MODIFY_USER", element_name) == 0) { append_attribute (attribute_names, attribute_values, "user_id", @@ -7870,6 +7877,12 @@ gmp_xml_handle_start_element (/* unused */ GMarkupParseContext* context, attribute_values); break; + case CLIENT_MODIFY_TLS_CERTIFICATE: + modify_tls_certificate_element_start (gmp_parser, element_name, + attribute_names, + attribute_values); + break; + case CLIENT_MODIFY_USER: if (strcasecmp ("COMMENT", element_name) == 0) set_client_state (CLIENT_MODIFY_USER_COMMENT); @@ -27871,6 +27884,13 @@ gmp_xml_handle_end_element (/* unused */ GMarkupParseContext* context, set_client_state (CLIENT_AUTHENTIC); break; + case CLIENT_MODIFY_TLS_CERTIFICATE: + if (modify_tls_certificate_element_end (gmp_parser, + error, + element_name)) + set_client_state (CLIENT_AUTHENTIC); + break; + case CLIENT_MODIFY_USER: { if ((modify_user_data->name == NULL @@ -30095,6 +30115,9 @@ gmp_xml_handle_text (/* unused */ GMarkupParseContext* context, modify_ticket_element_text (text, text_len); break; + case CLIENT_MODIFY_TLS_CERTIFICATE: + modify_tls_certificate_element_text (text, text_len); + break; APPEND (CLIENT_RUN_WIZARD_MODE, &run_wizard_data->mode); diff --git a/src/gmp_tls_certificates.c b/src/gmp_tls_certificates.c index 928f09b58..c5e348c7e 100644 --- a/src/gmp_tls_certificates.c +++ b/src/gmp_tls_certificates.c @@ -433,3 +433,211 @@ create_tls_certificate_element_text (const gchar *text, gsize text_len) { xml_handle_text (create_tls_certificate_data.context, text, text_len); } + + +/* MODIFY_TLS_CERTIFICATE. */ + +/** + * @brief The modify_tls_certificate command. + */ +typedef struct +{ + context_data_t *context; ///< XML parser context. +} modify_tls_certificate_t; + +/** + * @brief Parser callback data. + * + * This is initially 0 because it's a global variable. + */ +static modify_tls_certificate_t modify_tls_certificate_data; + +/** + * @brief Reset command data. + */ +static void +modify_tls_certificate_reset () +{ + if (modify_tls_certificate_data.context->first) + { + free_entity (modify_tls_certificate_data.context->first->data); + g_slist_free_1 (modify_tls_certificate_data.context->first); + } + g_free (modify_tls_certificate_data.context); + memset (&modify_tls_certificate_data, 0, sizeof (modify_tls_certificate_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_tls_certificate_start (gmp_parser_t *gmp_parser, + const gchar **attribute_names, + const gchar **attribute_values) +{ + memset (&modify_tls_certificate_data, + 0, + sizeof (modify_tls_certificate_t)); + modify_tls_certificate_data.context = g_malloc0 (sizeof (context_data_t)); + modify_tls_certificate_element_start (gmp_parser, + "modify_tls_certificate", + 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_tls_certificate_element_start (gmp_parser_t *gmp_parser, + const gchar *name, + const gchar **attribute_names, + const gchar **attribute_values) +{ + xml_handle_start_element (modify_tls_certificate_data.context, + name, + attribute_names, + attribute_values); +} + +/** + * @brief Execute command. + * + * @param[in] gmp_parser GMP parser. + * @param[in] error Error parameter. + */ +void +modify_tls_certificate_run (gmp_parser_t *gmp_parser, GError **error) +{ + entity_t entity, comment, name, certificate; + const char *tls_certificate_id; + + entity = (entity_t) modify_tls_certificate_data.context->first->data; + + tls_certificate_id = entity_attribute (entity, "tls_certificate_id"); + + /* Check the given info. */ + + comment = entity_child (entity, "comment"); + name = entity_child (entity, "name"); + certificate = entity_child (entity, "certificate"); + + /* Modify the tls_certificate. */ + + if (tls_certificate_id == NULL) + SEND_TO_CLIENT_OR_FAIL + (XML_ERROR_SYNTAX ("modify_tls_certificate", + "MODIFY_TLS_CERTIFICATE requires a tls_certificate_id" + " attribute")); + else switch (modify_tls_certificate + (tls_certificate_id, + comment ? entity_text (comment) : NULL, + name ? entity_text (name) : NULL, + certificate ? entity_text (certificate) : NULL)) + { + case 0: + SENDF_TO_CLIENT_OR_FAIL (XML_OK ("modify_tls_certificate")); + log_event ("tls_certificate", + "TLS Certificate", + tls_certificate_id, + "modified"); + break; + case 1: + SEND_TO_CLIENT_OR_FAIL + (XML_ERROR_SYNTAX ("modify_tls_certificate", + "TLS Certificate exists already")); + log_event_fail ("tls_certificate", + "TLS certificate", + tls_certificate_id, + "modified"); + break; + case 2: + log_event_fail ("tls_certificate", + "TLS Certificate", + tls_certificate_id, + "modified"); + if (send_find_error_to_client ("modify_tls_certificate", + "TLS certificate", + tls_certificate_id, + gmp_parser)) + { + error_send_to_client (error); + return; + } + break; + case 3: + SEND_TO_CLIENT_OR_FAIL + (XML_ERROR_SYNTAX ("modify_tls_certificate", + "Invalid certificate content")); + + log_event_fail ("tls_certificate", + "TLS Certificate", + tls_certificate_id, + "modified"); + break; + case 99: + SEND_TO_CLIENT_OR_FAIL + (XML_ERROR_SYNTAX ("modify_tls_certificate", + "Permission denied")); + log_event_fail ("tls_certificate", + "TLS Certificate", + tls_certificate_id, + "modified"); + break; + case -1: + default: + SEND_TO_CLIENT_OR_FAIL + (XML_INTERNAL_ERROR ("modify_tls_certificate")); + log_event_fail ("tls_certificate", + "TLS Certificate", + tls_certificate_id, + "modified"); + break; + } + + modify_tls_certificate_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_tls_certificate_element_end (gmp_parser_t *gmp_parser, GError **error, + const gchar *name) +{ + xml_handle_end_element (modify_tls_certificate_data.context, name); + if (modify_tls_certificate_data.context->done) + { + modify_tls_certificate_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_tls_certificate_element_text (const gchar *text, gsize text_len) +{ + xml_handle_text (modify_tls_certificate_data.context, text, text_len); +} + diff --git a/src/gmp_tls_certificates.h b/src/gmp_tls_certificates.h index 522c381ab..91a860635 100644 --- a/src/gmp_tls_certificates.h +++ b/src/gmp_tls_certificates.h @@ -50,4 +50,18 @@ create_tls_certificate_element_end (gmp_parser_t *, GError **error, void create_tls_certificate_element_text (const gchar *, gsize); +void +modify_tls_certificate_start (gmp_parser_t *, const gchar **, const gchar **); + +void +modify_tls_certificate_element_start (gmp_parser_t *, const gchar *, + const gchar **, const gchar **); + +int +modify_tls_certificate_element_end (gmp_parser_t *, GError **error, + const gchar *); + +void +modify_tls_certificate_element_text (const gchar *, gsize); + #endif /* not _GVMD_GMP_TLS_CERTIFICATES_H */ diff --git a/src/manage_sql.c b/src/manage_sql.c index 03e805678..20565a2f5 100644 --- a/src/manage_sql.c +++ b/src/manage_sql.c @@ -670,6 +670,7 @@ command_t gmp_commands[] {"MODIFY_TARGET", "Modify an existing target."}, {"MODIFY_TASK", "Update an existing task."}, {"MODIFY_TICKET", "Modify an existing ticket."}, + {"MODIFY_TLS_CERTIFICATE", "Modify an existing TLS certificate."}, {"MODIFY_USER", "Modify a user."}, {"MOVE_TASK", "Assign task to another slave scanner, even while running."}, {"RESTORE", "Restore a resource."}, diff --git a/src/manage_sql_tls_certificates.c b/src/manage_sql_tls_certificates.c index a8b71822e..23cefe66c 100644 --- a/src/manage_sql_tls_certificates.c +++ b/src/manage_sql_tls_certificates.c @@ -698,6 +698,132 @@ inherit_tls_certificates (user_t user, user_t inheritor) inheritor, user); } +/** + * @brief Modify a TLS certificate. + * + * @param[in] tls_certificate_id UUID of TLS certificate. + * @param[in] comment New comment on TLS certificate. + * @param[in] name New name of TLS certificate. + * @param[in] certificate New certificate file content. + * + * @return 0 success, 1 TLS certificate exists already, + * 2 failed to find TLS certificate, + * 3 invalid certificate content, 99 permission denied, -1 error. + */ +int +modify_tls_certificate (const gchar *tls_certificate_id, + const gchar *comment, + const gchar *name, + const gchar *certificate) +{ + tls_certificate_t tls_certificate; + + assert (tls_certificate_id); + assert (current_credentials.uuid); + + sql_begin_immediate (); + + /* Check permissions and get a handle on the TLS certificate. */ + + if (acl_user_may ("modify_tls_certificate") == 0) + { + sql_rollback (); + return 99; + } + + tls_certificate = 0; + if (find_resource_with_permission ("tls_certificate", + tls_certificate_id, + &tls_certificate, + "modify_tls_certificate", + 0)) + { + sql_rollback (); + return -1; + } + + if (tls_certificate == 0) + { + sql_rollback (); + return 2; + } + + /* Update certificate if requested. */ + + if (certificate) + { + gchar *quoted_certificate; + int ret; + char *md5_fingerprint, *subject_dn, *issuer_dn; + time_t activation_time, expiration_time; + + ret = get_certificate_info (certificate, + &activation_time, + &expiration_time, + &md5_fingerprint, + &subject_dn, + &issuer_dn); + + if (ret) + return 3; + + quoted_certificate = sql_quote (certificate); + sql ("UPDATE tls_certificates SET" + " certificate = '%s'," + " activation_time = %llu," + " expiration_time = %llu," + " md5_fingerprint = '%s'," + " subject_dn = '%s'," + " issuer_dn = '%s'," + " modification_time = m_now ()" + " WHERE id = %llu;", + quoted_certificate, + activation_time, + expiration_time, + md5_fingerprint, + subject_dn, + issuer_dn, + tls_certificate); + g_free (quoted_certificate); + } + + /* Update comment if requested. */ + + if (comment) + { + gchar *quoted_comment; + + quoted_comment = sql_quote (comment); + sql ("UPDATE tls_certificates SET" + " comment = '%s'," + " modification_time = m_now ()" + " WHERE id = %llu;", + quoted_comment, + tls_certificate); + g_free (quoted_comment); + } + + /* Update name if requested. */ + + if (name) + { + gchar *quoted_name; + + quoted_name = sql_quote (name); + sql ("UPDATE tls_certificates SET" + " name = '%s'," + " modification_time = m_now ()" + " WHERE id = %llu;", + quoted_name, + tls_certificate); + g_free (quoted_name); + } + + sql_commit (); + + return 0; +} + /** * @brief Return the UUID of a TLS certificate. * diff --git a/src/manage_tls_certificates.h b/src/manage_tls_certificates.h index 1c6924669..b867b72a3 100644 --- a/src/manage_tls_certificates.h +++ b/src/manage_tls_certificates.h @@ -80,6 +80,10 @@ int copy_tls_certificate (const char*, const char*, const char*, tls_certificate_t*); +int +modify_tls_certificate (const gchar *, const gchar *, const gchar *, + const gchar *); + char* tls_certificate_uuid (tls_certificate_t); From 4ec4776f588901d085c843c57b36fb68363d0564 Mon Sep 17 00:00:00 2001 From: Timo Pollmeier Date: Thu, 13 Jun 2019 09:48:51 +0200 Subject: [PATCH 08/18] Add missing error case for create_tls_certificate The case for invalid certificate content was missing. --- src/gmp_tls_certificates.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/gmp_tls_certificates.c b/src/gmp_tls_certificates.c index c5e348c7e..ac4385e08 100644 --- a/src/gmp_tls_certificates.c +++ b/src/gmp_tls_certificates.c @@ -384,6 +384,17 @@ create_tls_certificate_run (gmp_parser_t *gmp_parser, GError **error) free (uuid); break; } + case 1: + { + SEND_TO_CLIENT_OR_FAIL + (XML_ERROR_SYNTAX ("create_tls_certificate", + "Invalid certificate content")); + log_event_fail ("tls_certificate", + "TLS Certificate", + NULL, + "created"); + break; + } case 99: SEND_TO_CLIENT_OR_FAIL (XML_ERROR_SYNTAX ("create_tls_certificate", From 50ac57f608b73ad2341aa74db8abfabfd5f27564 Mon Sep 17 00:00:00 2001 From: Timo Pollmeier Date: Thu, 13 Jun 2019 10:59:34 +0200 Subject: [PATCH 09/18] Add option to change trust of tls_certificates The trust can be optionally set in both create_tls_certificate and modify_tls_certificate. --- src/gmp_tls_certificates.c | 31 ++++++++++++++++++++++++++++--- src/manage_sql_tls_certificates.c | 23 +++++++++++++++++++---- src/manage_tls_certificates.h | 4 ++-- 3 files changed, 49 insertions(+), 9 deletions(-) diff --git a/src/gmp_tls_certificates.c b/src/gmp_tls_certificates.c index ac4385e08..8725f83ec 100644 --- a/src/gmp_tls_certificates.c +++ b/src/gmp_tls_certificates.c @@ -291,7 +291,8 @@ create_tls_certificate_element_start (gmp_parser_t *gmp_parser, const gchar *nam void create_tls_certificate_run (gmp_parser_t *gmp_parser, GError **error) { - entity_t entity, copy, comment, name, certificate; + entity_t entity, copy, comment, name, certificate, trust; + int trust_int; tls_certificate_t new_tls_certificate; entity = (entity_t) create_tls_certificate_data.context->first->data; @@ -368,11 +369,21 @@ create_tls_certificate_run (gmp_parser_t *gmp_parser, GError **error) name = entity_child (entity, "name"); comment = entity_child (entity, "comment"); certificate = entity_child (entity, "certificate"); + trust = entity_child (entity, "trust"); + + trust_int = 0; + if (trust) + { + if (strcmp (entity_text (trust), "") + && strcmp (entity_text (trust), "0")) + trust_int = 1; + } switch (create_tls_certificate (name ? entity_text (comment) : NULL, comment ? entity_text (comment) : "", certificate ? entity_text (certificate) : NULL, + trust_int, &new_tls_certificate)) { case 0: @@ -529,8 +540,9 @@ modify_tls_certificate_element_start (gmp_parser_t *gmp_parser, void modify_tls_certificate_run (gmp_parser_t *gmp_parser, GError **error) { - entity_t entity, comment, name, certificate; + entity_t entity, comment, name, certificate, trust; const char *tls_certificate_id; + int trust_int; entity = (entity_t) modify_tls_certificate_data.context->first->data; @@ -541,6 +553,18 @@ modify_tls_certificate_run (gmp_parser_t *gmp_parser, GError **error) comment = entity_child (entity, "comment"); name = entity_child (entity, "name"); certificate = entity_child (entity, "certificate"); + trust = entity_child (entity, "trust"); + + trust_int = -1; + if (trust) + { + if (strcmp (entity_text (trust), "") + && strcmp (entity_text (trust), "0")) + trust_int = 1; + else + trust_int = 0; + } + /* Modify the tls_certificate. */ @@ -553,7 +577,8 @@ modify_tls_certificate_run (gmp_parser_t *gmp_parser, GError **error) (tls_certificate_id, comment ? entity_text (comment) : NULL, name ? entity_text (name) : NULL, - certificate ? entity_text (certificate) : NULL)) + certificate ? entity_text (certificate) : NULL, + trust_int)) { case 0: SENDF_TO_CLIENT_OR_FAIL (XML_OK ("modify_tls_certificate")); diff --git a/src/manage_sql_tls_certificates.c b/src/manage_sql_tls_certificates.c index 23cefe66c..023738a13 100644 --- a/src/manage_sql_tls_certificates.c +++ b/src/manage_sql_tls_certificates.c @@ -363,6 +363,7 @@ trash_tls_certificate_writable (tls_certificate_t tls_certificate) * @param[in] name Name of new TLS certificate. * @param[in] comment Comment of TLS certificate. * @param[in] certificate Plain certificate file content. + * @param[in] trust Whether to trust the certificate. * @param[out] tls_certificate Created TLS certificate. * * @return 0 success, 1 invalid certificate, 99 permission denied, -1 error. @@ -371,14 +372,13 @@ int create_tls_certificate (const char *name, const char *comment, const char *certificate, + int trust, tls_certificate_t *tls_certificate) { int ret; char *md5_fingerprint, *subject_dn, *issuer_dn; time_t activation_time, expiration_time; - subject_dn = NULL; // TODO add to get_certificate_info - ret = get_certificate_info (certificate, &activation_time, &expiration_time, @@ -394,7 +394,7 @@ create_tls_certificate (const char *name, " certificate, subject_dn, issuer_dn, trust," " activation_time, expiration_time, md5_fingerprint)" " SELECT make_uuid(), (SELECT id FROM users WHERE users.uuid = '%s')," - " '%s', '%s', m_now(), m_now(), '%s', '%s', '%s', 0," + " '%s', '%s', m_now(), m_now(), '%s', '%s', '%s', %d," " %ld, %ld, '%s';", current_credentials.uuid, name ? name : md5_fingerprint, @@ -402,6 +402,7 @@ create_tls_certificate (const char *name, certificate ? certificate : "", subject_dn ? subject_dn : "", issuer_dn ? issuer_dn : "", + trust, activation_time, expiration_time, md5_fingerprint); @@ -705,6 +706,7 @@ inherit_tls_certificates (user_t user, user_t inheritor) * @param[in] comment New comment on TLS certificate. * @param[in] name New name of TLS certificate. * @param[in] certificate New certificate file content. + * @param[in] trust New trust value or -1 to keep old value. * * @return 0 success, 1 TLS certificate exists already, * 2 failed to find TLS certificate, @@ -714,7 +716,8 @@ int modify_tls_certificate (const gchar *tls_certificate_id, const gchar *comment, const gchar *name, - const gchar *certificate) + const gchar *certificate, + int trust) { tls_certificate_t tls_certificate; @@ -819,6 +822,18 @@ modify_tls_certificate (const gchar *tls_certificate_id, g_free (quoted_name); } + /* Update trust if requested */ + + if (trust != -1) + { + sql ("UPDATE tls_certificates SET" + " trust = %d," + " modification_time = m_now ()" + " WHERE id = %llu;", + trust, + tls_certificate); + } + sql_commit (); return 0; diff --git a/src/manage_tls_certificates.h b/src/manage_tls_certificates.h index b867b72a3..1695402da 100644 --- a/src/manage_tls_certificates.h +++ b/src/manage_tls_certificates.h @@ -73,7 +73,7 @@ int trash_tls_certificate_writable (tls_certificate_t); int -create_tls_certificate (const char *, const char *, const char *, +create_tls_certificate (const char *, const char *, const char *, int, tls_certificate_t *); int @@ -82,7 +82,7 @@ copy_tls_certificate (const char*, const char*, const char*, int modify_tls_certificate (const gchar *, const gchar *, const gchar *, - const gchar *); + const gchar *, int); char* tls_certificate_uuid (tls_certificate_t); From 92bec252f67cc2df9c7ffe52a8fa982a284cee68 Mon Sep 17 00:00:00 2001 From: Timo Pollmeier Date: Thu, 13 Jun 2019 11:49:23 +0200 Subject: [PATCH 10/18] Handle special cases for tls_certificate times The activation_time and expiration_time have special cases for "unknown" and "unlimited" to be considered in the GMP elements and filters. --- src/manage_pg.c | 11 ++++++++ src/manage_sql_tls_certificates.c | 4 +-- src/manage_sqlite3.c | 42 +++++++++++++++++++++++++++++++ 3 files changed, 55 insertions(+), 2 deletions(-) diff --git a/src/manage_pg.c b/src/manage_pg.c index caa0181ca..16e13ba54 100644 --- a/src/manage_pg.c +++ b/src/manage_pg.c @@ -991,6 +991,17 @@ manage_create_sql_functions () " END;" "$$ LANGUAGE plpgsql;"); + sql ("CREATE OR REPLACE FUNCTION certificate_iso_time (integer)" + " RETURNS text AS $$" + " BEGIN" + " RETURN CASE" + " WHEN ($1 = 0) THEN 'unlimited'" + " WHEN ($1 = -1) THEN 'unknown'" + " ELSE iso_time($1)" + " END;" + " END;" + "$$ LANGUAGE plpgsql;"); + sql ("CREATE OR REPLACE FUNCTION days_from_now (seconds integer)" " RETURNS integer AS $$" " DECLARE" diff --git a/src/manage_sql_tls_certificates.c b/src/manage_sql_tls_certificates.c index 023738a13..e8a1c7482 100644 --- a/src/manage_sql_tls_certificates.c +++ b/src/manage_sql_tls_certificates.c @@ -78,12 +78,12 @@ KEYWORD_TYPE_STRING \ }, \ { \ - "iso_time (activation_time)", \ + "certificate_iso_time (activation_time)", \ "activation_time", \ KEYWORD_TYPE_INTEGER \ }, \ { \ - "iso_time (expiration_time)", \ + "certificate_iso_time (expiration_time)", \ "expiration_time", \ KEYWORD_TYPE_INTEGER \ }, \ diff --git a/src/manage_sqlite3.c b/src/manage_sqlite3.c index 4cf1d2a86..0b30737db 100644 --- a/src/manage_sqlite3.c +++ b/src/manage_sqlite3.c @@ -1205,6 +1205,34 @@ sql_iso_time (sqlite3_context *context, int argc, sqlite3_value** argv) } } +/** + * @brief Convert an epoch time like iso_time with certificate special cases. + * + * This is a callback for a scalar SQL function of one argument. + * + * @param[in] context SQL context. + * @param[in] argc Number of arguments. + * @param[in] argv Argument array. + */ +void +sql_certificate_iso_time (sqlite3_context *context, int argc, + sqlite3_value** argv) +{ + time_t epoch_time; + gchar *iso; + + assert (argc == 1); + + epoch_time = sqlite3_value_int64 (argv[0]); + + iso = certificate_iso_time (epoch_time); + if (iso) + sqlite3_result_text (context, iso, -1, SQLITE_TRANSIENT); + else + sqlite3_result_error (context, "Failed to format time", -1); + g_free (iso); +} + /** * @brief Calculate difference between now and epoch time in days * @@ -2929,6 +2957,20 @@ manage_create_sql_functions () return -1; } + if (sqlite3_create_function (gvmd_db, + "certificate_iso_time", + 1, /* Number of args. */ + SQLITE_UTF8, + NULL, /* Callback data. */ + sql_certificate_iso_time, + NULL, /* xStep. */ + NULL) /* xFinal. */ + != SQLITE_OK) + { + g_warning ("%s: failed to create certificate_iso_time", __FUNCTION__); + return -1; + } + if (sqlite3_create_function (gvmd_db, "days_from_now", 1, /* Number of args. */ From cf8a1efbe919b19671380e3d11472f5b6467380d Mon Sep 17 00:00:00 2001 From: Timo Pollmeier Date: Thu, 13 Jun 2019 17:49:44 +0200 Subject: [PATCH 11/18] Add TLS Certificate GMP documentation This adds documentation for the commands create_tls_certificate get_tls_certificates and modify_tls_certificate. --- src/schema_formats/XML/GMP.xml.in | 611 ++++++++++++++++++++++++++++++ 1 file changed, 611 insertions(+) diff --git a/src/schema_formats/XML/GMP.xml.in b/src/schema_formats/XML/GMP.xml.in index 27a9c0c5b..2a02acdc7 100644 --- a/src/schema_formats/XML/GMP.xml.in +++ b/src/schema_formats/XML/GMP.xml.in @@ -3111,6 +3111,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. create_target create_task create_ticket + create_tls_certificate create_user delete_agent delete_alert @@ -3164,6 +3165,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. get_targets get_tasks get_tickets + get_tls_certificates get_users get_version get_vulns @@ -3190,6 +3192,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. modify_target modify_task modify_ticket + modify_tls_certificate modify_user restore resume_task @@ -3239,6 +3242,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. create_target create_task create_ticket + create_tls_certificate create_user delete_agent delete_alert @@ -3292,6 +3296,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. get_targets get_tasks get_tickets + get_tls_certificates get_users get_version get_vulns @@ -3317,6 +3322,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. modify_tag modify_target modify_ticket + modify_tls_certificate modify_task modify_user restore @@ -6082,6 +6088,96 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + + create_tls_certificate + Create a TLS certificate + +

+ The client uses the create_tls_certificate command to create a new + TLS certificate. +

+
+ + comment + copy + name + trust + certificate + + + comment + A comment on the TLS certificate + + text + + + + copy + The UUID of an existing TLS certificate + + uuid + + + + name + + The name of the certificate, defaulting to the MD5 fingerprint + + + text + + + + trust + Whether the certificate is trusted + + boolean + + + + certificate + The certificate data + + text + + + + + + status + status + 1 + + + status_text + text + 1 + + + id + uuid + 1 + + + + + Create a TLS certificate + + + Example Certificate + -----BEGIN CERTIFICATE----- + [...] + + + + + + + + +
create_user Create a user @@ -22581,6 +22677,430 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + + get_tls_certificates + Get one or many TLS certificates + +

+ The client uses the "get_tls_certificates" command to retrieve one + or more TLS certificates. +

+
+ + + tls_certificate_id + ID of single TLS certificate to get + uuid + + + filter + Filter term to use to filter query + text + + + uuid + uuid + Unique ID + + + name + name + Name + + + comment + text + Comment text + + + created + iso_time + Creation time + + + modified + iso_time + Modification time + + + owner + name + Name of the owner + + + subject_dn + text + + Distinguished name (DN) of the certificate subject + + + + issuer_dn + text + + Distinguished name (DN) of the certificate issuer + + + + md5_fingerprint + text + + MD5 fingerprint of the certificate + + + + activates + iso_time + Time before which the certificate is not valid + + + expires + iso_time + Time after which the certificate is not valid + + + valid + boolean + Whether the certificate is currently valid + + + + + filt_id + ID of filter to use to filter query + uuid + + + + + + status + status + 1 + + + status_text + text + 1 + + tls_certificate + filters + sort + tls_certificates + tls_certificate_count + + + tls_certificate + + + id + ID of TLS certificate + uuid + 1 + + owner + name + comment + creation_time + modification_time + writable + in_use + permissions + certificate + md5_fingerprint + trust + activation_time + expiration_time + subject_dn + issuer_dn + + + owner + Owner of the TLS certificate + + name + + + name + The name of the owner + name + + + + name + The name of the TLS certificate + text + + + comment + The comment on the TLS certificate + text + + + creation_time + Creation time of the TLS certificate + iso_time + + + modification_time + Last time the TLS certificate was modified + iso_time + + + writable + Whether the TLS certificate is writable + boolean + + + in_use + Whether this TLS certificate is currently in use + boolean + + + permissions + + Permissions that the current user has on the TLS certificate + + + permission + + + permission + + name + + + name + The name of the permission + name + + + + + certificate + The certificate file as plain text + text + + + md5_fingerprint + The MD5 fingerprint of the certificate + text + + + trust + Whether the certificate is trusted + boolean + + + valid + Whether the certificate is currently valid + boolean + + + activation_time + Time before which the certificate is not valid + iso_time + + + expiration_time + Time after which the certificate is not valid + iso_time + + + subject_dn + Distinguished name (DN) of the certificate subject + text + + + issuer_dn + Distinguished name (DN) of the certificate issuer + text + + + + filters + + + id + UUID of filter if any, else 0 + uuid + 1 + + term + name + keywords + + + term + Filter term + text + + + name + Filter name, if applicable + text + + + keywords + Filter broken down into keywords + keyword + + keyword + + column + relation + value + + + column + Column prefix + text + + + relation + Relation operator + + + = + : + ~ + > + < + + + + + value + The filter text + text + + + + + + sort + + text + field + + + field + + order + + + order + + + + ascending + descending + + + + + + + + tls_certificates + + + start + First TLS certificate + integer + 1 + + + max + Maximum number of TLS certificates + integer + 1 + + + + + tls_certificate_count + + filtered + page + + + filtered + Number of TLS certificate after filtering + integer + + + page + Number of TLS certificate on current page + integer + + + + + Get the TLS certificates + + + + + + + + admin + + Example Certificate + + 2019-06-12T14:36:53Z + 2019-06-13T08:56:36Z + 1 + 0 + + + Everything + + + -----BEGIN CERTIFICATE----- + [...] + + 28:3d:7f:0a:15:82:f8:bb:9b:4e:93:97:95:59:d7:af + 1 + 1 + 2019-02-26T14:24:15Z + 2021-02-25T14:24:15Z + CN=localhost,O=GVM Users,L=Osnabrueck,C=DE + OU=Certificate Authority for localhost,O=GVM Users,L=Osnabrueck,C=DE + + + first=1 rows=10 sort=name + + + first + = + 1 + + + rows + = + 1000 + + + sort + = + name + + + + + nameascending + + + 1 + 1 + 1 + + + + +
get_version Get the OpenVAS Manager Protocol version @@ -25627,6 +26147,97 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + + modify_tls_certificate + Create a TLS certificate + +

+ The client uses the modify_tls_certificate command to modify an + existing TLS certificate. +

+
+ + + tls_certificate_id + uuid + 1 + + comment + copy + name + trust + certificate + + + comment + A comment on the TLS certificate + + text + + + + copy + The UUID of an existing TLS certificate + + uuid + + + + name + + The name of the certificate, defaulting to the MD5 fingerprint + + + text + + + + trust + Whether the certificate is trusted + + boolean + + + + certificate + The certificate data + + text + + + + + + status + status + 1 + + + status_text + text + 1 + + + + + + Modify the name and certificate content of a TLS certificate + + + + Updated Example Certificate + -----BEGIN CERTIFICATE----- + [...] + + + + + + + + +
modify_user Modify a user From a8a620dee2af399bba062fb1e2a5a467c8f31f5f Mon Sep 17 00:00:00 2001 From: Timo Pollmeier Date: Thu, 13 Jun 2019 18:05:43 +0200 Subject: [PATCH 12/18] Add check if certificate is empty The certificate must not be empty for create_tls_certificate and modify_tls_certificate. --- src/gmp_tls_certificates.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/src/gmp_tls_certificates.c b/src/gmp_tls_certificates.c index 8725f83ec..7d7e3a56d 100644 --- a/src/gmp_tls_certificates.c +++ b/src/gmp_tls_certificates.c @@ -371,6 +371,19 @@ create_tls_certificate_run (gmp_parser_t *gmp_parser, GError **error) certificate = entity_child (entity, "certificate"); trust = entity_child (entity, "trust"); + if (certificate == NULL + || strcmp (entity_text (certificate), "") == 0) + { + SEND_TO_CLIENT_OR_FAIL + (XML_ERROR_SYNTAX ("create_tls_certificate", + "CERTIFICATE is required and must not be empty.")); + log_event_fail ("tls_certificate", + "TLS Certificate", + NULL, + "created"); + return; + } + trust_int = 0; if (trust) { @@ -555,6 +568,19 @@ modify_tls_certificate_run (gmp_parser_t *gmp_parser, GError **error) certificate = entity_child (entity, "certificate"); trust = entity_child (entity, "trust"); + if (certificate + && strcmp (entity_text (certificate), "") == 0) + { + SEND_TO_CLIENT_OR_FAIL + (XML_ERROR_SYNTAX ("create_tls_certificate", + "New CERTIFICATE must not be empty if given.")); + log_event_fail ("tls_certificate", + "TLS Certificate", + NULL, + "created"); + return; + } + trust_int = -1; if (trust) { @@ -565,7 +591,6 @@ modify_tls_certificate_run (gmp_parser_t *gmp_parser, GError **error) trust_int = 0; } - /* Modify the tls_certificate. */ if (tls_certificate_id == NULL) From d51b020f6f4caf6ed1e3a43a5e91782699000d56 Mon Sep 17 00:00:00 2001 From: Timo Pollmeier Date: Tue, 18 Jun 2019 18:30:43 +0200 Subject: [PATCH 13/18] Change tls_certificates to use Base64 The commands create_tls_certificate and modify_tls_certificate now expect the certificate in Base64 encoding, so the DER format can be used in addition to PEM. --- src/gmp.c | 20 ++++++------ src/gmp_tls_certificates.c | 22 ++++++++++++- src/manage.c | 37 +++++++++++++++++---- src/manage.h | 4 ++- src/manage_sql_tls_certificates.c | 54 +++++++++++++++++++++++-------- src/schema_formats/XML/GMP.xml.in | 19 ++++------- 6 files changed, 112 insertions(+), 44 deletions(-) diff --git a/src/gmp.c b/src/gmp.c index e66befc29..fad12779e 100644 --- a/src/gmp.c +++ b/src/gmp.c @@ -13726,9 +13726,9 @@ handle_get_credentials (gmp_parser_t *gmp_parser, GError **error) time_t activation_time, expiration_time; gchar *activation_time_str, *expiration_time_str; gchar *fingerprint, *issuer; - get_certificate_info (cert, + get_certificate_info (cert, -1, &activation_time, &expiration_time, - &fingerprint, NULL, &issuer); + &fingerprint, NULL, &issuer, NULL); activation_time_str = certificate_iso_time (activation_time); expiration_time_str = certificate_iso_time (expiration_time); SENDF_TO_CLIENT_OR_FAIL @@ -17087,9 +17087,9 @@ handle_get_scanners (gmp_parser_t *gmp_parser, GError **error) { /* CA Certificate */ gchar *fingerprint, *issuer; - get_certificate_info (scanner_iterator_ca_pub (&scanners), + get_certificate_info (scanner_iterator_ca_pub (&scanners), -1, &activation_time, &expiration_time, - &fingerprint, NULL, &issuer); + &fingerprint, NULL, &issuer, NULL); activation_time_str = certificate_iso_time (activation_time); expiration_time_str = certificate_iso_time (expiration_time); SENDF_TO_CLIENT_OR_FAIL @@ -17132,9 +17132,9 @@ handle_get_scanners (gmp_parser_t *gmp_parser, GError **error) { /* Certificate */ gchar *fingerprint, *issuer; - get_certificate_info (scanner_iterator_key_pub (&scanners), + get_certificate_info (scanner_iterator_key_pub (&scanners), -1, &activation_time, &expiration_time, - &fingerprint, NULL, &issuer); + &fingerprint, NULL, &issuer, NULL); activation_time_str = certificate_iso_time (activation_time); expiration_time_str = certificate_iso_time (expiration_time); SENDF_TO_CLIENT_OR_FAIL @@ -18010,10 +18010,10 @@ handle_get_settings (gmp_parser_t *gmp_parser, GError **error) gchar *activation_time_str, *expiration_time_str, *fingerprint; gchar *issuer; - get_certificate_info (setting_iterator_value (&settings), + get_certificate_info (setting_iterator_value (&settings), -1, &activation_time, &expiration_time, &fingerprint, - NULL, &issuer); + NULL, &issuer, NULL); activation_time_str = certificate_iso_time (activation_time); expiration_time_str = certificate_iso_time (expiration_time); SENDF_TO_CLIENT_OR_FAIL @@ -20763,9 +20763,9 @@ gmp_xml_handle_end_element (/* unused */ GMarkupParseContext* context, "%s", ldap_cacert); - get_certificate_info (ldap_cacert, &activation_time, + get_certificate_info (ldap_cacert, -1, &activation_time, &expiration_time, &fingerprint, - NULL, &issuer); + NULL, &issuer, NULL); activation_time_str = certificate_iso_time (activation_time); expiration_time_str = certificate_iso_time (expiration_time); SENDF_TO_CLIENT_OR_FAIL diff --git a/src/gmp_tls_certificates.c b/src/gmp_tls_certificates.c index 7d7e3a56d..e5df802a0 100644 --- a/src/gmp_tls_certificates.c +++ b/src/gmp_tls_certificates.c @@ -419,6 +419,17 @@ create_tls_certificate_run (gmp_parser_t *gmp_parser, GError **error) "created"); break; } + case 2: + { + SEND_TO_CLIENT_OR_FAIL + (XML_ERROR_SYNTAX ("create_tls_certificate", + "CERTIFICATE is not valid Base64.")); + log_event_fail ("tls_certificate", + "TLS Certificate", + NULL, + "created"); + return; + } case 99: SEND_TO_CLIENT_OR_FAIL (XML_ERROR_SYNTAX ("create_tls_certificate", @@ -572,7 +583,7 @@ modify_tls_certificate_run (gmp_parser_t *gmp_parser, GError **error) && strcmp (entity_text (certificate), "") == 0) { SEND_TO_CLIENT_OR_FAIL - (XML_ERROR_SYNTAX ("create_tls_certificate", + (XML_ERROR_SYNTAX ("modify_tls_certificate", "New CERTIFICATE must not be empty if given.")); log_event_fail ("tls_certificate", "TLS Certificate", @@ -645,6 +656,15 @@ modify_tls_certificate_run (gmp_parser_t *gmp_parser, GError **error) tls_certificate_id, "modified"); break; + case 4: + SEND_TO_CLIENT_OR_FAIL + (XML_ERROR_SYNTAX ("modify_tls_certificate", + "CERTIFICATE is not valid Base64.")); + log_event_fail ("tls_certificate", + "TLS Certificate", + NULL, + "modified"); + return; case 99: SEND_TO_CLIENT_OR_FAIL (XML_ERROR_SYNTAX ("modify_tls_certificate", diff --git a/src/manage.c b/src/manage.c index c7d0de525..17b375cd6 100644 --- a/src/manage.c +++ b/src/manage.c @@ -301,20 +301,24 @@ truncate_private_key (const gchar* private_key) * @brief Gathers info from a certificate. * * @param[in] certificate The certificate to get data from. + * @param[in] certificate_len Length of the certificate, -1: null-terminated * @param[out] activation_time Pointer to write activation time to. * @param[out] expiration_time Pointer to write expiration time to. * @param[out] fingerprint Pointer for newly allocated fingerprint. * @param[out] subject Pointer for newly allocated subject DN. * @param[out] issuer Pointer for newly allocated issuer DN. + * @param[out] format Pointer to certificate format. * * @return 0 success, -1 error. */ int -get_certificate_info (const gchar* certificate, +get_certificate_info (const gchar* certificate, gssize certificate_len, time_t* activation_time, time_t* expiration_time, - gchar** fingerprint, gchar **subject, gchar** issuer) + gchar** fingerprint, gchar **subject, gchar** issuer, + gnutls_x509_crt_fmt_t *certificate_format) { gchar *cert_truncated; + gnutls_x509_crt_fmt_t certificate_format_internal; cert_truncated = NULL; if (activation_time) @@ -327,30 +331,49 @@ get_certificate_info (const gchar* certificate, *subject = NULL; if (issuer) *issuer = NULL; + if (certificate_format) + *certificate_format = 0; if (certificate) { int err; gnutls_datum_t cert_datum; gnutls_x509_crt_t gnutls_cert; + static const gchar* begin_str = "-----BEGIN "; - cert_truncated = truncate_certificate (certificate); - if (cert_truncated == NULL) + if (certificate_len < 0) + cert_datum.size = strlen (cert_truncated); + else + cert_datum.size = certificate_len; + + if (g_strrstr_len (certificate, cert_datum.size, begin_str)) { - return -1; + cert_truncated = truncate_certificate (certificate); + if (cert_truncated == NULL) + { + return -1; + } + certificate_format_internal = GNUTLS_X509_FMT_PEM; + } + else + { + cert_truncated = g_memdup (certificate, cert_datum.size); + certificate_format_internal = GNUTLS_X509_FMT_DER; } cert_datum.data = (unsigned char*) cert_truncated; - cert_datum.size = strlen (cert_truncated); gnutls_x509_crt_init (&gnutls_cert); err = gnutls_x509_crt_import (gnutls_cert, &cert_datum, - GNUTLS_X509_FMT_PEM); + certificate_format_internal); if (err) { g_free (cert_truncated); return -1; } + if (certificate_format) + *certificate_format = certificate_format_internal; + if (activation_time) { *activation_time diff --git a/src/manage.h b/src/manage.h index 0873391e7..893796b38 100644 --- a/src/manage.h +++ b/src/manage.h @@ -159,11 +159,13 @@ truncate_private_key (const gchar*); int get_certificate_info (const gchar *, + gssize, time_t *, time_t *, gchar **, gchar **, - gchar **); + gchar **, + gnutls_x509_crt_fmt_t *); gchar * certificate_iso_time (time_t); diff --git a/src/manage_sql_tls_certificates.c b/src/manage_sql_tls_certificates.c index e8a1c7482..dba08b541 100644 --- a/src/manage_sql_tls_certificates.c +++ b/src/manage_sql_tls_certificates.c @@ -362,29 +362,41 @@ trash_tls_certificate_writable (tls_certificate_t tls_certificate) * * @param[in] name Name of new TLS certificate. * @param[in] comment Comment of TLS certificate. - * @param[in] certificate Plain certificate file content. + * @param[in] certificate_b64 Base64 certificate file content. * @param[in] trust Whether to trust the certificate. * @param[out] tls_certificate Created TLS certificate. * - * @return 0 success, 1 invalid certificate, 99 permission denied, -1 error. + * @return 0 success, 1 invalid certificate content, 2 certificate not Base64, + * 99 permission denied, -1 error. */ int create_tls_certificate (const char *name, const char *comment, - const char *certificate, + const char *certificate_b64, int trust, tls_certificate_t *tls_certificate) { int ret; + gchar *certificate_decoded; + gsize certificate_len; char *md5_fingerprint, *subject_dn, *issuer_dn; time_t activation_time, expiration_time; + gnutls_x509_crt_fmt_t certificate_format; - ret = get_certificate_info (certificate, + certificate_decoded + = (gchar*) g_base64_decode (certificate_b64, &certificate_len); + + if (certificate_decoded == NULL || certificate_len == 0) + return 2; + + ret = get_certificate_info (certificate_decoded, + certificate_len, &activation_time, &expiration_time, &md5_fingerprint, &subject_dn, - &issuer_dn); + &issuer_dn, + &certificate_format); if (ret) return 1; @@ -399,7 +411,7 @@ create_tls_certificate (const char *name, current_credentials.uuid, name ? name : md5_fingerprint, comment ? comment : "", - certificate ? certificate : "", + certificate_b64 ? certificate_b64 : "", subject_dn ? subject_dn : "", issuer_dn ? issuer_dn : "", trust, @@ -705,18 +717,19 @@ inherit_tls_certificates (user_t user, user_t inheritor) * @param[in] tls_certificate_id UUID of TLS certificate. * @param[in] comment New comment on TLS certificate. * @param[in] name New name of TLS certificate. - * @param[in] certificate New certificate file content. + * @param[in] certificate_b64 New Base64 certificate file content. * @param[in] trust New trust value or -1 to keep old value. * * @return 0 success, 1 TLS certificate exists already, * 2 failed to find TLS certificate, - * 3 invalid certificate content, 99 permission denied, -1 error. + * 3 invalid certificate content, 4 certificate is not valid Base64, + * 99 permission denied, -1 error. */ int modify_tls_certificate (const gchar *tls_certificate_id, const gchar *comment, const gchar *name, - const gchar *certificate, + const gchar *certificate_b64, int trust) { tls_certificate_t tls_certificate; @@ -753,24 +766,39 @@ modify_tls_certificate (const gchar *tls_certificate_id, /* Update certificate if requested. */ - if (certificate) + if (certificate_b64) { gchar *quoted_certificate; int ret; char *md5_fingerprint, *subject_dn, *issuer_dn; time_t activation_time, expiration_time; + gnutls_x509_crt_fmt_t certificate_format; + + gchar *certificate_decoded; + gsize certificate_len; + + certificate_decoded + = (gchar*) g_base64_decode (certificate_b64, &certificate_len); + + if (certificate_decoded == NULL || certificate_len == 0) + { + sql_rollback (); + return 4; + } - ret = get_certificate_info (certificate, + ret = get_certificate_info (certificate_decoded, + certificate_len, &activation_time, &expiration_time, &md5_fingerprint, &subject_dn, - &issuer_dn); + &issuer_dn, + &certificate_format); if (ret) return 3; - quoted_certificate = sql_quote (certificate); + quoted_certificate = sql_quote (certificate_b64); sql ("UPDATE tls_certificates SET" " certificate = '%s'," " activation_time = %llu," diff --git a/src/schema_formats/XML/GMP.xml.in b/src/schema_formats/XML/GMP.xml.in index 3cf740479..0c3dd3b28 100644 --- a/src/schema_formats/XML/GMP.xml.in +++ b/src/schema_formats/XML/GMP.xml.in @@ -6136,7 +6136,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. certificate - The certificate data + The Base64 encoded certificate data (x.509 DER or PEM) text @@ -6165,9 +6165,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. Example Certificate - -----BEGIN CERTIFICATE----- - [...] - + MIIDNjCCAp+gAwIBAgIBATANBgkqhkiG9w0BAQQFADCBqTELM[...] @@ -22878,7 +22876,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. certificate - The certificate file as plain text + The Base64 encoded certificate data (x.509 DER or PEM) text @@ -23058,10 +23056,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. Everything - -----BEGIN CERTIFICATE----- - [...] - - 28:3d:7f:0a:15:82:f8:bb:9b:4e:93:97:95:59:d7:af + MIIDNjCCAp+gAwIBAgIBATANBgkqhkiG9w0BAQQFADCBqTELM[...] + ba:ec:16:30:27:ca:99:17:ff:df:a4:4c:bc:bf:1b:98 1 1 2019-02-26T14:24:15Z @@ -26135,7 +26131,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. certificate - The certificate data + The Base64 encoded certificate data (x.509 DER or PEM) text @@ -26162,8 +26158,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. Updated Example Certificate - -----BEGIN CERTIFICATE----- - [...] + LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUVrVENDQ[...] From 868820b95b70927387ab2ed2ee7fd95758d93335 Mon Sep 17 00:00:00 2001 From: Timo Pollmeier Date: Wed, 19 Jun 2019 09:24:52 +0200 Subject: [PATCH 14/18] Fix size checks in get_certificate_info The size of the certificate datum has to be set after truncation and certificate_len is used before that. If certificate_len < 0 and the certificate does not look PEM-encoded, the function will return and not try to determine the size with strlen. --- src/manage.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/manage.c b/src/manage.c index 17b375cd6..e2346a03b 100644 --- a/src/manage.c +++ b/src/manage.c @@ -341,12 +341,7 @@ get_certificate_info (const gchar* certificate, gssize certificate_len, gnutls_x509_crt_t gnutls_cert; static const gchar* begin_str = "-----BEGIN "; - if (certificate_len < 0) - cert_datum.size = strlen (cert_truncated); - else - cert_datum.size = certificate_len; - - if (g_strrstr_len (certificate, cert_datum.size, begin_str)) + if (g_strstr_len (certificate, certificate_len, begin_str)) { cert_truncated = truncate_certificate (certificate); if (cert_truncated == NULL) @@ -357,10 +352,23 @@ get_certificate_info (const gchar* certificate, gssize certificate_len, } else { - cert_truncated = g_memdup (certificate, cert_datum.size); + if (certificate_len < 0) + { + g_warning ("%s: PEM encoded certificate expected if" + " certificate_length is negative", + __FUNCTION__); + return -1; + } + + cert_truncated = g_memdup (certificate, certificate_len); certificate_format_internal = GNUTLS_X509_FMT_DER; } + cert_datum.data = (unsigned char*) cert_truncated; + if (certificate_len < 0) + cert_datum.size = strlen (cert_truncated); + else + cert_datum.size = certificate_len; gnutls_x509_crt_init (&gnutls_cert); err = gnutls_x509_crt_import (gnutls_cert, &cert_datum, From f9e9d83949e58ed3a27b5a5137cbaf8e1d56cb43 Mon Sep 17 00:00:00 2001 From: Timo Pollmeier Date: Wed, 19 Jun 2019 09:33:28 +0200 Subject: [PATCH 15/18] Fix get_certificate_info doc The certificate_format parameter was listed with the wrong name. --- src/manage.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/manage.c b/src/manage.c index e2346a03b..84a65a5a9 100644 --- a/src/manage.c +++ b/src/manage.c @@ -300,14 +300,14 @@ truncate_private_key (const gchar* private_key) /** * @brief Gathers info from a certificate. * - * @param[in] certificate The certificate to get data from. - * @param[in] certificate_len Length of the certificate, -1: null-terminated - * @param[out] activation_time Pointer to write activation time to. - * @param[out] expiration_time Pointer to write expiration time to. - * @param[out] fingerprint Pointer for newly allocated fingerprint. - * @param[out] subject Pointer for newly allocated subject DN. - * @param[out] issuer Pointer for newly allocated issuer DN. - * @param[out] format Pointer to certificate format. + * @param[in] certificate The certificate to get data from. + * @param[in] certificate_len Length of certificate, -1: null-terminated + * @param[out] activation_time Pointer to write activation time to. + * @param[out] expiration_time Pointer to write expiration time to. + * @param[out] fingerprint Pointer for newly allocated fingerprint. + * @param[out] subject Pointer for newly allocated subject DN. + * @param[out] issuer Pointer for newly allocated issuer DN. + * @param[out] certificate_format Pointer to certificate format. * * @return 0 success, -1 error. */ From 85bbea74dfb6ca14325f3c27c03f0128b838b110 Mon Sep 17 00:00:00 2001 From: Timo Pollmeier Date: Wed, 19 Jun 2019 10:38:28 +0200 Subject: [PATCH 16/18] Add certificate format to tls_certificates The format (DER or PEM) can help clients determine the MIME content type of the decoded certificate. --- src/gmp_tls_certificates.c | 5 ++- src/manage_pg.c | 6 ++- src/manage_sql_tls_certificates.c | 70 ++++++++++++++++++++++++++----- src/manage_sqlite3.c | 4 +- src/manage_tls_certificates.h | 3 ++ src/schema_formats/XML/GMP.xml.in | 17 +++++++- 6 files changed, 88 insertions(+), 17 deletions(-) diff --git a/src/gmp_tls_certificates.c b/src/gmp_tls_certificates.c index e5df802a0..8cc018bfa 100644 --- a/src/gmp_tls_certificates.c +++ b/src/gmp_tls_certificates.c @@ -183,7 +183,7 @@ get_tls_certificates_run (gmp_parser_t *gmp_parser, GError **error) /* Send tls_certificate info. */ SENDF_TO_CLIENT_OR_FAIL - ("%s" + ("%s" "%s" "%d" "%d" @@ -192,6 +192,9 @@ get_tls_certificates_run (gmp_parser_t *gmp_parser, GError **error) "%s" "%s" "", + tls_certificate_iterator_certificate_format (&tls_certificates) + ? tls_certificate_iterator_certificate_format (&tls_certificates) + : "unknown", tls_certificate_iterator_certificate (&tls_certificates), tls_certificate_iterator_md5_fingerprint (&tls_certificates), tls_certificate_iterator_trust (&tls_certificates), diff --git a/src/manage_pg.c b/src/manage_pg.c index d3bd76a3e..701f04cfd 100644 --- a/src/manage_pg.c +++ b/src/manage_pg.c @@ -2530,7 +2530,8 @@ create_tables () " activation_time integer," " expiration_time integer," " md5_fingerprint text," - " trust integer);"); + " trust integer," + " certificate_format text);"); sql ("CREATE TABLE IF NOT EXISTS tls_certificates_trash" " (id SERIAL PRIMARY KEY," @@ -2546,7 +2547,8 @@ create_tables () " activation_time integer," " expiration_time integer," " md5_fingerprint text," - " trust integer);"); + " trust integer," + " certificate_format text);"); sql ("CREATE TABLE IF NOT EXISTS scanners" " (id SERIAL PRIMARY KEY," diff --git a/src/manage_sql_tls_certificates.c b/src/manage_sql_tls_certificates.c index dba08b541..ba8597032 100644 --- a/src/manage_sql_tls_certificates.c +++ b/src/manage_sql_tls_certificates.c @@ -44,7 +44,7 @@ */ #define TLS_CERTIFICATE_ITERATOR_FILTER_COLUMNS \ { GET_ITERATOR_FILTER_COLUMNS, "subject_dn", "issuer_dn", "md5_fingerprint", \ - "activates", "expires", "valid", NULL } + "activates", "expires", "valid", "certificate_format", NULL } /** * @brief TLS Certificate iterator columns. @@ -94,6 +94,11 @@ "valid", \ KEYWORD_TYPE_INTEGER \ }, \ + { \ + "certificate_format", \ + NULL, \ + KEYWORD_TYPE_STRING \ + }, \ { \ "activation_time", \ "activates", \ @@ -155,6 +160,11 @@ "valid", \ KEYWORD_TYPE_INTEGER \ }, \ + { \ + "certificate_format", \ + NULL, \ + KEYWORD_TYPE_STRING \ + }, \ { \ "activation_time", \ "activates", \ @@ -305,6 +315,16 @@ tls_certificate_iterator_valid (iterator_t *iterator) return iterator_int (iterator, GET_ITERATOR_COLUMN_COUNT + 7); } +/** + * @brief Get a column value from a tls_certificate iterator. + * + * @param[in] iterator Iterator. + * + * @return Value of the column or NULL if iteration is complete. + */ +DEF_ACCESS (tls_certificate_iterator_certificate_format, + GET_ITERATOR_COLUMN_COUNT + 8); + /** * @brief Return whether a tls_certificate is in use. * @@ -357,6 +377,27 @@ trash_tls_certificate_writable (tls_certificate_t tls_certificate) return trash_tls_certificate_in_use (tls_certificate) == 0; } +/** + * @brief Get a string representation of a certificate format. + * + * @param[in] certificate_format The format as gnutls_x509_crt_fmt_t. + * + * @return A string representation of the format (e.g. "PEM" or "DER"). + */ +static const char* +tls_certificate_format_str (gnutls_x509_crt_fmt_t certificate_format) +{ + switch (certificate_format) + { + case GNUTLS_X509_FMT_DER: + return "DER"; + case GNUTLS_X509_FMT_PEM: + return "PEM"; + default: + return "unknown"; + } +} + /** * @brief Create a TLS certificate. * @@ -404,10 +445,11 @@ create_tls_certificate (const char *name, sql ("INSERT INTO tls_certificates" " (uuid, owner, name, comment, creation_time, modification_time," " certificate, subject_dn, issuer_dn, trust," - " activation_time, expiration_time, md5_fingerprint)" + " activation_time, expiration_time, md5_fingerprint," + " certificate_format)" " SELECT make_uuid(), (SELECT id FROM users WHERE users.uuid = '%s')," " '%s', '%s', m_now(), m_now(), '%s', '%s', '%s', %d," - " %ld, %ld, '%s';", + " %ld, %ld, '%s', '%s';", current_credentials.uuid, name ? name : md5_fingerprint, comment ? comment : "", @@ -417,7 +459,8 @@ create_tls_certificate (const char *name, trust, activation_time, expiration_time, - md5_fingerprint); + md5_fingerprint, + tls_certificate_format_str (certificate_format)); if (tls_certificate) *tls_certificate = sql_last_insert_id (); @@ -452,7 +495,8 @@ copy_tls_certificate (const char *name, ret = copy_resource ("tls_certificate", name, comment, tls_certificate_id, "certificate, subject_dn, issuer_dn, trust," - "activation_time, expiration_time, md5_fingerprint", + "activation_time, expiration_time, md5_fingerprint," + "certificate_format", 0, new_tls_certificate, &old_tls_certificate); if (ret) return ret; @@ -547,11 +591,13 @@ delete_tls_certificate (const char *tls_certificate_id, int ultimate) sql ("INSERT INTO tls_certificates_trash" " (uuid, owner, name, comment, creation_time, modification_time," " certificate, subject_dn, issuer_dn, trust," - " activation_time, expiration_time, md5_fingerprint)" + " activation_time, expiration_time, md5_fingerprint," + " certificate_format)" " SELECT" " uuid, owner, name, comment, creation_time, modification_time," " certificate, subject_dn, issuer_dn, trust," - " activation_time, expiration_time, md5_fingerprint" + " activation_time, expiration_time, md5_fingerprint," + " certificate_format" " FROM tls_certificates WHERE id = %llu;", tls_certificate); @@ -620,11 +666,13 @@ restore_tls_certificate (const char *tls_certificate_id) sql ("INSERT INTO tls_certificates" " (uuid, owner, name, comment, creation_time, modification_time," " certificate, subject_dn, issuer_dn, trust," - " activation_time, expiration_time, md5_fingerprint)" + " activation_time, expiration_time, md5_fingerprint," + " certificate_format)" " SELECT" " uuid, owner, name, comment, creation_time, modification_time," " certificate, subject_dn, issuer_dn, trust," - " activation_time, expiration_time, md5_fingerprint" + " activation_time, expiration_time, md5_fingerprint," + " certificate_format" " FROM tls_certificates_trash WHERE id = %llu;", trash_tls_certificate); @@ -806,7 +854,8 @@ modify_tls_certificate (const gchar *tls_certificate_id, " md5_fingerprint = '%s'," " subject_dn = '%s'," " issuer_dn = '%s'," - " modification_time = m_now ()" + " modification_time = m_now ()," + " certificate_format = '%s'" " WHERE id = %llu;", quoted_certificate, activation_time, @@ -814,6 +863,7 @@ modify_tls_certificate (const gchar *tls_certificate_id, md5_fingerprint, subject_dn, issuer_dn, + tls_certificate_format_str (certificate_format), tls_certificate); g_free (quoted_certificate); } diff --git a/src/manage_sqlite3.c b/src/manage_sqlite3.c index 0b30737db..b1d2ae408 100644 --- a/src/manage_sqlite3.c +++ b/src/manage_sqlite3.c @@ -3860,13 +3860,13 @@ create_tables () " name text, comment text, creation_time integer," " modification_time integer, certificate text, subject_dn text," " issuer_dn text, activation_time integer, expiration_time integer," - " md5_fingerprint text, trust integer);"); + " md5_fingerprint text, trust integer, certificate_format text);"); sql ("CREATE TABLE IF NOT EXISTS tls_certificates_trash" " (id INTEGER PRIMARY KEY, uuid text UNIQUE, owner integer," " name text, comment text, creation_time integer," " modification_time integer, certificate text, subject_dn text," " issuer_dn text, activation_time integer, expiration_time integer," - " md5_fingerprint text, trust integer);"); + " md5_fingerprint text, trust integer, certificate_format text);"); sql ("CREATE TABLE IF NOT EXISTS scanners" " (id INTEGER PRIMARY KEY, uuid, owner INTEGER, name, comment," " host, port, type, ca_pub, credential INTEGER," diff --git a/src/manage_tls_certificates.h b/src/manage_tls_certificates.h index 1695402da..5272431f5 100644 --- a/src/manage_tls_certificates.h +++ b/src/manage_tls_certificates.h @@ -60,6 +60,9 @@ tls_certificate_iterator_expiration_time (iterator_t*); int tls_certificate_iterator_valid (iterator_t *); +const char* +tls_certificate_iterator_certificate_format (iterator_t*); + int tls_certificate_in_use (tls_certificate_t); diff --git a/src/schema_formats/XML/GMP.xml.in b/src/schema_formats/XML/GMP.xml.in index 0c3dd3b28..bddef8184 100644 --- a/src/schema_formats/XML/GMP.xml.in +++ b/src/schema_formats/XML/GMP.xml.in @@ -22877,7 +22877,20 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. certificate The Base64 encoded certificate data (x.509 DER or PEM) - text + + + format + The format of the certificate + + + DER + PEM + unknown + + + 1 + + md5_fingerprint @@ -23056,7 +23069,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. Everything - MIIDNjCCAp+gAwIBAgIBATANBgkqhkiG9w0BAQQFADCBqTELM[...] + MIIDNjCCAp+gAwIBAgIBATANBgkqhkiG9w0BAQQFADCBqTELM[...] ba:ec:16:30:27:ca:99:17:ff:df:a4:4c:bc:bf:1b:98 1 1 From 987d31a232ada6cbd8ef67ccc031f4c14cac0c1f Mon Sep 17 00:00:00 2001 From: Timo Pollmeier Date: Wed, 19 Jun 2019 10:52:13 +0200 Subject: [PATCH 17/18] Show tls_certificate Base64 only with details The certificate element in the get_tls_certificates response will only contain the Base64 content if details are requested. --- src/gmp_tls_certificates.c | 4 +++- src/schema_formats/XML/GMP.xml.in | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/gmp_tls_certificates.c b/src/gmp_tls_certificates.c index 8cc018bfa..beb7331ba 100644 --- a/src/gmp_tls_certificates.c +++ b/src/gmp_tls_certificates.c @@ -195,7 +195,9 @@ get_tls_certificates_run (gmp_parser_t *gmp_parser, GError **error) tls_certificate_iterator_certificate_format (&tls_certificates) ? tls_certificate_iterator_certificate_format (&tls_certificates) : "unknown", - tls_certificate_iterator_certificate (&tls_certificates), + get_tls_certificates_data.get.details + ? tls_certificate_iterator_certificate (&tls_certificates) + : "", tls_certificate_iterator_md5_fingerprint (&tls_certificates), tls_certificate_iterator_trust (&tls_certificates), tls_certificate_iterator_valid (&tls_certificates), diff --git a/src/schema_formats/XML/GMP.xml.in b/src/schema_formats/XML/GMP.xml.in index bddef8184..5fc400ca4 100644 --- a/src/schema_formats/XML/GMP.xml.in +++ b/src/schema_formats/XML/GMP.xml.in @@ -22876,7 +22876,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. certificate - The Base64 encoded certificate data (x.509 DER or PEM) + The Base64 encoded certificate data if details are requested, empty otherwise format From 106673d51b67f0c62e005f3a64236f27b81d4586 Mon Sep 17 00:00:00 2001 From: Timo Pollmeier Date: Fri, 21 Jun 2019 17:22:47 +0200 Subject: [PATCH 18/18] Clean up tls_certificates typos / formatting This fixes some typos, formatting issue and copy-paste errors in the new code for handling TLS certificates. --- src/gmp_tls_certificates.c | 19 ++++++++++--------- src/manage_sql_tls_certificates.c | 8 ++++---- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/gmp_tls_certificates.c b/src/gmp_tls_certificates.c index beb7331ba..875104f23 100644 --- a/src/gmp_tls_certificates.c +++ b/src/gmp_tls_certificates.c @@ -261,8 +261,8 @@ create_tls_certificate_reset () */ void create_tls_certificate_start (gmp_parser_t *gmp_parser, - const gchar **attribute_names, - const gchar **attribute_values) + const gchar **attribute_names, + const gchar **attribute_values) { memset (&create_tls_certificate_data, 0, sizeof (create_tls_certificate_t)); create_tls_certificate_data.context = g_malloc0 (sizeof (context_data_t)); @@ -279,12 +279,13 @@ create_tls_certificate_start (gmp_parser_t *gmp_parser, * @param[in] attribute_values All attribute values. */ void -create_tls_certificate_element_start (gmp_parser_t *gmp_parser, const gchar *name, - const gchar **attribute_names, - const gchar **attribute_values) +create_tls_certificate_element_start (gmp_parser_t *gmp_parser, + const gchar *name, + const gchar **attribute_names, + const gchar **attribute_values) { - xml_handle_start_element (create_tls_certificate_data.context, name, attribute_names, - attribute_values); + xml_handle_start_element (create_tls_certificate_data.context, name, + attribute_names, attribute_values); } /** @@ -398,7 +399,7 @@ create_tls_certificate_run (gmp_parser_t *gmp_parser, GError **error) } switch (create_tls_certificate - (name ? entity_text (comment) : NULL, + (name ? entity_text (name) : NULL, comment ? entity_text (comment) : "", certificate ? entity_text (certificate) : NULL, trust_int, @@ -593,7 +594,7 @@ modify_tls_certificate_run (gmp_parser_t *gmp_parser, GError **error) log_event_fail ("tls_certificate", "TLS Certificate", NULL, - "created"); + "modified"); return; } diff --git a/src/manage_sql_tls_certificates.c b/src/manage_sql_tls_certificates.c index ba8597032..74ab63b21 100644 --- a/src/manage_sql_tls_certificates.c +++ b/src/manage_sql_tls_certificates.c @@ -580,7 +580,7 @@ delete_tls_certificate (const char *tls_certificate_id, int ultimate) return 0; } - /* Ticket was found in regular table. */ + /* TLS certificate was found in regular table. */ if (ultimate == 0) { @@ -713,13 +713,13 @@ empty_trashcan_tls_certificates () LOCATION_TRASH, current_credentials.uuid); - sql ("DELETE FROM tickets_trash" + sql ("DELETE FROM tls_certifcates_trash" " WHERE owner = (SELECT id FROM users WHERE uuid = '%s');", current_credentials.uuid); } /** - * @brief Delete all TLS certificate owner by a user. + * @brief Delete all TLS certificate owned by a user. * * Also delete trash TLS certificates. * @@ -753,7 +753,7 @@ inherit_tls_certificates (user_t user, user_t inheritor) sql ("UPDATE tls_certificate SET owner = %llu WHERE owner = %llu;", inheritor, user); - /* Trash tickets. */ + /* Trash TLS certificates. */ sql ("UPDATE tls_certificate_trash SET owner = %llu WHERE owner = %llu;", inheritor, user);