/* Copyright (C) 2018-2021 Greenbone Networks GmbH * * SPDX-License-Identifier: AGPL-3.0-or-later * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ #ifndef _GVMD_GMP_BASE_H #define _GVMD_GMP_BASE_H #include /** * @brief A handle on a GMP parser. */ typedef struct { int (*client_writer) (const char *, void *); ///< Writes to the client. void *client_writer_data; ///< Argument to client_writer. int importing; ///< Whether the current op is importing. int read_over; ///< Read over any child elements. int parent_state; ///< Parent state when reading over. gchar **disabled_commands; ///< Disabled commands. } gmp_parser_t; int find_attribute (const gchar **, const gchar **, const char *, const gchar **); int append_attribute (const gchar **, const gchar **, const char *, gchar **); void buffer_xml_append_printf (GString *, const char *, ...); gboolean send_to_client (const char *, int (*) (const char *, void *), void *); gboolean send_find_error_to_client (const char *, const char *, const char *, gmp_parser_t *); void error_send_to_client (GError **); void internal_error_send_to_client (GError **); /** * @brief Send response message to client and return a given value on error. * * Queue a message in \ref to_client with \ref send_to_client. On failure * call \ref error_send_to_client on a GError* called "error" and do a return. * * @param[in] err_ret Return value on send error. * @param[in] format Format string for message. * @param[in] args Arguments for format string. */ #define SENDF_TO_CLIENT_OR_FAIL_WITH_RETURN(err_ret, format, args...) \ do \ { \ gchar *msg = g_markup_printf_escaped (format, ##args); \ if (send_to_client (msg, gmp_parser->client_writer, \ gmp_parser->client_writer_data)) \ { \ g_free (msg); \ error_send_to_client (error); \ return err_ret; \ } \ g_free (msg); \ } \ while (0) /** * @brief Send response message to client, returning on fail. * * Queue a message in \ref to_client with \ref send_to_client. On failure * call \ref error_send_to_client on a GError* called "error" and do a return. * * @param[in] format Format string for message. * @param[in] args Arguments for format string. */ #define SENDF_TO_CLIENT_OR_FAIL(format, args...) \ do \ { \ gchar *msg = g_markup_printf_escaped (format, ##args); \ if (send_to_client (msg, gmp_parser->client_writer, \ gmp_parser->client_writer_data)) \ { \ g_free (msg); \ error_send_to_client (error); \ return; \ } \ g_free (msg); \ } \ while (0) /** * @brief Send response message to client, returning on fail. * * Queue a message in \ref to_client with \ref send_to_client. On failure * call \ref error_send_to_client on a GError* called "error" and do a return. * * @param[in] msg The message, a string. */ #define SEND_TO_CLIENT_OR_FAIL(msg) \ do \ { \ if (send_to_client (msg, gmp_parser->client_writer, \ gmp_parser->client_writer_data)) \ { \ error_send_to_client (error); \ return; \ } \ } \ while (0) void log_event (const char *, const char *, const char *, const char *) __attribute__ ((weak)); void log_event_fail (const char *, const char *, const char *, const char *); /* Status codes. */ /* HTTP status codes used: * * 200 OK * 201 Created * 202 Accepted * 400 Bad request * 401 Must auth * 404 Missing */ /** * @brief Response code for a syntax error. */ #define STATUS_ERROR_SYNTAX "400" /** * @brief Response code when authorisation is required. */ #define STATUS_ERROR_MUST_AUTH "401" /** * @brief Response code when authorisation is required. */ #define STATUS_ERROR_MUST_AUTH_TEXT "Authenticate first" /** * @brief Response code for forbidden access. */ #define STATUS_ERROR_ACCESS "403" /** * @brief Response code text for forbidden access. */ #define STATUS_ERROR_ACCESS_TEXT "Access to resource forbidden" /** * @brief Response code for a missing resource. */ #define STATUS_ERROR_MISSING "404" /** * @brief Response code text for a missing resource. */ #define STATUS_ERROR_MISSING_TEXT "Resource missing" /** * @brief Response code for a busy resource. */ #define STATUS_ERROR_BUSY "409" /** * @brief Response code text for a busy resource. */ #define STATUS_ERROR_BUSY_TEXT "Resource busy" /** * @brief Response code when authorisation failed. */ #define STATUS_ERROR_AUTH_FAILED "400" /** * @brief Response code text when authorisation failed. */ #define STATUS_ERROR_AUTH_FAILED_TEXT "Authentication failed" /** * @brief Response code on success. */ #define STATUS_OK "200" /** * @brief Response code text on success. */ #define STATUS_OK_TEXT "OK" /** * @brief Response code on success, when a resource is created. */ #define STATUS_OK_CREATED "201" /** * @brief Response code on success, when a resource is created. */ #define STATUS_OK_CREATED_TEXT "OK, resource created" /** * @brief Response code on success, when the operation will finish later. */ #define STATUS_OK_REQUESTED "202" /** * @brief Response code text on success, when the operation will finish later. */ #define STATUS_OK_REQUESTED_TEXT "OK, request submitted" /** * @brief Response code for an internal error. */ #define STATUS_INTERNAL_ERROR "500" /** * @brief Response code text for an internal error. */ #define STATUS_INTERNAL_ERROR_TEXT "Internal error" /** * @brief Response code when a service is unavailable. */ #define STATUS_SERVICE_UNAVAILABLE "503" /** * @brief Response code when a service is down. */ #define STATUS_SERVICE_DOWN "503" /** * @brief Response code text when a service is down. */ #define STATUS_SERVICE_DOWN_TEXT "Service temporarily down" /** * @brief Expand to XML for a STATUS_ERROR_SYNTAX response. * * @param tag Name of the command generating the response. * @param text Text for the status_text attribute of the response. */ #define XML_ERROR_SYNTAX(tag, text) \ "<" tag "_response" \ " status=\"" STATUS_ERROR_SYNTAX "\"" \ " status_text=\"" text "\"/>" /** * @brief Expand to XML for a STATUS_ERROR_ACCESS response. * * @param tag Name of the command generating the response. */ #define XML_ERROR_ACCESS(tag) \ "<" tag "_response" \ " status=\"" STATUS_ERROR_ACCESS "\"" \ " status_text=\"" STATUS_ERROR_ACCESS_TEXT "\"/>" /** * @brief Expand to XML for a STATUS_SERVICE_UNAVAILABLE response. * * @param tag Name of the command generating the response. * @param text Status text. */ #define XML_ERROR_UNAVAILABLE(tag, text) \ "<" tag "_response" \ " status=\"" STATUS_SERVICE_UNAVAILABLE "\"" \ " status_text=\"" text "\"/>" /** * @brief Expand to XML for a STATUS_ERROR_MISSING response. * * @param tag Name of the command generating the response. */ #define XML_ERROR_MISSING(tag) \ "<" tag "_response" \ " status=\"" STATUS_ERROR_MISSING "\"" \ " status_text=\"" STATUS_ERROR_MISSING_TEXT "\"/>" /** * @brief Expand to XML for a STATUS_ERROR_AUTH_FAILED response. * * @param tag Name of the command generating the response. */ #define XML_ERROR_AUTH_FAILED(tag) \ "<" tag "_response" \ " status=\"" STATUS_ERROR_AUTH_FAILED "\"" \ " status_text=\"" STATUS_ERROR_AUTH_FAILED_TEXT "\"/>" /** * @brief Expand to XML for a STATUS_ERROR_BUSY response. * * @param tag Name of the command generating the response. */ #define XML_ERROR_BUSY(tag) \ "<" tag "_response" \ " status=\"" STATUS_ERROR_BUSY "\"" \ " status_text=\"" STATUS_ERROR_BUSY_TEXT "\"/>" /** * @brief Expand to XML for a STATUS_OK response. * * @param tag Name of the command generating the response. */ #define XML_OK(tag) \ "<" tag "_response" \ " status=\"" STATUS_OK "\"" \ " status_text=\"" STATUS_OK_TEXT "\"/>" /** * @brief Expand to XML for a STATUS_OK_CREATED response. * * @param tag Name of the command generating the response. */ #define XML_OK_CREATED(tag) \ "<" tag "_response" \ " status=\"" STATUS_OK_CREATED "\"" \ " status_text=\"" STATUS_OK_CREATED_TEXT "\"/>" /** * @brief Expand to XML for a STATUS_OK_CREATED response with %s for ID. * * @param tag Name of the command generating the response. */ #define XML_OK_CREATED_ID(tag) \ "<" tag "_response" \ " status=\"" STATUS_OK_CREATED "\"" \ " status_text=\"" STATUS_OK_CREATED_TEXT "\"" \ " id=\"%s\"/>" /** * @brief Expand to XML for a STATUS_OK_REQUESTED response. * * @param tag Name of the command generating the response. */ #define XML_OK_REQUESTED(tag) \ "<" tag "_response" \ " status=\"" STATUS_OK_REQUESTED "\"" \ " status_text=\"" STATUS_OK_REQUESTED_TEXT "\"/>" /** * @brief Expand to XML for a STATUS_INTERNAL_ERROR response. * * @param tag Name of the command generating the response. */ #define XML_INTERNAL_ERROR(tag) \ "<" tag "_response" \ " status=\"" STATUS_INTERNAL_ERROR "\"" \ " status_text=\"" STATUS_INTERNAL_ERROR_TEXT "\"/>" /** * @brief Sends XML for a STATUS_SERVICE_DOWN response. * * @param tag Name of the command generating the response. */ #define SEND_XML_SERVICE_DOWN(tag) \ do \ { \ char *str; \ str = \ g_strdup_printf ("<%s_response status='%s' status_text='%s'/>", tag, \ STATUS_SERVICE_DOWN, STATUS_SERVICE_DOWN_TEXT); \ SEND_TO_CLIENT_OR_FAIL (str); \ g_free (str); \ } \ while (0); #endif /* not _GVMD_GMP_BASE_H */